Resetting input handlers in EaselJS

I've been working on some stuff in EaselJS. Recently I typed up a little object to handle managing different Scene type things in a stage. Each scene inherits off a collection, but the superglobal inputs were bugging me, so I wrote this up to default out the input handlers and not have to worry about the game's scale.

In the game's resize I set the self's (just the this of the object) inverseScale to be equal to 1 / the original Canvas scale for each dimension.

It's been working well so far!

this.switchScene = function (newscene, retain) {

      if (self.currentScene) {
        createjs.Ticker.removeListener(self.currentScene);
        if (!retain) {
          self.currentScene.removeAllChildren();
          delete self.currentScene;
        }
        this.stage.removeAllChildren();
      }
      self.currentScene = newscene;

      //reset input handlers
      (function (target) {
        ['onMouseDown', 'onMouseMove', 'onMouseUp', 'onPress', 'onClick'].map(
          function (inputType) {
            if (newscene.hasOwnProperty(inputType)) {
              target.stage[inputType] = function (event) {
                event.stageX *= self.inverseScale.x;
                event.stageY *= self.inverseScale.y;
                return newscene[inputType](event);
              };
            } else {
              target.stage[inputType] = undefined;
            }
          }
        );
      })(self);

      self.stage.addChild(newscene);
      self.stage.update();
    };

BeautifulSouping Some Movie Recommendations

There was a link on Metafilter a while back to a bunch of movie directors and their top ten movie picks (over at http://www.combustiblecelluloid.com/faves.shtml). I found some good ones on there, but kinda wanted a big ol' aggregate list, so I python'd one up. I'm just giving them points according to how high they are on a given list and adding those up. List and codes follow:

from bs4 import BeautifulSoup
import urllib
from collections import defaultdict

def get_things():
    soup = BeautifulSoup(urllib.urlopen('http://www.combustiblecelluloid.com/faves.shtml'))
    rows = soup.find_all('table')
    result = []
    for r in rows:
        children = list(r.children)
        if len(children) == 5:
            kidz = children[3].find_all('i')
            result.append((children[1].find('font'), [(tag.string, len(kidz) - (i)) for i, tag in enumerate(kidz)]))
    return result

if __name__ == "__main__":
    things = get_things()
    aggregate = defaultdict(int)
   
    for thing, films in things:
        for film, score in films:
            aggregate[film] += score

    sorts = sorted(aggregate.items(), cmp=lambda x,y:cmp(x[1], y[1]))[::-1]

    print "\n".join(["%s : %d" % (k,v) for k, v in sorts])

Continue reading "BeautifulSouping Some Movie Recommendations"

An interesting visualization demonstrating why not to use floating point calculations to determine if large integers are perfect squares

I've been working through The Art and Craft of Problem Solving, and there's been a few problems in it based on Pascal's Triangle. After some hours of scribbling numbers on paper, I got lazy and wrote up a generator for it in Python. The book wants the reader to examine some of the properties of the triangle, so I had my triangle renderer (renderer? ha, it's text!) take a function that'd return a boolean to determine if something should be shown or not. While scribbling odd and even values of the triangle on paper, I noticed that it kind of resembled Sierpinski's triangle, so I started with that.

Now this looked pretty neat to me, so I was thinking of another easy pattern I could look for. Perfect squares came to mind; just check to see if the square root of a number is an integer and you're all setup, right? I tried passing that function into the triangle renderer and beheld an interesting result.

It appeared as if perfect squares formed a kind of parabola past 100 rows of the triangle! What a discovery! Of course, I'm really doubting my naive perfect square test at this point, so I googled up a better one and tried that out. A less interesting result awaited me:

Even though I hadn't made the amazing discovery that perfect squares existed, buried within Pascal's triangle in an almost perfect parabola, I had learned to distrust floating point tests on gigantic integers. So there's that.

Code Follows:
Continue reading "An interesting visualization demonstrating why not to use floating point calculations to determine if large integers are perfect squares"

Pipe Viewer (pv) is Pretty Swell

A pretty common task in my workflow is updating my development database to what's currently on the live servers. The database isn't too large, but it does take about 30 seconds to import -- and I do positively loathe not knowing what's going on. Enter pipeviewer! I remembered reading a post that was linked off reddit some number of internet decades ago.

With this mighty tool in hand, I set to apply it to those 30 seconds of terrifying mystery that MySQL was plaguing my dreams with.

pv databasedump.sql | mysql -uDATABASEUSER -p databasename

And like magic, a beautiful progress bar was rendered. Life had incrementally improved.

I'd also recently used pv to watch the progress of dd-ing an ISO onto a USB stick, like so:

pv -ptre ubuntu-10.04-desktop-i386.iso | dd of=/dev/disk1 bs=1mb
  • The "-ptre" turns on all the rate monitors and progress bars and such.
  • /dev/disk1 is where OSX had my USB stick mounted.
  • bs=1mb sets the blocksize of dd to 1 megabyte, which made the copying process go a lot faster (minutes instead of hours.)

Django TestCase Comedy

Here's a little snippet that'll entertain the vast throngs of people who are interested in both Rock Paper Scissors strategy and Django unit testing.

def test_desperate_futility_of_avalanche(self):
        for futile_attempt in range(100):
            Round.objects.create(game=self.normal_game,
                                 initiator_choice=self.rock,
                                 opponent_choice=self.rock)
        self.failUnlessEqual(self.normal_game.result(), UNRESOLVED)

For the uninitiated: