test: add timeout draw and perfect victory ELO tests to lifecycle suite

- Both bots timing out every round: verified draw with zero damage
- Perfect victory (10-0): verified correct ELO calculation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-12 23:49:34 +00:00
co-authored by Claude Opus 4.6
parent e6c3894443
commit 14dbb29377
+56
View File
@@ -505,6 +505,62 @@ describe('fight lifecycle', () => {
}
})
it('both bots timing out every round produces draw with zero damage', () => {
const botA = { id: 'to-a', name: 'TimeoutA' }
const botB = { id: 'to-b', name: 'TimeoutB' }
const usedTypes = new Set<string>()
const timeout = { answer: '', timeMs: 8000, timedOut: true, error: false }
for (let r = 0; r < 10; r++) {
const challenge = pickChallenge(usedTypes, null, undefined, r + 1)
usedTypes.add(challenge.type)
const result = scoreRound(challenge, botA, botB, timeout, timeout, null, 0, 0)
// Both timeout = draw, no damage
expect(result.winnerId).toBeNull()
expect(result.botADamage).toBe(0)
expect(result.botBDamage).toBe(0)
expect(result.botAScore).toBe(0)
expect(result.botBScore).toBe(0)
}
})
it('perfect victory (10-0) — correct ELO calculation', () => {
// Bot A wins every round, Bot B always wrong
const eloA = 1200
const eloB = 1200
// Simulate 10 rounds where A always correct, B always wrong
const botA = { id: 'pv-a', name: 'PerfA' }
const botB = { id: 'pv-b', name: 'PerfB' }
const usedTypes = new Set<string>()
let aRoundWins = 0
for (let r = 0; r < 10; r++) {
const challenge = pickChallenge(usedTypes, null, undefined, r + 1)
usedTypes.add(challenge.type)
const resp = mockResponse(challenge, 'confident', 1800)
const result = scoreRound(
challenge, botA, botB,
{ answer: resp.answer, timeMs: 200, timedOut: false, error: false },
{ answer: 'wrong answer completely', timeMs: 200, timedOut: false, error: false },
null, aRoundWins, 0,
)
if (result.winnerId === botA.id) aRoundWins++
}
expect(aRoundWins).toBeGreaterThan(5) // A should win most rounds
// ELO calculation for equal-elo matchup with clear winner
const { newWinnerElo, newLoserElo } = calculateElo(eloA, eloB)
expect(newWinnerElo).toBeGreaterThan(eloA)
expect(newLoserElo).toBeLessThan(eloB)
// ELO change should be moderate for equal-elo matchup
const change = newWinnerElo - eloA
expect(change).toBeGreaterThan(5)
expect(change).toBeLessThan(40)
})
it('fight loop throughput: >500 fights/second (no I/O)', () => {
const fights = 5000
const start = performance.now()