import { describe, expect, it } from 'vitest'; import type { PlayerStats } from '../../src/lib/leaderboard.js'; import { EFFICIENCY_MIN_DOWNS, EFFICIENCY_MIN_GAMES, EFFICIENCY_MIN_KILLS, efficiencyEligible, efficiencyMetrics, efficiencyRequirement, efficiencySample, efficiencyValue, isEfficiencyMetric, type EfficiencyMetric } from '../../src/lib/leaderboard-efficiency.js'; const stats = (overrides: Partial = {}): PlayerStats => ({ highestRound: 20, kills: 100, roundsSurvived: 47, headshots: 31, revives: 7, downs: 5, gamesPlayed: 5, gamesCompleted: 3, bestKills: 50, bestScore: 12000, ...overrides }); describe('efficiency ranking qualification', () => { it.each(efficiencyMetrics)( 'requires five ended games for $key even when other counters are large', ({ key }) => { expect( efficiencyEligible( stats({ gamesPlayed: EFFICIENCY_MIN_GAMES - 1, kills: 10000, downs: 100 }), key ) ).toBe(false); expect(efficiencyEligible(stats({ gamesPlayed: EFFICIENCY_MIN_GAMES }), key)).toBe( true ); } ); it('requires enough kills for headshot rate and enough downs for kills per down', () => { expect(efficiencyEligible(stats({ kills: EFFICIENCY_MIN_KILLS - 1 }), 'headshotRate')).toBe( false ); expect(efficiencyEligible(stats({ kills: EFFICIENCY_MIN_KILLS }), 'headshotRate')).toBe( true ); expect(efficiencyEligible(stats({ downs: EFFICIENCY_MIN_DOWNS - 1 }), 'killsPerDown')).toBe( false ); expect(efficiencyEligible(stats({ downs: EFFICIENCY_MIN_DOWNS }), 'killsPerDown')).toBe( true ); expect(efficiencyEligible(stats({ kills: 0 }), 'killsPerDown')).toBe(true); }); it('counts departed players in ended-game samples and applies no extra counter minimum to game averages', () => { const departed = stats({ kills: 0, headshots: 0, downs: 0, roundsSurvived: 0, gamesCompleted: 0 }); for (const metric of ['averageKills', 'averageRounds', 'completionRate'] as const) { expect(efficiencyEligible(departed, metric)).toBe(true); expect(efficiencyValue(departed, metric)).toBe(0); } expect( efficiencyValue(stats({ gamesPlayed: 5, gamesCompleted: 3 }), 'completionRate') ).toBe(3 / 5); }); }); describe('efficiency values', () => { it.each([ ['headshotRate', { kills: 0 }], ['killsPerDown', { downs: 0 }], ['averageKills', { gamesPlayed: 0 }], ['averageRounds', { gamesPlayed: 0 }], ['completionRate', { gamesPlayed: 0 }] ] as Array<[EfficiencyMetric, Partial]>)( 'leaves %s undefined with no denominator', (metric, zeroDenominator) => { expect(efficiencyValue(stats(zeroDenominator), metric)).toBeNull(); } ); it('uses ratios of totals instead of equally weighting games with different sample sizes', () => { // One game has 1/1 headshots and 1 kill/down; another has 9/99 and 99/9. const aggregate = stats({ gamesPlayed: 2, headshots: 1 + 9, kills: 1 + 99, downs: 1 + 9 }); expect(efficiencyValue(aggregate, 'headshotRate')).toBe((1 + 9) / (1 + 99)); expect(efficiencyValue(aggregate, 'headshotRate')).not.toBe((1 / 1 + 9 / 99) / 2); expect(efficiencyValue(aggregate, 'killsPerDown')).toBe((1 + 99) / (1 + 9)); expect(efficiencyValue(aggregate, 'killsPerDown')).not.toBe((1 / 1 + 99 / 9) / 2); expect(efficiencyEligible(aggregate, 'headshotRate')).toBe(false); }); it('preserves fractional ratios and low samples without rounding, capping or inventing a denominator', () => { const small = stats({ gamesPlayed: 3, gamesCompleted: 1, kills: 2, headshots: 1, downs: 3, roundsSurvived: 7 }); expect(efficiencyValue(small, 'headshotRate')).toBe(1 / 2); expect(efficiencyValue(small, 'killsPerDown')).toBe(2 / 3); expect(efficiencyValue(small, 'averageKills')).toBe(2 / 3); expect(efficiencyValue(small, 'averageRounds')).toBe(7 / 3); expect(efficiencyValue(small, 'completionRate')).toBe(1 / 3); expect(efficiencyValue(stats({ kills: 1000000, downs: 1 }), 'killsPerDown')).toBe(1000000); }); }); describe('efficiency explanations', () => { it('shows the actual numerator and denominator with their units', () => { const player = stats({ kills: 1200 }); expect(efficiencySample(player, 'headshotRate')).toBe('31 headshots / 1,200 kills'); expect(efficiencySample(player, 'killsPerDown')).toBe('1,200 kills / 5 downs'); expect(efficiencySample(player, 'averageKills')).toBe('1,200 kills / 5 ended games'); expect(efficiencySample(player, 'averageRounds')).toBe( '47 observed rounds / 5 ended games' ); expect(efficiencySample(player, 'completionRate')).toBe('3 finishes / 5 ended games'); expect(efficiencySample(stats({ kills: 1, downs: 0 }), 'killsPerDown')).toBe( '1 kill / 0 downs' ); }); it('identifies ratio metrics and publishes the thresholds used to qualify them', () => { for (const { key, description } of efficiencyMetrics) { expect(isEfficiencyMetric(key)).toBe(true); expect(description).toContain('divided by'); expect(efficiencyRequirement(key)).toContain(`${EFFICIENCY_MIN_GAMES} ended games`); } expect(efficiencyRequirement('headshotRate')).toContain(`${EFFICIENCY_MIN_KILLS} kills`); expect(efficiencyRequirement('killsPerDown')).toContain(`${EFFICIENCY_MIN_DOWNS} downs`); expect( efficiencyMetrics .filter((metric) => metric.format === 'percent') .map((metric) => metric.key) ).toEqual(['headshotRate', 'completionRate']); expect(isEfficiencyMetric('kills')).toBe(false); expect(isEfficiencyMetric('')).toBe(false); }); });