Files
electric-cherry/src/lib/match-history.ts
T

63 lines
1.9 KiB
TypeScript

import type { ContextualChatEntry } from './game-chat.js';
// Reset/abandoned games at round 1 do not qualify as gameplay records.
export const MIN_RECORDED_ROUND = 2;
export interface ServerMatch {
id: number;
game: string;
observedRound: number | null;
server: string;
server_deleted_at?: string | null;
map: string;
startedAt: string;
lastReportedAt: string | null;
endedAt: string | null;
status: 'active' | 'completed' | 'interrupted' | 'end-report-missing';
reporterMatchKey: string | null;
// Unknown without sequence reports; otherwise gaps through the highest received sequence.
missingReports: number | null;
startPlayers: number | null;
uniquePlayers: number;
endPlayers: number | null;
durationMs: number | null;
finalRound: number | null;
}
export interface MatchPlayer {
guid: string;
name: string;
hasStats: boolean;
presentAtEnd: boolean;
canViewProfile: boolean;
firstSeenAt: string;
lastSeenAt: string;
// Combat counters and score are the highest reported values; rounds survived
// counts observed progression. These are not a final scoreboard snapshot.
// A player seen only at game_start has no observed gameplay stats.
highestRound: number | null;
roundsSurvived: number | null;
kills: number | null;
headshots: number | null;
downs: number | null;
revives: number | null;
bestScore: number | null;
/** Highest reported cumulative match score; null when the reporter omitted it. */
scoreTotal: number | null;
}
export interface MatchDetail extends ServerMatch {
game: string;
startObserved: boolean;
players: MatchPlayer[];
chat: ContextualChatEntry[];
}
export interface MatchHistoryResponse {
matches: ServerMatch[];
total: number;
page: number;
limit: number;
maps: Array<{ key: string; name: string; game: string }>;
}