Polish MLS simulator: configNumber zero, logger warning, Map lookup
Three small fixes from secondary code review: 1. configNumber: allow value >= 0 (not just > 0) so admins can legitimately set baseDrawRate or drawDecay to 0 without the value being silently discarded and replaced with the default. 2. Add logger.warn when a participant is excluded from simulation due to a missing Elo rating, matching the NLL bracket-aware pattern. Gives admins a visible signal instead of a silent exclusion. 3. getBySeeds: build a Map once instead of calling Array.find() per seed. Eliminates 4M linear scans across 50k iterations for a 9- element array — trivially fast either way, but Map is the right tool. https://claude.ai/code/session_015wkBJ3SYGcMGjsddKKGkwa
This commit is contained in:
parent
43c9128e59
commit
8a0103e4c4
1 changed files with 11 additions and 3 deletions
|
|
@ -46,6 +46,7 @@ import { getParticipantSimulatorInputs, getSportsSeasonSimulatorConfig } from "~
|
|||
import { simulateEloSoccerMatch, simulateSimpleSoccerGoals } from "./soccer-helpers";
|
||||
import type { EloSoccerMatchOptions } from "./soccer-helpers";
|
||||
import { normalizeSimulationResultColumns } from "./simulation-probabilities";
|
||||
import { logger } from "~/lib/logger";
|
||||
|
||||
// ─── Default constants (overridable via season simulator config) ───────────────
|
||||
|
||||
|
|
@ -62,7 +63,7 @@ const MLS_PLAYOFF_TEAMS_PER_CONF = 9;
|
|||
|
||||
function configNumber(config: Record<string, unknown> | undefined, key: string, fallback: number): number {
|
||||
const value = config?.[key];
|
||||
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : fallback;
|
||||
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : fallback;
|
||||
}
|
||||
|
||||
// ─── Public types ─────────────────────────────────────────────────────────────
|
||||
|
|
@ -205,8 +206,9 @@ function getBySeeds(
|
|||
seeds: MlsConferenceSeed[],
|
||||
...seedNums: number[]
|
||||
): MlsConferenceSeed[] {
|
||||
const byNum = new Map(seeds.map((s) => [s.seed, s]));
|
||||
return seedNums.map((n) => {
|
||||
const entry = seeds.find((s) => s.seed === n);
|
||||
const entry = byNum.get(n);
|
||||
if (!entry) throw new Error(`MLS playoff seed ${n} not found in conference bracket.`);
|
||||
return entry;
|
||||
});
|
||||
|
|
@ -397,7 +399,13 @@ export class MLSSimulator implements Simulator {
|
|||
const teamsWithElo = participants.flatMap((p): MlsTeamEntry[] => {
|
||||
const elo = eloMap.get(p.id);
|
||||
const conf = conferenceMap.get(p.id);
|
||||
if (elo === undefined || conf === undefined) return [];
|
||||
if (elo === undefined || conf === undefined) {
|
||||
logger.warn(
|
||||
`MLSSimulator: no Elo rating for participant "${p.name}" (${p.id}). ` +
|
||||
`They will be excluded from simulation. Enter sourceElo or projectedTablePoints via Admin → Elo Ratings.`
|
||||
);
|
||||
return [];
|
||||
}
|
||||
const standing = standingsMap.get(p.id);
|
||||
const wins = standing?.wins ?? 0;
|
||||
const draws = standing?.ties ?? 0;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue