Skip to content

fix: render the season in progress rather than dropping it at the loader and the window - #12

Merged
stxkxs merged 1 commit into
mainfrom
fix/season-in-progress
Sep 19, 2026
Merged

stxkxs merged 1 commit into
mainfrom
fix/season-in-progress

Conversation

@stxkxs

@stxkxs stxkxs commented Sep 19, 2026

Copy link
Copy Markdown
Owner

Two independent defects hid the season under way. Five tools opened on the season before it; the sixth carried its rows but showed none of them.

The participation sidecar

nfl_data_py's import_pbp_data merges a per-season pbp_participation asset and reads it under the same try as the play-by-play. Its handler names an unbound Error, so every failure in that block raises NameError in place of the failure that reached it. nflverse publishes the two assets independently, so a season carrying play-by-play and no sidecar raises NameError, which the loader reads as a season the request cannot obtain and drops whole.

_nflverse_pbp declines the merge. No column this repository reads comes from the sidecar. The drop reached past the red zone view: a season in progress reaches the play-by-play derivation in _fetch_weekly_stats, and that path raised the same NameError.

The weeks that open a season

Snap Share and Waiver Wire ended on drop_nulls(["rolling_avg", "velocity"]), and velocity needed three rows inside one season, so a season's opening weeks left the frame — and with them the season itself, because both screens build their filters from the trended rows.

Every week a player has usage for is now a row; the week opening their season carries its share and a null trend, rendered as the em dash the screens already used for every other absent measure. Velocity slopes across weeks rather than rows: a lag is admitted only where the weeks it spans fall inside the window, so a player back from a long absence carries no velocity rather than a whole absence's change reported as one week of movement.

One line per player-week

Derived weekly stats emitted a player twice in a week from two directions — fumbles grouped on posteam, which on a return names the kicking team, and each role grouped on the player's name beside their id. Both fed the waiver join, where a duplicate became a player trended against their own second row.

The season a trade is made in

Trade Value gated its season filter on the three completed weeks a ranking rests on, presenting a finished season's closing chart as the live one. The filter offers a season as soon as one of its weeks has been played, and the table says what the season is still short of.

Verification

  • 480 tests pass; ruff check, ruff format --check and mypy src clean.
  • Against live nflverse data, all six tools resolve season options ending in 2026 and default to it.
  • Zero duplicate (player_id, season, week) rows in the derived weekly stats, down from nine.

…der and the window

Two independent defects hid the season under way. Five tools opened on the
season before it; the sixth carried its rows but showed none of them.

─── The participation sidecar ───

nfl_data_py's import_pbp_data merges a per-season pbp_participation asset and
reads it under the same try as the play-by-play. Its handler names an unbound
`Error`, so every failure in that block raises NameError in place of the
failure that reached it. nflverse publishes the two assets independently, so a
season carrying play-by-play and no sidecar raises NameError, which the loader
reads as a season the request cannot obtain and drops whole.

_nflverse_pbp declines the merge. No column this repository reads comes from
the sidecar: import_pbp_data joins it on play_id and old_game_id and
contributes only columns named nowhere in src. The option reaches nfl_data_py
bound onto the importer through functools.partial, which leaves _download one
keyword — its own timeout — and no way for an importer argument to shadow it.

The drop reached further than the red zone view. nflverse publishes a
weekly-stats asset per season after its games, so a season in progress reaches
the play-by-play derivation in _fetch_weekly_stats, and that path raised the
same NameError. Declining the sidecar restores both.

─── What a drop can claim ───

A missing release asset and a failed transfer reach these loaders as one
exception, so nothing below them can name a cause. The warning and the
RuntimeError name the dataset and the seasons that yielded nothing, and stop
there; _SeasonUnavailable says the importer returned no data rather than that
the source holds none. The README troubleshooting section draws the same line:
a season that returns on the next load was a failed transfer, and one that
stays absent is waiting on the source.

─── The weeks that open a season ───

Snap Share and Waiver Wire ended their trend computation on
drop_nulls(["rolling_avg", "velocity"]), and velocity needed three rows inside
one season, so a season's opening weeks left the frame — and with them the
season itself, because both screens build their filters from the trended rows.

A share is a measurement and a trend is a comparison. Every week a player has
usage for is a row; the week that opens their season carries its share and a
null rolling average, delta, velocity and trend. The screens render an absent
trend as the em dash they already rendered every other absent measure with, and
sort the rows carrying none of it last.

Velocity slopes across weeks rather than rows. `shift` counts a player's
appearances, so a candidate lag reaches a week whose distance depends on which
weeks they were active; each lag is admitted only where the weeks it spans fall
inside the window, and the slope divides by those weeks. A player back from an
absence longer than the window carries no velocity and no trend: there is no
recent series under them. Without that check a returning player's first row
divides a whole absence's change by one week and sorts to the top of the alert
panel.

─── One line per player-week ───

Weekly stats derived from play-by-play emitted a player twice in a week from
two directions. Fumbles grouped on posteam, which on a punt or a kickoff names
the kicking team, so a returner's fumble opened a second line under a team they
never played for; fumbled_1_team names the fumbler's own. Each role grouped on
the player's name beside their id, and nflverse spells a name from the source
field of each play, so one id carrying two spellings inside one role split its
week into two partial lines. The name is taken off the group instead.

Both halves fed the waiver join, where a duplicate became a player trended
against their own second row.

─── The season a trade is made in ───

Trade Value gated its season filter on the three completed weeks a ranking
rests on, so until a season reached them the filter offered only the season
before — presenting a finished season's closing chart as the live one. The
filter offers a season as soon as one of its weeks has been played, and the
table says what the season is still short of.

An empty filter and absent data are separate answers. _no_ranking_message
distinguishes a load carrying no played week, a season not yet chosen, a season
fewer weeks deep than the floor, and a week not yet chosen. Clearing the season
clears the week and team options with it, which otherwise stand offering the
weeks of whichever season was chosen before.

─── Tests ───

FakeNflverse records the keyword arguments of every call, and two tests pin the
sidecar option on both play-by-play paths. Because that fake replaces the
function performing the binding, a third installs a stand-in nfl_data_py module
and asserts the importer itself receives the option.

The engine tests assert that a season's opening week is kept without a trend,
that the week after it slopes across the one week behind it, and that a week
beyond the window from the last one played carries neither velocity nor trend.
The stats tests cover a fumble on a return and a player spelled two ways inside
one role. The view tests cover a season too few weeks deep to rank, a season
with no played week, and a cleared season filter.

Co-authored-by: stxkxsbot <275011021+stxkxsbot@users.noreply.github.com>
@stxkxs
stxkxs merged commit 763c981 into main Sep 19, 2026
2 checks passed
@stxkxs
stxkxs deleted the fix/season-in-progress branch September 19, 2026 18:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant