Add persistent player leaderboards from game telemetry

This commit is contained in:
2026-09-18 16:43:44 -04:00
parent 0f55fa5f77
commit a182aeb950
16 changed files with 1135 additions and 17 deletions
+2
View File
@@ -5,6 +5,7 @@ import { config } from '../config.js';
import schemaSql from './schema.sql?raw';
import { requirement, type BetaPlan, type BetaRequirement } from '../../beta-plan.js';
import { emptyMetrics } from '../fleet/beta-evaluation.js';
import { backfillLeaderboard } from '../fleet/leaderboard-ingest.js';
let _db: Database.Database | null = null;
@@ -259,6 +260,7 @@ export function db(): Database.Database {
backfillMultiScriptJoins(handle);
assertSnapshotSchemeSafe(handle);
migrateGameTelemetry(handle);
backfillLeaderboard(handle);
} catch (err) {
handle.close();
throw err;
+50
View File
@@ -6,6 +6,56 @@
PRAGMA journal_mode = WAL;
PRAGMA foreign_keys = ON;
-- Historical gameplay deliberately has no FK to servers: destroying a server
-- must not erase records. Each player's counters are high-water marks per match.
CREATE TABLE IF NOT EXISTS leaderboard_matches (
id INTEGER PRIMARY KEY AUTOINCREMENT,
server TEXT NOT NULL,
game TEXT NOT NULL,
map TEXT NOT NULL,
map_key TEXT NOT NULL,
map_name TEXT NOT NULL,
started_at TEXT NOT NULL,
ended_at TEXT,
last_received_at TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'active', -- active | completed | interrupted
start_observed INTEGER NOT NULL DEFAULT 0,
highest_round INTEGER NOT NULL DEFAULT 0,
last_event TEXT NOT NULL,
last_fingerprint TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_leaderboard_server ON leaderboard_matches(server, id DESC);
CREATE INDEX IF NOT EXISTS idx_leaderboard_map ON leaderboard_matches(game, map_key);
CREATE TABLE IF NOT EXISTS leaderboard_players (
game TEXT NOT NULL,
guid TEXT NOT NULL,
name TEXT NOT NULL,
first_seen_at TEXT NOT NULL,
last_seen_at TEXT NOT NULL,
PRIMARY KEY (game, guid)
);
CREATE TABLE IF NOT EXISTS leaderboard_match_players (
match_id INTEGER NOT NULL REFERENCES leaderboard_matches(id) ON DELETE CASCADE,
guid TEXT NOT NULL,
highest_round INTEGER NOT NULL DEFAULT 0,
rounds_survived INTEGER NOT NULL DEFAULT 0,
kills INTEGER NOT NULL DEFAULT 0,
headshots INTEGER NOT NULL DEFAULT 0,
downs INTEGER NOT NULL DEFAULT 0,
revives INTEGER NOT NULL DEFAULT 0,
best_score INTEGER NOT NULL DEFAULT 0,
last_round INTEGER NOT NULL DEFAULT 0,
present INTEGER NOT NULL DEFAULT 1,
has_stats INTEGER NOT NULL DEFAULT 0,
completed INTEGER NOT NULL DEFAULT 0,
first_seen_at TEXT NOT NULL,
last_seen_at TEXT NOT NULL,
PRIMARY KEY (match_id, guid)
);
CREATE INDEX IF NOT EXISTS idx_leaderboard_player_matches ON leaderboard_match_players(guid, match_id);
CREATE TABLE IF NOT EXISTS servers (
name TEXT PRIMARY KEY,
komodo_type TEXT NOT NULL DEFAULT 'deployment', -- deployment|stack|container