Feature Requests
Planned
[G2] Achievement engine: registry, evaluation, import backfill, notifications
The machinery that unlocks achievements. Ships with a handful of definitions for testing; the real catalogue is [G3].
Depends on: [G1] XP ledger, scoring model and level curve.
Scope
- Definitions live in code, in a shared registry — not in database rows. A self-host install must never need seeding.
UserAchievement { userId, key, unlockedAt }— only unlocks are stored. Progress is derived on read, so it stays recomputable, import-proof and free of migration debt.Two evaluation paths:
- event-driven, hooked on
ActivityEvent(already emitted fromlibrary,games,books,music,lists,reviews); - a nightly job (
JobRun, keygamification.evaluate) for everything time-based — streaks, seasonal windows.
- event-driven, hooked on
- Import backfill. Imports write straight to the database and bypass
activity.emit(), so a full recompute pass is required after an import, plus a one-off backfill when the feature ships. - Unlock notification via
NotificationwithdedupeKey = achievement:<key>, which makes it idempotent for free. - Achievement shape, one model covering three formats: an optional
tier(tiers of a family are distinct entries sharing a root) and an optional progress target give unique achievements (no tier, no target), Steam-style tiers (bronze/silver/gold with "42/100"), and secret achievements (asecretflag: the slot shows, the content doesn't). - XP award on unlock, through the G1 ledger.
Rules that constrain the engine
- No "one object = one achievement". Completion achievements only ever count diversified aggregates (50 series watched, 5 series of 5+ seasons finished), never a single completion. A given object feeds at most one achievement of its family.
- Thresholds are calibrated per domain and per consumption type — 100 episodes, 100 movies and 100 finished series are not the same effort.
- Imports grant achievements, but not all of them — which ones are excluded is decided in G3.
Out of scope
The catalogue itself and its wording/icons (G3), all UI (G4/G5), the leaderboard (G7).
0 Comments
Sign in to comment
No comments yet. Be the first to share your thoughts!
