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:
co-authored by
Claude Opus 4.6
parent
e6c3894443
commit
14dbb29377
@@ -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)', () => {
|
it('fight loop throughput: >500 fights/second (no I/O)', () => {
|
||||||
const fights = 5000
|
const fights = 5000
|
||||||
const start = performance.now()
|
const start = performance.now()
|
||||||
|
|||||||
Reference in New Issue
Block a user