Showing World Cup scores correctly with JavaScript — at 1am in the morning

I’m not a soccer fan. But last night I learnt a couple of things about soccer, JavaScript and how mistakes are made when people are tired.

A brief background…

Odds.com.au is a website that helps people find the best betting-odds for different sporting events. The site uses AWS infrastructure to get score data and store it in a database. It also sends events via Pusher to webpages that are already loaded in a browser, which allows us to update the score without refreshing the page (or polling an API).

A problem with distributed architectures is that they are difficult to test end-to-end. I had tested all of the individual components, and checked that the outputs of “component A” would be successfully handled by “component B” (and so-on down the line), but had never seen it all work “in the wild”.

Tonight was the night.

10pm

Before going to bed, I thought I’d better check what time the first World Cup 2018 match starts in Melbourne, Australia (where I live). A quick Google took me to the SBS website where they confirmed the match started at 1:00am. So I set my alarm and went to sleep.

1:15am

The alarm goes off. In a state of confusion, I reach for the phone and turn off the alarm. FaceID™️ isn’t great when you are squinting at your phone due to the brightness of the screen. Opening my phone’s browser, I see this:

12 minutes in, 0–0, but Gazinskiy 12" ???

“Looks like the site isn’t working”, I thought. But I was confused. It seemed odd to me that “Gazinskiy” was showing on the screen but the score was 0–0. A few moments later, it also occurred to me that the webpage looked different to how I remembered it. “Maybe it’s just the mobile view”. So I got out of bed to check on my laptop….

1:20am

With the laptop open, I was pleasantly surprised to see this:

(not actually a laptop screenshot, but representative of the desktop view)

Russia had scored, and the score was showing! Then it dawned on me — I’d been looking at the SBS website on my phone! So their website was broken, not ours. Relief… but why wasn’t there a score for Saudi Arabia?

1:25am

After some investigation, I noticed this JavaScript code in the web component that was responsible for rendering scores:

What could possibl-i go wrong?

Hmmm… the AWS logs indicated we were sending the scores correctly for both teams (1 and 0 respectively, at that point in time). Can you spot the problem?

Zero-hour

JavaScript has a “feature” whereby it allows values to be cast to boolean-values. Values like "foo", 1, 200, {}, [] are considered true by JavaScript, but “blank” values — "", undefined, null, 0 are considered false.

So the reason why Saudi Arabia’s score wasn’t showing was because this expression score && viewportWidth >= 760 evaluates to false because score was 0. Hence, the {{score}} template value was never rendered.

The solution to this problem is to explicitly check for the no-scores-value, which is null in our case:

Yep, works perfectly.

You can see the result of the changes here, or below:

Back to bed

After waiting for a few more minutes to see the score change from 1-<blank> to 2-<blank> (because the code changes above were not-yet live (but they are now)), I was confident that live-scores were working end-to-end.

In Summary

  1. Live scores for AFL, NRL and soccer (football) are working correctly on www.odds.com.au.
  2. It’s quite common to have zero-scores in soccer (so we should have checked this before going live 😬).
  3. It’s good to know how JavaScript will convert non-boolean values to booleans, as not all “falsey” values are equivalent in every context (e.g. null and 0).
  4. Mistakes will be made when people are tired. Even by the SBS team. 😉