Adds Major League Soccer as a draftable sport with a full-season Monte Carlo
simulator. Models both preseason regular-season projection (34 games across
Eastern and Western conferences) and the MLS Cup Playoffs bracket, including
the Wild Card (single game + PKs), Round 1 best-of-3 series, Conference
Semis/Finals (single game), and MLS Cup.
P1–P8 mapping: MLS Cup winner, finalist, Conference Finals losers, Conference
Semifinals losers. Conference assignment reads from regularSeasonStandings.conference
or falls back to the region simulator input ("Eastern"/"Western").
Admin inputs: projectedTablePoints (primary, max 102 for 34×3), with derivation
chain to sourceElo via existing input-policy; sourceOdds as alternative.
No hardcoded team data — all inputs are admin-managed per season.
- database/schema.ts: add mls_bracket to simulatorTypeEnum
- drizzle/0104_chief_boom_boom.sql: migration for the new enum value
- mls-simulator.ts: MLSSimulator + exported pure helpers for testability
- registry.ts / manifest.ts / simulator-config.ts: register mls_bracket
- mls-simulator.test.ts: 38 unit tests covering all helpers and sync checks
https://claude.ai/code/session_015wkBJ3SYGcMGjsddKKGkwa
110 lines
3.2 KiB
TypeScript
110 lines
3.2 KiB
TypeScript
/**
|
|
* Simulator Configuration
|
|
*
|
|
* Per-sport parameters used by simulators and admin UI tools.
|
|
* Centralizes season length, parity factors, and other sport-specific
|
|
* constants so they can be shared between simulators and the Elo Ratings
|
|
* admin page (e.g., for projected wins → Elo conversion).
|
|
*/
|
|
|
|
import type { SimulatorType } from "./registry";
|
|
|
|
export interface SimulatorConfig {
|
|
/** Total regular season games per team in this sport. */
|
|
seasonGames: number;
|
|
/** Elo parity factor for single-game win probability.
|
|
* P(A) = 1 / (1 + 10^((eloB - eloA) / parityFactor))
|
|
* Higher = more unpredictable per game. */
|
|
parityFactor: number;
|
|
/** Average opponent Elo — used for season projections against a generic opponent. */
|
|
averageOpponentElo: number;
|
|
/** Label/type for the admin projection input. Defaults to projected wins. */
|
|
projectionInput?: "wins" | "tablePoints";
|
|
}
|
|
|
|
const CONFIG: Record<SimulatorType, SimulatorConfig | null> = {
|
|
afl_bracket: {
|
|
seasonGames: 23,
|
|
parityFactor: 450,
|
|
averageOpponentElo: 1500,
|
|
},
|
|
nfl_bracket: {
|
|
seasonGames: 17,
|
|
parityFactor: 400,
|
|
averageOpponentElo: 1500,
|
|
},
|
|
nba_bracket: {
|
|
seasonGames: 82,
|
|
parityFactor: 400,
|
|
averageOpponentElo: 1500,
|
|
},
|
|
nhl_bracket: {
|
|
seasonGames: 82,
|
|
// NHL is the highest-parity major North American league — roughly 1 in 3 games
|
|
// goes to overtime/shootout and favourites win far less reliably than in NBA/NFL.
|
|
// 1000 was calibrated so that a team projected at 55 wins (67%) maps to ~1570 Elo,
|
|
// which keeps the spread tight and reflects the empirical upset rate.
|
|
parityFactor: 1000,
|
|
averageOpponentElo: 1500,
|
|
},
|
|
mlb_bracket: {
|
|
seasonGames: 162,
|
|
parityFactor: 400,
|
|
averageOpponentElo: 1500,
|
|
},
|
|
epl_standings: {
|
|
seasonGames: 38,
|
|
parityFactor: 400,
|
|
averageOpponentElo: 1500,
|
|
projectionInput: "tablePoints",
|
|
},
|
|
wnba_bracket: {
|
|
seasonGames: 44,
|
|
parityFactor: 400,
|
|
averageOpponentElo: 1500,
|
|
},
|
|
nll_bracket: {
|
|
seasonGames: 18,
|
|
parityFactor: 400,
|
|
averageOpponentElo: 1500,
|
|
},
|
|
mls_bracket: {
|
|
seasonGames: 34,
|
|
parityFactor: 400,
|
|
averageOpponentElo: 1500,
|
|
projectionInput: "tablePoints",
|
|
},
|
|
// Simulators below don't use projected-wins → Elo conversion.
|
|
// They can be populated later if needed.
|
|
f1_standings: null,
|
|
indycar_standings: null,
|
|
golf_qualifying_points: null,
|
|
playoff_bracket: null,
|
|
ucl_bracket: null,
|
|
ncaam_bracket: null,
|
|
ncaaw_bracket: null,
|
|
snooker_bracket: null,
|
|
tennis_qualifying_points: null,
|
|
world_cup: null,
|
|
darts_bracket: null,
|
|
cs2_major_qualifying_points: null,
|
|
ncaa_football_bracket: null,
|
|
llws_bracket: null,
|
|
college_hockey_bracket: null,
|
|
brackt: null,
|
|
};
|
|
|
|
/**
|
|
* Get the simulator config for a given simulator type.
|
|
* Returns null for simulator types that don't have season-game / Elo config.
|
|
*/
|
|
export function getSimulatorConfig(simulatorType: SimulatorType): SimulatorConfig | null {
|
|
return CONFIG[simulatorType];
|
|
}
|
|
|
|
/**
|
|
* Check if a simulator type supports projected-wins → Elo conversion.
|
|
*/
|
|
export function supportsProjectedWins(simulatorType: SimulatorType): boolean {
|
|
return CONFIG[simulatorType] !== null;
|
|
}
|