import { describe, expect, it, vi } from "vitest"; /** * The Expected Values admin page renders EV from the stored probability columns. * * It used to carry its own hardcoded scoring table (100/70/45/45/20/20/20/20), which * flattened positions 5–8 to 20 points each. For a standard single-elimination bracket * that was invisible — all four quarterfinal losers share one tier worth * avg(25,25,15,15) = 20 anyway — but for the templates that split 5–8 into two tiers * (llws_20, afl_10) it reported a team locked into 5th–6th and a team locked into * 7th–8th as the same 20 points. These pin it to the shared DEFAULT_SCORING_RULES. */ vi.mock("../admin.sports-seasons.$id.expected-values.server", () => ({ loader: vi.fn(), })); import { evFromProbs } from "../admin.sports-seasons.$id.expected-values"; const ZERO = { probFirst: "0", probSecond: "0", probThird: "0", probFourth: "0", probFifth: "0", probSixth: "0", probSeventh: "0", probEighth: "0", }; describe("evFromProbs", () => { it("gives a team locked into the 5th–6th tier 25 points, not 20", () => { expect(evFromProbs({ ...ZERO, probFifth: "0.5", probSixth: "0.5" })).toBe(25); }); it("gives a team locked into the 7th–8th tier 15 points, not 20", () => { expect(evFromProbs({ ...ZERO, probSeventh: "0.5", probEighth: "0.5" })).toBe(15); }); it("still gives a single 5th–8th tier (4 QF losers) 20 points", () => { const ev = evFromProbs({ ...ZERO, probFifth: "0.25", probSixth: "0.25", probSeventh: "0.25", probEighth: "0.25", }); expect(ev).toBe(20); }); it("keeps 3rd and 4th distinct rather than a flat 45 each", () => { expect(evFromProbs({ ...ZERO, probThird: "1" })).toBe(50); expect(evFromProbs({ ...ZERO, probFourth: "1" })).toBe(40); }); it("preserves the 340 total-EV invariant across a full set of unit columns", () => { const perPosition = [ evFromProbs({ ...ZERO, probFirst: "1" }), evFromProbs({ ...ZERO, probSecond: "1" }), evFromProbs({ ...ZERO, probThird: "1" }), evFromProbs({ ...ZERO, probFourth: "1" }), evFromProbs({ ...ZERO, probFifth: "1" }), evFromProbs({ ...ZERO, probSixth: "1" }), evFromProbs({ ...ZERO, probSeventh: "1" }), evFromProbs({ ...ZERO, probEighth: "1" }), ]; expect(perPosition.reduce((sum, ev) => sum + ev, 0)).toBe(340); }); it("returns 0 for a participant with no probability mass", () => { expect(evFromProbs(ZERO)).toBe(0); }); });