Poker Stats: Auto-detecting Full Tilt Poker Hand History

Here’s a gory report of some technical internals of my app. If Java or concurrent programming bores you, avert your eyes.

Yesterday I completed the mechanism to detect the user’s Full Tilt Poker hand history. I’m pleased with the result. It gave me a chance to give the java.util.concurrency API a good work out. I have the interesting challenge of keeping the GUI responsive while performing some processor intensive parsing. I got to write a simple implementation of Google’s MapReduce algorithm too.

Here’s what happens: my Poker stats app scans for hand history files in the ~/Documents/HandHistory folder, which is where Full Tilt Poker writes its hand history, unless instructed otherwise. This folder can be changed in the preferences.

A background thread is launched to monitor this folder. Any file that has either not been parsed yet, or has changed in file size since last parsed is added to a list of files to be parsed. This process is repeated every 10 seconds. To be precise, it is repeated 10 seconds after the end of the previous scan. Through careful monitoring I’ve proven that this regular scanning causes no discernible ongoing load on the system.

The list of files needing scanning is then sent to the parser. I’ve used every trick I know to make the parser fast. On my dual core 2.4 Ghz Mac Book Pro, it currently rips through the hand history files at the rate of about 2500 hands per second, although it sometimes peaks at 4000 hands per second. On a multi-CPU or multi-core processor, my MapReduce implementation creates multiple parsing threads, so this rate could feasibly be much higher. I’ll have to find a way to test this on a machine with more than 2 cores.

As soon as all the hands in a file are parsed, the GUI is notified to update, via the Observer pattern. Newest files are parsed first, so that upon start-up the most recent statistics appear immediately, whereas the older stats may take a few seconds to appear.

Poker Stats: What’s in a Name?

I watched a video recently of Tim Ferriss giving a presentation to Google London. Tim Ferriss is the author of “The 4-Hour Workweek“, a title I think is poxy. It turns out he does too. In this video he revealed how he came up with the name.

His original title was “Dealing Drugs for Fun and Profit”. His publisher said that such a Wal-Mart unfriendly title would be terrible for his sales and he needed a new name. So he came up with about 10 different titles. For each he registered the domain and set up a simple “coming soon” page. He then spent about $150 in total on Google Adwords campaigns to see which attracted the most clicks. Apparently “The 4-Hour Workweek” was an order of magnitude more popular than any other candidate.

Oh, and Tim has made a massive heap of money, I guess, from this book.

I’m taking the same approach for my Poker Stats app. I’m gathering 10 candidate names of which, thanks to help from Scott Kane and Rob Meredith, I already have 5. Then I’ll let the market speak, courtesy of Google Adwords.

I’m still keen to hear suggestions for names, especially if the domain for the name is available.

Poker Stats: Banished the Calculating Bugs

I played about 100 hands of poker yesterday, carefully tracking the results of each hand manually. Comparing to the results of my app, I discovered my calculation problems. They were due to the subtle differences between “raising $1” and “raising to $1”. The linguistic difference is subtle, the mathemathical difference any but.

Poker Stats: Side-by-Side Screenshot

Here’s a screenshot showing how you can use my as-yet-unamed Poker Stats app to monitor your play with Full Tilt Poker in real-time. After I complete each hand, within a few seconds the chart and stats are updated. Click for larger image.


The screenshot also shows a bug that I’ll have to track down: why the big dip towards the end of the graph? My guess is that in certain hands the calculations are getting confused.

Poker App: Finished the parser

I knuckled down today and completed the parser for Full Tilt Poker hand history. This is the second parser I wrote, the first being for Party Poker, another online poker site. The second one was definitely much easier to write than the first one, because for the first one I had to relearn how to write a parser, something I hadn’t needed to do since my university days. It’s more than 15 years since I finished university, which is adequate time to forget most everything I learnt.

Now I’ve got the less enjoyable part to do: manually reading through various hand history files, calculating with pen and paper the expected results, which I can then compare to the results my Poker statistics app gives. After all, I don’t want my app to be telling people they are poker gods, if they are only poker mortals.

I spent a little time on the name dilemma. Damn, it’s hard finding a pithy but appropriate name whose domain is free.

Poker App: Some Progress

I finally got around to importing my project source into Subversion source control. I know, I know, I should have done it long ago. :-)

I added a red dot to the end of the Sparkline, to make it clearer that the number beside the Sparkline is the value of the last data point. If this means nothing to you, be patient, I intend to explain what Sparklines are, why I’m using them, and I how I implemented them in Java sometime soon.

I got cracking with a hand history parser for Full Tilt Poker. I needed to test against a wide range of hand history files, which meant I had to play for a while. Nice when I can play online poker and consider it work. If all goes well tomorrow, I should have the parser finished.

I experimented with building a DMG file, which is how OS X apps are typically distributed. It was a bit cumbersome, I’m definitely going to have to create a one-step process to build the distributables.

If anyone reading this plays Full Tilt Poker on the Mac, and would like to help me out by trying out the DMG file and running the app on your own system, let me know. It would be good to know if I’ve accidentally included any dependencies on my own environment.

Making Dialogs in Java Close When Escape is Pressed

In Windows and in OS X, if you press the escape key, dialogs close. It is equivalent to clicking on Cancel.

By default JDialogs in Java do not have this behaviour. If you want to add it to your JDialogs, you can use this subclass of JDialog. Instead of extending JDialog, extend EscapeKeyAwareDialog instead:

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.*;

public class EscapeKeyAwareDialog extends JDialog {

public EscapeKeyAwareDialog() throws HeadlessException {
super();
addCloseOnEscape(this);
}

public EscapeKeyAwareDialog(Dialog owner) throws HeadlessException {
super(owner);
addCloseOnEscape(this);
}

public EscapeKeyAwareDialog(Dialog owner, boolean modal) throws HeadlessException {
super(owner, modal);
addCloseOnEscape(this);
}

public EscapeKeyAwareDialog(Dialog owner, String title) throws HeadlessException {
super(owner, title);
addCloseOnEscape(this);
}

public EscapeKeyAwareDialog(Dialog owner, String title, boolean modal) throws HeadlessException {
super(owner, title, modal);
addCloseOnEscape(this);
}

public EscapeKeyAwareDialog(Dialog owner, String title, boolean modal, GraphicsConfiguration gc) throws HeadlessException {
super(owner, title, modal, gc);
addCloseOnEscape(this);
}

public EscapeKeyAwareDialog(Frame owner) throws HeadlessException {
super(owner);
addCloseOnEscape(this);
}

public EscapeKeyAwareDialog(Frame owner, boolean modal) throws HeadlessException {
super(owner, modal);
addCloseOnEscape(this);
}

public EscapeKeyAwareDialog(Frame owner, String title, boolean modal) throws HeadlessException {
super(owner, title, modal);
addCloseOnEscape(this);
}

public EscapeKeyAwareDialog(Frame owner, String title, boolean modal, GraphicsConfiguration gc) {
super(owner, title, modal, gc);
addCloseOnEscape(this);
}

public EscapeKeyAwareDialog(java.awt.Frame owner, String title) throws java.awt.HeadlessException {
super(owner, title);
addCloseOnEscape(this);
}

private void addCloseOnEscape(final JDialog dialog) {
ActionListener cancelListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
setVisible(false);
}
};

KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
JRootPane rootPane = dialog.getRootPane();
rootPane.registerKeyboardAction(cancelListener, stroke, JComponent.WHEN_IN_FOCUSED_WINDOW);
}
}

How can I Format Java Code with Blogger?

Does anyone know of a good tool that will help me with this?

When I paste Java code into this blog, I’d love for it to be nicely formattly with syntax highlighting and indenting. Unfortunately simply copying and pasting into the Compose window eats my indenting. And I really don’t want to have to do all the formatting manually in the “Edit HTML” window.

Any suggestions?

Poker Stats: Getting the Mac Feel Right

I can always tell when a Mac app is a quick port from Windows done by people who haven’t taken the time to grok the OS X environment. Things just aren’t quite right. For example, in OS X, the keystroke Command+, always brings up Preferences. Additionally they are always available from a standard location on the menu bar. Always? Did I say always? I meant always except for those who just dump a Windows app onto the Mac with the bare minimum work required to get in running.

I’m trying very hard to get the Mac feel right. I’m grateful to Apple for providing ample quality documentation in this area. For example, the Apple guidelines specify the preferred size and location of new windows. Horizontally centred, vertically with a gap between the top of the window and the screen equal to half the gap below the window.

I’ve created a helper method in my SwingUtils class to take care of locating new windows for me. Here’s the source:

/**
* Aligns the position of an object (dialog, window, frame) so that it is located
* according to the Apple UI guidelines.
*
* @param window object to locate
*/
public static void alignObject(final Window window) {
final Dimension size = window.getSize();
final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
int x = ((int) screenSize.getWidth() – (int) size.getWidth()) / 2;
int y = ((int) screenSize.getHeight() – (int) size.getHeight()) / 3;
window.setLocation(new Point(x, y));
}

Poker Stats: More Decisions Made

There are many online poker apps, all of which have their own way of writing hand history files. These hand history files are the input for my app.

I’ve been playing Party Poker exclusively until a few days ago, and my app currently only parses hand history files from Party Poker. However Party Poker creates two problems for me. First, the Mac version doesn’t write hand history files, and I’ve decided only to release a Mac version initially. Secondly, the hand history files it writes are messy and interlaced with chat messages, causing some parsing reliability problems.

Over the last couple of days I’ve been trying Full Tilt Poker. This has a good Mac version, writes hand history files on Macs, and the hand history files are better structured. A friend told me that it has much more users than Party Poker too, although I’ve been unable to verify this.

So the decision: the first version will only support Full Tilt Poker hand history files.