Fix oxlint violations in LLWS simulator
- Replace non-null assertions with null-safe access (! → ?? / optional chaining) - Replace .sort() with .toSorted() per linting rules - Promote bump() to simulate() scope and pass it into simulateSideBracket, removing the need to pass counts into that function Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
971c475cb6
commit
31b03e19a8
2 changed files with 17 additions and 16 deletions
|
|
@ -153,9 +153,9 @@ describe("LLWSSimulator", () => {
|
||||||
setupMockDb(defaultParticipants(), makeEvRows(ALL_IDS, { includeOdds: true }));
|
setupMockDb(defaultParticipants(), makeEvRows(ALL_IDS, { includeOdds: true }));
|
||||||
const results = await new LLWSSimulator().simulate("season-1");
|
const results = await new LLWSSimulator().simulate("season-1");
|
||||||
const byId = new Map(results.map((r) => [r.participantId, r]));
|
const byId = new Map(results.map((r) => [r.participantId, r]));
|
||||||
expect(byId.get("us-1")!.probabilities.probFirst).toBeGreaterThan(
|
const us1prob = byId.get("us-1")?.probabilities.probFirst ?? 0;
|
||||||
byId.get("us-10")!.probabilities.probFirst
|
const us10prob = byId.get("us-10")?.probabilities.probFirst ?? 0;
|
||||||
);
|
expect(us1prob).toBeGreaterThan(us10prob);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("works when no odds are entered (all 50/50 fallback)", async () => {
|
it("works when no odds are entered (all 50/50 fallback)", async () => {
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,7 @@ function simulatePoolPlay(pool: Team[]): [Team, Team] {
|
||||||
// the comparator is consistent (Math.random() inside a comparator is a bug — the
|
// the comparator is consistent (Math.random() inside a comparator is a bug — the
|
||||||
// engine may call it multiple times per pair and get contradictory results).
|
// engine may call it multiple times per pair and get contradictory results).
|
||||||
const tiebreaker = new Map(pool.map((t) => [t.participantId, Math.random()]));
|
const tiebreaker = new Map(pool.map((t) => [t.participantId, Math.random()]));
|
||||||
const ranked = [...pool].sort((a, b) => {
|
const ranked = pool.toSorted((a, b) => {
|
||||||
const diff = (wins.get(b.participantId) ?? 0) - (wins.get(a.participantId) ?? 0);
|
const diff = (wins.get(b.participantId) ?? 0) - (wins.get(a.participantId) ?? 0);
|
||||||
return diff !== 0 ? diff : (tiebreaker.get(a.participantId) ?? 0) - (tiebreaker.get(b.participantId) ?? 0);
|
return diff !== 0 ? diff : (tiebreaker.get(a.participantId) ?? 0) - (tiebreaker.get(b.participantId) ?? 0);
|
||||||
});
|
});
|
||||||
|
|
@ -178,12 +178,8 @@ function simulateSideBracket(
|
||||||
poolA2: Team,
|
poolA2: Team,
|
||||||
poolB1: Team,
|
poolB1: Team,
|
||||||
poolB2: Team,
|
poolB2: Team,
|
||||||
counts: Map<string, PlacementCounts>
|
bump: (id: string, key: keyof PlacementCounts) => void
|
||||||
): { sideChampion: Team; sideLoser: Team } {
|
): { sideChampion: Team; sideLoser: Team } {
|
||||||
const bump = (id: string, key: keyof PlacementCounts) => {
|
|
||||||
const entry = counts.get(id);
|
|
||||||
if (entry) entry[key]++;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Winners bracket
|
// Winners bracket
|
||||||
const g1 = simGame(poolA1, poolB2);
|
const g1 = simGame(poolA1, poolB2);
|
||||||
|
|
@ -331,6 +327,10 @@ export class LLWSSimulator implements Simulator {
|
||||||
const counts = new Map<string, PlacementCounts>(
|
const counts = new Map<string, PlacementCounts>(
|
||||||
allIds.map((id) => [id, { champion: 0, finalist: 0, thirdPlace: 0, fourthPlace: 0, bracketLoser: 0 }])
|
allIds.map((id) => [id, { champion: 0, finalist: 0, thirdPlace: 0, fourthPlace: 0, bracketLoser: 0 }])
|
||||||
);
|
);
|
||||||
|
const bump = (id: string, key: keyof PlacementCounts) => {
|
||||||
|
const entry = counts.get(id);
|
||||||
|
if (entry) entry[key]++;
|
||||||
|
};
|
||||||
|
|
||||||
// 6. Run Monte Carlo simulations.
|
// 6. Run Monte Carlo simulations.
|
||||||
for (let s = 0; s < NUM_SIMULATIONS; s++) {
|
for (let s = 0; s < NUM_SIMULATIONS; s++) {
|
||||||
|
|
@ -346,19 +346,19 @@ export class LLWSSimulator implements Simulator {
|
||||||
|
|
||||||
// Double-elimination bracket per side.
|
// Double-elimination bracket per side.
|
||||||
const { sideChampion: usChamp, sideLoser: usLose } =
|
const { sideChampion: usChamp, sideLoser: usLose } =
|
||||||
simulateSideBracket(usA1, usA2, usB1, usB2, counts);
|
simulateSideBracket(usA1, usA2, usB1, usB2, bump);
|
||||||
const { sideChampion: intlChamp, sideLoser: intlLose } =
|
const { sideChampion: intlChamp, sideLoser: intlLose } =
|
||||||
simulateSideBracket(intlA1, intlA2, intlB1, intlB2, counts);
|
simulateSideBracket(intlA1, intlA2, intlB1, intlB2, bump);
|
||||||
|
|
||||||
// Consolation game: 3rd / 4th place.
|
// Consolation game: 3rd / 4th place.
|
||||||
const consolation = simGame(usLose, intlLose);
|
const consolation = simGame(usLose, intlLose);
|
||||||
counts.get(consolation.winner.participantId)!.thirdPlace++;
|
bump(consolation.winner.participantId, "thirdPlace");
|
||||||
counts.get(consolation.loser.participantId)!.fourthPlace++;
|
bump(consolation.loser.participantId, "fourthPlace");
|
||||||
|
|
||||||
// World Series: 1st / 2nd place.
|
// World Series: 1st / 2nd place.
|
||||||
const ws = simGame(usChamp, intlChamp);
|
const ws = simGame(usChamp, intlChamp);
|
||||||
counts.get(ws.winner.participantId)!.champion++;
|
bump(ws.winner.participantId, "champion");
|
||||||
counts.get(ws.loser.participantId)!.finalist++;
|
bump(ws.loser.participantId, "finalist");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7. Convert counts to probability distributions.
|
// 7. Convert counts to probability distributions.
|
||||||
|
|
@ -366,8 +366,9 @@ export class LLWSSimulator implements Simulator {
|
||||||
const bracketLosersPerSim = 4;
|
const bracketLosersPerSim = 4;
|
||||||
const bracketDivisor = bracketLosersPerSim * NUM_SIMULATIONS;
|
const bracketDivisor = bracketLosersPerSim * NUM_SIMULATIONS;
|
||||||
|
|
||||||
|
const zeroCounts: PlacementCounts = { champion: 0, finalist: 0, thirdPlace: 0, fourthPlace: 0, bracketLoser: 0 };
|
||||||
return allIds.map((id) => {
|
return allIds.map((id) => {
|
||||||
const c = counts.get(id)!;
|
const c = counts.get(id) ?? zeroCounts;
|
||||||
const bracketProb = c.bracketLoser / bracketDivisor;
|
const bracketProb = c.bracketLoser / bracketDivisor;
|
||||||
return {
|
return {
|
||||||
participantId: id,
|
participantId: id,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue