Fix game timer: cycle-key tracking, wall-clock only, active gate

games_sp.log is not wiped on restart, so old J; lines from prior
sessions were poisoning the anchor. Now the scanner walks the tail
backward to the LATEST InitGame and only considers lines after it,
returning an opaque cycle key (the first J; line) plus a state. The
worker stamps game_started_at/ended_at with Date.now() at observation
time instead of inferring from the log's own timestamps. Same-players
game restarts produce a new key and cleanly re-anchor. When the server
transitions to 0 players, game state is cleared server-side and the
UI also gates the timer display on activeSince.

Adds servers.game_cycle_key column with additive migration.
This commit is contained in:
2026-09-13 22:47:03 -04:00
parent 8186bb1ccc
commit efd4a4fa66
7 changed files with 87 additions and 97 deletions
+4 -1
View File
@@ -180,7 +180,10 @@
);
let activeElapsed = $derived(effectiveActiveSince ? elapsedSince(effectiveActiveSince, $uiNow) : null);
let inactiveElapsed = $derived(effectiveInactiveSince ? elapsedSince(effectiveInactiveSince, $uiNow) : null);
let gameInProgress = $derived(!!effectiveGameStartedAt && !effectiveGameEndedAt);
// Game timer only runs while active — see ServerCard.svelte.
let gameInProgress = $derived(
!!effectiveGameStartedAt && !effectiveGameEndedAt && !!effectiveActiveSince
);
let gameElapsed = $derived(gameInProgress ? elapsedSince(effectiveGameStartedAt, $uiNow) : null);
let showTiming = $derived(
effectiveHealth !== 'offline' &&