Fix darts simulator timeout and world-cup bracket edge case
All checks were successful
🚀 Deploy / 🧪 Test (pull_request) Successful in 2m26s
🚀 Deploy / ʦ TypeScript (pull_request) Successful in 1m16s
🚀 Deploy / 🔍 Lint (pull_request) Successful in 48s
🚀 Deploy / 🐳 Build (pull_request) Has been skipped
🚀 Deploy / 🚀 Deploy (pull_request) Has been skipped
All checks were successful
🚀 Deploy / 🧪 Test (pull_request) Successful in 2m26s
🚀 Deploy / ʦ TypeScript (pull_request) Successful in 1m16s
🚀 Deploy / 🔍 Lint (pull_request) Successful in 48s
🚀 Deploy / 🐳 Build (pull_request) Has been skipped
🚀 Deploy / 🚀 Deploy (pull_request) Has been skipped
- Add numSimulations constructor param to DartsSimulator (same pattern as WorldCupSimulator); drop default from 50k→10k; update manifest to match - Pass 200 iterations in the slow darts column-sum test to prevent CI timeout - Fix world-cup "SF losers" test to use 48 participants — with only 8, the R32 pool has 6 teams and SF never runs, leaving all placement counts at 0 and normalization producing probFirst=probThird=1 for one team - Add manifest iterations: 10_000 override for darts_bracket Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
c3b7c77f09
commit
c0f674f648
4 changed files with 14 additions and 9 deletions
|
|
@ -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 = [
|
||||
|
|
|
|||
|
|
@ -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([]);
|
||||
|
|
|
|||
|
|
@ -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<T>(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<SimulationResult[]> {
|
||||
const db = database();
|
||||
|
||||
|
|
@ -325,7 +331,7 @@ export class DartsSimulator implements Simulator {
|
|||
const sfLoserCounts = new Map<string, number>(participantIds.map((id) => [id, 0]));
|
||||
const qfLoserCounts = new Map<string, number>(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,
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ const PROFILES: Record<SimulatorType, Omit<SimulatorManifestProfile, "simulatorT
|
|||
setupSections: ["participants", "eloRatings", "futuresOdds", "events"],
|
||||
},
|
||||
darts_bracket: {
|
||||
defaultConfig: { ...BASE_CONFIG, eloDivisor: 400 },
|
||||
defaultConfig: { ...BASE_CONFIG, iterations: 10_000, eloDivisor: 400 },
|
||||
requiredInputs: ["sourceElo", "worldRanking"],
|
||||
optionalInputs: ["seed"],
|
||||
setupSections: ["participants", "eloRatings", "rankings"],
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue