So I was looking at one of the Siggnal to noise graphs, thinking about how I might define the cutoff function. One can kind of ignore the low volume things near the origin, since the data is less significant, and not much of a concern anyway. You’d want to cut out most of the noise, with a gradual cut over perhaps taking out some of the really high volume siggnal as well. And it occurred to me that designing that algorithm was a game in and of itself.
So here is the idea: take more-or-less a graphing calculator and wrap it up as a game, with targets to hit and/or points to avoid. These form a progressively more difficult levels running from simple y=x to to more convoluted equations. (Meanwhile, perhaps I shouldn’t be using equations at all)
Raphael doesn’t actually have a line method. You can use the more general ‘path’ which uses a compact sub-language to specify move-to, line-to, etc. Since I’m drawing one continuous line, it thankfully reduces to a small header and then a straight list of coordinates.
Raphael has a few conveniences, such as a built in animation system. On the other hand it frustrates me because there doesn’t appear to be a global transform – you always get an object in pixel-space, and one then needs to transform every object to the working coordinate space, which sometimes requires a bit of care. Transforming a radius, for instance, is different than transforming a point (which has to be translated) I also had to handle text separately to keep it from flipping upside down. I couldn’t simply flip it back because it gets ‘stuck’ upside down if you ever do a negative scale on it. And of course I do need a negative scale, because math says Y is up, and the screens say Y is down.
A clever plot
At the moment I only handle equations of the form ‘y’ in terms of ‘x’. I’ve got some behind-the-scenes code that calculates ‘x’ in terms of ‘t’ with an eye to exposing both equations at some point. It’s using a simple 100-samples, which sometimes gets jagged and misses targets. I should switch to a subdivision algorithm for accuracy, although I might need to limit depth initially and do a sort of progressive enhancement.
I’m updating the graph on every change of the input, so it needs to keep fairly responsive. It was working pretty well in Chrome, until Chrome simply stopped reloading my changed files, a common problem that frustrates a lot of developers, judging from online posts. Normally I’d go back to FireFox, but it’s response time was rather unsatisfactory; I had a similar experience on the meetup.com text boxes shortly after FireFox 4 came out, which put quite a damper on my brief attempt to switch back. I’ve been testing in Opera, which is responsive and reloads, but doesn’t display objects in it’s console.log (just the toString value)
After getting a proof of concept working, I figured it might be a good opportunity to try out CoffeeScript. I tried the RequireJS plugin, but ultimately concerns about the async requests put me off, and I switched to the coffeescript filesystem watcher, which has the added benefit of making it easy to examine the generated files for error-line lookups and such.
Another small oops was that I spent some time refactoring code in Disk Clock to pull out my own take on streamlining object creation, only to stumble across ‘class’ in coffeescript, which gets things mostly right and obviates the need for my own library.
Formula for disaster
The problem I’ve run into is that it’s AST is focused on displaying latex, so, for instance exponentiation sets the exponent in superscript. It has no relation to the base as a proper binary operator should. I can get the previous element to put together a Math.pow(base, exponent). However, text generation is recursive descent, so the base has already been printed something else. I’ve got an awefull hack that goes back and deletes it, but I don’t really consider it scalable, and there are probably more dark corners to be explored.
In both cases one runs into the challenge that they are set up to produce large number of equation types, which I’ll either have to support or somehow remove.