Programming is a wonderful mix of art and science; source code is both a poem and a math problem. It should be as simple and elegant as it is functional and fast. This blog is about that (along with whatever else I feel like writing about).

Thursday, November 06, 2008

The Entire Problem with Microsoft

Steve Ballmer has always had the uncanny ability to take something complicated and sum it up in a nice, simple phrase that explains it so everyone can understand. In dismissing Android as a competitor, he's done it again:
"Google doesn't exactly bubble to the top of the list of the top competitors we've got going in mobile. They might someday. But right now..." he said.
In other words, Microsoft doesn't bother trying to compete with someone until they're already beaten. It worked when they created Windows after they'd been beaten by the MacOS, but since then it's been far less successful (IE, Vista, search, Zune, etc).

Perhaps they should try competing with something while it's still new and weak? Maybe they could finally win again? Like when the 360 beat the PS3 by attacking it before it was ready?

Just a thought.

Sunday, October 26, 2008

Breadcrumb History in Django

This afternoon I wanted to add a breadcrumb-like feature to an application I've been writing in Django. I figured the best way to do this is with sessions, so the first step is to turn those on.

The way I wanted it to work is like a rolling history of pages visited. So there's no implied hierarchy of pages, it just shows you the pages you've visited most recently. I figured limiting it to four pages was reasonable, but I can certainly see myself increasing that number in the future.

The first thing to do is to create a helper function that adds the current page to the history. You want to create the default empty history if there's nothing for it in the session, and you want to make sure it doesn't get too long. Also, you access the session and the address of the current page through the HttpRequest object that's available to every view in Django, so we just pass that in.

Here's my function:
# the breadcrumb history is a list of the last pages the user has visited
# the newest page is at the end of the list
# the length of the list is limited; currently it is at four pages
def add_breadcrumb_history(request):
    history = request.session.get('breadcrumb_history', [])

    # if the last item in the history is the current page, we don't want to add this page to the history
    # if it's not the last item in the history, we do add it
    if len(history) == 0 or history[len(history)-1] != request.path:
        history.append(request.path)

    # if there are more than four items in the history, pop the first one
    if len(history) > 4:
        history.pop(0)

    # save the history to the session
    request.session['breadcrumb_history'] = history

    # return the current breadcrumb
    return history

And in your views, its usage is simple enough. You call:
breadcrumb = add_breadcrumb_history(request)

in your view, preferably after you verify the user's permission to view that page. Then you want to add it to the list of variables exposed to your template, usually in your call to render_to_response().

Then you have to add the breadcrumb handler to the template. I put mine in my base.html, so it's available on every page.
{% if breadcrumb %}
<p class="breadcrumb">
{% for page in breadcrumb %}
<a href="{{ page }}">{{ page }}</a>
{% endfor %}
</p>
{% endif %}

Very simple; if there's no breadcrumb history, it doesn't display anything. If there is, it displays the links in order.

I like this feature; while I recognize it's close to useless in some situations (namely those where the data actually adheres to a strict hierarchy), in others it can be really useful. It means I have to do a lot less state checking on my pages to try to "calculate where the user came from" to get to that page, and can trust that users can easily navigate back to recent pages even if they POSTed information in between. (While I like that "You POSTed information on this page, do you really want to hit the back button?" feature, it can be really annoying in practice.)

Just thought I'd toss this up there in case anyone found it useful -- or is aware of similar functionality elsewhere.

Thursday, October 02, 2008

Asus 1000H vs Acer Aspire One ... A Pack of Lies

I just saw this "brilliant" visual comparison of the Eee 1000H vs the Acer Aspire One, and I can't just let it pass. I mean, I understand that the netbook marketplace has become absurdly overcrowded, and the main differentiators between the machines are 1) price, 2) software, 3) packaging. Asus is clearly annoyed that despite virtually inventing the category, they are left as the overpriced competitor much maligned for their confusing marketing and unpredictable product cycle.

Meanwhile, Acer has pumped out exactly one netbook, priced it competitively, and just let people buy it and enjoy it. And here comes Asus to rain on Acer's parade in the most immature way possible. (They couldn't even bring themselves to spell out Aspire, instead spelling it "A*****" -- um, lame?)

As the owner of an Asus laptop and an Acer Aspire One, I find myself compelled to take on the comparison point by point.

1) Battery life

Asus: 6 cells, 7 hours
Acer: 3 cells, 2.25 hours

I haven't used the Eee 1000H, but my Aspire One gets 3.5-4 hours of battery life when I use it normally (ie, wifi 100% of the time, internet browsing, typing). And that's with the default 3 cell battery, not the add-on 6 cell. If the Eee really gets 7 hours of battery I'd be impressed, but I wouldn't be at all surprised if they're lying about their own battery life to the same extent they're lying about the Acer's.

2) Hard drive

Asus: 160 GB
Acer: 120 GB

Firstly, big f'ing deal. It's a netbook. If you're storing a bunch of media locally, you're doing it wrong. Secondly, the Acer defaults to a nice little SSD that more than gets the job done and allows me to 1) not worry at all about the fact that I keep dropping it, and 2) boot/sleep really quickly. 40 GB is meaningless on a laptop, moreso on a netbook.

3) RAM

Asus: 1024 MB
Acer: 512 MB

Yes, I could go for more RAM. It's not like I've been dying without it, but this is a pretty clear win for the Asus.

4) Size

Asus: Large touchpad, large screen, large keyboard (92% standard), wider palm rest
Acer: Tiny touchpad, small screen, small keyboard (80% standard -- although it's actually 85%), tiny palm rest

Every single point here is true ... and made possible by the fact that the Asus is a 10.2" netbook while the Acer is an 8.9" netbook. I wonder how Asus feels about its own 7" netbooks. Also, more lying ... the keyboard is bigger than Asus claims it is. And Acer's sub-9" netbook is certainly more portable than the over-10" Asus. Which, I think, is the point of netbooks.

5) Um, miscellaneous networking, I guess

Asus: Bluetooth & 802.11n, 1.3 megapixel webcam, "Digital Array Mic"
Acer: No Bluetooth & 802.11n, 0.3 megapixel webcam

Frankly I wish my Acer had Bluetooth, but I can't say I miss it all that much -- I don't even use it on my full-size Asus. And 802.11n isn't that meaningful to me, since I don't have an 802.11n router (and neither does anyone else). Oh, and the webcam? My full-size Asus has a 1.3 MP webcam, and it looks awful compared to the 0.3 MP on the Acer, when both are using Skype on Linux. Seriously, Acer's 0.3MP webcam is surprisingly awesome. And what the hell is the "Digital Array Mic?" Is it something that solves the horrible feedback problem my full-size Asus has? Because if it is, that's nice, but the Aspire One doesn't have any feedback problems with its mic.

6) Location of touchpad buttons

Apparently the familiar position of the Asus' touchbad buttons allows easy usage, while the odd location of the buttons on the Aspire One leads to "unsmooth usage." I've heard other people complain about this too, and I just don't get it. It seems to me that it's an innovative use of space given the obvious size constraints, and it's not exactly counterintuitive -- the "right click" button is "on the right side" of the touchpad. Holy crap, I'd never find it!

7) Temperature

Asus: Gives off no heat at all -- the whole thing is green!!
Acer: It's on fire! Look at all the red!

In reality ... I can't speak to the Asus, but the Aspire One doesn't give off any heat. I've used it for 10 hours straight, plugged in for 4, then 3 hours on battery, then plugged in for another 4, and the temperature remained constant the entire time. And it remained constantly the same temperature as it was when it was off. Both on the top and bottom, it's comfortably cool the entire time. I don't know how they came up with this test, but the only way it could be true is if the Asus has The Al Gore Anti-Global-Warming Super-Prius Hybrid Engine built into it, or something, and actively sucks heat and carbon emissions into it and converts them into sunshine and virgins. I call bullshit.

8) "Work Efficiently"

Asus: Boots in 30 seconds, ready in 38 seconds, ready to launch "AP" in 41 seconds, shuts down in 15 seconds
Acer: Boots in 45 seconds, ready in 62 seconds, ready to launch "AP" in 74 seconds, shuts down in 30 seconds

Apparently time goes faster in my apartment, because the Aspire One actually boots in about 10 seconds. And shuts down in about 5. And goes from "off" to "browsing the web" in 12-15. I don't know what "AP" is, so I'll go ahead and skip it. I guess I don't use it. Hopefully Asus' users really like it, because it seems to take a really long time. The only computers I've seen get going faster than the Aspire One are Macbooks. And, um, those are in a slightly different market segment, and I don't think I'd compare them.

9) "Quiet Computing"

Asus: Idle, 25.1 dB; Media Player, 28.8 dB
Acer: Idle, 30.7 dB; Media Player, 31.5 dB

I guess the 2.7-5.6 dB difference is simply massive, the difference between "silent" and "a fucking jet engine." But I have two things to say: 1) I haven't heard the Aspire One since I've owned it; I wasn't even aware it had a fan in it. 2) If you're using the media player and not wearing headphones, you're doing it wrong; it's not like these things come with great speakers. Also, 2.7 dB? Did you know that normal humans can't tell the difference?

Finally, the major differences as I see them:

1) Size

The Acer is a 9" netbook, and is smaller, thinner, and lighter (2.2 lbs vs 3.2 lbs) than Asus' 10" entry. Really, Asus? That extra 1" of screen space weighs an entire pound? Are you sure you're not just bad at this?

2) Price

I bought my Aspire One for $400 a couple months ago, and it's down to $330 from Amazon. On the other hand, the Eee costs $530 and is available for pre-order. Raise your hand if you can tell which is better.

3) Linux

The Aspire One runs Linux, and runs it well. The Eee 1000H runs Windows XP, and I'm sure it runs it worse than computer with 2-5x its specs that can barely keep themselves on their feet. Acer wins.

In conclusion, the choice of a netbook really comes down to personal taste and how much you want to pay for it -- you might prefer a 10" Windows machine to a 9" Linux machine, and you might not. But this kind of childish lying about yourself and your competitor is the stuff of Microsoft and Republicans. Is that really who Asus wants to model themselves after? Oh yeah, and I thought false advertising was illegal?

Sunday, August 31, 2008

The Contractor Experiment Ends, Plus My First Wordpress Plugin

It's been a while since I've posted anything, but I figured I should mention this: The Contractor Experiment is over, after just one contract. I found myself in a place I liked, with a good working environment and good co-workers ... and I became a full time employee last week. I plan on working exactly the same way as an employee as I did when I was a contractor -- why else would they have hired me? -- and it should remain a lot of fun.

Meanwhile, I think I should also mention a little side project I've been working on, and have just released. It's a Wordpress plugin that downloads baseball player's stats and displays them on your blog.

It can be seen in action at my baseball blog, Fire Gardy. To learn more about the program, you can visit the Fire Gardy Stat Grabber home page. Or just jump straight to the project page at Github. (It's GPL software.)

When I wrote it, the first step was to write a Baseball-Reference.com parser, which grabs the requested player's page (via PHP's CURL), and runs through it line by line to get the player's batting statistics (pitching stats will have to be added later).

Once that was there, it was time to turn it into a Wordpress plugin. It was actually a lot easier than I thought it'd be.

First you go to your blog's wp-content/plugins directory. Create a new directory inside it for your plugin (mine was called "fire-gardy-stat-grabber"). Inside that new directory, create a PHP file with the same name as the plugin directory ("fire-gardy-stat-grabber.php").

Open it up and put a comment inside it that will tell Wordpress the details of your program. Mine looks like this:
/*
Plugin Name: FireGardy Stat Grabber
Plugin URI: http://stat-grabber.firegardy.com
Description: Download a player's stats from Baseball-Reference.com and display them on the page.
Version: 0.1a
Author: Sean Schulte
Author URI: http://seancode.blogspot.com
*/
Really, only the "Plugin Name" line is required.

You need to define a function that will display what you want -- because for this plugin we'll be using a "Template Tag" (which allows us to put it anywhere on the page by editing the theme's template files).

It's a simple PHP function, that can take any parameters you want. It doesn't return anything, and needs to echo your desired HTML output to the screen. Mine has the following signature:
function fire_gardy_stat_grabber($playerName, $playerId, $year)
I'm not going to print all the code for it here -- you can go check it out at Github.

You can use the Wordpress database in this function -- which is useful for caching the results you get back from Baseball-Reference. There are two options for using the database. One is to create your own tables and use actual SQL queries; that'd be useful for more complicated plugins. The other is to use the Wordpress options table which stores anything -- accessible as part of a simple name-value pair.
get_option($key);
delete_option($key);
update_option($key, $value);
The plugin also uses a Wordpress Plugin hook to load some CSS. A function like this writes the CSS:
function fg_baseball_reference_css()
And this line makes it load:
add_action('wp_footer', 'fg_baseball_reference_css');
Once you've got that in place, just toss it into your sidebar.php in your theme's template:
<?php fire_gardy_stat_grabber('Nick Punto', 'puntoni01', 2008); ?>
And that's that! Now that I've finally written a Wordpress plugin I expect to do it significantly more often. I expected there'd be a lot more BS involved in hooking extensions into the Wordpress system, and realistically anyone who can write even the simplest PHP functions can do this.

Friday, July 04, 2008

Flex Injection: Passing a Function to a Component

Sometimes, in Flex, I find myself in the situation of using a ViewStack to define different screens of my application. And I want to be able to navigate between those views easily, in addition to using components to make development simpler.

I've found that having a "Back" button inside a component can be useful, but if the back button is hidden inside the component, it can't access the ViewStack (since it's in the parent).

I thought it would be useful to be able to pass a little bit of ActionScript to the component that would jump back to the previous view. It would effectively inject functionality from the parent to the child. Here's what my component looks like:
<?xml version="1.0" encoding="utf-8" ?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%">
<mx:Script>
<![CDATA[

[Bindable] private var _labelText:String;
[Bindable] private var _buttonClick:Function;

public function set labelText(str:String):void {
_labelText = str;
}

public function set buttonClick(func:Function):void {
_buttonClick = func;
}

]]>
</mx:Script>

<mx:Label text="{_labelText}" />
<mx:Button label="Back" click="{_buttonClick()}" />
</mx:VBox>
As you can see, this component allows you to define some text to display and the back button's click handler. The click handler has to be a Function object.

Note that when you call this Function object, you have to put () at the end. It thinks this is actually a method that it can call, so you have to call it like any other method.

But when you instantiate this component, you can't just do something simple like buttonClick="viewStack.selectedChild=anotherView" ... while that may be the ActionScript code you want to execute, and it may work when you're defining the actual click event, the component will interpret this as a String instead of a Function, and it won't work. So you actually have to create a Function object in the parent.
<?xml version="1.0" encoding="utf-8" ?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:components="components.*"
width="100%"
height="100%">
<mx:Script>
<![CDATA[
[Bindable] private var backToViewZero:Function =
function():void { viewStack.selectedChild = viewZero };
]]>
</mx:Script>

<mx:ViewStack id="viewStack" width="100%" height="100%">
<mx:VBox id="viewZero" width="100%" height="100%">
<mx:Label text="Start here!" />
<mx:Button label="One" click="viewStack.selectedChild=viewOne" />
<mx:Button label="Two" click="viewStack.selectedChild=viewTwo" />
</mx:VBox>
<components:MyBox id="viewOne" labelText="One" buttonClick="{backToViewZero}" />
<components:MyBox id="viewTwo" labelText="Two" buttonClick="{backToViewZero}" />
</mx:ViewStack>

</mx:Application>
Here, we create an anonymous method and assign it to the Function object, and then we can pass it to the component when we instantiate it.

This works splendidly, and is a pretty cool way to inject functionality down into your components that wouldn't otherwise be possible. (The component doesn't have to reach up to the parent somehow, which means your component doesn't need to know what the ViewStack is called, or about any of the other views; instead, it just needs to know that it's going to do something, and the parent is responsible for knowing what.)

It leaves me wondering, though, if there's a way to get around the problem of passing in code and having it interpreted as a String rather than the preferred Function. Perhaps by having the buttonClick setter take a String and create the Function object at that point, using something like eval(). Unfortunately, ActionScript 3.0 doesn't have eval(), so I don't know if this is possible. Maybe I'll figure something out later. In the mean time, I'll be creating Function objects in the parent.

Tuesday, February 26, 2008

The Freedom Framework Bends to Your Will

On Sunday, I came up with the concept for the Freedom Framework, which consists of PHP Object Generator, EpiCode, and Smarty. I'd like to take some time and go into what I feel are some of its actual advantages, over other frameworks and over not using a framework at all.

First, you define your data model from the perspective of the database, rather than from the code. While you don't actually have to write any SQL, you're defining the fields and their types as if you're just creating a table. It adds to this with the Parent/Child/Sibling concept, but doesn't go as far as other frameworks which give you the impression that you're just creating and working with objects, and then try to generate the database from that (or make you write both the database and the models).

When you've done this, you edit the config file with your database's login information and run setup. It tests your database connectivity, creates the tables, and then runs some unit tests to make sure everything's working. At this point you have a set of classes that give you CRUD functionality for the tables you've defined.

And now, EpiCode comes in to define your controllers. This is the best part of the "framework." Since you define the controller classes yourself (rather than having them generated), you have a little extra freedom there. And since you actually define the routes table (rather than generating it or being stuck with a convention), you gain more control over the URLs that'll be used by your application. If it's a small application, you can use just one controller class, even if you have a bunch of differently named URLs pointing to its methods.

That freedom allows for excellent refactoring support. As I was feeling my way around the new "framework," I had only one controller class. After my methods started growing, I decided it would be best to separate them into multiple classes. This was the work of a few seconds (made easier since these are static methods); then I just had to update the routes table to point the URLs to the new classes and methods ... and voila! The project graduates from being a simple proof of concept to being a maintanable MVC application.

Even Smarty allows this sort of flexibility for the view. When I was putting together my proof of concept, I just threw the .html files into the root templates/ directory. As it grew, and I decided that this was more than just a tiny project, I created subdirectories underneath the templates/ directory and moved the .html files into them. (It's probably simplest to name these subdirectories in such a way that they match the URLs, but you don't HAVE to.)

The goal of the Freedom Framework is to minimize the things you're forced to do to work with it. There's no generated filesystem structure or controller classes; you can name them and structure them however you please. The framework grows with each project, starting out as just a little bit of glue and expanding into a well defined structure for your code (and since it's YOUR code, you get to define that structure). You don't have to know (or be told) the final structure before you start working on it.

The more I think about this "framework," the more I like it. The more I use it, the more I like it. It's the first I've found that doesn't inherently limit the way I want to work. The tool bends to my will. That's what makes it a good tool.

Sunday, February 24, 2008

POG + EpiCode + Smarty == The Freedom Framework

I generally have a problem with web frameworks, like Rails, CakePHP, Symfony, and the millions of others that have sprung up lately (moreso in PHP than in Ruby, as Ruby hadn't really been used for web development until Rails came along). As a rule, they force you to do things a certain way, and -- more importantly -- to think in a certain way. In most cases, this "way" is mimicry of Rails, but in all cases, this "correct way of thinking" is the way the framework developers think. That's the aspect of frameworks that I take issue with, while at the same time acknowledging the productivity gains that are possible with these frameworks.

Since everybody likes productivity gains ... I decided to go out and see if there was some way to get the same increase in productivity without using a framework. I want to use tools in such a way that makes sense to me, not to the tool.

The place I started was with the model; I needed to find a good ORM tool for PHP. I hadn't found one that I like yet, so this search took me a while. I still haven't found a real ORM library that I like, but I have come across an interesting tool. The PHP Object Generator allows you to define a database table (with an interface similar to phpMyAdmin, which I don't care for, but at least it's a familiar concept), and from that it generates not only the SQL to create the table, but also a PHP class with the standard CRUD methods. It handles relationships between tables with a parent/child concept (a parent can have multiple children, but a child may only have one parent). At first, it didn't support has_and_belongs_to_many relationships, but added that in with the concept of "siblings." I think that terminology is a bit of a stretch, and the documentation on it isn't the best, but it works well enough.

For the controller, I wanted something really light. I considered just making my own, and that probably would have worked. But by chance, I discovered EpiCode, which is just about exactly what I would have wanted to create on my own. It uses a .htaccess file to direct all HTTP access to the index.php file, which contains an array called $routes, which in turn wires paths to functions (or static methods, which works even better). It doesn't touch the query string parameters, so you get to process those however you like.

For the view, I stuck with the old Smarty standby, and it works like a charm for this. You have to define which variables to open up to the template, as well as which template file to use; despite having to type a couple of extra lines of code, I prefer this to being forced into a particular directory structure and naming convention that is common among the true frameworks.

In my first foray into the POG+EpiCode+Smarty "framework," I made an IMDB clone in about an hour and a half, and I didn't have to write a single line of SQL (table creation or queries). In fact, I didn't even have to log into the database (as the POG setup process creates the tables and verifies that everything's working). I'd say that's a fairly significant increase in productivity over my previous methods, and I still got to define my workflow for myself, rather than kneeling before some anonymous framework creator.

I know a lot of people like frameworks, and a lot of people use them. Because of this, my opinion on the matter probably isn't very popular. But I think this freedom is really valuable. And I find it difficult to believe that my opinion is unique.

Saturday, February 23, 2008

PHP: Reading Key/Value Pairs from a File

I'm working on an application in which I have to parse a file with key-value pairs, looking for a single value. I decided to make the datafile look like this:
key0|val0
key1|val1
key2|val2
...
key2000|val2000
I don't expect to have more than 2000 values in the file, but just in case I set up a second sample file with 100000 values just to see how that would affect things. (That kind of growth in usage would be awesome.)

My initial thoughts on this are to keep it simple. Performance is important, but I don't think spending the time for a binary search file seek algorithm would be worth it; also, that would be premature optimization. So I want to check out the performance of a couple simpler options first.

My first option was to loop through each line, explode on the | character, and compare the keys. Like this:
function searchLinearly($filename, $key) {
$lines = file($filename);

foreach ($lines as $line) {
list($k, $v) = explode('|', $line);

if ($k == $key) {
return $v;
}
}

return false;
}
That's just about as simple as you can get. But how does it perform? I searched for a few keys throughout the file, and measured how long it took to find them.

In a 2000 line datafile:
Key 10: 0.00215s
Key 150: 0.00233s
Key 900: 0.00555s
Key 1700: 0.00866s
In a 100000 line datafile:
Key 10: 0.11047s
Key 1500: 0.04429s
Key 50000: 0.11832s
Key 99000: 0.18710s
What's really strange about this is that key 1500 is consistently faster than key 10, whether I search for key 10 first or second, or just search once per run (in an attempt to separate caching issues). I can't explain that.

Another option is to use fscanf() instead of just using file() to get all the lines. The idea is to define a regex that matches the format of the lines in your file, and "scan" through the file, extracting the pieces of data along the way. That version looks like this:
function searchFscanf($filename, $key) {
$f = fopen($filename, 'r');
while ($line = fscanf($f, "%[^\|]|%[^\|]\n")) {
list($k, $v) = $line;

if ($k == $key) {
fclose($f);
return $v;
}
}

fclose($f);
return false;
}
It's only slightly more complicated; does it perform faster?

In a 2000 line datafile:
Key 10: 0.00052s
Key 150: 0.00101s
Key 900: 0.00572s
Key 1700: 0.01033s
In a 100000 line datafile:
Key 10: 0.00052s
Key 1500: 0.00947s
Key 50000: 0.12980s
Key 99000: 0.20901s
I think these results are pretty interesting. Using fscanf() can actually be considerably faster, and it isn't affected by the size of the file. However, it is drastically affected by the key you're searching for; if you have to scan through a lot of lines, it slows down significantly and steadily.

In contrast, the file() method is more affected by the filesize than by which key you're searching for (searching for later keys does take longer, but it's not nearly as significant).

So which option is better? As the number of records increases, it appears the fscanf() method becomes more and more advantageous (assuming that early records are hit as often as later records, considerably less time is spent searching than with the file() method). The same consideration remains true even if the number of records remains constant, it just isn't as noticeable or significant at that level.

Unsurprisingly, fscanf() beats file(). But not by as much as I'd like. In order to maximize performance, another method is going to have to be devised; either a binary search that minimizes the number of comparisons made (O(ln n) versus O(n)), or perhaps just using something like memcached to keep the datafile in memory at all times. Maybe both.

Something to think about.

Monday, February 18, 2008

Using the Velocity Template Engine

Templates are really important for separating the presentation of your program from the actual code. In PHP, I prefer Smarty (mostly because it's the one I'm most familiar with). In Java, I've taken to using Velocity.

The advantages of templates are very quick to see. Imagine you're creating a web page. You could pretty easily put the <html> code right in along with your PHP or Java code. In PHP this is absurdly easy, just by using the <?php ?> tags. The problem is that this very quickly gets cumbersome when you want to change things. Changing the way the display looks requires changing the way the program works. That's not really what you want at all. So you use templates to separate the display from the logic; that way you can change the two independently.

But templates aren't just for web development. I recently found a reason to use templates in a Java program. It is intended to create content for a web-delivered program, but it doesn't have to be dynamically generated; instead, we can pre-generate all the necessary content periodically. When I first threw the content generator together, I simply used a StringBuilder to put the content together; then I had to change something, and it was horrible. I had to parse these long append() lines, then re-compile the entire program. It became especially obvious that something needed to change because my program has to support multiple languages ... and I only speak one. I'll be getting translations from other people, and I'm not that interested it pasting translations into my code (or giving commit access to the translators). In steps Velocity. I moved the content out into its own file:
my_template.vm:
------------------------------
This is my content. My name is $name.
Of course, you can have any number of these template files, and you can load any of them at runtime just by specifying the filename.

In order to do that, you have to set up your program to load the template files at runtime using a classloader.
Properties p = new Properties();
p.setProperty("resource.loader", "class");
p.setProperty("class.resource.loader.class",
"org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
(That's an important step. A lot of Velocity documentation leaves that out. I figured I'd put it before the more "significant" stuff that actually "does the work." Without this, the work doesn't happen.)

Speaking of which, let's get to the meaty part.
VelocityEngine ve = new VelocityEngine();
ve.init(p);
Here we set up the VelocityEngine. Note that we pass the Properties object to the init() method. That's where the classloader setup actually happens, so don't overlook that little character.
VelocityContext vc = new VelocityContext();
vc.put("name", "Sean");
The VelocityContext is where you put all the data you want to expose to the template. It's essentially a set of name-value pairs; like most templating engines, Velocity allows you to use conditionals and loops within the templates. These are almost always necessary in non-trivial templates, but you should start from the standpoint of avoiding it if at all possible. After all, before you're used to using templates, it's natural to attempt to put your program's logic into the template. That totally defeats the point.
StringWriter writer = new StringWriter();
Template template = ve.getTemplate("<package_name>/templates/my_template.vm");
template.merge(vc, writer);
System.out.println(writer.toString());
Here you load the template, merge it (which basically matches up all the name-value pairs in the VelocityContext with all the $tags matching the names in the template), and output it. In a web application, your output would be printing it back to the browser. In my case, it was using a FileWriter to output the text to a file. I've used PHP's templating a whole lot more than Java's, but I've already found Java to be considerably more flexible in what you do with the output after it's been generated.

I hope that example helped if you wanted to start using Velocity ... or if you hadn't considered using templates. It's pretty essential.

Saturday, February 16, 2008

Java Properties Files

Yesterday I posted about using JSch to SCP a File in Java, and the code I'd written at the time was pretty simplistic. It only sent a file to a remote server, and it even foolishly had string constants in the code that specified the location of the known_hosts file and the information about the remote server. I closed with a call to action to move that to a config file. Well, I've now done that, using the simple but effective Properties files that comes built in with Java.

I added a properties file to the package, and it opened right up for editing. The basic concept is that you fill it out with name-value pairs. Here's the properties file:
knownHostsFilename=/home/sschulte/.ssh/known_hosts
numServers=1
server0_host=172.16.40.128
server0_username=user
server0_password=user
I designed it with the idea in mind that I could send files and commands to multiple servers at once. I'd just have to increment the numServers field and add a new set of server info fields. Pretty nice.

To load the properties file, I just add these lines:
Properties configFile = new Properties();
configFile.load(this.getClass().getClassLoader().getResourceAsStream("remoteappmain/serverconfig.properties"));
Note that "remoteappmain" is the name of my package, which is why it's in the path to the properties file. To get one of the values, you just call the getProperty() method, passing it the key. They're strings, so in the case of numServers I had to parse it into an integer using Integer.parseInt(). No big deal.

To simplify my classes and to standardize their interfaces, I created a RemoteAuth class that encapsulates the hostname, username, and password values. And there's now an abstract base class called RemoteConnector that the FileSender extends. The constructor takes a RemoteAuth object and a known_hosts filename.

Creating an abstract base class allowed me to quickly create another class with useful functionality. This one is RemoteExecutor, which allows you to execute a command on a remote server. Stuff like "ls -la" or "rm my_file" or anything else you might type into the command line.
RemoteExecutor re = new RemoteExecutor(auth, knownHostsFilename);
re.execute("rm AllPhysics.wmv");
re.execute("ls -la");
System.out.println(re.getResult());
That's what you'd do if you wanted to delete a file, then call ls on the directory, and display it to the screen (which is what the getResult() method does).

I think that pretty much covers what I wanted. The main thing I want to add now is a FileGrabber class so I can download a file from a server as well as upload one. I feel like these classes are going to be pretty useful; I guess I'll know more about what I missed here once I use them in a few projects and decide on what they're lacking.

Friday, February 15, 2008

JSch: SCP a File in Java

If you want to upload a file to another computer, SCP is an excellent way to go. And if you want to do it from within a Java program, your best bet is to use the JSch library from JCraft. They've implemented the SSH protocol purely in Java, and it works splendidly. I've written a nice little class that encapsulates the action of sending a file.

Using the class is pretty simple. It goes like this:
FileSender fs = new FileSender("172.16.40.128", "user", "user");
boolean ret = fs.sendFile("/home/sschulte/Desktop/AllPhysics.wmv", "AllPhysics.wmv");
The constructor takes a host, a username, and a password. The sendFile() method takes a source filename and a destination filename. It returns true if the upload was successful, false if it failed.

I developed it in Netbeans, and in order to use JSch, the first step is to download the JAR and add it as a library in your project. (When I first tried it, I downloaded the ZIP instead, and added the source to my project; this works, but it's not necessary to compile this library along with your project unless you plan to edit it. I didn't.)

Most of the code in this class is taken from the ScpTo example included in the ZIP file. I recommend reading it. Something to pay close attention to, however, is the SSH known_hosts file. Their example file doesn't take this into account, so if you just run their code, you get an unknown host exception and it doesn't work. So be sure to include the following:
String knownHostsFilename = "/home/sschulte/.ssh/known_hosts";
jsch.setKnownHosts(knownHostsFilename);
(This is, of course, after you instantiate your JSch object.)

I like it, and it works. But it definitely needs a few things before I'm satisfied.
  • Read the known_hosts filename from a config file, rather than compiling it into the code.
  • Have a config file for the host/username/password information, possibly for multiple hosts at once.
  • Throw exceptions for various types of failures, rather that simply returning false.
Pretty cool stuff. The JCraft guys did a great job with this library.

Monday, February 11, 2008

Using CURL to Download a File in PHP

Today at work I came across an interesting problem. I had to make a REST-style call to a backend server, which would do some processing and return a file. The filename and content type of that file is not known to me at the time I make the call, but the file must be downloaded properly directly to the client. And the file could easily be large, meaning that I can't load it completely into memory before sending it to the client (and even if I could, that would be unwise due to the double-time download).

I'd used CURL in PHP before, but was having problems getting the content type. If I typed the REST URL directly into the browser, it would download successfully, but display a useless byte stream instead of the file itself. After discovering the CURLOPT_HEADER option, I came up with the initial solution of making the call twice: the first time I just got the headers (and not the body, using CURLOPT_NOBODY), and then set the headers using header() before making a second call which would get the body. This worked ... except that the backend team informed me that it's possible that the processing could get pretty extensive, and they didn't want it to be doubled every time. Needless to say, that made my solution pretty stupid.

That's when I dug deeper and discovered CURLOPT_HEADERFUNCTION. With this, you register a callback function which will process the headers.

curl_setopt($c, CURLOPT_HEADERFUNCTION, array(&$this, 'applyHeaders'));

The third parameter here is the function that processes the header. If you're using an instance method, you pass an array containing a reference to the current object and the name of the method. In this case, my callback function looks like this:
function applyHeaders($c, $header) {
header($header);
return strlen($header);
}

It simply calls the header() function on the file's headers and returns the length of the header (which is necessary for the callback function to work).

This way, you can keep CURLOPT_RETURNTRANSFER false, meaning you don't have to load the file into memory and it's streamed directly to the browser, and the applyHeaders() method set the content type and filename properly, so it gets downloaded just as it's supposed to. Best of all, you only have to make one call to the backend, and the processing is only done once.

Excellent. And the documentation on this isn't the best, so I figured I should post it on here to help out. And to help me remember.

Sunday, February 10, 2008

An Early Update into the Life of a Consultant

I've now been on my current contract for about 2.5 months, so I figure it's a good time to come back and post an update.

The work isn't that challenging. The complicated problems are on the backend, and that team is constantly frantic and has been falling behind as the codebase becomes larger. Unfortunately, I'm not on that team, and can't help out. All I'm doing is making XML-RPC calls to the backend and displaying the data to the user. My days are currently spent waiting, either for something to be finished on the backend so I can finish it on the frontend, or for a bug to be found so I can fix it. On some days, neither happens.

But enough of the bad. I don't much care for complaining.

The people are great. The developers I've been working with and talking to are talented, and the managers I report to are very technical. From a personnel standpoint, this is just about ideal. However, I've begun to think that this might actually be a problem. Sooner or later, this contract will end and I'll be moving on, possibly never working with these guys again. I'll have to start over, left to hope that the people at the next contract are as talented and fun as they are at this one. This is the life of a consultant, I suppose.

This has led to me eating lunch by myself, eschewing the chance to get close to my coworkers and managers. This is probably unwise, but I feel it's a natural response to the situation I'm in, where I'll probably be leaving them soon. I should try to make an active effort to change my behavior and start spending more time socializing with my coworkers, starting at lunchtime.

And things are looking up, workload-wise. The current project is close enough to being complete that I'm apparently going to be placed onto another one this week. I think this is excellent, and hopefully I can slide over easily to the new project and get its wheels moving as fast as possible. That should feel pretty good.

Tuesday, January 08, 2008

Flex: Automatically Compile and Deploy to Server

One thing that's been irking me a little bit about my Flex development process is that I have to upload the SWF to the server in order to test it. Normally you don't have to, but I'm using HTTPService to load XML from the server to populate the components. I really like that feature, but for security reasons, it doesn't allow cross-domain access.

One option is to put a crossdomain.xml file on my web server, but since I'd be testing from a local machine, I'd have to define the allowed domains as "*" ... which probably isn't the best idea. Also, I'm not that excited about hard-coding the domain name of my server into the application. (I currently have them just using absolute URL's, without the domain, ie "/server/api.php".)

Up until now, I've been uploading the file manually with scp after the compile successfully finishes. For that, I have to enter the compile command, check if it was successful, enter the upload command, type my password, and then I'm done. Figuring there must be a way to automate that, I learned that Flex works with Ant, which can do all these things (and allegedly supports FTP and SCP).

After setting up my build.xml file, I learned that Ant doesn't support FTP and SCP without some esoteric libraries ... which I didn't really feel like hunting down. I thought to myself ... "Why do I have to use Ant, when there must be a way to do this with roughly the same effort as this build.xml file, but that actually does the work?"

Enter Python.

#!/usr/bin/python

import commands
import pexpect

sourceFile = name of source file
outputFile = name of output file

username = remote username
password = remote password
serverAddress = remote server
remoteDir = path to destination folder on remote server

print "BUILDING..."
(compileStatus, compileOutput) = commands.getstatusoutput('mxmlc -file-specs ' + sourceFile + ' -output="' + outputFile + '"')

if (compileStatus > 0):
#the build failed, display the output
print "BUILD FAILED!"
print compileOutput
else:
#the build was successful, upload it
print compileOutput
print "UPLOADING..."
scpCommand = 'scp ' + outputFile + ' ' + username + '@' + serverAddress + ':' + remoteDir + '/' + outputFile

scp = pexpect.spawn(scpCommand)
scp.expect('Password:')
scp.sendline(password)
try:
scp.interact()
except:
print "(exception)"
finally:
print "Done!"

This script uses pexpect, which is a cool little program that lets you programmatically interact with the command line. This is necessary to enter your password into scp (which doesn't allow you to pass it into the command as a parameter, for obvious security reasons).

It's pretty simple. Basically, you compile using mxmlc, and if it was unsuccessful you display all the errors. If it worked ... you upload it to the server and you're done. Much easier than doing everything manually every time.

You have to set the constants in the file before executing, which isn't really a problem. I could make it so it takes parameters, but that almost defeats the point. I'm looking at this as a build.xml replacement, not as a full-bore program. So there shouldn't be a problem with setting some constants inside.

Enjoy the 3-5 seconds you'll repeatedly save! I know I have.

Saturday, January 05, 2008

An Awesome Flex HTML Escaper

One of the problems I frequently come across when trying to post code online is that the characters need to be escaped. For example, when entering a bunch of MXML code, the browser vainly attempts to display the code in the mistaken belief that it's actually HTML.

So one of the simple applications I like to make in any new language is an HTML escaper. Since I'm playing with Flex right now, I figured I'd make one (and hopefully it'll be useful, since I'll be using it to post the code).

It took a couple of minutes, but here's the code:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" backgroundColor="#f6f6f6">
<mx:Script>
<![CDATA[

public function escapeHTML(str:String):String {
str = str.replace(/&/g, "&amp;");
str = str.replace(/</g, "&lt;");
str = str.replace(/>/g, "&gt;");
return str;
}

public function outputClickHandler(event:Event):void {
System.setClipboard(output.text);
}

]]>
</mx:Script>

<mx:VBox>
<mx:Label text="Original" fontSize="14" fontWeight="bold" />
<mx:TextArea id="input" width="800" height="200" />

<mx:Label text="Escaped" fontSize="14" fontWeight="bold" />
<mx:TextArea id="output" text="{escapeHTML(input.text)}" click="outputClickHandler(event)" width="800" height="200" />
</mx:VBox>
</mx:Application>

The cool things about this little application are:
  • The data binding
    • Note that the second TextArea's text attribute is defined as text="{escapeHTML(input.text)}". What that means is that the two text fields are bound together, with the ActionScript function between them as a sort of filter. Any change you make in the first box will immediately show up in the second box.
  • The event handler
    • The second box has an event listener set inline by the click attribute. It calls the outputClickHandler() method, which simply sets the your clipboard to be the result of the escaping. That way you don't have to manually select everything when you're ready to copy the results.
While this is a really small, simple application, it demonstrates the power of Flex pretty well. The event model is nice, clean, and simple ... but the data binding is what gives you real power. It's the best kind of magic: the kind that you very explicitly tell it what you want, and raise you eyebrows in pleasant surprise when it works better than you could have imagined.

This is by far the best HTML escaper program I've written, and it's all thanks to Flex. Awesome.

(Feel free to use the HTML Escaper Application to your heart's content.)

Flex Layouts Make Things Much Simpler

A while ago, when I discovered Flex, I wrote about a simple application that calculates a QB Rating for both the NFL and the NCAA. It was meant to demonstrate how you get started using Flex.

From my perspective, the main limitation of that program was that it used absolute layout, meaning each element needed to be manually placed using the x and y attributes. Frankly, that's pretty lame. Even as I wrote it, I knew I'd have to learn about Flex's layouts.

Since that time, I have. And thus far, they seem to be both powerful and simple. They beat the pants off of both HTML and Swing, which were the UI technologies I had compared Flex to.

The layouts are based on the concept of containers. A container is an element in which other elements can be placed (whether they're other containers or actual UI components). The containers have different properties that control how things are laid out inside them.

For example, if you wanted to put two buttons right next to each other, you'd use an HBox, like this:

<mx:HBox>
<mx:Button label="One" />
<mx:Button label="Two" />
</mx:hbox>

That's much nicer than having to define the x/y coordinates and the width of both buttons.

So what did I decide to do to update my QB Rating application? I used a Form Container, with a set of FormItem containers inside it, to lay out the TextInput fields where you enter the QB's stats. And below that, I have a VBox for the results. It looks like this:

<mx:Form left="10" top="10">
<mx:FormHeading label="Calculate QB Rating" fontSize="20" fontWeight="bold" />

<mx:FormItem label="Completions">
<mx:TextInput id="completions" />
</mx:FormItem>

<mx:FormItem label="Attempts">
<mx:TextInput id="attempts" />
</mx:FormItem>

<mx:FormItem label="Yards">
<mx:TextInput id="yards" />
</mx:FormItem>

<mx:FormItem label="TDs">
<mx:TextInput id="touchdowns" />
</mx:FormItem>

<mx:FormItem label="INTs">
<mx:TextInput id="interceptions" />
</mx:FormItem>

<mx:FormItem>
<mx:Button id="calcButton" label="Calculate QB Rating" click="{calcRatings();}" />
</mx:FormItem>

<mx:VBox>
<mx:Label id="nflRating" text="" fontsize="16" />
<mx:Label id="ncaaRating" text="" fontsize="16" />
</mx:VBox>
</mx:Form>

And my oh my, is that nicer than the previous version. If you looked at the old version of the QB Rating application, it had a Label and a TextInput for each field, and the left and top attributes were set for each one. The new version actually takes up a few more lines of code, but it requires you to have less extensive knowledge of the size of the elements. For example, if you decide to change the font size of one of the elements, you won't have to change the "top" attribute on everything below it. If you change the title of one of the labels, you won't have to change the "left" attribute on all the TextInputs so they all line up and don't overlap their labels. I think that's worth a couple more lines of code.

So ... why did I learn about the absolute positioning first? Well, that's how the examples on Adobe's sites all work. At first glance that doesn't make sense, but I've recently learned that absolute positioning is the default in Flex Builder 2 (which I don't have). So it looks like the guys writing these examples are building their applications in Flex Builder 2 and then going through the generated code in their articles. I don't have a problem with that in general, but it seems to me that if you're ostensibly teaching someone about writing the code, it should be code that was actually written. That's a pretty minor quibble though, especially since Adobe's online documentation about layouts and containers is pretty excellent.

If you want to check out the new app or source code, by all means do so.

Flex: MXML Highlighting in VIM

For the first couple of weeks I've been using Flex, I've had to do it without syntax highlighting. My editor of choice is vim, which doesn't support MXML and ActionScript out of the box. However, syntax highlighting is a great invention, and now that I'm in the middle of a sizable Flex project, I figured I needed to get my hands on some syntax highlighting. (It'll be a whole lot cheaper than buying Flex Builder 2!)

The first thing you need to do is download the following two files:
actionscript.vim
mxml.vim

(Even if you only plan on editing MXML files, you need both of these. The MXML syntax depends on the ActionScript syntax, because MXML files can include ActionScript code.)

(Thanks to Abdul Qabiz for these files.)

You need to put these files into vim's syntax folder. On Ubuntu 7.10, it's /usr/share/vim71/syntax. (Make sure you install vim-full, using sudo aptitude install vim-full ... for some reason my installation of Ubuntu came with vim-tiny, which doesn't support syntax highlighting.)

Once that's done, you need to make sure the following lines are in your ~/.vimrc file:

au BufNewFile,BufRead *.mxml set filetype=mxml
au BufNewFile,BufRead *.as set filetype=actionscript
syntax on

Now ... the next time you open up an mxml file in vim, it'll have syntax highlighting for you. Excellent. My development environment just got a little bit better.

Thursday, January 03, 2008

Modal Dialog Box in Javascript

Occasionally you want to be able to pop up a modal dialog box over your web page, so you can force the user to enter something before they continue. You could just use confirm(), but that's pretty lame and doesn't allow you to exercise much control over the user's input options. Yes/No? Okay/Cancel? Lame.

Well, the way to do it, of course, is with a transparent div! That'd be the background, and then you have another div that you put right in the middle of the screen, mimicking a popup window. You'll be able to see through the background div (kind of), but you can't click through it ... which makes it perfect.

First, you need to throw in the HTML:

<div id="modalBackgroundDiv" class="modalPopupTransparent" style="display: none;"> </div>

<div id="modalWindow" class="modalPopupWindow" style="display: none; width: 560px;">
It's awesome that you can put whatever you want in here.
</div>

Then you need some CSS to make it so they actually work as planned:

div.modalPopupTransparent {
filter: alpha(opacity=75);
-moz-opacity: .75;
background: #CCCCCC;
position: absolute;
top: 0px;
left: 0px;
}

div.modalPopupWindow {
position: absolute;
background-color: #FFFFFF;
border: 2px solid black;
padding: 8px;
text-align: left;
}

The most important thing here is that the background div's style has its opacity set to 75%. It has to be done twice because IE and Firefox use different commands for this. (Typical.) The second most important thing to notice is the absolute positioning. That's what allows them to display on top of everything else. It's not that useful if your transparent div shows up below the page, is it?

It's also not that useful if the modal dialog has no functionality and can't pop up. Which is why we now have to add in the Javascript:

function openModalWindow() {
var div = $('modalWindow');
var bgDiv = $('modalBackgroundDiv');

var docDim = Element.getDimensions(document.body);

//get the size of the window and calculate where the box should be placed
var wDim = getBrowserWindowSize();
var dDim = Element.getDimensions(div);

div.style.top = ((wDim.height - dDim.height*2) / 2) + 'px';
div.style.left = ((wDim.width - dDim.width) / 2) + 'px';

if (docDim.height > wDim.height) {
wDim.height = docDim.height;
}

bgDiv.style.width = wDim.width + 'px';
bgDiv.style.height = wDim.height + 'px';

Element.show(div);
Element.show(bgDiv);
}

function closeModalWindow() {
Element.hide('modalWindow');
Element.hide('modalBackgroundDiv');
}

function getBrowserWindowSize() {
var winW = 630, winH = 460;

if (parseInt(navigator.appVersion)>3) {
if (navigator.appName=="Netscape") {
winW = window.innerWidth;
winH = window.innerHeight;
}
if (navigator.appName.indexOf("Microsoft")!=-1) {
winW = document.body.offsetWidth;
winH = document.body.offsetHeight;
}
}

var rval = {
width: winW,
height: winH
};

return rval;
}

To open the modal window, the first thing we need to do is grab a reference to the window, the background, and the document body. We then determine the size of the visible browser window (using a custom function, shown above) and the size of the modal dialog (using Prototype's handy method).

Since we want the transparent background to cover the entire page (not just what's visible), we set the height of the background to be the height of the document body instead of the browser window -- if necessary. That way the user can't scroll down and click something lower on the page if there's a modal dialog up.

Then we center the popup, make the background as big as it should be, and display them. Simple enough. Similarly, in order to close the window, we just hide both elements.

And there you have it. A nice, simple modal dialog, with a transparent gray background that dims out everything else on the page so the user knows what to focus on. I wouldn't use it too often, but in some cases it can be exactly what you want.

Enjoy!

Wednesday, January 02, 2008

PHP usort(): Sort an array of objects

PHP is nice enough to include a nice, fast sort() function that works on simple datatypes like numbers and strings. Saves you the time of having to write your own sorting functions. However, how often is your important data in an array of integers or strings? Considerably more often, you have an array of more complex data structures that you'd like sorted. And the sort() function just can't do it.

One option you have is to write your own sorting function, as I've already mentioned. In fact, I've done this numerous times. But why should I have to type out a quicksort algorithm -- slightly modified to compare objects or associative arrays -- rather than having the libraries do it and move on to more important things. This isn't CS class any more. I shouldn't have to "prove" that I understand the quicksort algorithm ... I need to get things done!

Well, as it turns out, PHP does indeed offer the capability to sort an array of objects. And it's not so bad. Check out usort. The basic concept is that you pass it the array of objects and a function (or static method) that'll act as a comparison function between two objects. This function is something you write yourself, since you're the one who knows about your classes. I usually put it right in the class itself, acting as a static method. Here's a quick example:


class Item {
var $a;
var $b;

function Item($pA, $pB) {
$this->a = $pA;
$this->b = $pB;
}

function _cmpAscA($m, $n) {
if ($m->a == $n->a) {
return 0;
}

return ($m->a < $n->a) ? -1 : 1;
}

function _cmpDescA($m, $n) {
if ($m->a == $n->a) {
return 0;
}

return ($m->a > $n->a) ? -1 : 1;
}
}

//let's make an array
$arr = array();
$arr[] = new Item(1, 2);
$arr[] = new Item(4, 3);
$arr[] = new Item(2, 3);

//now we can sort it!
$sorted = usort($arr, array('Item', '_cmpAscA'));


Note that the second parameter to the usort() function is an array. This is because I'm calling a static method. The first item('Item') denotes the class, and the second item('_cmpAscA') denotes the method name. If I had simply made a comparison function that wasn't in a class, the second parameter to usort() would have been a string, not an array.

I typically make two comparison functions per sortable field in my objects; I want to be able to sort ascending and descending, without having to muck with strrev(). My way is a bit faster ... but may force you to use a bit more code. It seems to me that that's a matter of personal preference. And I have this preference because I feel that it allows you to more accurately describe what you want. If you want to sort in descending order, you say "sort this in descending order," rather than "sort this and then reverse it."

Anyhow, usort() is a powerful tool to add to the toolbox. I know I'll be using it in the future for all my object-sorting needs. Hope you find it as useful.