Section 4.5 - Race timing - details
Finally we reach the details about the Timing window. When loading the Timing window, you will have to specify:
- The timing dictionary. This is the file generated by the Compile window that allows fsTimer to look up name, age, and gender by bib ID. It will be named project_name_timing_dict.json, unless you specifically renamed it.
- A "pass" ID. As explained previously, when the pass ID is given to a time, it leaves that time out of the results, essentially blanking it out. It also acts as a placeholder for times that will be later corrected, as described in Section 3.1.
- The key for marking times. We generally use spacebar, but you can also use period or forward slash. It is important that whatever key you use it is not contained in any of the bib IDs! For instance, if the bib IDs are "A 01", "B 02", etc., with a space actually in the ID, then you should not use spacebar to mark times.
- It is possible to strip leading zeros from IDs as they are recorded, for example, if 021 is scanned or entered, then the ID that is actually recorded is 21. If this feature is selected, then it is important that the IDs in the registration database do not have leading zeros. I think it unlikely that you would use this feature.
- If it is a multiple lap race, and if so, the number of laps. The lap timing mode will be discussed below.
Once these have been specified, the timing window loads.
Entering and editing times
The first thing you will do in a race will be to press "Start!" at the exact moment that the race begins. This starts the clock ticking (of course, in reality it uses the system clock which is always "ticking") and all marked times will be recorded relative to this moment. When you press "Start!", to the right of that button is "t0:" and a very long number will appear after that. This long number is the starting time for the race, given in seconds since the Unix epoch began. What that means isn't really important.

Pressing the "Edit" button next to the "Start!" button will allow you to change the t0, to adjust the start time for the race. Exercise caution doing this, as the old time is not saved and this change cannot be (automatically) undone. It is very unlikely that you will ever need to modify the start time, but if you do, then simply add or subtract to the large t0 number the number of seconds that you wish to change the start time by. For the image above, if we wanted to move the start time to be 5 minutes earlier, then we would subtract 300 seconds from the t0 and change it to be 1395622297.15. It is important to note that fsTimer records all times relative to this t0 start time. If you change t0 mid-race, it will
not adjust any times that have already been recorded.
At the bottom of the window in the screenshot above it says "0 racers checked in out of 10 registered." The 10 registered are the number of unique IDs in the timing dictionary. This will generally be the number of people registered for the race, but can differ from the actual number if, for instance, there were overloaded IDs that were de-assigned during compilation. It can also differ from the actual number of racers on the course if there are racers who register and pick up a bib (and thus are in the timing dictionary), but don't end up running the race. As you check in racers (by entering their bib numbers into the timing window), if the bib number is one of those in the timing dictionary, then the number at the bottom of the window will increment.
All of the tasks related to the timing process take place in the entrybox at the bottom of the window. Make sure that you have clicked in that entrybox, otherwise any input (like pressing spacebar to mark a time, or entering a bib ID) will not be recognized.
Pressing spacebar (or whichever key you chose for marking times when opening the Timing window) will record the current time (relative to the Start! time) as a blank time in the window. The time is listed as hr:min:sec, and the "ID" column will be blank. As multiple times are marked, they will be recorded in their proper order.

This is the stack of marked times, and their corresponding bib IDs must be entered (although there is no hurry; as long as the record of bib IDs stays synchronized with the list of marked times, you can enter them all in at your convenience). In our suggested finish line design in
Section 3.1, Crew 2 is the individual entering the times. Bib IDs are entered by typing them into the entrybox (the same one that must be selected to mark times) and pressing Enter. Note that if you use a USB barcode scanner, then the default behavior of most (all?) USB barcode scanners is to type whatever is in the barcode followed by Enter, so the software will work very naturally with a barcode scanner. Entering "109" will assign that bib ID to the oldest time that has not yet been assigned an ID:

Thus as long as the bib IDs are entered in the same order that they crossed the finish line, they will be correlated with their correct marked times. Entering "101" and "110" fills in the IDs for the next two times:

If an ID is entered and there aren't any "blank" times available, it will just be added to the stack of bib IDs and the next marked time will be assigned to it. Here we have entered "102" without any un-assigned marked times, so the time is left blank but will be filled in with the next time that is marked:

Marked times can also always be filled with the pass ID (we usually choose 0) the same way it would be assigned to a bib ID:

As a note, if you just hit Enter without anything entered into the entrybox, then it will do a usual ID entry where the ID is a blank string ''. Blank IDs are not included in the results printouts (they behave in the same way as the pass ID).
The "Edit" button on the right side of the window allows you to edit the ID and/or time of any of the marked times. For instance, suppose one of the pass IDs used in the above screenshot was a placeholder for a runner whose bib ID could not be obtained immediately (see
Section 3.1 for some situations where you might want to do this). We can later go back and replace the pass ID (the 0) with his true ID by pressing "Edit", and replacing "0" with his true ID:

As the red warning states, you should exercise extreme caution when making these edits, as they cannot be undone if you forget the original values.
There are actually two editing modes in the timing window. The first is shown above, when a single entry is selected and "Edit" is pressed. Then, the ID and time of that entry can be modified as desired. Alternative, an entire block of times can be modified together. This is accomplished by selecting the block of times (using shift) and pressing "Edit":

The block edit window allows for all of the selected times to be adjusted forward or backwards by a certain amount of time. In the screenshot above, pressing "OK" will add 25 seconds to all of the times:

The "Drop ID" and "Drop time" functionalities drop the ID (or, respectively, time) from the selected row, and shift all IDs (resp. times) downward to match. This is useful for keeping the ID stack and the times stack properly synced, for instance, if an ID was accidentally entered twice, or spacebar was accidentally hit twice. Consider the following example, where the ID "109" was erroneously entered twice:

Due to this error, there is one more ID in the ID stack than there are times in the time stack (the stacks are out of sync). Selecting the 2nd "109" and pressing "Drop ID" yields:

After pressing "Yes," the results are corrected:

"Drop time" performs the same function, but on the stack of times. Exercise extreme caution when dropping IDs or times, as this cannot be automatically undone.
Saving and printing results
The "Save" button on the right saves the results (t0, times, and bib IDs) to a file whose name will include the date and time that the Timing window was opened (this way, results will never be accidentally overwritten if you open the Timing window at another time). If the Timing window was opened on Jun 1, 2013 at 2:10pm and 30 seconds, then the results are saved to a file project_name_Sat_Jun_1_141030_2013_times.json.
It is a good idea to save periodically during timing in case something catastrophic happens (like the computer dies), however keep in mind that any time the entrybox in the timing window is not selected (for instance, because you have used the mouse to press the "Save" button), no times may be marked and no IDs may be entered, until the mouse has moved back to select the entrybox. In our suggested finish line setup (
Section 3.1), Crew 1 is operating the computer while Crew 2 enters the bib IDs with the barcode scanner. Crew 1 would need to tell Crew 2 to stop scanning for the period of time it takes to save, and then to resume when the entrybox has been reselected.
If you need to reload the results in the Timing window (for instance, to re-print the results after making edits to the registration database), then the "Resume" button is used to load a previously saved results file. You would press Resume, and then load the previously saved file (project_name_Sat_Jun_1_141030_2013_times.json above). Keep in mind that "Resume" will load the marked times, the bib IDs assigned to them, and the Start time. It will not load the timing dictionary (this will still be whatever was selected when opening the Timing window), which allows you to make edits to the timing dictionary, and then re-load the times. We'll give some more details about this later below.
Finally, the "Print" button automatically generates nicely formatted results printouts. As mentioned in
Section 2.5, it does not physically print the results, rather it saves them (the overall results and the divisional results) as html files in the project directory. These html files can then be opened in any web browser and printed from there. The actual filenames will again incorporate the date and time at which the Timing window was opened, so as to not be automatically overwritten by a later session in which the Timing window is opened. With the same date and time as above, the filenames would be project_name_Sat_Jun_1_141030_2013_alltimes.html for the overall results and project_name_Sat_Jun_1_141030_2013_divtimes.html for the divisional results.
We will now describe the results for a single-lap race. After this, we will describe how lap timing works.
The overall results might look like this:

The results will automatically be sorted into places, and the name, age, and gender will be filled in from the timing dictionary. If some information is blank in the database, this is not a problem; it will simply be left blank in the results. For example, 5th place in the screenshot above (bib 128) had a blank name in the database, so the name is left blank in the results. 4th place (bib 101) had a blank gender in the database, so it is blank in the results. Notice also bibs 110 and 120. These were the overloaded IDs from
Section 4.4 that were left unassigned to any particular racer. They still show up in the results, however they do not have any name/age/gender associated with them. The same will be true for any bib that is not in the registration database, for example, if someone shows up after registration has closed but is given a bib anyway and runs the race.
Notice also that the "pass" IDs (0) do not show up in the results. Any times with pass IDs will be ignored when creating the results.
A final note about the overall results: If, for whatever reason, a bib ID is entered twice (and thus associated with two times), the results will use only the faster of the times. Note that this is
not the case for lap timing.
The divisional times are automatically generated using the registration information in the timing dictionary, and the divisions specified when creating the new project. The printed results will look something like this:

Because the divisions are defined by age and gender, notice that any IDs that do not have both age and gender in the timing dictionary will be left out of the divisional results. From two screenshots up, bibs 109, 110, 101, 120, and 103 do not have complete gender and age information and so are left out of the divisional results. (In a normal race setting, there will usually not be very many entries missing age and gender information - this will usually only happen if there are errors from the people entering information at the registration table, or for individuals that showed up after registration had already closed and were just handed bibs without being entered into fsTimer).
If there are not so many fields that they won't fit in one page, all of the fields used in the divisions will be shown as columns on the divisional results. The "fit in one page" is calculated only using the titles of the fields used in divisionals, so if you find that the results are not fitting nicely in one page, it is probably because some of the options for the combobox are very long - try making them shorter, or use the CSV file from below.
The "Save CSV" button will save the same results (all times, and divisional times) to CSV files. The names will be the same as the html files, except the extension. All of the columns used in divisions (regardless of number or length) will be included in the CSV dump.
Lap timing
When the "Multiple laps?" checkbox is selected, fsTimer can be used for lap timing. For lap timing, the time must be marked at the end of every lap. For example, below all of the racers except 7 have completed 2 laps:

Unlike in the single-lap case, here we track all of the times for which an ID is associated. When results are printed, we include both the lap times and the total time, computed using the number of laps that were specified when loading the timing window. In the results below, the number of laps was previously specified as 2:

Results are sorted by total time. Any IDs that do not have exactly the correct number of laps (in this case 2) will not have their total time listed, because it would not make sense to compare times from different numbers of laps. In the above example, we only timed one lap from racer number 7, and so that racer is not given a total time or place in the final results.
Making corrections to results
We will now briefly discuss making corrections to the results, which can typically only be done after the race has finished.
As mentioned above, times and their associated bib IDs can be edited using the "Edit" button in the timing window. You can edit times so that they are no longer in order in the window, like 1 in the screenshot below, and this is not a problem; fsTimer will correctly sort them when generating the results printouts:

When editing times, it is important to keep the leading 0 ("0:22:37" instead of "22:37") or the results will not sort correctly.
Making corrections to anything other than bib IDs and times will require a few more steps. Some examples of the types of corrections you might want to make are:
- You identified the people with the overloaded IDs, and want to correctly add their bib IDs to their registration entries so that they show up in the divisional results.
- You want to add in name/age/gender information for individuals who showed up after registration had closed, but were given bibs and ran anyway.
- An individual has the wrong gender in the registration database (this is an unfortunately common data entry error - make the registration volunteers triple check this!) and so they show up in the wrong divisionals.
- The name and/or age are wrong.
Correcting all of these errors requires making edits to the registration database, which requires leaving the timing window. The following is the procedure you would follow:
- Save the timing results by pressing "Save" in the Timing window.
- Leave the timing window by pressing "Done".
- Open the Registration window. Choose a registration number that was not used by any of the registration computers (e.g., 99). For the "pre-registration", select the compiled registration (project_name_registration_compiled.json). This loads the complete, compiled registration database into the Registration window where you can easily make edits.
- Make all necessary edits to the registration database entries. Save the results. If you chose 99 as the registration number, the results are saved as project_name_registration_99.json.
- Close the Registration window, and open the Compile window to compile the new registration database (project_name_registration_99.json). This will generate a new timing dictionary that contains the corrected information.
- Open the Timing window. Select the new, corrected timing dictionary.
- Click "Resume" and select the previously saved timing results. When the results have been loaded, press "Print" and the new printouts will use the corrected timing dictionary and thus will have the corrected name/age/gender information.
When all necessary corrections have been made, the whole timing process is finished!
This completes all of the details about using fsTimer - You are now ready to time the race! The next section contains details about the source code that will be useful only for those who are interested in modifying the code. Do not bother with that section unless you are planning to do actual coding on fsTimer.
Continue on to
Additional details for developers.