* feat: EV simulation framework with F1 Monte Carlo simulator - Add EV snapshot tables (participant_ev_snapshots, team_ev_snapshots) and simulation_status column on sports seasons - Add ev-snapshot model with upsert and history query functions - Add simulator framework: types, bracket/F1/golf simulators, registry - F1 simulator: vig-removed ICM weighted draw (pre-season) + race-by-race Monte Carlo from current standings (in-season); per-position column normalization to prevent floating-point EV drift - Add admin simulate route and Run Simulation button on sports season page - Rework futures-odds admin page to save odds then run simulation in one action - Remove recalculate-probabilities route (superseded by simulate route) - Remove EV trend chart panel and associated DB queries Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: map simulators to sports via simulatorType field Adds a `simulator_type` enum column to the `sports` table so each sport can be assigned a specific simulation algorithm rather than deriving it from the sports season's scoring pattern. - Add `simulatorTypeEnum` (f1_standings, indycar_standings, golf_qualifying_points, playoff_bracket) + `simulatorType` nullable column on `sports` table; migration 0037 - Rewrite simulator registry to key off `SimulatorType` instead of `ScoringPattern`; indycar_standings shares F1Simulator for now - `findSportsSeasonById` now returns `SportsSeasonWithSport` so callers have typed access to `sport.simulatorType` - Simulate and futures-odds actions read `sport.simulatorType`; guard fires before setting `simulationStatus: running` - Admin sport edit page gains a Simulator Type dropdown Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
32 lines
1.3 KiB
TypeScript
32 lines
1.3 KiB
TypeScript
/**
|
||
* Golf / Qualifying Points Simulator
|
||
*
|
||
* TODO: Port the Python golf/majors simulator here.
|
||
*
|
||
* Input data available:
|
||
* - Current QP standings: getQPStandings(sportsSeasonId)
|
||
* Returns { participant.id, participant.name, totalQualifyingPoints, eventsScored }
|
||
* - Remaining majors: sportsSeason.totalMajors - sportsSeason.majorsCompleted
|
||
* - Per-major QP config: qualifyingPointConfig table (points per placement for each major)
|
||
*
|
||
* Expected output: SimulationResult[] — one entry per participant with
|
||
* probabilities (0–1) for finishing 1st through 8th in the final QP standings.
|
||
*
|
||
* Algorithm sketch (replace with the Python model logic):
|
||
* 1. Get current QP totals for all participants
|
||
* 2. For each remaining major, model each participant's probability of
|
||
* finishing at each placement (using world rankings, recent form, etc.)
|
||
* 3. Monte Carlo: simulate remaining majors N times, add QP, tally final standings
|
||
* 4. Convert tally counts → probabilities
|
||
*/
|
||
|
||
import type { Simulator, SimulationResult } from "./types";
|
||
|
||
export class GolfSimulator implements Simulator {
|
||
async simulate(_sportsSeasonId: string): Promise<SimulationResult[]> {
|
||
throw new Error(
|
||
"GolfSimulator not yet implemented. " +
|
||
"Port the Python golf/majors model to TypeScript and implement this method."
|
||
);
|
||
}
|
||
}
|