feat(games): track Reverse: 1999, which resets at 05:00

Adds the r1999 GameId and its metadata, plus GameMeta.resetHourLocal for
the fact that makes it unlike every other game here: it rolls its day at
05:00 server time rather than 04:00, on a single global UTC-5 server, so
its day-key boundary is 10:00 UTC.

resetOffsets could not carry that. Landing 10:00 UTC through the offset
would mean claiming a UTC-6 server, and serverOffsetUtc answers more
questions than this one. The new field overrides RESET_HOUR_LOCAL per game
and is absent everywhere else, so no existing reader's logged day moved —
a test pins that for the games that already had readers.

Both facts are read off the source, not assumed: all 154 rows of the
wiki's event list state (UTC-5) and run 05:00 to 04:59, an event ending
one minute before the reset the next one begins on.

No adapter yet, so the game has no events until one lands.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
Lucas Winther
2026-08-17 22:45:40 +02:00
co-authored by Claude Opus 5
parent 7926a70850
commit 1a65a1f06c
6 changed files with 105 additions and 3 deletions
+19 -1
View File
@@ -137,6 +137,24 @@ export function serverOffsetUtc(region: Region, game?: LaneId): number {
return override ?? REGION_RESET_UTC_OFFSET[region];
}
/**
* The hour of its own server day a game rolls over on.
*
* Almost always `RESET_HOUR_LOCAL`. A game that resets on a different hour says
* so in `resetHourLocal` (`games.ts`) — Reverse: 1999 rolls at 05:00 — and that
* cannot be folded into `serverOffsetUtc`: shifting a game's stated offset to
* land the right reset instant would misreport the server clock to everything
* else that asks for it.
*
* A lane the reader invented has no server to know about and takes the default,
* for the same reason `serverOffsetUtc` does.
*/
export function resetHourFor(game?: LaneId): number {
const override =
game === undefined ? undefined : GAMES[game as GameId]?.resetHourLocal;
return override ?? RESET_HOUR_LOCAL;
}
/**
* Offset from UTC midnight to this game's reset instant.
*
@@ -147,7 +165,7 @@ export function serverOffsetUtc(region: Region, game?: LaneId): number {
* a data change, not a constant.
*/
function shift(region: Region, game?: LaneId): number {
return serverOffsetUtc(region, game) * HOUR - RESET_HOUR_LOCAL * HOUR;
return serverOffsetUtc(region, game) * HOUR - resetHourFor(game) * HOUR;
}
/**