mirror of
https://github.com/domfelipe/pokebuddy.git
synced 2026-08-07 06:56:50 +00:00
feat: add XP progression engine
This commit is contained in:
parent
d4adb04e10
commit
78697fb163
1 changed files with 70 additions and 0 deletions
70
src/progression.js
Normal file
70
src/progression.js
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
export const XP_REWARDS = Object.freeze({
|
||||||
|
task_started: 2,
|
||||||
|
task_done: 25,
|
||||||
|
task_cancelled: 1,
|
||||||
|
command_success: 6,
|
||||||
|
command_failure: 2,
|
||||||
|
tests_passed: 18,
|
||||||
|
tests_failed: 4,
|
||||||
|
build_passed: 16,
|
||||||
|
build_failed: 3,
|
||||||
|
lint_passed: 12,
|
||||||
|
lint_failed: 3,
|
||||||
|
typecheck_passed: 12,
|
||||||
|
typecheck_failed: 3,
|
||||||
|
commit_created: 20,
|
||||||
|
merge_completed: 28,
|
||||||
|
push_attempted: 8,
|
||||||
|
docs_written: 15,
|
||||||
|
watch_changed: 4,
|
||||||
|
manual_focus: 10
|
||||||
|
});
|
||||||
|
|
||||||
|
export const LEVEL_TITLES = Object.freeze([
|
||||||
|
{ min: 1, title: 'Hatchling' },
|
||||||
|
{ min: 2, title: 'Junior Companion' },
|
||||||
|
{ min: 5, title: 'Debug Partner' },
|
||||||
|
{ min: 10, title: 'Terminal Guardian' },
|
||||||
|
{ min: 20, title: 'Senior Beast' },
|
||||||
|
{ min: 35, title: 'Mythic Companion' },
|
||||||
|
{ min: 50, title: 'Legend of the Prompt' }
|
||||||
|
]);
|
||||||
|
|
||||||
|
export function xpForNextLevel(level) {
|
||||||
|
return Math.max(1, level) * Math.max(1, level) * 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function levelFromXp(xp = 0) {
|
||||||
|
let level = 1;
|
||||||
|
while (xp >= xpForNextLevel(level)) {
|
||||||
|
level += 1;
|
||||||
|
}
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function titleForLevel(level = 1) {
|
||||||
|
return LEVEL_TITLES.filter((entry) => level >= entry.min).at(-1)?.title ?? 'Hatchling';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function progressToNextLevel(xp = 0) {
|
||||||
|
const level = levelFromXp(xp);
|
||||||
|
const previous = level <= 1 ? 0 : xpForNextLevel(level - 1);
|
||||||
|
const next = xpForNextLevel(level);
|
||||||
|
return {
|
||||||
|
level,
|
||||||
|
title: titleForLevel(level),
|
||||||
|
current: Math.max(0, xp - previous),
|
||||||
|
needed: Math.max(1, next - previous),
|
||||||
|
previous,
|
||||||
|
next
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function applyXp(entry, amount) {
|
||||||
|
const beforeLevel = entry.level ?? levelFromXp(entry.xp ?? 0);
|
||||||
|
entry.xp = Math.max(0, (entry.xp ?? 0) + amount);
|
||||||
|
entry.level = levelFromXp(entry.xp);
|
||||||
|
entry.energy = Math.min(100, Math.max(0, (entry.energy ?? 50) + Math.min(12, Math.ceil(amount / 3))));
|
||||||
|
entry.mood = entry.level > beforeLevel ? 'level-up' : amount >= 15 ? 'proud' : 'focused';
|
||||||
|
return { beforeLevel, afterLevel: entry.level, leveledUp: entry.level > beforeLevel };
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue