Refresh repository documentation
Some checks failed
Deploy to Production / test (push) Failing after 33s
Some checks failed
Deploy to Production / test (push) Failing after 33s
- Rewrite AGENTS and README files to match the current app layout - Document API routes, trivia UI, and the active panel design language
This commit is contained in:
@@ -1,11 +1,36 @@
|
||||
# Economy Module
|
||||
# Economy module
|
||||
|
||||
- All currency values are `bigint`. Never use `Number()` for arithmetic on balances -- use BigInt literals (e.g., `0n`, `500n`) and `sql` template expressions for DB updates.
|
||||
- `modifyUserBalance` is the canonical way to change a user's balance. It checks for insufficient funds on negative amounts, logs a transaction record, and emits `BALANCE_CHANGED` for quest progression. Bypass it only if you have a very good reason.
|
||||
- Daily rewards reset at **UTC midnight**, not 24h from last claim. The cooldown `expiresAt` is set to the next UTC 00:00:00. Streak breaks if the user misses an entire 24h window after the cooldown expired.
|
||||
- Daily reward is capped at `MAX_DAILY_REWARD = 500n` regardless of streak/weekly bonus.
|
||||
- The streak has a grace period: if a user's timer record is missing (e.g., DB migration), the code allows one "free" increment to avoid unfair resets.
|
||||
- Weekly bonus triggers every 7th consecutive day (streak % 7 === 0).
|
||||
- **Exam system**: a weekly check-in that rewards users based on XP gained since their last exam. The reward uses scaled BigInt arithmetic (`* 10000 / 10000n`) to avoid floating-point precision loss. Exams are locked to a specific day of the week set at registration time. Missing your exam day means zero reward -- there is no retroactive claim.
|
||||
- Lootdrops use **in-memory state** (`Map`s for channel activity and cooldowns). This state is lost on restart. The DB stores only spawned/claimed drops. Claiming uses an atomic `UPDATE ... WHERE claimedBy IS NULL` to prevent race conditions.
|
||||
- Lootdrops expire after 10 minutes and are cleaned up by a 60-second interval.
|
||||
This area is split across three services:
|
||||
|
||||
- `economy.service.ts`
|
||||
- `exam.service.ts`
|
||||
- `lootdrop.service.ts`
|
||||
|
||||
## Core rules
|
||||
|
||||
- Currency values are `bigint`
|
||||
- `modifyUserBalance()` is the canonical balance mutator for most features because it logs a transaction and emits `BALANCE_CHANGED`
|
||||
- direct balance updates still exist in a few flows where the service owns the full transaction, such as trivia entry/win and exam payout
|
||||
|
||||
## Daily rewards
|
||||
|
||||
- `claimDaily()` uses a UTC-midnight cooldown, not a rolling 24-hour timer
|
||||
- streak bonus is linear from `config.economy.daily.streakBonus`
|
||||
- weekly bonus applies every seventh claim
|
||||
- total daily reward is capped at `500n`
|
||||
- missing more than 24 hours after the cooldown expired resets the streak
|
||||
|
||||
## Weekly exam
|
||||
|
||||
- stored in `user_timers` with type `EXAM_SYSTEM`
|
||||
- registration locks the user to the current weekday
|
||||
- payout is based on XP gained since the previous exam snapshot
|
||||
- missing the assigned weekday rolls the timer forward and pays nothing
|
||||
|
||||
## Lootdrops
|
||||
|
||||
- channel activity and cooldowns are kept in memory
|
||||
- spawned drops are persisted in the `lootdrops` table
|
||||
- claiming uses an atomic update where `claimedBy IS NULL`
|
||||
- expired drops and stale activity are cleaned every 60 seconds
|
||||
- spawned drops expire after 10 minutes
|
||||
|
||||
Reference in New Issue
Block a user