brackt/app
Chris Parsons 766ba948e1
Add MLS standings sync and fix simulator conference resolution (#423)
* Add MLS standings sync and fix simulator conference resolution

- New MlsStandingsAdapter using ESPN's free soccer API (no key required),
  returning Eastern/Western conference data, W/D/L/GF/GA/GD/PTS, conference
  rank, and home/away records; registered under mls_bracket
- Display route now shows soccer table columns and a 9-team playoff cutoff
  line for mls_bracket (top 9 per conference qualify for MLS Cup Playoffs)
- MLS simulator gains a third conference fallback: reads externalId="Eastern"
  or "Western" on the participant, mirroring the LLWS pool-assignment pattern
  so admins can bootstrap conference data before the first standings sync
- 9 unit tests covering stat mapping, conference normalization, rank ordering,
  and error paths

https://claude.ai/code/session_01WhzXHpv6taXdHzhgvnv83u

* Address code review feedback on MLS standings + simulator

1. Update mls-simulator.ts module comment to document the new step-3
   externalId fallback in the conference resolution order
2. Tighten normalizeConference to exact-match "Eastern"/"Western
   Conference" instead of broad substring, preventing false matches
   on names like "Northeast"
3. Pre-parse statsMap for each entry before the sort so it isn't
   rebuilt O(n log n) times during comparison
4. Document the externalId name-matching tradeoff on
   parseConferenceFromExternalId
5. Try ESPN's gamesPlayed stat before falling back to wins+losses+ties
   sum; export parseConferenceFromExternalId for direct testing
6. Add tests: normalizeConference passthrough, winPct=0 at preseason,
   and parseConferenceFromExternalId (case-insensitivity, null/undefined,
   numeric ESPN IDs, unrecognized strings)

https://claude.ai/code/session_01WhzXHpv6taXdHzhgvnv83u

* Fix lint: replace != null with !== null && !== undefined

oxlint enforces eqeqeq; the five != null checks in mls.ts were flagged.

https://claude.ai/code/session_01WhzXHpv6taXdHzhgvnv83u

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-05-14 15:39:40 -07:00
..
components Fix standings table bugs and polish across all three scoring patterns (#415) 2026-05-12 10:39:25 -07:00
contexts
hooks Add electric flash + fade animation for draft picks, fixes #381 (#407) 2026-05-10 23:17:29 -07:00
lib Add branded dark-themed HTML email template (#402) 2026-05-10 11:18:57 -07:00
models Fix EPL simulator parity config (#421) 2026-05-13 15:02:23 -07:00
routes Add MLS standings sync and fix simulator conference resolution (#423) 2026-05-14 15:39:40 -07:00
services Add MLS standings sync and fix simulator conference resolution (#423) 2026-05-14 15:39:40 -07:00
test Remove first and last name from user profiles (#399) 2026-05-09 09:18:50 -07:00
types Redesign standings page with sortable table, 7-day change, and chart repositioned (#205) 2026-03-22 11:05:13 -07:00
utils Canonical tournament layer: schema + backfill (1/2) (#365) 2026-05-01 20:13:18 -07:00
welcome Redesign to dark-mode-only with navy palette and accent colors (#13) 2026-02-20 19:26:11 -08:00
app.css Add electric flash + fade animation for draft picks, fixes #381 (#407) 2026-05-10 23:17:29 -07:00
entry.client.tsx Filter unnecessary sentry css and js errors. 2026-03-15 10:24:57 -07:00
entry.server.tsx Replace console.* with structured logger, fix no-inferrable-types (closes #98) (#199) 2026-03-21 13:41:39 -07:00
root.tsx Add Cloudinary-backed avatar system (#385) 2026-05-06 14:47:37 -07:00
routes.ts Formalize simulator system with manifest, input-policy, runner, and admin UI (#409) 2026-05-11 21:09:53 -07:00