fix: lower darts ELO_DIVISOR to 400 and fallback Elo to 1400

ELO_DIVISOR 500 → 400: elite darts is more skill-dominated than the
previous setting implied. A 400-point gap now gives ~78% per-set win
probability (vs ~73% before).

fallbackElo 1600 → 1400: unseeded PDC World Championship entrants
(regional qualifiers, Q-School players) are materially weaker than
seeded tour professionals. 1400 better reflects that gap.

Combined effect: a dominant player (e.g. 2000 Elo vs 1400-1600 field)
now produces EV ≈ 65 instead of ≈ 30, which better matches expectations
for a top-ranked player in a 128-player bracket.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Chris Parsons 2026-04-09 04:06:50 +00:00
parent d5aa8a3de4
commit f3af6b424e
2 changed files with 16 additions and 10 deletions

View file

@ -40,9 +40,9 @@ describe("setWinProb", () => {
expect(setWinProb(1000, 3000)).toBeGreaterThan(0); expect(setWinProb(1000, 3000)).toBeGreaterThan(0);
}); });
it("calibration: 100-pt gap → ~55% per set (ELO_DIVISOR=500)", () => { it("calibration: 100-pt gap → ~56% per set (ELO_DIVISOR=400)", () => {
// 1 / (1 + e^(-100/500)) ≈ 0.5499 // 1 / (1 + e^(-100/400)) ≈ 0.5622
expect(setWinProb(1900, 1800)).toBeCloseTo(0.5499, 2); expect(setWinProb(1900, 1800)).toBeCloseTo(0.5622, 2);
}); });
}); });

View file

@ -59,12 +59,12 @@ const NUM_SIMULATIONS = 50000;
* Lower = sharper (Elo differences matter more). * Lower = sharper (Elo differences matter more).
* *
* Standard chess uses 400. Snooker (more random than chess) uses 700. * Standard chess uses 400. Snooker (more random than chess) uses 700.
* Darts is moderately volatile; 500 gives: * Darts at the elite level is relatively skill-dominated; 400 gives:
* 100-pt gap ~55% per set * 100-pt gap ~56% per set
* 300-pt gap ~63% per set * 300-pt gap ~67% per set
* 500-pt gap ~73% per set * 500-pt gap ~78% per set
*/ */
const ELO_DIVISOR = 500; const ELO_DIVISOR = 400;
/** /**
* Sets needed to win per round, in bracket order (R1 first, Final last). * Sets needed to win per round, in bracket order (R1 first, Final last).
@ -289,7 +289,10 @@ export class DartsSimulator implements Simulator {
participantIds.push(m.participant1Id, m.participant2Id); participantIds.push(m.participant1Id, m.participant2Id);
} }
const fallbackElo = 1600; // 1400 reflects the typical strength of unseeded PDC World Championship
// qualifiers (regional/Q-School players), who are significantly weaker than
// the seeded tour players.
const fallbackElo = 1400;
// Cache matchWinProb — Elo values are fixed across simulations. // Cache matchWinProb — Elo values are fixed across simulations.
const matchProbCache = new Map<string, number>(); const matchProbCache = new Map<string, number>();
@ -457,7 +460,10 @@ export class DartsSimulator implements Simulator {
); );
} }
const fallbackElo = 1600; // 1400 reflects the typical strength of unseeded PDC World Championship
// qualifiers (regional/Q-School players), who are significantly weaker than
// the seeded tour players.
const fallbackElo = 1400;
// Sort participants by world ranking (ascending). Fall back to Elo order (descending) for // Sort participants by world ranking (ascending). Fall back to Elo order (descending) for
// any without a ranking, then alphabetical as a final tiebreak. // any without a ranking, then alphabetical as a final tiebreak.