Skip to content

The course ending shows the longest streak and the Module Rewards - #557

Merged
maximsan merged 4 commits into
mainfrom
feat/completion-moment-derived-stats
Sep 9, 2026
Merged

The course ending shows the longest streak and the Module Rewards#557
maximsan merged 4 commits into
mainfrom
feat/completion-moment-derived-stats

Conversation

@maximsan

@maximsan maximsan commented Sep 9, 2026

Copy link
Copy Markdown
Owner

Closes #149.

The completion moment's two flagged substitutions become the derivations the
spec asked for: the learner's longest streak, and the number of Module
Rewards
they earned. Both come off state that already exists, so nothing new
is stored and a reset still leaves nothing behind.

The longest run is the streak fold read at its high-water mark rather than at
its end — one fold, so it and the current streak cannot disagree about what a
run is. A Module Reward is a card the collectibles bank points at a module;
that pointer is the only thing separating the five from the thirty-two lesson
cards.

Worth knowing: collectedCardsProvider was the completion screen's last
reader, so it goes, and the two invalidations that kept it warm go with it —
the cards grid and the new count both hang off cardsWithCollectionProvider,
which those callers already refresh. getCardForModule matched on a hazard
that no longer exists (a lesson card carries no module pointer); its condition
and its note now say the same thing.

Checks: flutter analyze clean, full suite green, metrics clean, comment cap
clean on every file the branch touches.

The completion moment's two flagged substitutions (#120's build notes) are
replaced by the derivations #149 asks for, now that both inputs exist.

The longest run is the streak fold read at its high-water mark rather than
its end, so the two numbers cannot disagree about what a run is: a day a
freeze covered joins the run either side of it for both. A Module Reward is
a card the collectibles bank points at a module — the pointer only a
module-awarded card carries — counted off the cards the learner owns.

Nothing new is stored: both come off the day set and the owned-collectible
set a reset already clears.

Along the way: `collectedCardsProvider` was the completion screen's only
reader, so it goes, and with it the two invalidations that were keeping a
value nothing read. `getCardForModule` matched on a hazard that no longer
exists — a lesson card carries no module pointer — so its condition and its
note now say the same thing.

Closes #149
`isModuleReward` becomes a getter on `CoffeeCardModel`, next to the field it
reads — the shape `CollectibleUnlock.isValid` already uses. The trap it guards
against (a lesson card's owning module lives in `moduleTag`) was written out
twice; `getCardForModule` now points at the getter instead of restating it.

The count loses its provider. It chained `cardsWithCollectionProvider.future`,
which is the shape the comment directly above it warns about — a chained read
hit a Riverpod pause-state assertion under the shell. The screen watches the
grid's own provider and counts, so there is nothing new to invalidate.

Restores the half of that comment still owed: a caller that collects a card
invalidates `cardsWithCollectionProvider`, and everything showing a collection
hangs off it.
@maximsan
maximsan merged commit f1eb2a2 into main Sep 9, 2026
7 checks passed
@maximsan
maximsan deleted the feat/completion-moment-derived-stats branch September 9, 2026 17:37
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.

Completion-moment stats: longest streak and the Module Reward count, once derivable

1 participant