Mark Hildreth

You have reached the home page of Mark Hildreth


Ludum Dare

programming ludum-dare

After a few months of jumping around on a few different projects, I think I found one that has found some staying power: Ludum Dare.

Ludum Dare (Latin for "to give a game") is a video game making contest where a theme is voted on by participants. When the theme is announced, participants have 48 hours to make a game from scratch. This includes asset creation (graphics, sounds, music) and code (although, of course, you can use existing frameworks, as long as they are publicly available before the contest).

There are a few reasons why this interests me. First, writing video games was what got me into programming, and it has always held a special place in my heart. Second, the 48-hour constraint seems like a great place to test out my abilities to code something without going all architecture happy (unfortunately, this has really just lead me to start creating my own game architecture.

The first Ludum Dare I will be participating in takes place starting August 24th. Until then, I will be working on honing my skills for such a challenge.


Forcing Page Reload with jQuery Mobile

programming javascript jquery-mobile

I recently started fussing with jQuery Mobile. One problem I ran into was in the way JQuery Mobile would work. Basically, every time you load a page, it would keep that page in the DOM, until you moved two pages away. So, if you went from Page A to Page B, and then Page B to Page C, page A would be unloaded from the DOM before moving to Page C. If while on Page B you went to Page A, it would simply modify the DOM, and not make the AJAX call to reload A.

I wanted to have new content every time the user clicked a button on a page. Obviously, if going from pages A to B to A was not going to refresh page A, then going from page A to page A is definitely not going to do it. Failing to see a simple way around this, I simply subscribed to the click event on the button.

HTML inside the "random_positive" page

<a class="force-reload" href="/random_positive" data-role="button">See Another Random Positive</a>

Javascript Event (in custom.js)

$('a.force-reload').live('click', function(e) {
    var url = $(this).attr('href');
    $.mobile.changePage( url, { reloadPage: true, transition: "none"} );
});

The only thing I'm unsure of with this solution is what happens if you accidentally use "force-reload" on a link that is already out of the DOM. I didn't really check to see what happens first between the click event and the actual page load, so the page might load twice.


node.js: After "Hello, World!"

nodejs javascript npm virtualenv

Today was my first day with node.js, and while there seemed to be plenty of tutorials on it's event-based structure and how to write the code, none really seemed to talk about the eco-system. This might be fine for the "Hello World" tutorials, which I was able to complete, but what next? How do I install 3rd party libraries? The Linux distributions have out-of-date packages, right? What happens after "Hello, World!"? The following is what I did to bring myself from having a simple "Hello World" without 3rd party libraries to one that uses 3rd party libraries and can be set up on a remote server if necessary. I don't show too much code, I assume you can handle that yourself.

Setting up the Environment for Third-Party Libraries

The first thing to note is that you might have (like me) gotten away with using the node.js that installs with your Linux distribution. You might want to consider uninstalling that, and installing a (most likely) newer version. The best way I've found to do this is to clone the node.js repository, and just install using the install script into a ~~/local/bin directory. Keep in mind that if you do things this way, you might want to checkout to a tag of the latest stable version.

git clone git://github.com/joyent/node.git
cd node
git checkout v0.4.11
./configure --prefix=$HOME/local 
make install # You may need to install ~/local/bin into your path to get node to run.

As of this writing, the git repository checks you out to somewhere in version 0.5.4, but a more stable version is v0.4.11. You can find the current most stable version on the Node Web Site. There you can also find a download of that version if you don't want to mess with git.

Similar to Ruby Gems and Python Distribute, node.js has npm, or "Node Package Manager". You can install it using a similar method through npm's git repository. Or, you can use the install script which will do everything for you...

curl http://npmjs.org/install.sh | sh

Using npm to install a Library

npm isn't like virtualenv so much as it's like pip, which will install your libraries for you. npm chooses to install your libraries into a directory called node_modules in your current directory. For example, to install the mustache.js templating library, you can do...

npm install mustache

You can use the -g option to install the library globally. Useful for something that is more a command-line utility than a library you're using in your code. But of course, this means that you can't install a library that includes some command-line utilities without needing to install it to some directory that ALL your node.js projects will be looking at. There actually is a virtualenv-like library for node.js, but I did not check it out.

Once this was installed, I was able to use the 3rd party library in my code as follows:

var mustache = require("./node_modules/mustache");

npm allows you to define a "package.json" file in the root of your website. While you can see this being useful for creating a library, it's also useful for making a site, since you can define your dependencies. For example...

{
    "name" : "mysitename",
    "version" : "0.0.1",
    "dependencies" : {
        "mustache" : "0.3.1-dev"
    }
}

Once this package.json file is defined, you can simply run

npm install

to have all of the dependencies installed in your node_modules directory. This will probably be useful later on when you want to deploy your site on a different computer.

Conclusion

At first thought, my unfamiliarity with the node.js ecosystem made me want to just start working without these libraries. Once I understood that you really just need node and npm, and the libraries are installed in a pretty obvious place that doesn't overlap with multiple projects, I felt more comfortable looking into other libraries. One that I'm definitely going to check out is express, which sits on top of node and provides to you many of the elements you might find helpful (routing, redirection helpers, built-in static serving for development, etc.)


Monit without Pidfiles

pystynamic monit

One item encountered while setting up my home site generated by pystynamic was the need to run a script file in the background, and ensure that it was always running. Previously, I've used cron jobs and other such devices. I decided I would use try out monit, which is designed pretty much to ensure that your system is running smoothly, and restart processes/send e-mails/do other healing tasks if it detects that something's amiss.

Monit seems to be designed for dealing with pid files, but of course my small scripts don't create pid files. Luckily, the monit has a wrapper script recipe that seems to work pretty well. Mine looks like this:

#!/bin/bash

PIDFILE=/home/mark/.pids/update_site_endpoint.pid

case $1 in
   start)
      echo $$ > ${PIDFILE};
      source /home/mark/incoming/bin/activate
      exec python /home/mark/incoming/incoming/run_update_site_endpoint.py 2>/dev/null
      ;;
    stop)
      kill `cat ${PIDFILE}` ;;
    *)
      echo "usage: update_site_endpoint {start|stop}" ;;
esac
exit 0

...and the Monit rule...

check process update_site_endpoint with pidfile /home/mark/.pids/update_site_endpoint.pid
    start program = "/home/mark/bin/update_site_endpoint start" uid 1000 gid 1000
    stop program = "/home/mark/bin/update_site_endpoint stop" uid 1000 gid 1000

Couple of notes here:

  • The run_update_site_endpoint.py python file needs to be run in a virtualenv, thus the "source" command.
  • The "exec" command ensures that the python process replaces the shell, so the pid placed in the pid file is correct.
  • The Monit rule allows me to run the program using a non-root user.

This works pretty well for me. Note that Monit does allow for checking using matching rules (an example in the documentation is shown below):

check process matching "/sbin/dynamic_pager -F /private/var/vm/swapfile"

However, I'll stick with the pidfile script.


No One Wins at Code Golf

programming

I'm not sure where I originally heard the phrase, although some googling showed me that it was probably from Steven Lott, particularly from one of his many StackOverflow comments. In any case...

What does this line of code do?

categories = reduce(lambda x,y: x | y, [set(x.categories) for x in published_articles])

Got it? Okay, now what does this code do?

categories = set()
for article in published_articles:
    categories = categories.union(article.categories)

Both of these blocks of code do the same thing. However, time and time again, I find myself writing something like the first block instead of the second block. I'm guessing some of it is just boredom, challenging myself to write that for loop in a single line rather than two or three. Of course, once you do write it "concisely", then you want to keep it around for all the world to see and be awed by.

This idea of taking some logic and reducing it into as few lines and/or characters as possible actually has a name: "Code Golf", and there's an entire active Stack Exchange Site dedicated to it.

Of course, the problem with these ultra-concise monstrosities isn't that we're creating them, it's that we're creating them in PRODUCTION CODE. It's funny how many times I see someone write five lines of code in Python and say, "How can I write this better". While sometimes people do respond with a bit more consise code that is just as readable, other times people take this to mean playing a round of code golf.


First Post! Hello, World! Etc!

me pystynamic

So here it is, the mandatory first post of my blog. It's tough to write without forgetting that this time I'm not writing "Hello World" to test out my site, but it's really not a blog.

You see, I made this site from scratch. I actually have made it a few times over (using django, flask, and even my own web framework, puzzle. These all failed, however. I really couldn't stand the idea of keeping my hosted service up to date for such a simple as a blog. How do I keep the software up to date? What if I change database schemas? Backups!?

Finally, I decided on another solution: static page generation. Basically, the site you're reading now it just serving static pages. These pages were generated by a script (actually a library I'm working on called pystynamic) that read over a bunch of source files in my web site's repository on bitbucket. While this makes administration pretty much zero (needing to rebuild my site is simply recloning the repository and running the 'pystynamic generate' command), it does mean that I've lost some capabilities (comments on entries served without the help of third-parties like disqus come to mind). However, I'm more than willing to keep this tradeoff for the simplicity of making a blog entry simply be creating a file and committing it to a repository.

EDIT:

As of 2014, I switched from using my own static site generator to using Frozen-Flask.

My Whack-a-Mole Existence on the Web