Commit graph

8 commits

Author SHA1 Message Date
ee099c64cd claude/clever-archimedes-dvye42 (#110)
Some checks failed
🚀 Deploy / 🧪 Test (push) Successful in 3m7s
🚀 Deploy / ʦ🔍 Typecheck & Lint (push) Failing after 50s
🚀 Deploy / 🐳 Build (push) Has been skipped
🚀 Deploy / 🚀 Deploy (push) Has been skipped
Co-authored-by: Claude <noreply@anthropic.com>
Reviewed-on: #110
2026-06-26 05:16:54 +00:00
03726f1a66 Fix simulator correctness bugs and reduce test iteration counts (#61)
All checks were successful
🚀 Deploy / 🧪 Test (push) Successful in 2m27s
🚀 Deploy / ʦ TypeScript (push) Successful in 1m18s
🚀 Deploy / 🔍 Lint (push) Successful in 47s
🚀 Deploy / 🐳 Build (push) Successful in 15m5s
🚀 Deploy / 🚀 Deploy (push) Successful in 32s
## Summary

- **Bug fix**: EPL Elo/odds fallback was gated on \`dbEloMap.size === 0\` — if any team had a direct \`sourceElo\`, teams with only \`sourceOdds\` were never populated and the simulator threw "Missing Elo" instead of using their odds data
- **Iterations**: WorldCupSimulator default 50k→10k; manifest \`defaultConfig\` for \`world_cup\` and \`epl_standings\` now explicitly override \`BASE_CONFIG\` with 10k so the production fallback matches; test iterations reduced (WorldCup 500→100, EPL 10k→500) to fix timeout failures on slower CI
- **Cleanup**: Extracted \`runKnockoutRound\` out of the 10k-iteration simulation loop; replaced two hot-loop \`toSorted()\` calls on 2-element arrays with a conditional string comparison; removed local \`normalizeProbabilities\` in favour of the shared \`normalizeSimulationResultColumns\`

## Test plan

- [ ] \`npm run test:run\` — all simulator unit tests pass without timeout
- [ ] Typecheck passes (\`npm run typecheck\`)
- [ ] EPL simulate with mixed Elo+odds data no longer throws

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Chris Parsons <chrisparsons1127@gmail.com>
Reviewed-on: #61
2026-05-31 17:39:43 +00:00
Chris Parsons
c097e4827c
Add MLS sport simulator (mls_bracket) (#422)
* Add MLS sport simulator (mls_bracket)

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

* Fix MLS simulator: config loading, sourceOdds fallback, normalization

Three issues found in code review comparing against EPL and NFL simulators:

1. Load simulator config from DB via getSportsSeasonSimulatorConfig so
   admins can override iterations, seasonGames, parityFactor, drawRates
   per season without code changes. Previously all constants were hardcoded.

2. Add sourceOdds → convertFuturesToElo fallback when no sourceElo is
   present. EPL and NFL both do this; MLS was throwing immediately instead
   of attempting the odds conversion that the manifest declares as optional.

3. Call normalizeSimulationResultColumns before returning results, matching
   EPL's local normalization pattern for consistency (runner also normalizes
   globally, but EPL calls it locally too).

https://claude.ai/code/session_015wkBJ3SYGcMGjsddKKGkwa

* 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

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-05-14 12:45:53 -07:00
Chris Parsons
06339fd4b6
Fix EPL simulator parity config (#421) 2026-05-13 15:02:23 -07:00
Chris Parsons
af64a29cfa
Fix NCAAW futures odds simulation and admin import UX (#420)
- Revert ncaaw-simulator to Barthag win probability formula; set
  realistic rating bounds (ratingMin: 0.70, ratingMax: 0.97) so derived
  ratings stay in the range where the formula behaves well
- Add batchSaveFuturesOddsForSimulator which clears all ratings (manual
  and generated) before upserting sourceOdds, so futures odds always
  drive the simulation rather than being silently overridden by existing
  Barthag ratings from Simulator Setup
- Add clearSourceOddsForParticipants to zero out both tables for
  participants excluded from a bulk import
- Add "Clear existing odds" checkbox to the bulk import card; applies
  client-side on match and server-side on submit
- Fix missing sportsSeasonId filter in batchSaveFuturesOddsForSimulator
  pre-clear UPDATE (could have wiped ratings across other seasons)
- Fix race condition: run batchSaveSourceOdds then
  batchSaveFuturesOddsForSimulator sequentially so the simulator inputs
  table always ends in the correct cleared state
- Fix Math.round in convertFuturesToElo collapsing Barthag-scale ratings
  to 0 or 1; Elo callers already round after clamping
- Handle all-identical-odds edge case in convertFuturesToElo (assign
  midpoint instead of throwing)
- Add missingRatingStrategy: worstKnownMinus to ncaaw_bracket manifest
  so fallbackRatingDelta is live config, not dead
- Log warning in resolveRatings when only 1 participant has odds
- Reset clearExisting checkbox after applyMatches

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 01:06:16 -07:00
Chris Parsons
c88ae6b745
Upgrade NCAA preseason simulators (#419) 2026-05-12 22:26:25 -07:00
Chris Parsons
5b261bf258
Add NLL box lacrosse simulator implementation plan and preseason-draftability guidance (#417)
* docs: plan NLL preseason simulator

* Add NLL Season + Playoffs Monte Carlo simulator

14-team regular season (18 games) projects top-8 via Elo + decaying
projectedWins prior (adjusts for games already played). Playoff bracket:
QF single-game (1v8, 2v7, 3v6, 4v5), SF and Finals best-of-3. Three
runtime modes: bracket-aware → known-seed → regular-season projection.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 14:22:34 -07:00
Chris Parsons
e5295812f6
Formalize simulator system with manifest, input-policy, runner, and admin UI (#409)
Introduces three new schema tables (simulator_profiles,
sports_season_simulator_configs, season_participant_simulator_inputs),
a central model layer (app/models/simulator.ts), and a single runner
entry point so every simulator run follows the same prepare → simulate
→ persist → snapshot → recalculate flow.

Key additions:
- manifest.ts: per-simulator display names, default configs, required/
  optional inputs, derivable-input declarations, and setup sections
- input-policy.ts: resolves sourceElo from projectedWins,
  projectedTablePoints, or sourceOdds; resolves ratings from sourceOdds;
  supports block / fallbackElo / averageKnown / worstKnownMinus strategies
- runner.ts: single entry point for admin simulation runs; materialises
  derived inputs, normalises result columns, zeroes omitted participants,
  snapshots EVs, and recalculates linked fantasy standings
- /admin/simulators: inventory page with per-season readiness and bulk run
- /admin/sports-seasons/:id/simulator: per-season setup page with readiness
  summary, input-policy editor, raw JSON config override, and CSV bulk input
- NCAAM/NCAAW simulators now read ratings from season_participant_simulator_inputs,
  falling back to the hardcoded name-keyed maps while DB data is being populated
- Clone flow copies simulator config by default; volatile inputs (odds, Elo)
  only copied when explicitly requested

Code-review fixes included in this commit:
- source field in compatibility bridge checked with !== null instead of !== undefined
- sourceEloRequirementLabel no longer appends "configured fallback" when the
  participant is already excluded from all resolved sources
- Duplicate inline label maps in input-policy.ts replaced with simulatorInputLabel
- save-config preserves existing inputPolicy when the submitted JSON omits it
- Input table truncation label added (Showing 20 of N)
- CSV description notes values must not contain commas
- N+1 comment added to listSportsSeasonSimulatorSummaries
- assertRegistrySchemaDriftFree called in manifest tests
- Runner test suite added covering happy path, already-running guard,
  readiness failure, empty results, and error recovery with status reset

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 21:09:53 -07:00