# mmo.rpg — overview for AI code generation
`mmo.rpg` (PHP package `mmo.rpg`, namespace `MMO\rpg`) turns real-life objectives — habits, skills,
recovery goals — into an RPG-style progression system: pluggable XP/level curves, tiers, streaks and
inactivity decay tracked on `Objective` entities, plus simpler daily/mood event logging. It depends on
`mmo.core` (entities, routing, repositories) and `mmo.client` (the `` configurator UI is a
`.jhs` custom element).
Read the other documentation resources this server exposes (`resources/list` under the `mmo.rpg` library)
in this order:
1. **xp-system** (`docs/XP system.md`) — the design framework this package implements: the 5 original
curve families (linear/polynomial/exponential/logarithmic/logistic), the per-action XP formula,
starting-level calibration from a 0–1 skill score, tiers, and a worked example. Two notes added to
keep it honest: the shipped code has 13 curve shapes, not 5 (§3), and the "suggested objectives" table
(§7) predates the specialized curve types — `src/xp/presets.php` is the authoritative mapping now.
2. **xp-curves** (`docs/XP curves.md`) — "Human Experience Curves": the narrative/psychological background
(habit S-curve, skill step-stair, addiction inverted-hyperbolic, sustainability cyclical-wave) that
motivated the curve shapes in §1. No code maps to this 1:1 — it's the "why", not a spec.
3. **curves-framework** (`docs/Curves framework.md`) — a much broader mathematical reference catalog
(30+ curve families with formulas: Weibull, Gompertz, J-curve, inverted-U, threshold/relapse models,
multidimensional feedback loops...). Most of it is **not implemented** — it's a reference catalog to
draw from if you're adding a new `iCurve` to `CurveFactory`, not a description of current behavior.
4. **training** (`docs/Training.md`) — heads up: this is a personal workout routine (in French), not
documentation of the package. It has nothing to do with the XP system; skip it unless asked about it
specifically.
## The things that matter most
1. **A curve is an `iCurve`** (`src/xp/Curves.php`): one method, `xpForLevel(int $n, array $params): float`
— the XP cost to go from level `n-1` to level `n`. Get one via `CurveFactory::make($type)`, list all
type keys via `CurveFactory::types()`. **`CurveFactory::catalog()` is the single source of truth** for
the full list, formulas, param keys and defaults — it drives the configurator UI and is more complete
and more current than the design docs. The 13 shipped types: `linear`, `polynomial`, `exponential`,
`logarithmic`, `logistic`, `habit`, `learning`, `addiction`, `sustain`, `gompertz`, `saturation`,
`weibull`, `regression`.
2. **All the real math routes through `XPCalculator`** (`src/xp/XPCalculator.php`), constructed with
`new XPCalculator(['curveType' => ..., 'curveParams' => ..., 'tiers' => ...])`. Key methods:
`xpForLevel($n)`, `cumulativeXp($n)`, `levelTable($lMax)` (full level→tier→XP table), `tierForLevel($level, $lMax)`,
`startingLevel($skillScore, $lMax)` (`round(S × L_max)`), `levelFromTotalXp($totalXp, $lMax)` (resolve a
raw XP total into current level/progress), `actionXp($params)` (per-action XP with streak +
diminishing-returns handling), and `applyInactivityDecay($totalXp, $inactiveDays, $graceDays, $halfLifeDays, $floorXp)`
(Ebbinghaus-style half-life decay for regression).
3. **`Objective` is the persisted unit** (`src/entities/Objective.php`) — a curve config (`curveType`,
`curveParams`, `lMax`, `tiers`) plus running state (`totalXp`, `streakDays`, `lastLogDate`,
`sameDayCount`). **Don't drive `XPCalculator` by hand from application code that logs progress** — call
`$objective->logAction(float $quantity, ?float $difficultyOverride = null): array`. It folds in any
pending inactivity decay first (a lapse costs XP even if you're about to log again right now), updates
streak/diminishing-returns bookkeeping, and returns `['xpGained', 'xpDecayed', 'inactiveDays']`. Read
current status via the entity's computed properties — `getProgress()` (level/tier/XP into next level),
`getPendingDecay()`, `getInactiveDays()` — never trust a stale `totalXp` for display; it isn't corrected
for decay until `logAction()` actually persists.
4. **Ready-made objective configs live in `src/xp/presets.php`**, keyed by slug (`quit_drinking`,
`exercise`, `guitar`, `reading`, `language`, `meditation`, `running`, `cooking`, `sleep`,
`screen_time`, `saving_money`, `cold_showers`, `coding`, `public_speaking`,
`leadership_development`, `reduce_bad_habit`). Each entry is
`{name, unit, lMax, curveType, curveParams, action: {xpBase, difficultyMultiplier}, regression?, why}` —
exactly the shape `Objective`'s ArrayProperty fields expect, so a preset can be spread directly into a
new-objective payload.
5. **HTTP surface** (`src/controllers/XPController.php`) adds four routes beyond generic entity CRUD:
`GET rpg/xp/curves.json` (the catalog), `GET rpg/xp/presets.json`, `POST rpg/xp/compute.json`
(stateless level-table preview for any curve config — no `Objective` needed, used by the live
configurator before saving), and `POST rpg/xp/objectives/{id}/log.json` (calls `logAction()` on a saved
objective and commits). Saved-objective CRUD itself is **generic** `MMO\core\controllers\RepositoryController`
over `data/main/objectives.json` — there is no bespoke create/update/delete route for `Objective`.
6. **``** (`src/customElements/elements/mmo-xp-lab.jhs`) is the reference client for all of the
above: a curve configurator with a live preview chart, a preset picker, and a progress-logging panel.
If you're building any UI against this package, read it first — it exercises every route above with the
exact request/response shapes, including the two-phase bootstrap gotcha (catalog/presets must land in
the view before `form.curveType` is set, or the `