Project Euler

I started messing with Project Euler this week. It’s actually a lot of fun. I’ve only solved three problems so far, but I’ve been enjoying it, so I think I’ll keep going and see how far I get before I get tired of it, or I get pulled into something else, or the problems get too hard.
I’d been thinking that maybe I’d try a new language for this, but I decided to stick with C#, as I’m not really doing much C# at work, and I want to keep in practice with it.
I’ll also admit that I haven’t had any reason to do the kind of math problems that are found at Project Euler in a very long time, so my skills there are a bit rusty. But I’m managing to remember what Fibonacci numbers are and all that fun stuff!

Here’s my badge:

Opening multiple projects in MorphX at startup

The MorphX IDE used for X++ programming in Microsoft Dynamics AX is a fairly decent environment to work in, but it definitely has some shortcomings and oddities. There is a “project” abstraction in MorphX that allows you to create a named group of objects that all relate to a project that you are working on. There’s little meaning to these projects, other than that. You can export all objects in a project into a single XPO file, but other than that, it’s basically just a structure to help a programmer keep track of a list of related objects. You can set a single project as your “startup project”, and that project will then open automatically when you open MorphX. Since I’m usually juggling three or four projects at a time, I’ve been thinking that it would be great if you could open a group of projects instead of just one, so I decided to try and write some code to do that.

My realization that this could be done at all mostly came from the book Microsoft Dynamics AX 2012 Development Cookbook. The section “Modifying the right-click context menu” described a method of setting and clearing the startup project via the context menu. Prior to reading this, I hadn’t realized that the development environment was as customizable as the AX front-end, though (in retrospect) it makes sense that it is.

The project I’m going to describe here will do a few, fairly simple, things:

  1. Maintain a list of startup projects in a simple text file, stored in my personal “documents” folder.
  2. Allow for adding and removing projects from this list, via the right-click context menu.
  3. Allow the user to open all projects in this list, via the MorphX “tools” menu.

I could probably do a lot more with this project, such as actually open the projects at MorphX startup, rather than just through the tools menu, but I’m fine with the project as-is, for now.

This blog post is going to walk through the steps necessary to implement this functionality.

First, we’re going to create a class called “AjhDevLaunchStartupProjects”. Our class will have methods to add and remove projects from the list, and to open all projects specified in the list. We’re not going to go overboard with efficiency here. I’m assuming that the list will, at most, have three or four projects on it at a time, so we’re simply going to read them from disk into an array, and write them back out from the array.

We’ll start with an entirely standard static constructor:

// https://gist.github.com/andyhuey/5315492
public static AjhDevLaunchStartupProjects construct()
{
    return new AjhDevLaunchStartupProjects();
}

Now let’s add a method to get the file name for the text file:

// https://gist.github.com/andyhuey/5315509
private str getStartProjFileName()
{
    str myDocsPath;

    #WinAPI

    myDocsPath = WinAPI::getFolderPath(#CSIDL_PERSONAL);
    return myDocsPath + @"\axStartProjects.txt";
}

Now, methods to read and write the file:

// https://gist.github.com/andyhuey/5315524
private Array getProjectList()
{
    // get the project list from a file.
    str startProjFileName;
    TextBuffer tbProjList;
    Array projects = new Array(Types::String);
    int nProjects;

    startProjFileName = this.getStartProjFileName();
    tbProjList = new TextBuffer();

    // if it doesn't exist, create an empty file & return.
    if (!WinAPI::fileExists(startProjFileName))
    {
        WinAPI::createFile(startProjFileName);
        return projects;
    }

    // should probably assert permission...
    tbProjList.fromFile(startProjFileName);

    nProjects = 0;
    while (tbProjList.nextToken(true))
    {
        nProjects++;
        projects.value(nProjects, tbProjList.token());
    }
    return projects;
}

private boolean writeProjectList(Array projects)
{
    // write out a project list to file, overwriting existing list.
    str startProjFileName;
    TextBuffer tbProjList;
    int i;

    startProjFileName = this.getStartProjFileName();

    tbProjList = new TextBuffer();

    for (i=1; i <= projects.lastIndex(); i++)
    {
        tbProjList.appendText(projects.value(i));
        tbProjList.appendText("\n");
    }

    return tbProjList.toFile(startProjFileName);
}

And the methods to add and remove projects from the list:

// https://gist.github.com/andyhuey/5315547
private void addProject(str newProject)
{
    // add a new project to the list.
    Array projects;
    int i;

    projects = this.getProjectList();

    // make sure it's not already there...
    for (i=1; i <= projects.lastIndex(); i++)
    {
        if (projects.value(i) == newProject)
            return;
    }
    // add it and save.
    projects.value(projects.lastIndex()+1, newProject);
    this.writeProjectList(projects);
}

private void removeProject(str projectToRemove)
{
    // remove a project from the list.
    Array projectsIn, projectsOut;
    int i, j;

    projectsIn = this.getProjectList();
    projectsOut = new Array(Types::String);

    j=1;
    for (i=1; i <= projectsIn.lastIndex(); i++)
    {
        if (projectsIn.value(i) != projectToRemove)
        {
            projectsOut.value(j, projectsIn.value(i));
            j++;
        }
    }
    this.writeProjectList(projectsOut);
}

And here’s the code to open all active projects:

// https://gist.github.com/andyhuey/5315552
public void openAllProjects()
{
    // get the project list, and open all projects.
    Array projects;
    int i;
    ProjectNode sharedProjects, privateProjects, projectNode;

    projects = this.getProjectList();

    sharedProjects = Infolog.projectRootNode().AOTfindChild('Shared');
    if (!sharedProjects)
        throw error("Error: cannot locate shared project node!");

    privateProjects = Infolog.projectRootNode().AOTfindChild('Private');
    if (!privateProjects)
        throw error("Error: cannot locate private project node!");

    for (i=1; i <= projects.lastIndex(); i++)
    {
        projectNode = sharedProjects.AOTfindChild(projects.value(i));
        if (!ProjectNode)
            projectNode = privateProjects.AOTfindChild(projects.value(i));

        if (projectNode)
            projectNode.getRunNode();
        else
            warning(strFmt("Project %1 cannot be found.", projects.value(i)));
    }
}

(I probably found the code to open a project from this blog post, or a similar one.)
Now, we will create three new “action” menu items:

  1. AjhDevStartupProjectAdd – to add a project.
  2. AjhDevStartupProjectRemove – to remove a project.
  3. AjhDevStartupProjectOpenAll – to open all projects.

Each one will have ObjectType set to “Class”, and the object will be our class, “AjhDevLaunchStartupProjects”. The static main() method in our class will use args.menuItemName() to determine which action to take.
Here’s that method:

// https://gist.github.com/andyhuey/5315559
public static void main(Args args)
{
    AjhDevLaunchStartupProjects obj = AjhDevLaunchStartupProjects::construct();
    SysContextMenu contextMenu;
    str projectName, x;
    ;

    // should always be called from a menu item.
    if (!args.menuItemName())
    {
        return;
    }

    // if called from the add-ins context menu...
    if (SysContextMenu::startedFrom(args))
    {
        contextMenu = args.parmObject();
        projectName = contextMenu.getFirstNode().treeNodeName();
    }

    switch (args.menuItemName())
    {
        case menuitemActionStr(AjhDevStartupProjectAdd):
            obj.addProject(projectName);
            break;
        case menuitemActionStr(AjhDevStartupProjectRemove):
            obj.removeProject(projectName);
            break;
        case menuitemActionStr(AjhDevStartupProjectOpenAll):
            obj.openAllProjects();
        default:
            return;
    }
}

The add and remove menu items will be added to the SysContextMenu. This way, they will show in the context menu under “add-ins”. The “open all” menu item will be added to the DevelopmentTools menu. This way, it will show under the “Tools” menu in MorphX.

We will also change the “verifyItem” method of the “SysContextMenu” class, so that the add & remove items will only show in the context menu for projects (and not for other objects). (If we wanted to go further with this, we would also add logic here to show only one or the other option, depending on whether or not the project is already on the startup list.)

Here’s the code that we will add to “verifyItem”, at the end of the large case statement there:

    // https://gist.github.com/andyhuey/5315566
    // ajh 2013-04-03: my own startup project thing...
    case menuitemActionStr(AjhDevStartupProjectAdd):
    case menuitemActionStr(AjhDevStartupProjectRemove):
        if (firstNode.handle() != classNum(ProjectNode) || !match(#pathProjects, firstNode.treeNodePath()))
        {
            return 0;
        }
        return 1;

So I think this is all pretty straightforward. My purpose in writing this up in such detail was largely so that I could get a bit of X++ code on this blog, and in the hope that someone else might find this useful. I haven’t had the chance to write much general-purpose code at my current job, so there isn’t much I’m working on that would be appropriate to post here, but this seemed like a worthwhile little project to work on, and hopefully it may prove helpful to someone else.

My new job, Dynamics AX, and X++

I started a new job (at SHI) back in January. I’ve been wanting to post something about it for awhile now, but I’ve been pretty busy. Also, I kind of wanted to keep quiet about it for a bit, just in case it didn’t work out. Well, I’ve been there for about two months now, and it seems to be going well.

Right now, I’m doing development for our Dynamics AX system, using AX’s proprietary programming language, X++. It’s a reasonably decent and relatively modern language, very similar to C# and/or Java. I do miss the more chaotic environment I’d previously been working in, where I was using a mix of ASP.NET / C#, JavaScript, and PHP / Drupal, depending on the project. SHI does have a fairly mixed environment, but there are enough programmers working here that they’re not likely to need me on anything other than X++ any time soon, so I guess I’ll have to get used to a bit less variety than I’ve had in the past.

The development environment built into AX is called MorphX. (This is also the name of a mediocre XBox 360 game, which kind of skews Google results for MorphX, but that’s OK.) Microsoft has obviously made some effort to add some nice features to MorphX since they acquired AX, but it’s not quite up to the standard set by Visual Studio. They’ve also tried to standardize some of the keyboard shortcuts between VS and MorphX, but there are still a few annoying inconsistencies there.

I recently found a project on CodePlex called Microsoft Dynamics AX 2012 X++ Editor Extensions, which adds a few missing features to the X++ code editor. I tend to worry about add-ins like this slowing things down or introducing instability, but these three extensions all seem to work well. (It’s funny how you don’t really think of, for instance, brace matching as being a big deal, until you don’t have it…)

I haven’t really blogged much about programming recently, so I’d really like to get back into the habit. I have a few possible topics in mind for AX-related posts, so hopefully I can find the time to write those up soon.

Bullseye

The main product of the company I currently work for is a hosted store locator and lead manager service, named Bullseye. We’ve been concentrating on both improving it and marketing it recently, so there’s some fairly interesting things going on that I thought I would write up. I’ve mentioned some of these things previously, but I thought it might be useful to have a single consolidated post with some pointers.

We have a Facebook store locator, which you can find at https://www.facebook.com/BullseyeStoreLocator. The Facebook locator was an interesting project. The first iteration was outsourced to an external developer, and was completed before I started working for the company. Due to some major changes in the way Facebook supported app development, we had to do a lot of work on the Facebook locator in mid-2011. I did a pretty major rewrite of it, using the Facebook C# SDK (which seems to have moved to Github, and gotten a nicely redesigned website since I last looked at it). Since that rewrite, one of our other developers has been working on it, mostly adding new features. The most recent new feature is one that allows you to attach ‘like’ buttons to individual locations in the returned results, linking them to individual Facebook pages for each location. It’s described in a blog post here.

We also now have a Drupal module that allows you to easily implement a store locator in any Drupal 7 site. (I’ve blogged about this previously.) It’s still a sandbox project under my drupal.org account. Cleaning it up and getting it ready to be promoted to a full project is on my rainy-day to-do list. (I’ve done a bit of work towards that goal, but I still need to do some more.)

And we now have a way to import and sync locations from Salesforce into Bullseye. This was another component that was initially outsourced. I’ve done some maintenance work on the project, and it’s pretty interesting. We’ve implemented a way to filter the results that we pull in from Salesforce, using serialized LINQ expressions. I was initially leery about this approach, and there are still some things I don’t like about it, but if you need to abstract out and save complex filter conditions to a database, I guess there isn’t a better way to do it than this. The one difficulty is that it’s fairly difficult to read and comprehend the expressions, once they’re serialized, so it’s important to keep track of the original LINQ expressions, for reference.

CoffeeScript

I wanted to take a break from my usual .Net and Drupal stuff for a weekend, and try to learn something new. So I started reading Jump Start CoffeeScript today. CoffeeScript is a language, somewhat similar to Python in terms of syntax, that compiles into JavaScript. In theory, it makes JavaScript easier to use, and easier to read. I’m not entirely sold on it yet, but it’s interesting.

The book I’m reading is supposed to be a quick start, that you can get through in a weekend. It walks you through a sample application, an HTML5 game. I’m finding the sample code less useful than I’d like. It’s mostly drawing on the HTML5 canvas. I think I’d rather see code doing more typical stuff that you’d see being done on a typical web site. It’s hard to relate the canvas stuff to anything I’ve actually done before.

That said, it’s a pretty well-written book, and kind of fun. I had hoped to finish it tomorrow, but it looks like I need to take a trip into NYC tomorrow, and I’ll have company, so I won’t be reading on the train. And I’m working on New Year’s Eve, but maybe I can finish it on New Year’s Day!

Amazon Web Services

My boss has gotten enthusiastic about AWS recently. We’ve messed around with a bit with in on a couple of projects, and also just for testing. We used a Linux EC2 instance for the Gisgraphy project I blogged about a while back. And we would up using a dedicated Windows EC2 instance for the gas finder site that we put up after Hurricane Sandy.

In addition to that, I’ve done some experimenting with RDS (for SQL Server) and Elastic Beanstalk. I was initially enthusiastic about both, but, once I got to working with them, I saw enough limitations that I decided to back off. RDS is a nice way to have a low-maintenance SQL Server in the cloud, but the main limitation I found was the inability to easily get a local backup of a large database loaded onto it, and vice versa. While there are ways to get data in and out of RDS, of course, there’s no support for standard SQL backups and restores, to (and from) .bak files. The recommended approach is to script the db out to T-SQL, using the standard export capability, but given the size and complexity of some of our databases, that’s just not workable.

And, as for Elastic Beanstalk, it’s a nice way to get a single ASP.NET application up and running on EC2, with a pre-configured load balancer, but we really don’t have any single site that would benefit from that, and easily fit into that model.

For now, we’ve tentatively decided to move some of our stuff up to AWS, using a few EC2 instances, but really that won’t be much different than what we’re doing now (external hosting on a managed server at PEER1). The main difference will be that we’re planning on breaking some stuff up so that we’ll have a few smaller instances, so we can scale them as needed, and we’ll have the option of spinning up a second copy of the instance running our web service, if needed. I’m not really sure how all this will work out, but I’ll blog more as we go forward, if I learn anything that seems like it would be worth sharing.

Meanwhile, I’ve been watching this screencast series on AWS. Unfortunately, I’ve found that it’s mostly covering ground that I’ve already figured out on my own. But, if you’re new to AWS, and want a guided tour, included a (somewhat leisurely) look at some cloud basics, this might be for you.

Selenium

OK, one more post for tonight. (This is another one I suspected that I may have previously written up, but apparently not.)

I’ve known about Selenium for awhile now, mostly because one of our clients has a “testing guy” and he uses it. I’ve always wanted to be able to do some automated testing of web site projects, but it always seemed like the tools for doing so were too limited or complex. I’ll admit I put off downloading & learning Selenium, largely because I thought it would be a hassle and eat up a lot of time before I could really do anything useful with it. When I finally gave it a chance, though, I was surprised how easy it was to use.

I initially started with WebDriver, which is basically a couple of DLLs that let you “drive” Firefox (or another browser), sending keystrokes and click events, and looking for certain responses. You can get started with WebDriver quickly by grabbing it via NuGet. My first project with WebDriver was a simple console program that launches Firefox, then goes to several of the store locator web sites that use our Bullseye API, does a search at each one, and checks to see if it gets results. Nothing big, but just a useful program that I can run any time I roll out code changes to the API. Previously, I’d been checking this stuff by hand after each rollout.

Today, I took another step, and downloaded Selenium IDE. This is a Firefox plugin that lets you record a series of actions as you do them, then save them to a script. There are plugins allowing you save the script in several languages, including C#. So, I can record some steps, export some C# code, then fix it up to do some reasonable testing. My main purpose today was to record the steps involved in a fairly complex workflow on one of our client sites. It’s a multi-step process (around 20 steps, I think). Just in and of itself, the script is useful to have, as I often need to step through it to establish a new test account, so now I can just “play” it instead of clicking through the whole process myself. But, I would also like to use it to automate some testing of this process. Now that I have a base script, I can go in and replace the values I entered today with variables, so I can abstract things out in such a way that I can run the code repeatedly, testing multiple scenarios. And since I can do this all in C#, I can also then check the database, and see if the values I entered were interpreted and stored in the database correctly.

This may all seem pretty routine to some people, but I have to admit that I’ve never really had a chance to do this kind of testing before. It’s kind of cool!

I think my next project is going to have to be trying WebDriver with browsers other than Firefox.  I’d like to be able to test the same workflow in IE, Firefox, and Chrome, at least. (And if I get really ambitious, maybe I’ll see about iOS browser automation…)

Stumbling my way through the Drupal API

I’ve had to fix some interesting problems at work recently, related to a Drupal site that we’ll be rolling out soon. I just finished fixing one issue that, while seemingly minor, took quite a while to figure out.

I’m really glad to have come up with a good solution. The thing that amuses me most about this is that, after more than eight hours of messing around, the final solution involved writing only about a half-dozen lines of code.

The problem, in a nutshell, is that we have a content type in the system that represents a university. There’s a location field on each node with, minimally, city and country specified. The user can search for locations, using some custom search code, and the search results are displayed via a standard Drupal view. We allow the user to sort the results by one of a few different fields, with the sort drop-down exposed from the view. This works fine, except when sorting by country. On the location record, only the two-letter country code is stored, for instance “AE” for “United Arab Emirates”. So, when you sort by country, it’s really sorting on country code, so “AE” goes to the top, which isn’t really what the client wanted.

Of course, the first thing I did was Google the problem. I found this issue discussion, which pretty much matches my problem. There was a suggestion in the comments there about using hook_views_pre_render to re-sort the results right before displaying them. That works great, if you’re not paging results. But, if you’re pulling results back one page at a time from a large result set, this doesn’t work, since the pre-render hook only gives you the current page.

So I figured out that I really need to sort by country name at the SQL level, while retrieving results. This led to my next problem, which is that, even with the location module installed, there’s no SQL country lookup table in Drupal. The list of country codes and names is just stored in code, in an array, which can be retrieved via _country_get_predefined_list. (You shouldn’t call that directly, though, of course; you should use country_get_list.)

So off I went to find a module that could give me a SQL table with country info in it. The countries module does that, and a bit more. So, I installed that and figured out where the country table was. Then, my next blind alley was figuring out how to join to the new country table in a view. I was hoping I could just add a join to it in the view definition, and go from there. Well, I still don’t know that much about Drupal views, and it didn’t seem possible to do that easily.

So, the next blind alley was to see if I could alter the view SQL with hook_views_query_alter, which seemed sensible. Well, the query object that you get from that hook isn’t a nice simple query object that can easily be changed, so that turned out to be another dead end. (It’s likely possible that I could have figured it out, but it seemed like the wrong approach.)

Then, finally, I stumbled across this SO question. The one answer posted there led me in the direction of modifying the query with hook_query_alter, which can be used to modify just about any query Drupal issues to MySQL. So, finally, I found a workable solution.

hasAllTags('views', 'views_university_search')) {
    $ord =& $query->getOrderBy();
    if (array_key_exists('location_country', $ord)) {
      $query->addJoin('INNER', 'countries_country', 'cc', 'cc.iso2 = location.country');
      $ord = array('cc.name' => $ord['location_country']);
    }
  }
}

So that’s it. I add a join, and replace the ‘order by’ clause. About a half-dozen lines of code. Oh, and I now also understand passing by reference in PHP a little better too!

fun with WSDL and CURL

Ever since the debacle described in this blog post, I’ve made it a point to double-check the WSDL on the SOAP web services for our main product, any time I’m doing a non-trivial rollout, even if I know I haven’t changed anything that should affect the WSDL.

Up until today, I’ve always just done it by bringing up the WSDL URL for each web service in Firefox, and saving it to a text file. There’s only a half-dozen web services, so it doesn’t take that long. But this morning I finally broke down and wrote a batch file to fetch them all, using cURL.

I’ve gotten a bit more enthusiastic about using cURL, and other tools, to simplify things for me recently, since reading this blog post by Scott Hanselman.

random PHP functions

I’m still doing a fair amount of PHP work. Right now, it’s all Drupal, for a site we’re rolling out very soon. I keep stumbling across random PHP functions I hadn’t heard of before, and that turn out to be nice little time savers. Two examples:

  1. curl_setopt_array: I used to just call curl_setopt() a bunch of times to set all my options Now I can set a bunch of options in one fell swoop.
  2. http_build_query: Nothing I couldn’t previously do with simple string concatenation, but this is much cleaner.