Function
The catalog levels and the rules deciding earned tickets and claimed prizes
Each course's module prizes and their tickets
Nothing here is stored: achievements are recomputed from what the caller says the learner has earned and claimed, which keeps this module free of storage and hooks and lets the client use the same completion rule every progress surface uses.
A module's prize comes from the prize catalog by its slug. A module holding no
lessons has nothing to redeem, so it has no prize. A prize whose tickets are
all earned is ready until the learner claims it on the counter, and
claimed from then on — so only claimed prizes count as redeemed.
The distinction follows tickets alone: claiming changes nothing about it.
Derives the learner's tickets, module prizes, totals and distinction from the catalog.