Skip to main content
XP calculation is deterministic and pure. The calculator lives in packages/core/src/xp/calculator.ts.

Formula

final_xp = base_xp × difficulty_multiplier × streak_multiplier × proof_multiplier
All multipliers are applied multiplicatively, not additively.

Difficulty Multipliers

DifficultyMultiplier
easy1.0
medium1.5
hard2.0
epic3.0

Streak Multipliers

Streak DaysTierMultiplier
0–2None1.00
3–6Spark1.10
7–13Flame1.20
14–29Blaze1.30
30–59Inferno1.40
60–99Wildfire1.45
100+Eternal Fire1.50

Proof Multipliers

Proof TypeMultiplier
self-report1.00
timestamp1.05
duration1.10
process-check1.20
file-change1.20
git-commit1.30
screenshot1.30
calendar-match1.30
ai-verify1.40
multi-proof1.50

Level Curve

Character level uses an exponential curve. Early levels are fast; later levels require significantly more XP:
levelFromXp(xp: number): number
The curve is defined in xp/constants.ts as a threshold array. Level 1 requires ~100 XP; each subsequent level requires ~20% more than the previous.

Skill Level Curve

Skill levels use the same curve shape as character levels but with independent counters. A skill’s level reflects only XP earned from quests tagged with that skill.
skillLevelFromXp(xp: number): number

Using the Calculator

import { calculateXp, levelFromXp, skillLevelFromXp } from "@grindxp/core/xp";

const xp = calculateXp({
  baseXp: 100,
  difficulty: "hard",
  streakDays: 14,
  proofType: "git-commit",
});
// → 100 × 2.0 × 1.30 × 1.30 = 338

const level = levelFromXp(totalXp);
const skillLevel = skillLevelFromXp(skillXp);