From f3af6b424eaa81b03dfc59370de0a6c4dfc0404e Mon Sep 17 00:00:00 2001 From: Chris Parsons Date: Thu, 9 Apr 2026 04:06:50 +0000 Subject: [PATCH] fix: lower darts ELO_DIVISOR to 400 and fallback Elo to 1400 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- .../__tests__/darts-simulator.test.ts | 6 +++--- app/services/simulations/darts-simulator.ts | 20 ++++++++++++------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/app/services/simulations/__tests__/darts-simulator.test.ts b/app/services/simulations/__tests__/darts-simulator.test.ts index 1df59e7..9c4deda 100644 --- a/app/services/simulations/__tests__/darts-simulator.test.ts +++ b/app/services/simulations/__tests__/darts-simulator.test.ts @@ -40,9 +40,9 @@ describe("setWinProb", () => { expect(setWinProb(1000, 3000)).toBeGreaterThan(0); }); - it("calibration: 100-pt gap → ~55% per set (ELO_DIVISOR=500)", () => { - // 1 / (1 + e^(-100/500)) ≈ 0.5499 - expect(setWinProb(1900, 1800)).toBeCloseTo(0.5499, 2); + it("calibration: 100-pt gap → ~56% per set (ELO_DIVISOR=400)", () => { + // 1 / (1 + e^(-100/400)) ≈ 0.5622 + expect(setWinProb(1900, 1800)).toBeCloseTo(0.5622, 2); }); }); diff --git a/app/services/simulations/darts-simulator.ts b/app/services/simulations/darts-simulator.ts index 922e6ba..79efc8d 100644 --- a/app/services/simulations/darts-simulator.ts +++ b/app/services/simulations/darts-simulator.ts @@ -59,12 +59,12 @@ const NUM_SIMULATIONS = 50000; * Lower = sharper (Elo differences matter more). * * Standard chess uses 400. Snooker (more random than chess) uses 700. - * Darts is moderately volatile; 500 gives: - * 100-pt gap → ~55% per set - * 300-pt gap → ~63% per set - * 500-pt gap → ~73% per set + * Darts at the elite level is relatively skill-dominated; 400 gives: + * 100-pt gap → ~56% per set + * 300-pt gap → ~67% 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). @@ -289,7 +289,10 @@ export class DartsSimulator implements Simulator { 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. const matchProbCache = new Map(); @@ -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 // any without a ranking, then alphabetical as a final tiebreak.