Store cumulative player scores alongside balances
CI / checks (push) Successful in 6m27s

This commit is contained in:
2026-10-12 13:57:34 -04:00
parent 76325b99ad
commit 6059ebf2a5
12 changed files with 181 additions and 5 deletions
+16 -1
View File
@@ -71,7 +71,21 @@ export function recordLeaderboardTelemetry(
report: GameTelemetry
): { matchId: number; current: boolean } {
if (report.match !== undefined) return recordKeyedTelemetry(handle, report);
return { matchId: recordLegacyTelemetry(handle, report), current: true };
const matchId = recordLegacyTelemetry(handle, report);
saveScoreTotals(handle, report, matchId);
return { matchId, current: true };
}
// Separate from applyReport so the historical version-0 backfill still works
// before the score_total migration. Missing totals never erase known values.
function saveScoreTotals(handle: Database.Database, report: GameTelemetry, matchId: number): void {
if (report.event === 'game_start') return;
const players = report.players.filter((player) => player.score_total !== undefined);
if (!players.length) return;
const save = handle.prepare(`UPDATE leaderboard_match_players
SET score_total = MAX(COALESCE(score_total, 0), ?)
WHERE match_id = ? AND guid = ?`);
for (const player of players) save.run(player.score_total, matchId, player.guid);
}
// Also used by the version-0 snapshot backfill, before keyed schema exists.
@@ -325,6 +339,7 @@ function recordKeyedTelemetry(
.get(report.server) as { id: number } | undefined;
result.current = latest?.id === match.id && match.server_deleted_at === null;
}
if (applied) saveScoreTotals(handle, report, match.id);
if (applied && report.seq !== undefined) {
handle
.prepare(
+1
View File
@@ -125,6 +125,7 @@ export function getMatchDetail(id: number): MatchDetail | null {
CASE WHEN p.has_stats = 1 THEN p.downs END AS downs,
CASE WHEN p.has_stats = 1 THEN p.revives END AS revives,
CASE WHEN p.has_stats = 1 THEN p.best_score END AS bestScore,
p.score_total AS scoreTotal,
EXISTS (SELECT 1 FROM leaderboard_players identity
WHERE identity.guid = p.guid AND identity.game IN ('t5', 't6')) AS canViewProfile
FROM leaderboard_match_players p WHERE p.match_id = ?