# Leveling module

## Model

- total XP is the source of truth
- level is derived from XP on each award
- XP curve is driven by `config.leveling.base` and `config.leveling.exponent`

## Main methods

- `getXpToReachLevel(level)`
- `getLevelFromXp(totalXp)`
- `getXpForNextLevel(currentLevel)`
- `addXp(userId, amount)`
- `processChatXp(userId)`

## Chat XP

- gated by a `user_timers` cooldown on `TimerKey.CHAT_XP`
- base award is random between `config.leveling.chat.minXp` and `maxXp`
- active XP boost timers can multiply the award

## Notes

- `addXp()` emits `XP_GAINED` for quest progression
- the level curve currently converts `bigint` XP to `number` for the math loop, so extremely large totals would be the stress point to watch
