This commit is contained in:
@@ -25,46 +25,55 @@ export function saveTelemetry(report: GameTelemetry): GameTelemetry {
|
||||
? JSON.parse(row.payload)
|
||||
: undefined;
|
||||
recordLeaderboardTelemetry(handle, report);
|
||||
// Record each occupancy transition at receipt, before a heartbeat can
|
||||
// replace game_start or an empty report between status polls.
|
||||
const after = latestGameSubmission(report.server);
|
||||
if (!after || Date.parse(report.receivedAt) > Date.parse(after)) {
|
||||
if (report.players.length > 0) {
|
||||
handle
|
||||
.prepare(
|
||||
'UPDATE servers SET active_since = COALESCE(active_since, ?), inactive_since = NULL WHERE name = ?'
|
||||
)
|
||||
.run(report.receivedAt, report.server);
|
||||
if (report.event === 'game_start') {
|
||||
handle
|
||||
.prepare(
|
||||
'UPDATE servers SET game_started_at = ?, game_ended_at = NULL WHERE name = ?'
|
||||
)
|
||||
.run(report.receivedAt, report.server);
|
||||
} else if (report.event === 'game_end') {
|
||||
handle
|
||||
.prepare('UPDATE servers SET game_ended_at = ? WHERE name = ?')
|
||||
.run(report.receivedAt, report.server);
|
||||
}
|
||||
} else {
|
||||
handle
|
||||
.prepare(
|
||||
`UPDATE servers SET active_since = NULL, inactive_since = COALESCE(inactive_since, ?),
|
||||
game_started_at = NULL, game_ended_at = NULL WHERE name = ?`
|
||||
)
|
||||
.run(report.receivedAt, report.server);
|
||||
}
|
||||
}
|
||||
const match = handle
|
||||
.prepare(
|
||||
'SELECT id, started_at, start_observed FROM leaderboard_matches WHERE server = ? ORDER BY id DESC LIMIT 1'
|
||||
)
|
||||
.get(report.server) as { id: number; started_at: string; start_observed: number };
|
||||
const sameMatch = previous?.timing?.matchId === match.id;
|
||||
const serverTiming = handle
|
||||
.prepare(
|
||||
`SELECT active_since AS activeSince, inactive_since AS inactiveSince,
|
||||
game_started_at AS gameStartedAt, game_ended_at AS gameEndedAt FROM servers WHERE name = ?`
|
||||
)
|
||||
.get(report.server) as ServerTiming;
|
||||
const match = handle
|
||||
.prepare('SELECT id FROM leaderboard_matches WHERE server = ? ORDER BY id DESC LIMIT 1')
|
||||
.get(report.server) as { id: number };
|
||||
const sameMatch = previous?.timing?.matchId === match.id;
|
||||
// Record each occupancy transition at receipt, before a heartbeat can
|
||||
// replace game_start or an empty report between status polls.
|
||||
const after = latestGameSubmission(report.server);
|
||||
if (!after || Date.parse(report.receivedAt) > Date.parse(after)) {
|
||||
const occupied = report.players.length > 0;
|
||||
serverTiming.activeSince = occupied
|
||||
? (serverTiming.activeSince ?? report.receivedAt)
|
||||
: null;
|
||||
serverTiming.inactiveSince = occupied
|
||||
? null
|
||||
: (serverTiming.inactiveSince ?? report.receivedAt);
|
||||
// Match boundaries follow history, independently of roster occupancy.
|
||||
// Recover starts discarded by older receivers only when a start was
|
||||
// actually observed; an inferred match has no known start time.
|
||||
const startedAt =
|
||||
report.event === 'game_start'
|
||||
? report.receivedAt
|
||||
: ((sameMatch ? serverTiming.gameStartedAt : null) ??
|
||||
(match.start_observed ? match.started_at : null));
|
||||
serverTiming.gameStartedAt =
|
||||
startedAt && (!after || Date.parse(startedAt) > Date.parse(after))
|
||||
? startedAt
|
||||
: null;
|
||||
serverTiming.gameEndedAt = report.event === 'game_end' ? report.receivedAt : null;
|
||||
handle
|
||||
.prepare(
|
||||
`UPDATE servers SET active_since = ?, inactive_since = ?,
|
||||
game_started_at = ?, game_ended_at = ? WHERE name = ?`
|
||||
)
|
||||
.run(
|
||||
serverTiming.activeSince,
|
||||
serverTiming.inactiveSince,
|
||||
serverTiming.gameStartedAt,
|
||||
serverTiming.gameEndedAt,
|
||||
report.server
|
||||
);
|
||||
}
|
||||
// A gap beyond the normal heartbeat window cannot establish continuity.
|
||||
const continuous =
|
||||
previous && Date.parse(report.receivedAt) - Date.parse(previous.receivedAt) <= 120_000;
|
||||
|
||||
Reference in New Issue
Block a user