Thursday, March 13, 2008

Grader: Other GUI Thoughts

I listened to a very interesting inteview on ITConversations.com the other week. The interviewee was Bill Buxton, a principal researcher with Microsoft Research and author of Sketching User Experiences (now on my Amazon wish-list).

In the interview, Bill talks about using sketching, at the simplest level possible, to allow creative though and to get away from preconceived notions about what software has to look like. A very interesting non-software example he provided was that George Lucas intertwined scenes of the chariot race from Ben-Hur with NASCAR wreck footage, to sketch out the pod-racing scene in the The Phantom Menace. This technique allowed him to sense how the scene would play out with little expense or time commitment.

This interview struck a chord with me because I didn't really brainstorm too much on what the Grader GUI would look like. The grading data is tabular so I immediately envisioned an entry table and implemented it that way, not really considering any other options. Maybe a wizard-like entry system would have made for a better user experience (not likely :) ). But I didn't even give myself the option of brainstorming and allowing some bad ideas help spurn some ideas that might have worked better.

I'm also currently reading Tog On Software. This book was written in 1996 and predicts a user-interface revolution happening ten years out. Since the book is twelve years old, it's interesting to see how much of the book's predictions have yet to become reality. One of Tog's predictions was that computer systems would have seamless voice recognition systems by now, which got me thinking about how well Grader could work with such a user interface. A user speaking the words "2", "1", "2" "0", "Next Player", "0", "Next Play", etc... would likely be much easier than typing the scores and using the tab/arrow keys to move between cells. I think I might look for some open source voice recognition software and see what I can do with it. That sounds like a fun project and would probably be a good thing to learn for the future.

Anyway, I think these two sources have made me think harder about user interface design and the process involved. I especially took to heart Bill Buxton's interview as "sketching" is a general purpose technique that can be applied to all areas of creative thinking, not just UI design.

Grader: GUI

I find GUI programming to be enjoyable most of the time, with dashes of frustration thrown in for good measure. The fun part is the rapid feedback loop that exists as changes appear immediately on screen. It's also easy to bang out the code and get a lot accomplished in a short amount of time. The frustration comes in when my perfectionist tendencies inspire me to spend an inordinate amount of time trying to get every last detail exactly right, something that is quite difficult to do.

I've worked with QT for quite a while now (5+ years give or take) and really enjoy working with it. Having started out my professional career writing in Java, I like the similarities between the QT framework and the Java Standard library. But like the Java Standard library, QT is quite large and can require a lot of digging to uncover functionality you know is likely to exist, but doesn't seem to exist where you expect it.

Case in point...the Grader application uses a QTableWidget to allow users to enter player grades. After quickly getting the initial GUI up and running, I was surprised to see the cells of the table were not expanding to fit the entire widget, leaving empty white space along the bottom and right borders. I knew there had to be a way to correct this issue, but searched high and low through the QT documentation, unable to find it.

I reached the point where I was ready to give up, subclass QTableWidget, and write some overly complex code that filled the widget, making sure each column and row was the same size, handling resizing issues, etc... But one last search resulted in me finally finding what I needed in the QHeaderViewClass, the class that provides the table's row/column headers. I probably skipped over the function at least once when skimming the documentation, making things even more frustrating. But at least I didn't spend any time rewriting functionality that already existed.

I tackled two other issues in the first iteration of this project: fast data entry and displaying the grading data.

Fast Data Entry
I wanted to make sure the user could complete data entry without having his hands leave the keyboard. I used QActions to provide shortcut keys to save a play (Ctrl-S) and output a report (Ctrl-W). These actions exist in a menu, which I didn't really want to add as I didn't even want to give the user the option of using the mouse. But the QActions didn't seem to be active unless the menu was available.

Displaying Grade Data
My first attempt at this functionality was to display the entire grading table at the top of the window, using a QLabel with the text set to an html table. However, this resulted in a lot of screen clutter and looked really ugly. My next attempt was to just set the QLabel text to an html table that contained two columns, one for the grading scores and one for the grading descriptions based on the current selected column in the grade entry table. This worked well except that the table was always changing sizes and required the user to refocus when looking at the grade data. My brother actually complained about this problem when I gave him the first iteration to test out. I settled on using another QTableWidget which has the benefit of staying a fixed size, but has the disadvantage of looking as if it's editable even though I disabled any selection of the table cells (disabling the entire widget didn't look correct).

Overall, I think the GUI is decent enough for something that I wanted to keep as simple as possible. There probably are still some sizing issues that could be handled better but at this point, I think that's running into the Law of Diminishing Returns.

Wednesday, March 5, 2008

Grader: KISS (Keep It Simple Stupid)

When my brother first asked me to write this program, he mentioned that someone had suggested to him he could solve his problem using Microsoft Access. I haven't used Access much before, but looked into it as a starting point. Creating the data tables was not a problem, but when I started looking at creating entry forms that spanned multiple tables, I decided it would probably just be easier for me to write an application from scratch.

At this point, I figured my next decision should be to decide which database to code against. I was picturing the ability to query on players, plays, years...quite a grand scheme. Taking a step back, I realized that my brother had asked for none of this functionality. All he wanted was a way to input grades for a single game and a summary report so he could evaluate each player's performance over the entire game. From this point on, I decided I was going to create the simplest program possible, focusing more on providing a solid user experience, and adding functionality only when it was requested. This decision resulted in the following decisions:

No Database
All of the data entered by the user is stored in memory and is lost once a game is completed (unless you count the report summary html file). This decision saved me quite a bit of time, and the more I thought about it, saving the data to such a history wouldn't provide much value at the high school level. Why would a coach care to save data for a player that is going to graduate in a year or two anyway?

At startup, the user must select two files that they previously created (or use the default files created by my brother), which contain the data needed for grading. The first file is just a text file that contains the list of players begin graded. The other file is a comma-delimited file that contains the grading scores, grading categories and descriptions of each score for each category. For example, a simple file might contain the following:
Score,Catch,Yards After Catch
1,Circus Catch,Ran for Touchdown
0,Catch,No Yards
-1,Drop,Lost Yardage
HTML Summary Reports
I was originally going to provide the summary reports in a dialog window once a game was completed. I was also intending to provide the capability to print that report. Having written some printing code before, I knew this would turn out to be complicated. I was pretty happy with myself when I thought of the idea just to generate an html report file. Not only could the user just print the file from his web-browser, but the html format allows the user to put reports out on a web server where other coaches can view the data.

The next two missing features are things I think I will eventually implement, even if my brother does not request them, as they would be generally useful.

No Backspace
At this point, the user cannot go back to a previous play after it has been submitted. This probably isn't a big deal as it shouldn't be too hard to enter the data error-free. But it might be nice to have that capability if a play is accidentally submitted before all the data has been entered.

All or Nothing
Grader currently doesn't support any concept of saving off partial results. So the user must enter a complete game at one sitting. I think it would be pretty useful to allow the user to enter complete game data over a series of application sessions. Of course, the usefulness would depend on how long it takes to enter an average game, information I will have to get from my brother. If it only takes 5-10 minutes, then maybe this isn't a worthwhile function to implement.

I saved myself a lot of time and was able to deliver the product much faster than if I had decided to move forward on implementing any of the above features. Instead, I was able to spend more time on solving the little problems faced when trying to make a GUI look just the way you want, which is the topic I will discuss in my next post.

Grader: What?/How?

What?
Below is a screen-shot of the main window for the Grader application:


The Grading Key displays the grade data for the current grading category, which is determined by the current selected cell in the lower grade-entry table. The Grading Key provides a reference to the grading criteria as the user traverses through the grading table.

Although it does not require an entry, the play field allows the user to enter a name for the current play.

Other than that, the user simply enters grades for each player based on the grading criteria. As I said in my previous post, the application is pretty simple. The user submits the grades for a play by pressing Ctrl-S (or Grade->Save Play), at which point the grade-entry table is cleared and is ready for the next play.

At any point, the user can press Ctrl-W (or Grade->Write Game Report) to signal the completion of a game. At this point, the application outputs an html page that provides a grade summary for each player. Ctrl-N (or File->New Game) allows the user to start a new game.

The only other feature I provide at this point is the ability to pre-submit a list of plays when starting a new game. My brother's team already has a software package that tracks game information. This software allows them to export a list of plays which they can then just copy/paste into a dialog I provide. This results in a different "mode" in which the play field is disabled and is populated with the current play name as the user iterates through the plays. The Grader software then automatically generates the summary report after the last play has been submitted.

How?
I developed the program in C++, using the open-source version of QT (4.1) for the GUI. At some point, I want to put the application up on SourceForge so it is generally available.

The player data is stored in a designated text file and just contains the names of the players that will be graded. The grading data is stored in a designated csv file.

Sunday, March 2, 2008

New Product: Grader

I've recently released my first independent product. Calling it a product is a bit of a stretch as it is quite simple and isn't going to make me any money. However, it was a fun little project and I'd like to write a series of posts on some of the ideas/decisions I made while implementing it.

I created the application for my brother, who is an assistant football coach at the high school where he teaches. One of his responsibilities during the season is to review the film for each game, grading his players in several categories for each play. In the past, he completed this task manually, which obviously took quite a bit of time. Thus, he asked if I could develop an application that would help speed up this process and generate summary information to help him better evaluate his players' performance.

And so Grader was born (my creative juices were not flowing when I came up with the name). I think it turned out pretty well and will hopefully make his job easier. It also provides me with sample code to show any potential employers, although at this point it is probably too simple to make any kind of impression. However, I'm sure my brother will require more functionality in the future. I would also like to convert Grader to a web application using Ruby on Rails, as it would be an ideal project to dip my toes into learning that platform.