From 2387173cf5beb237411714daa80d9e4d9aa30889 Mon Sep 17 00:00:00 2001 From: Chris Parsons Date: Thu, 9 Apr 2026 04:24:53 +0000 Subject: [PATCH] fix: seed darts bracket by Elo instead of world ranking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit World ranking (PDC Order of Merit) is prize-money-based and can diverge from current skill — e.g. Kevin Doets (1818 Elo) was ranked 35th while Joe Cullen (1667 Elo) held the 32nd seed. Seeding the weaker player and leaving the stronger one unseeded contradicts the Elo-based match model. Seeding by Elo descending ensures the 32 strongest players (by the same metric used to compute match probabilities) get protected bracket positions. Co-Authored-By: Claude Sonnet 4.6 --- app/services/simulations/darts-simulator.ts | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/app/services/simulations/darts-simulator.ts b/app/services/simulations/darts-simulator.ts index b8759e6..46260c6 100644 --- a/app/services/simulations/darts-simulator.ts +++ b/app/services/simulations/darts-simulator.ts @@ -29,7 +29,7 @@ * Final: best-of-13 sets, first to 7 * * Seeding (pre-bracket path): - * Top 32 players (by world ranking) are seeded into fixed bracket positions + * Top 32 players (by Elo, descending) are seeded into fixed bracket positions * using the standard balanced bracket structure: * R1 seeds: 1v32, 16v17, 9v24, 8v25 (top half) + 5v28, 12v21, 13v20, 4v29 * 3v30, 14v19, 11v22, 6v27 (bottom half) + 7v26, 10v23, 15v18, 2v31 @@ -468,17 +468,14 @@ export class DartsSimulator implements Simulator { // 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. - const sorted = [...allParticipants].toSorted((a, b) => { - const rankA = rankingMap.get(a.id); - const rankB = rankingMap.get(b.id); - if (rankA !== undefined && rankB !== undefined) return rankA - rankB; - if (rankA !== undefined) return -1; // ranked before unranked - if (rankB !== undefined) return 1; - // Both unranked — sort by Elo descending - return (eloMap.get(b.id) ?? fallbackElo) - (eloMap.get(a.id) ?? fallbackElo); - }); + // Seed by Elo descending — the top 32 strongest players (by Elo) get protected + // bracket positions. World ranking (PDC Order of Merit) is prize-money-based and + // can diverge from current skill; a player ranked 35th by earnings might have a + // higher Elo than someone ranked 28th. Using Elo for seeding keeps the bracket + // consistent with the Elo-based match simulation. + const sorted = [...allParticipants].toSorted((a, b) => + (eloMap.get(b.id) ?? fallbackElo) - (eloMap.get(a.id) ?? fallbackElo) + ); const topSeeds = sorted.slice(0, TOP_SEEDS).map((p) => p.id); // seeds 1–32 const unseeded = sorted.slice(TOP_SEEDS).map((p) => p.id); // remaining players