[fix] Event Strength of Schedule crash and Simulation EPA column - #8
Closed
chondl wants to merge 2 commits into
Closed
[fix] Event Strength of Schedule crash and Simulation EPA column#8chondl wants to merge 2 commits into
chondl wants to merge 2 commits into
Conversation
Floor the EPA-percentile Gaussian variance so it is always > 0. When every team at an event shares the same pre-event start EPA (true for all events early in a season, before ratings diverge), epaSd is 0, so the variance (epaSd^2 * 5 / N) is 0 -- or NaN when floating-point error makes the variance argument to Math.sqrt slightly negative. gaussian() throws on variance <= 0, which rejected the un-awaited strengthOfSchedule() promise in the worker and left the SOS table blank; the NaN path instead rendered NaN in the EPA/Composite columns. Both are the same degeneracy. '|| 1e-9' treats 0 and NaN alike, yielding a neutral 0.5 EPA percentile, and leaves every real positive variance untouched.
Read the team EPA from epa.breakdown.total_points, the field the SOS tab and the simulation worker already use. simulation.tsx read epa.total_points.mean, which matches the stale APITeamEvent type but not the runtime shape: the backend serves epa.total_points as a plain number, so .mean is undefined and every row rendered EPA 0.
Owner
Author
|
Superseded — both fixes (SOS variance floor, Simulation EPA field) relocated to #5. Branch kept. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two fixes to the event page's live-simulation feature, both surfaced by
rigorously testing the Strength of Schedule and Simulation tabs against
several 2026 events. Both bugs are pre-existing:
worker.tsandsimulation.tsxare unchanged on every branch relative to
master.1. Strength of Schedule renders blank (or NaN) when pre-event EPAs are identical
Symptom. On the Strength of Schedule tab the RP/Rank/EPA/Composite score
columns fail to populate. Two observed manifestations across events:
NaNin EPA Score and Composite Score (RP/Rank Score present).Root cause.
strengthOfSchedule()calls_strengthOfSchedule(data, simCount, false)(the "Before Event" pass) first. That pass computesepaSd, the standarddeviation of every team's pre-event start EPA, and builds a Gaussian to score
EPA-based schedule strength:
Early in a season — before ratings diverge — every team at an event shares the
same cold-start EPA, so
epaSdis0, the variance is0, andgaussianthrows
Error('Variance must be > 0'). Because the worker's message handlercalls
strengthOfSchedule(...)withoutawait/catch, the throw becomes asilent unhandled promise rejection inside the worker: no message is posted and
the table stays blank. A floating-point variant produces the
NaNsymptom —with all EPAs equal,
Math.sqrt(sum(x^2)/n - avg^2)occasionally takes the rootof a tiny negative rounding residue, so
epaSdisNaN,gaussiandoes notthrow (
NaN <= 0is false), and every EPA percentile isNaN. Both are the samedegeneracy: EPA carries no schedule signal when all ratings are identical.
Fix. Floor the variance with
|| 1e-9, which treats both0andNaNasfalsy and substitutes a negligible positive variance; with
deltaEPA == 0theCDF at the mean is
0.5, so every team gets a neutral0.5EPA percentile — thecorrect answer when EPA is non-informative. Any real positive variance passes
through untouched, so events with diverged ratings are unaffected. Matches the
|| 0fallback idiom already used throughout this worker.2. Simulation tab shows EPA 0 for every team
Symptom. On the Simulation tab the EPA column reads
0for all teams(the predicted ranks, RP means, and percentiles are correct).
Root cause.
simulation.tsxreads the team EPA asteamEvent.epa.total_points.mean. That matches theAPITeamEventTypeScripttype, but not the runtime shape: the backend serves
epa.total_pointsas a plainnumber, so
.meanisundefinedand?? 0renders0.Fix. Read
epa.breakdown.total_points— the same field the SOS tab and thesimulation worker already use — which is present at runtime.
Verification
Reproduced and confirmed fixed against completed 2026 events:
epaSd == 0event: before — Gaussian throws, SOS blank; after — all score columns populate (EPA Score0.5).epaSd == NaN(float rounding) event: before — EPA/CompositeNaN; after — populate (EPA Score0.5).0.387before and after — unchanged (fix is inert on the non-degenerate path).0before, real per-team EPA after; predicted-rank distributions unchanged and still vary run-to-run.