/** * The official 2026 LLBWS bracket (Williamsport, Aug 19–30), transcribed from the PDF. * * The printed bracket numbers its games 1–38. Both the routing tests and the layout * tests check themselves against these numbers, so the transcription lives here rather * than in either one. */ // ── PDF game number ↔ (round, match number) ────────────────────────────────── // // Transcribed directly from the 2026 LLBWS bracket. U.S. games take the low match // numbers in each round, International the high ones. export const GAME_TO_MATCH: Record = { // Opening Round — U.S. G2,4,6,8 (M1–4); Intl G1,3,5,7 (M5–8) 2: { round: "Opening Round", matchNumber: 1 }, 4: { round: "Opening Round", matchNumber: 2 }, 6: { round: "Opening Round", matchNumber: 3 }, 8: { round: "Opening Round", matchNumber: 4 }, 1: { round: "Opening Round", matchNumber: 5 }, 3: { round: "Opening Round", matchNumber: 6 }, 5: { round: "Opening Round", matchNumber: 7 }, 7: { round: "Opening Round", matchNumber: 8 }, // Winners Round 2 — U.S. G10,12; Intl G9,11 10: { round: "Winners Round 2", matchNumber: 1 }, 12: { round: "Winners Round 2", matchNumber: 2 }, 9: { round: "Winners Round 2", matchNumber: 3 }, 11: { round: "Winners Round 2", matchNumber: 4 }, // Elimination Round 1 — U.S. G14,16; Intl G13,15 14: { round: "Elimination Round 1", matchNumber: 1 }, 16: { round: "Elimination Round 1", matchNumber: 2 }, 13: { round: "Elimination Round 1", matchNumber: 3 }, 15: { round: "Elimination Round 1", matchNumber: 4 }, // Winners Semifinals — U.S. G17,19; Intl G18,20 17: { round: "Winners Semifinals", matchNumber: 1 }, 19: { round: "Winners Semifinals", matchNumber: 2 }, 18: { round: "Winners Semifinals", matchNumber: 3 }, 20: { round: "Winners Semifinals", matchNumber: 4 }, // Elimination Round 2 — U.S. G22,24; Intl G21,23 22: { round: "Elimination Round 2", matchNumber: 1 }, 24: { round: "Elimination Round 2", matchNumber: 2 }, 21: { round: "Elimination Round 2", matchNumber: 3 }, 23: { round: "Elimination Round 2", matchNumber: 4 }, // Elimination Round 3 — U.S. G26,28; Intl G25,27 26: { round: "Elimination Round 3", matchNumber: 1 }, 28: { round: "Elimination Round 3", matchNumber: 2 }, 25: { round: "Elimination Round 3", matchNumber: 3 }, 27: { round: "Elimination Round 3", matchNumber: 4 }, // Winners Final — U.S. G30; Intl G29 30: { round: "Winners Final", matchNumber: 1 }, 29: { round: "Winners Final", matchNumber: 2 }, // Elimination Round 4 — U.S. G32; Intl G31 32: { round: "Elimination Round 4", matchNumber: 1 }, 31: { round: "Elimination Round 4", matchNumber: 2 }, // Elimination Final — U.S. G34; Intl G33 34: { round: "Elimination Final", matchNumber: 1 }, 33: { round: "Elimination Final", matchNumber: 2 }, // Bracket Championship — U.S. G36; Intl G35 36: { round: "Bracket Championship", matchNumber: 1 }, 35: { round: "Bracket Championship", matchNumber: 2 }, // Finals 37: { round: "Consolation Third Place", matchNumber: 1 }, 38: { round: "World Championship", matchNumber: 1 }, }; export const MATCH_TO_GAME = new Map( Object.entries(GAME_TO_MATCH).map(([game, m]) => [ `${m.round}#${m.matchNumber}`, Number(game), ]) ); export function gameNumberFor(round: string, matchNumber: number): number { const game = MATCH_TO_GAME.get(`${round}#${matchNumber}`); if (game === undefined) throw new Error(`No PDF game for ${round} #${matchNumber}`); return game; } /** Narrows a destination that the test expects to exist. */ export function required(destination: T | null): T { if (destination === null) throw new Error("Expected a destination, got null"); return destination; } /** PDF game number a destination points at. */ export function destinationGame( destination: { round: string; matchNumber: number } | null ): number { const d = required(destination); return gameNumberFor(d.round, d.matchNumber); } /** * The official bracket printed as feed labels: for each game, which prior game's * winner (W) or loser (L) fills each slot. `null` = a team seeded in directly. * * Transcribed from the PDF. This is the source of truth the routing must reproduce. */ export const EXPECTED_SLOTS: Record = { // Opening Round — all directly seeded 1: [null, null], 2: [null, null], 3: [null, null], 4: [null, null], 5: [null, null], 6: [null, null], 7: [null, null], 8: [null, null], // Winners Round 2 — bye team, then an Opening Round winner 9: [null, "W1"], 10: [null, "W2"], 11: [null, "W3"], 12: [null, "W4"], // Elimination Round 1 13: ["L3", "L5"], 14: ["L4", "L6"], 15: ["L1", "L7"], 16: ["L2", "L8"], // Winners Semifinals 17: ["W6", "W10"], 18: ["W5", "W9"], 19: ["W12", "W8"], 20: ["W11", "W7"], // Elimination Round 2 21: ["L9", "W13"], 22: ["L10", "W14"], 23: ["L11", "W15"], 24: ["L12", "W16"], // Elimination Round 3 — cross-over 25: ["L18", "W23"], 26: ["L17", "W24"], 27: ["L20", "W21"], 28: ["L19", "W22"], // Winners Final 29: ["W18", "W20"], 30: ["W17", "W19"], // Elimination Round 4 31: ["W27", "W25"], 32: ["W28", "W26"], // Elimination Final 33: ["L29", "W31"], 34: ["L30", "W32"], // Bracket Championship 35: ["W29", "W33"], 36: ["W30", "W34"], // Finals 37: ["L36", "L35"], 38: ["W36", "W35"], };