Exclude round one records from match history and statistics
This commit is contained in:
@@ -10,8 +10,8 @@ async function seedRecords() {
|
||||
const { db } = await import('../../src/lib/server/db/index.js');
|
||||
const handle = db();
|
||||
const match = handle.prepare(`INSERT INTO leaderboard_matches
|
||||
(id, server, game, map, map_key, map_name, started_at, last_received_at, status, last_event, last_fingerprint)
|
||||
VALUES (?, 'removed-server', ?, ?, ?, ?, ?, ?, ?, 'round_change', 'test')`);
|
||||
(id, server, game, map, map_key, map_name, started_at, last_received_at, status, highest_round, last_event, last_fingerprint)
|
||||
VALUES (?, 'removed-server', ?, ?, ?, ?, ?, ?, ?, ?, 'round_change', 'test')`);
|
||||
const player = handle.prepare(`INSERT INTO leaderboard_players (game, guid, name, first_seen_at, last_seen_at)
|
||||
VALUES (?, ?, ?, '2026-09-01T00:00:00.000Z', '2026-09-05T00:00:00.000Z')`);
|
||||
const record = handle.prepare(`INSERT INTO leaderboard_match_players
|
||||
@@ -19,12 +19,12 @@ async function seedRecords() {
|
||||
completed, has_stats, first_seen_at, last_seen_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, '2026-09-01T00:00:00.000Z', ?)`);
|
||||
const iso = (day: number) => `2026-09-0${day}T00:00:00.000Z`;
|
||||
match.run(1, 't5', 'zombie_theater', 't5:theater', 'Kino Der Toten', iso(1), iso(2), 'completed');
|
||||
match.run(2, 't5', 'zombie_theater', 't5:theater', 'Kino Der Toten', iso(2), iso(3), 'active');
|
||||
match.run(3, 't5', 'zombie_coast', 't5:coast', 'Call of the Dead', iso(3), iso(4), 'completed');
|
||||
match.run(4, 't6', 'zm_transit', 't6:town', 'Town Survival', iso(4), iso(5), 'completed');
|
||||
match.run(5, 't6', 'zm_transit', 't6:farm', 'Farm Survival', iso(5), iso(6), 'interrupted');
|
||||
match.run(6, 't5', 'custom_map', 't5:custom_map', 'Custom Map', iso(1), iso(7), 'active');
|
||||
match.run(1, 't5', 'zombie_theater', 't5:theater', 'Kino Der Toten', iso(1), iso(2), 'completed', 10);
|
||||
match.run(2, 't5', 'zombie_theater', 't5:theater', 'Kino Der Toten', iso(2), iso(3), 'active', 8);
|
||||
match.run(3, 't5', 'zombie_coast', 't5:coast', 'Call of the Dead', iso(3), iso(4), 'completed', 4);
|
||||
match.run(4, 't6', 'zm_transit', 't6:town', 'Town Survival', iso(4), iso(5), 'completed', 20);
|
||||
match.run(5, 't6', 'zm_transit', 't6:farm', 'Farm Survival', iso(5), iso(6), 'interrupted', 15);
|
||||
match.run(6, 't5', 'custom_map', 't5:custom_map', 'Custom Map', iso(1), iso(7), 'active', 2);
|
||||
player.run('t5', '101', 'Ace');
|
||||
player.run('t5', '202', 'Blake');
|
||||
player.run('t5', '303', 'Casey');
|
||||
@@ -44,6 +44,42 @@ async function seedRecords() {
|
||||
}
|
||||
|
||||
describe('persisted leaderboard queries', () => {
|
||||
it('excludes persisted round 0/1 matches from every history, total, ranking and map option', async () => {
|
||||
const handle = await seedRecords();
|
||||
const { getLeaderboard } = await import('../../src/lib/server/fleet/leaderboard.js');
|
||||
const { getPlayerProfile } = await import('../../src/lib/server/fleet/player-profile.js');
|
||||
const { serverMatchHistory } = await import('../../src/lib/server/fleet/match-history.js');
|
||||
const { leaderboardMetrics } = await import('../../src/lib/leaderboard.js');
|
||||
const boards = leaderboardMetrics.map(({ key }) => getLeaderboard({ metric: key, limit: 2, offset: 1 }));
|
||||
const profile = getPlayerProfile('t5', '101');
|
||||
const history = serverMatchHistory(undefined, 2);
|
||||
const scopedHistory = serverMatchHistory('removed-server', 2);
|
||||
const scopedBoard = getLeaderboard({ game: 't5', map: 't5:theater' });
|
||||
let id = 10;
|
||||
for (const status of ['active', 'completed', 'interrupted']) {
|
||||
for (const round of [0, 1]) {
|
||||
handle.prepare(`INSERT INTO leaderboard_matches
|
||||
(id, server, game, map, map_key, map_name, started_at, last_received_at,
|
||||
status, highest_round, last_event, last_fingerprint)
|
||||
VALUES (?, 'removed-server', 't5', 'reset_map', 't5:reset', 'Reset Map',
|
||||
'2026-09-20', '2026-09-20', ?, ?, 'game_end', 'reset')`).run(id, status, round);
|
||||
// A historical record with large counters must not change rankings or bests.
|
||||
handle.prepare(`INSERT INTO leaderboard_match_players
|
||||
(match_id, guid, highest_round, kills, headshots, revives, downs, best_score,
|
||||
has_stats, completed, first_seen_at, last_seen_at)
|
||||
VALUES (?, '101', ?, 99999, 99999, 99999, 99999, 99999, 1, 1, '2026-09-20', '2026-09-20')`)
|
||||
.run(id++, round);
|
||||
}
|
||||
}
|
||||
expect(leaderboardMetrics.map(({ key }) => getLeaderboard({ metric: key, limit: 2, offset: 1 }))).toEqual(boards);
|
||||
expect(getLeaderboard({ game: 't5', map: 't5:theater' })).toEqual(scopedBoard);
|
||||
expect(getLeaderboard({ map: 't5:reset' })).toMatchObject({ entries: [], total: 0,
|
||||
summary: { players: 0, matches: 0, kills: 0, highestRound: 0, firstTrackedAt: null, updatedAt: null } });
|
||||
expect(getPlayerProfile('t5', '101')).toEqual(profile);
|
||||
expect(serverMatchHistory(undefined, 2)).toEqual(history);
|
||||
expect(serverMatchHistory('removed-server', 2)).toEqual(scopedHistory);
|
||||
});
|
||||
|
||||
it('sums counters across matches, retains personal bests and separates games for the same GUID', async () => {
|
||||
await seedRecords();
|
||||
const { getLeaderboard } = await import('../../src/lib/server/fleet/leaderboard.js');
|
||||
@@ -129,11 +165,11 @@ describe('player profiles', () => {
|
||||
const handle = await seedRecords();
|
||||
for (let id = 10; id < 40; id++) {
|
||||
handle.prepare(`INSERT INTO leaderboard_matches
|
||||
(id, server, game, map, map_key, map_name, started_at, last_received_at, status, last_event, last_fingerprint)
|
||||
SELECT ?, server, game, map, map_key, map_name, started_at, last_received_at, status, last_event, last_fingerprint
|
||||
(id, server, game, map, map_key, map_name, started_at, last_received_at, status, highest_round, last_event, last_fingerprint)
|
||||
SELECT ?, server, game, map, map_key, map_name, started_at, last_received_at, status, highest_round, last_event, last_fingerprint
|
||||
FROM leaderboard_matches WHERE id = 1`).run(id);
|
||||
handle.prepare(`INSERT INTO leaderboard_match_players (match_id, guid, has_stats, first_seen_at, last_seen_at)
|
||||
VALUES (?, '101', 1, '2026-09-01', '2026-09-01')`).run(id);
|
||||
handle.prepare(`INSERT INTO leaderboard_match_players (match_id, guid, has_stats, highest_round, first_seen_at, last_seen_at)
|
||||
VALUES (?, '101', 1, 2, '2026-09-01', '2026-09-01')`).run(id);
|
||||
}
|
||||
const { getPlayerProfile } = await import('../../src/lib/server/fleet/player-profile.js');
|
||||
const first = getPlayerProfile('t5', '101')!;
|
||||
|
||||
Reference in New Issue
Block a user