Timekeeping for Fighting Robots

Table of Contents

Why Write Something Custom?

In short, the reason I architected something custom over something that existed was a desire for an easier time running an event. Even the tools that exist now to make our lives easier are still full of rough edges.

Even if I wanted to ignore that train of thought, it's easier to advocate for an institution when it feels they value you, and vice versa! Building something to specifically address the needs competitors have is one way I could show that.

Why Not Use Custom Hardware / Electronics / PCBs

GSCRL used to! The previous solution was somewhat tedious and had a number of rough edges for both iteration and use. What rough edges, you might ask? let me iterate some of them.

This encouraged us to find something else, and I opted for a browser-based solution. Chromebooks and small form factor tablet PCs are astonishingly inexpensive, and can be replaced without the need to get bespoke hardware. Additionally, it let us rearrange physically by simply using a different length ethernet cord.

In short?

Hardware is time consuming and expensive to update, software is cheaper and easier to evolve. If someone else wants to go down the route I did prior, PCBs and code for the old arena controls can be obtained here.[H-1][H-2]

A photo of work-in-progress hardware mid-way through iteration of a standalone hardware controller (ESP32 powered.)

So what does it need to do?

Choices

Using Bracketeer

Bracketeer, a tool for those who bracket (running the tournament matches) has a few major viewmodes, all of which were made to help users save time and effort.

Home menu of Bracketeer as a tool.

Painpoint 1 - Queueing

A major pain point for this and other robot sports alike is knowing how much time you have before you are next actively in a match. This is sometimes called "turnaround time" in other sports, but for competitors "late or not" was what it usually became at events.

TrueFinals, the bracketing software GSCRL now uses, handles a decent portion of match and event flow information for us, but it has rough edges. The largest rough edge was viewing and updating more than one "tournament" at a time.

As GSCRL events involve multiple weightclasses[H-3], without all views trivially accessible, competitors would often ask their point of contact for queueing, a volunteer, and interrupt her entry of the paper scorecards. Addressing this interruption, was therefore important.

An example of what the preview would look like on a high resolution screen at tournaments prior, something we didn't have.

As such, we'd prioritized a visible, information-dense view that can be viewed from anywhere on the arena network. Whether or not a competitor was late for a match was color-coded, so it was visible at a distance. Only the information needed would make it to this screen.

By making the upcoming matches easy to see, and how long they'd been aware of said match, and all competitors are able to manage their own timelines without asking other volunteers or competitors. It saves everyone time, frustration, and effort.

Bracketeer's queueing screen. There's also a simpler variant that only has the upcoming matches, for increased visibility at a distance.

Painpoint 2 - Match Control

We previously stated that a major criteria of bracketeer is that it needs to be able to run more than one arena easily. This is where the Match Control page comes in.

While many events only run one arena, GSCRL opts to run two sometimes due to the number of competitors. Audio callouts for match duration can be difficult to hear and even be conflated between the two.

As such, the timer controls for each arena can be delegated to a referee, judge, or production volunteer, minimizing the risk of one arena's timer being conflated for another.

The layout the arena controller or production volunteer uses, and makes their life easier.

The left pane is for timer controls, starting, stopping, or manually setting the match timer. by default there's a countdown built in from 3 to 0 seconds, and then 150 seconds of match play, with optional warning sounds played on stream and via the arena screens specifically.

The message box also allows for custom information to be rendered on the timer displays for competitors, enabling things like "matches resume at 1PM" to be said.

The sound test, hide timer, set cage unsafe, and set cage safe buttons are all shorthand for items that can be done otherwise with the menu tools present.

The right pane however, has some novelty and minutae that can at a glance give production crew better information faster.

Taking inspiration from the Queueing screen, the list of upcoming matches is visible, as well as hyperlinks to the competitor's path through the tournament so far. This enables any announcers or emcees to have easier access to the data they might need or want to help build an entertaining narrative.[A-1]

If the time since match was called is under 20 minutes, it's in orange. If it's marked as active or past the 20 minute buffer time, it turns red and shows a danger glyph next to it.

Painpoint 3 - Iteration Speed

Because of the architectural choices previously mentioned, iteration didn't involve an enormous volunteer lift. Some competitors opted to not use the tap-out button due to touch screen inconsistencies, so I disabled the button and informed teams to avoid am inconsistent potential safety feature.

The judges occasionally found it difficult to identify which robot was named as such, so the robot name as sent to the judges view and the competitor's view.

The above changes would not have been able to be facilitated if we'd as a league stuck with a microcontroller-derived timer solution.

A photo of the screens being live-iterated at the production desk during an event.

Painpoint N+1 - Quirks

Despite quite a few iterations of software, there exist some quirks in how Bracketeer ingests and handles data.

Notably, the quirks exist in the control page, and with how TrueFinals data is retrieved.

Quirk 1 - Rate Exhaustion

It's possible for repeatedly polling the TrueFinals API to cause rate limit exhaustion. The naive (but functional) resolution was to make a least-recently used cache that validates whether the rate limit is exhausted or not yet, and potentially returns (intentionally) stale data matching that endpoint to avoid any malformed data rendering or crashes.

At the time, I had no way of knowing the server crashing was due to rate limiting as it wasn't included in the TrueFinals' API Docs. After a quick chat with Tom (the developer of TrueFinals), he'd told me that information on how exhausted the rate limit was could be found in response headers.[A-2]

    
'x-ratelimit-limit': '10',
'x-ratelimit-remaining': '8',
'x-ratelimit-reset': '1736225420000',
'x-vercel-cache': 'MISS', 
'x-vercel-id': ' [ removed ]',
'transfer-encoding': 'chunked'

Quirk 2 - Timer Errata

The other major architectural decision that has quirky behavior is how the timer itself functions.

Network determinism is a difficult thing to figure out. Modern networking is resilient, but consistent and low latency packet transmission is sometimes difficult. If running Bracketeer via Wi-Fi and not Ethernet, sluggish Wi-Fi may cause the timer visible to competitors to "jump."

(Potential) Resolution 2

In the future, I'd love to move the timer to a per-client basis with remote controls (start/stop/jitter calculations borrowed from NTP) sent via the socket.io connection. As of yet though (2025/02/12), that work hasn't been done.

Debug Tools

Hidden in Bracketeer's codebase include some tools that I use to evaluate functionality and status (and while subject to change, may be interesting), like the clients page (showing all current socket.io clients and their open location) or the requests cache view (showing the last requests as internal to the database of the running server.)

The Setup As It Is

While there exist quite a few places I'd like to keep evolving Bracketeer as my skillset grows, moving from Philadelphia to Chicago has inevitably put a small damper on things. Until I get involved in a more local league (MRCA for example) it's unlikely I'll spend the time and effort on Bracketeer.

Some of those low-hanging fruit, you might ask? Well:

Right now any league can take the code we've put together and use it for their own league. The quirks mentioned before still do apply, but it's also open-source. Anyone can contribute and pull-requests are welcome.


Personal Aside

Thank you to everyone at GSCRL and at FUBAR Labs for letting me tinker and grow with the league. It's been an honor working with you, and I can't wait to see what y'all come up with next.


References