A basketball tournament every day, with games that tip off on a schedule and play live
Every day the league now plays a tournament. Sixteen teams are drawn into a bracket, and its fifteen games tip off one after another through the day, on Eastern time, ending with the final at 9 pm. The front page lists today's games and when each one starts.
When a game's time comes, its page plays it live: the clock on the page runs with the real clock, and a visitor who arrives late joins at the moment the game has reached, not at the start.
Decided ahead, revealed by the clock
Every game in the league is a function of its seed: the same seed and the same engine always play the same game, down to every step and shot. So a day's games are played when the site is built, and the page reveals each one from its tip-off. The site is plain files, which means the future is in those files for anyone who goes looking. What the page itself does is keep the story in order: an upcoming game shows only when it tips off, a live game cannot be skipped past the moment it has reached (its clock is held to the real time since tip-off, whatever the scrubber is dragged to), and a result and the next round's teams appear only once the game that decides them has ended. After a game ends it can be watched freely from the start.
const clamp = (t, h, edge = h.end) => Math.min(h.end, edge, Math.max(0, t));
A schedule on the wall clock
The games are spaced 48 minutes apart, back to back, so the first tips off at 9:48 in the morning and the final at 9 pm, Eastern. The schedule is kept in Eastern wall-clock time rather than a fixed offset from UTC, because 9 pm Eastern moves by an hour in UTC when the clocks change. Every game falls between 9:48 and 9 pm, so neither clock change, which happens at 2 in the morning, can land inside one, and tests pin both days.
A day never changes once it is shown
The engine keeps changing as the simulation grows. A day that has started, or is over, is kept exactly as it was played, under the engine version that played it, so a result someone has already seen never changes after the fact. A day ahead is played again if the engine moved before it began. Each build plays the next few days ahead, so there is no job running on a timer to keep the tournament going, and a day that was never played is never made up after the fact. Days older than a week leave the site.
Shared once, not copied fifteen times
Each game used to carry its own copy of the 3-D player and its library, 19 files a game. Now the player and the library are held once for the whole site, and a game's folder holds only its page, its recorded game and its results: 8 files (the page, the recorded game, its result and five results files). The host allows a fixed number of files per version of the site, so that change is what makes room for a new tournament every day.