On My Days Off
A couple of weeks ago I took some time off to set up a small party that I was planning. It involved a tournament for washers, a game similar to horseshoes, but better (as I sell it people).
As it turns out, I don’t know enough people willing to participate in what I was really planning, but I like what I’ve created and I’d like to show you why you should never leave me on my own for two days without checking in on me.
The following was created in 22 hours of work.
The Concept
Create a web application that can fully track and run an eight-team tournament that includes a round of “pool play” and a full set of brackets (including loser-brackets, resolving team-finishing places down to each individual position). The system must be easy enough to instruct players how to use, since at some point I will be playing and not manning a score station.
Planning Phase: General Rules
First things first, I needed to create a set of rules that would have to be followed so that I could wrap a system around that.
I came up with the following list:
- Eight teams will be broken into two pools
- Each team consists of two players
- In pool play, each team will play each other team in their pool once
- There will be two courts playing at once
- Each team will get to be a home team and an away team at least once in pool play
- Each team will play on each court at least once in pool play
- Pool play will determine the starting championship bracket
- All matches will be a best-of-three series, except matches to determine a finishing place which will be best-of-five
- All games are races to twenty-one, win by two
Planning Phase: The Schedule
Each team was going to need to play three games to finish pool play, and an eight-team bracket takes three rounds to resolve fully, which meant that each team was going to play six matches, five of which were best-of-three and the last being best-of-five.
Eight teams playing six games each create forty-eight teams playing matches, but since each team will always be playing another team in the list, we divide by two to get twenty-four total matches that need to be scheduled.
After a bit of science, I found that a best-of-three game can comfortably be completed in thirty minutes, even if all of the games went into overtime. A best-of-five series can be completed in forty-five minutes or so, and any overages would be allowed since the matches are only for important tournament events.
I got out my trusty Numbers (it’s an Apple app) and got to planning. The result was a schedule of matches starting at 1:00pm and lasting through 7:30pm, perfect timing for a fun-filled Saturday.
Keep in mind that there was more planning involved than just this, but I’m going to explain things in the order I built them to add drama.
Production Time: The Admin Area
The first project was creating a general admin area that would allow me to create places to play (“Courts”), players, teams and schedule matches between teams (and assign those matches to courts).
After some quick database schema work, I created my tables:
- courts
- pools (into which teams are placed)
- teams (into which players are placed)
- players (they’re made of people!)
- matches (head-to-head battles between teams)
This process only took a couple of hours, so things were moving along swimmingly (whatever that means). I added my set of eight fake teams, sixteen sample players (assigning them to teams), two pools (assign teams to them), two courts, and then created twenty-four matches, twelve of which were based on my Numbers sheet.
It’s important to note here that I couldn’t actually create twenty-four full matches with teams assigned to them because I didn’t know who would be playing which game starting with the first round of the tournament. The tournament started off with brackets that had pool a’s first place team playing pool b’s last place team, pool b’s first place team playing pool a’s last place team, and something similar for the second and third place teams. More on this later.
Production Time: Scorekeeper
There were two somewhat difficult humps to get over in the project, and creating an intuitive front-end interface was the first one. It was important that anyone could pick it up and learn it in a matter of minutes. Another added hoop of fire I decided to jump through is to create an iPhone interface for the scoring app (which I called Scorekeeper).
First screen you come to: choose your court. It makes sense to approach things this way since you’ll either be in one location or the other, and if I could find some dedicated laptops for the day you would never need to return back to this screen.
Featured right is a screenshot of this page. You can see a couple of buttons, one for each court that would be set up with a description as to where they were located.
Next, you will need to choose the match that you’re looking to score. This turned out to be a list of buttons that you could choose. The display included the match number, the scheduled time (iPhones have the time right up top, nice and easy to see what comes next), the teams playing (away vs. home team), and each team’s record. (Pictured to the right.)
This view changes a bit depending on what it happening for a match. Matches display in blue if they’re currently in progress, and the display now shows the match series score, as well and the current game’s score. (Both pictured in images side-by-side below.)
This button will turn gray once the match has been completed. You can always click on matches, and all clicks will bring you to the same place: the match overview.
This view displays which match you’re looking at, as well as the length of the series. You can see the current series score up top, and a list of the games played (or being played) at the bottom. If there’s a game in progress, you can choose the “Continue Match” button at the bottom. Otherwise, it will say, “Start a New Game.”
You’ll see the game number is in red. You can click those to either be taken to a game in progress, or to see a summary of the game once it’s complete. Let’s join the game in progress.
Inside the game in progress, you get the buttons for controlling the score. (Pictured to the right.) At the top is the match number and series length, followed by the current score, home team on the bottom.
Next, you’ll see a couple of players along with numbers. In washers, similar to horseshoes, you get two throws per “end.” Only one person can score per end, so you’re given a spot to enter each point value separately. More on why you do it this way in a bit. To choose a score, simply tap a number and the point value will increase by one. Once you get to three, your next tap resets the value back to zero.
Changing the score for one player automatically resets the other player’s scores to zero since only one player can score per end. Once you’re ready, you tap “Score.” The page refreshes, the score up top refresh to show the new score (four plus one plus two equals seven apparently). Next, the bottom of the interface now shows the players on the other end of the court who get to throw.
This system is designed to submit zero scores when no one scores. Again, more on this in a bit.
Next I added the “Edit Last End” button which lets you undo one move back in time. I figured you wouldn’t need more than this because eager scoreboard watchers would complain right away. Clicking “Edit Last End” displays the last score you’ve entered with a button to “Update” it.
This interface is smart enough to know the rules of the game, and you have to win by two.
You’ll be able to keep entering scores until the system knows that someone has won. (See right.) At that point, you’ll have one last chance to edit the last end, or mark a game as “Final.” By the way, this is also the summary screen if you click on a game that has finished back a couple screens ago.
We click “Final” and we’re taken back to the match overview screen. See how things changed? By the way, if you catch the match list between games, the interface also adjusts for this.


Something I didn’t yet mention was starting a new game. When you click “Start a New Game,” you have to select which players are throwing first. You are presented with all possible combinations of players that could throw first. As soon as you pick you’re off and running to score the match.
I’ve finished simulating the match for our purposes here, and to the right you’ll see an updated view of the match overview page when a match is complete.
Essentially, rinse and repeat. This continues until you’ve played all of the matches.
Production: Automatic Match Creation
Included in a match’s functionality is to know what to do when the match has completed. For the first eleven matches, we don’t have to do anything. After this, we need to make sure that we’re creating matches automatically based on positioning of teams and results of matches.
Essentially what is happening is that there’s a method that takes one parameter: a completed match. Based on this match and other matches saved in the database we can create new matches using the rules we’ve set up in planning. A new method had to be added to get a team based on the match result (“winner” or “loser”), but it wasn’t anything my PHP abilities couldn’t handle.
Production: Scoreboards
And here’s where things get exciting: making scoreboards. I decided to go with a Fenway Park type theme for my scoreboards. Both are designed to fit in 1920 x 1280 screens (as those were going to be the screens available for displays), but were both built in ems so that they scaled nicely regardless of what the size of the screen was.
First step here was to design the scoreboards. This is the center court scoreboard at a point to where we finished the Scorekeeper review.

Scoreboard features include:
- The current match number
- The current court (just in case you didn’t know where you were)
- The current time (official tournament time)
- The current score for the game
- The current match series score
- The next match scheduled on this court (and the time)
- A mini-scoreboard of what’s happening on the other court (because you couldn’t see the courts
- from one another, this features the same info the current game at this court features)
As a reference, I’ve provided a view from the other court. These games would be happening at the same time, so things would be changing a bunch.

I used jQuery to power the Ajax behind these scoreboards. I didn’t know anything about jQuery before tackling this project, but instantly fell in love with it.
For example, here’s a silly solution to a silly problem. The time in the top right corner could have used the local machine time via JavaScript, but I wanted to make sure that everyone is seeing the same time. The solution was to set up an API method to return the current server time.
Simple.
The scoreboard makes a series of Ajax requests to an informational API I set up for the system. The returned information can range from actual HTML (included through jQuery’s $.load() method) to a JSON object of data you might need to know. This would allow for any other remote site to easily connect to the scoreboard system and get information about teams, their records, their stats, game scores, match results, etc.
Production: Pavilion View
I’m about three-quarters through my two-day work period and I finish up my “required” elements, so I dove into my third scoreboard view (the other two being one for Center Court, and one for the Side Court): Pavilion View.

The schedule is set up that for every hour of play, you’re actually playing for thirty-ish minutes, and you’re socializing, using the bathroom and grabbing food and drink for the other thirty.
That said, I created a third view for the “Players Pavilion” inside. The Pavilion wasn’t really in view of either court, although you could see things if you made an effort. But additionally, I needed a spot to display current team standings and some other things (the bits that I alluded to earlier, here they come!).
To the right, you’ll see the Pavilion view. From here, you can see the current scores from each game, the current team standings, and top players in some individual stats at the bottom. We can easily calculate all of these numbers because we’re saving every shot taken by every player.
(As you can see, I was crushing it during the quick simulation back a couple sections ago.)
This page also updates in real-time via Ajax, so with every through players starts are constantly changing.
Once we’ve completed the first twelve matches, the top area with team standings turns into four sets of brackets showing the match ups that are taking place next. These brackets will fill out, and then a new set of brackets is displayed. This repeats one more time.
Production: Optimization
This became the second hardest point of creating this app: the logic calls were much too slow.
The Ajax scoreboards were not able to keep up with my very quick requests to update the scoreboards. While I’m sure I could have lowered the polling from every two seconds (hey, I was really excited about this), it was taking four or five seconds to load all the data needed for each scoreboard. The less seasoned developer would have simply increased the polling time and called things good, but I went in to optimize.
What I learned: at some point, OOP breaks down.
That may be because PHP isn’t truly an object-oriented language, but the number of calls and loops needed to create the information I was looking for simply no longer became sufficient for what I needed to do. The result was to create a similar but different set of data collection techniques for the API.
After an hour or so of re-factoring (cutting down on loops, and working some ridiculous SQL magic), the average call dropped from four seconds to about a tenth of a second. Whamo!
The Downside
I tried to hype up the entire afternoon, but I couldn’t get enough people to show up at the tournament to even use this system. People asked why I couldn’t just shrink the scale down, but hopefully after reading this you’ll understand why.
We were still able to use the scoreboard, I just short-circuited the place where the match updates other matches and told the code instead to erase everything and start over at the beginning. It’s too bad, I’d love to actually use this whole thing some day.
Future Ideas
I’m glad I didn’t spend more than two days on this, but I did have a couple of ideas that I’d like to add on to things.
- Instant Mobile Stats
I’d have liked to create a page that anyone could go to on their phone to see a list of teams. From there, they could click on any team they’re interested in (or their own team) and seen an up-to-the-second tournament overview for that team. This would include game results, match results, team rankings for stats (along with their values) and player rankings for stats (along with their values). - Alerts and Notification
It would have been nice to also include alerts on the scoreboards that could convert the status area (the match series information below the scores) into an alert box to say, “Fred just tossed a ringer!” Maybe even the ability to check when some team is on a crazy streak, like, “Team 1 is on a 14-0 run.” - Paging Players
Another touch that might have been nice is having the system send out text messages to players that are playing shortly. Maybe something that says, “In three minutes, you’re scheduled to play on the Center Court versus Team 3 (2-0).”
Conclusion
So that’s apparently what I do in my time off. It also occurs to me that this is the longest blog ever, I’m not sure that any living person can even read all the way through this, and I can’t imagine how many errors there are in this. Let me know if you see any.
Comments
Two observations:
(a) iMarc has more than sufficient employees to fill this game
(b) We have an all-hands status meeting every Monday morning
One weekend long ago (when AJAX was a new buzzword) I spent a weekend building a Secret Santa app... it was that weekend that I decided to start building furniture. Sadly I still end up designing what I build in SketchUp so it only slightly reduces the amount of time I spend in front of a screen outside of work :0)
Nonetheless, this is a VERY cool project.
Also, thanks for the insight into your design, production, testing processes.
Thanks, Love the meteor storm too!
Maybe it's just me, but I find this absolutely incredible...
Read something more recent.
Statements and opinions expressed in this blog and any comments made are the private opinions of the respective poster, and, as such, iMarc LLC is neither responsible nor liable for such content.
Visitors
I think you forgot the future idea where there's a jQuery-enhanced RFID chip in everyone's eye.