diff --git a/app/services/simulations/__tests__/darts-simulator.test.ts b/app/services/simulations/__tests__/darts-simulator.test.ts index 8a45803..6f0c842 100644 --- a/app/services/simulations/__tests__/darts-simulator.test.ts +++ b/app/services/simulations/__tests__/darts-simulator.test.ts @@ -325,7 +325,7 @@ describe("DartsSimulator.simulate() — Path A (bracket populated)", () => { it("each probability column sums to 1.0 across all 128 participants", async () => { mockDb.query.playoffMatches.findMany.mockResolvedValue(makeFullBracket()); - const sim = new DartsSimulator(); + const sim = new DartsSimulator(200); const results = await sim.simulate("season-1"); const keys = [ diff --git a/app/services/simulations/__tests__/world-cup-simulator.test.ts b/app/services/simulations/__tests__/world-cup-simulator.test.ts index bf2e9e4..0ea67b6 100644 --- a/app/services/simulations/__tests__/world-cup-simulator.test.ts +++ b/app/services/simulations/__tests__/world-cup-simulator.test.ts @@ -156,8 +156,7 @@ describe("WorldCupSimulator", () => { }); it("SF losers land in 3rd or 4th, never 1st or 2nd", async () => { - // Set up 8 participants (small bracket, 2 groups of 4) - const participants = makeParticipants(8); + const participants = makeParticipants(48); mockDb.query.seasonParticipants.findMany.mockResolvedValue(participants); mockDb.query.scoringEvents.findFirst.mockResolvedValue(null); mockDb.query.tournamentGroups.findMany.mockResolvedValue([]); diff --git a/app/services/simulations/darts-simulator.ts b/app/services/simulations/darts-simulator.ts index 673b37c..1671259 100644 --- a/app/services/simulations/darts-simulator.ts +++ b/app/services/simulations/darts-simulator.ts @@ -51,7 +51,7 @@ import type { Simulator, SimulationResult } from "./types"; // ─── Simulation parameters ──────────────────────────────────────────────────── -const NUM_SIMULATIONS = 50000; + /** * Controls how much Elo gaps affect per-set win probability. @@ -198,6 +198,12 @@ function shuffle(arr: T[]): T[] { // ─── Simulator ──────────────────────────────────────────────────────────────── export class DartsSimulator implements Simulator { + private readonly numSimulations: number; + + constructor(numSimulations = 10_000) { + this.numSimulations = numSimulations; + } + async simulate(sportsSeasonId: string): Promise { const db = database(); @@ -325,7 +331,7 @@ export class DartsSimulator implements Simulator { const sfLoserCounts = new Map(participantIds.map((id) => [id, 0])); const qfLoserCounts = new Map(participantIds.map((id) => [id, 0])); - for (let s = 0; s < NUM_SIMULATIONS; s++) { + for (let s = 0; s < this.numSimulations; s++) { // R1 (64 matches) const r1Winners: string[] = []; for (let i = 1; i <= 64; i++) { @@ -433,7 +439,7 @@ export class DartsSimulator implements Simulator { finalistCounts.set(finalist, (finalistCounts.get(finalist) ?? 0) + 1); } - return buildResults(participantIds, NUM_SIMULATIONS, { + return buildResults(participantIds, this.numSimulations, { championCounts, finalistCounts, sfLoserCounts, @@ -514,7 +520,7 @@ export class DartsSimulator implements Simulator { unseededPool.push(`__bye_${unseededPool.length}`); } - for (let s = 0; s < NUM_SIMULATIONS; s++) { + for (let s = 0; s < this.numSimulations; s++) { // Draw: shuffle the unseeded pool — seeded positions are pre-computed. const drawnUnseeded = shuffle([...unseededPool]); @@ -582,7 +588,7 @@ export class DartsSimulator implements Simulator { finalistCounts.set(finalist, (finalistCounts.get(finalist) ?? 0) + 1); } - return buildResults(allParticipantIds, NUM_SIMULATIONS, { + return buildResults(allParticipantIds, this.numSimulations, { championCounts, finalistCounts, sfLoserCounts, diff --git a/app/services/simulations/manifest.ts b/app/services/simulations/manifest.ts index 7558cda..e2e7f9f 100644 --- a/app/services/simulations/manifest.ts +++ b/app/services/simulations/manifest.ts @@ -163,7 +163,7 @@ const PROFILES: Record