Goal
Show whether each plotted team game was a win or loss so the Hits, Strikeouts, Runs, and future comparison charts can put the statistical trend in game-result context.
Data model
Prefer persisting the opponent's run total rather than a redundant W/L string:
- add
opponent_runs to the normalized/persisted team-game record
- derive the game result from
runs vs opponent_runs
- handle an equal score explicitly if the source ever represents a completed tie; do not silently classify equality as a loss
Because existing rows predate this field, preserve legacy data honestly. A migration should not fabricate opponent scores. If the new column must be nullable for old rows, fresh normalization should still require a real opponent score whenever the upstream source provides one, and re-importing a team-season should backfill it.
Before implementation, confirm which existing MLB response/schedule structure is the authoritative source for the opponent score. Do not add a new network call if the data is already present in the responses used for ingestion.
Chart behavior
For each individual-game observation, expose the result without changing the meaning of the metric:
- distinguish wins and losses on raw game markers
- include
Result: W / Result: L in hover text
- keep rolling averages, team season averages, and MLB averages unchanged
- do not encode W/L into the rolling or reference lines
- preserve readability and accessibility; do not rely on color alone if marker shape or another cue can distinguish outcomes
Apply the result treatment consistently to the team-game charts that exist on main at implementation time. Do not duplicate result logic separately inside each chart builder if one small typed/helper representation can carry the outcome cleanly.
Semantics
The result is descriptive context only. A win marker does not imply that the plotted metric caused the win.
Prefer deriving:
runs > opponent_runs -> W
runs < opponent_runs -> L
runs = opponent_runs -> T / explicit tie state if encountered
Do not store both scores and a second persisted result value unless there is a concrete reason; that would create two sources of truth.
Preserve
- existing Hits, Strikeouts, Runs analytics
- rolling-window calculations
- MLB-average calculations and COMPLETE coverage semantics
- browser routes remain DB-only
- server-rendered FastAPI/Jinja architecture
- local Plotly rendering
- empty/missing-data behavior
Testing
Cover at minimum:
- normalization/persistence of opponent runs
- migration behavior for legacy rows
- re-import/backfill behavior
- W/L derivation from team and opponent scores
- equality handled explicitly
- chart markers/hover show the correct result
- legacy rows without opponent score remain honest rather than inventing a result
- rolling/team/MLB averages remain numerically unchanged
- zero MLB API calls during normal browser rendering
Out of scope
- win probability
- Pythagorean expectation
- run-expectancy models
- causal claims between a metric and game outcome
- standings/record calculations
- using W/L to filter or recompute the statistical trend
Completion
A reader can look at an individual game point on the team charts and immediately tell whether that game was a win or loss, backed by persisted score data rather than a guessed or duplicated result field.
Goal
Show whether each plotted team game was a win or loss so the Hits, Strikeouts, Runs, and future comparison charts can put the statistical trend in game-result context.
Data model
Prefer persisting the opponent's run total rather than a redundant
W/Lstring:opponent_runsto the normalized/persisted team-game recordrunsvsopponent_runsBecause existing rows predate this field, preserve legacy data honestly. A migration should not fabricate opponent scores. If the new column must be nullable for old rows, fresh normalization should still require a real opponent score whenever the upstream source provides one, and re-importing a team-season should backfill it.
Before implementation, confirm which existing MLB response/schedule structure is the authoritative source for the opponent score. Do not add a new network call if the data is already present in the responses used for ingestion.
Chart behavior
For each individual-game observation, expose the result without changing the meaning of the metric:
Result: W/Result: Lin hover textApply the result treatment consistently to the team-game charts that exist on
mainat implementation time. Do not duplicate result logic separately inside each chart builder if one small typed/helper representation can carry the outcome cleanly.Semantics
The result is descriptive context only. A win marker does not imply that the plotted metric caused the win.
Prefer deriving:
Do not store both scores and a second persisted result value unless there is a concrete reason; that would create two sources of truth.
Preserve
Testing
Cover at minimum:
Out of scope
Completion
A reader can look at an individual game point on the team charts and immediately tell whether that game was a win or loss, backed by persisted score data rather than a guessed or duplicated result field.