Welcome!

PowerBuilder Authors: Dan Joe Barry, Carmen Gonzalez, Ian Thain, Yakov Werde, Paul Slater

Related Topics: PowerBuilder

PowerBuilder: Article

Building a Scoreboard in PowerBuilder

The results were well worth it

My favorite sport is artistic roller skating, where I act as the tabulator. It's a wonderful sport, a bit like ice skating, except that most events are skated on quad skates (four wheels in a rectangular layout). We do freestyle (with jumps and spins), figure skating (on the circles), and dance. A few of us do inline skating, too.

We had a tabulating program: a Visual Basic 3 application. It did its job, but the score sheets which it printed had only the skaters' numbers, not their names. Data was kept in flat files. Skaters and their parents would crowd around the score sheets once we posted them, trying to figure out how they did. The font was small, but you could figure it out with a little patience.

We never had a scoreboard for this sport. There are many scoreboard programs for sale on the Internet, but none were designed for this sport. Even if we found such a program, re-keying the information just to show it on the scoreboard would not be fun. A local contest can have up to 60 events, averaging 10 skaters each.

I wondered how hard it would be to create a real scoreboard for this application. The requirements were as follows: 1) it had to read the flat files from the existing tabulating program; 2) it had to be visually interesting: brightly colored letters on a black background; 3) it had to display the skaters' names; 4) it had to work on standard hardware (my laptop and standard displays).

Multiple Monitors
The first piece of the puzzle was figuring out how to drive the second monitor. My laptop has both a VGA and S-Video output, so I plugged in a 17-inch LCD monitor, and booted up. It turns out that Windows XP supports multiple monitors. Just click on Start, Control Panel, Display, and click the "Settings" tab. You should see two rectangles, numbered 1 and 2. Click on number 2, then check the box that says "Extend my Windows desktop onto this monitor." Click OK, and it takes effect. You can now drag and drop any window to the right to land on the second monitor. LCD output was crystal clear.

This same procedure works great for S-Video too. I hooked up my TV and saw the scoreboard come to life. My 27-inch TV did work, but the picture was not as crisp as it was on my 17-inch LCD monitor. Also, the colors needed a bit of adjustment to look good on my TV.

Which Events to Display
In the main window there is a schedule of events. This has a DataWindow that has one row per event. Here, I added a new checkbox called "Scbd" for Scoreboard. The tabulator simply checks the events to display on the scoreboard, and presses the "Display" button.

The Display button simply does a SaveAs() function to save the datawindow to the "Server Folder", and loops through the rows, copying the files needed for the events that are checked.

That's all the main window has to do. The scoreboard will read these files, as we will see.

Long ll_row,ll_max
string ls_server_folder,ls_cmd,ls_scoreboard,ls_src,ls_dst
String ls_event,ls_round,ls_file

RegistryGet(‘HKEY_CURRENT_USER\Software\ScoreMax', 'ServerFolder',RegString!,ls_server_folder)

FileDelete(ls_server_folder+'\schedule.txt')
dw_01.SaveAs(ls_server_folder+'\schedule.txt',Text!,FALSE)

ll_max=dw_01.RowCount()

FOR ll_row=1 TO ll_max
            ls_scoreboard=dw_01.GetItemString(ll_row,'scoreboard')
            IF ls_scoreboard='Y' THEN

                        ls_round=dw_01.GetItemString(ll_row,'type')
                        ls_event=dw_01.GetItemString(ll_row,'event')
                        ls_file=Upper(ls_event+ls_round+'.TAB')
                       ls_src=Upper(is_dir+ls_file)
                        ls_dst=ls_server_folder+'\'+ls_file
                        FileCopy(ls_src,ls_dst,TRUE)
           END IF
NEXT 

RETURN 0

To make coding easier, whenever there are DataWindows on tabs, I create an instance variable for it, and initialize it in the open event of the window. Then, you can refer to the datawindow using the instance variable. It's easier to type dw_01 than tab_1.tabpage_2.dw_1.

DataWindow dw_01

// Open event:
dw_01=tab_1.tabpage_2.dw_1

Scoreboard Layout
I created a new window in PowerBuilder to hold the scoreboard, and put two DataWindows on it, one on top, to be the main scoreboard, and one on the bottom.

The top DataWindow will show up to 12 skaters, sorted by placement, and also show skater number, name, and the ordinals. (An ordinal tells you how a particular judge ranked you in that event. An ordinal of one means the judge put you in first place.)

The bottom DataWindow has the judge's number and name, as well as the current time (see Figures 1 and 2).

Paging
That's fine for events that fit on one page. If there are more than 12 skaters, the scoreboard would need to show the first 12 for a while then scroll to the next 12, and so forth. This simple task turned out to be more complex than you might imagine. ScrollToRow() was not my friend - it was difficult to control which rows would appear on the screen. The solution: insert enough blank rows into the DataWindow so that the number of rows is always a multiple of 12, then use the ScrollNextPage() function. Here's the code.

// Instance variables:
Long il_pmax  // Max no of pages.
Long il_page  // Current page.

// Add blank lines
ll_max=dw_2.RowCount()
DO UNTIL Mod(ll_max,12)=0

            dw_2.InsertRow(0)
            ll_max++
LOOP

il_pmax=ll_max/12 // Set number of pages
il_page=1

Scoreboard Position
At first, I moved the scoreboard to the rightmost screen using my mouse. This gets old fast, and it is also difficult to completely hide the title bar of the window. Hiding the Title Bar is important to make it look like a real scoreboard.

We needed four buttons to "nudge" the screen up, down, left and right. Then, a "Save" button will store the coordinates in the Registry, so the next time you open the scoreboard, it shows up in the right place. The code for these buttons is in Listing 1.

Networking Scoreboards
The tabulating laptop is hidden inside an office in the skating rink. It turns out that the monitor to display the scoreboard is too far away to use a VGA cable. The solution here was to use the Apache Web server and set up a wireless network.

I installed Apache on the main laptop, and unit tested it. Apache is very easy to install, and you don't have to run Windows XP Pro - it's content to run on Windows XP Home.

Then the Tabulating program had to copy the scoring files to the Apache folder (by default, this is C:\Program Files\Apache Group\Apache2\htdocs.) This is done via a simple FileCopy() function in PowerBuilder. Be aware that you have to set the third argument of FileCopy() to TRUE to replace an existing file.

Then, on another laptop, you run another copy of the same application, and configure it to be a client. It will read from an address such as http://192.168.1.100, using the Microsoft XMLHTTP component. This component lets you read the contents of any Web page, allowing you to write your own "spider" program. Some code that does this reading is in Listing 2.

Overcoming Caching
You might be wondering why the URL has the "r" parameter added. Somewhere, either in Apache or the Microsoft component, the output gets cached. That's a problem because if you update the results file on the server, you keep getting the old version of the file on the client.

By adding a dummy parameter "r" with the value of the current date, you can defeat this caching issue.

Main Logic
The function wf_begin() begins the top-level of looping through a series of events. It reads the "Schedule" datawindow, and the file of judges. Then it calls wf_timer(), which paints the screen for the first page of the first event.

The first thing wf_timer() does is to determine if it needs to "Page Down" - there are more than 12 skaters, and there is an additional page. If so, it does the ScrollNextPage(), increments the page number, and returns.

Next, wf_timer() checks to see if we have finished showing the last event. If so, it calls wf_begin() to start the cycle over. This has to be done using POST to prevent a call loop.

If this is not the last event, wf_timer() will find the next checked event, and calls wf_show(), which actually displays the first page of an event.

Wf_show() is responsible for reading the flat files, and putting the data into both the upper and lower DataWindow. As discussed above, it also adds blank lines if needed so that the upper DataWindow's row count is a multiple of 12, and it calculates the number of pages.

Handling Network Downtime
During the meet, I had to reboot the tabulating laptop. This brought down the Apache server, and put the Scoreboard program at risk. The solution was to add code in the Scoreboard window so that every time it gets data from the Web address, it copied the file into a local Scoreboard directory.

Now, if Apache goes down, the Scoreboard can simply reuse the last copy of its files in the Scoreboard directory.

Bottom Line
When that local contest finally happened, it did take a bit more work: bringing in two laptops, my wireless router, and my 17-inch monitor. But, the results were well worth it. A lot of people watched the scoreboard, and many people now look forward to it.

More Stories By Victor A Reinhart

Victor Reinhart is a PowerBuilder architect and developer at Maintstar.

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.