fix(pet): человекочитаемые подписи в ленте XP питомца
Лента «последних начислений» печатала сырые коды причин из xp_log (achievement:cr_5_lessons, tb:math-6-ch1-ach-start, lesson_complete). Добавлен резолвер _xpReasonLabel: achievement:<slug> -> «Достижение «<title>»» через ACHIEVEMENT_DEFS, tb:* -> «Учебник», недостающие фиксированные причины (lesson_complete/daily_goal/daily_activity/ lab_experiment), сохранение уже-читаемых фраз, фолбэк «Награда». Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,36 @@
|
||||
'use strict';
|
||||
const db = require('../db/db');
|
||||
const { awardCoins } = require('./gamificationController');
|
||||
const { ACHIEVEMENT_DEFS } = require('./gamification/_shared');
|
||||
|
||||
/* ── XP-log reason → человекочитаемый ярлык для ленты активности питомца ──
|
||||
Сырые коды причин (`achievement:slug`, `tb:...`, `lesson_complete`, …)
|
||||
не должны попадать в UID — резолвим их в понятные подписи. */
|
||||
const SOURCE_LABELS = {
|
||||
hangman_win: 'Виселица', crossword_win: 'Кроссворд',
|
||||
test_answer: 'Тест', challenge: 'Задание',
|
||||
lab_activity: 'Лаборатория', lab_experiment: 'Лаборатория',
|
||||
assignment: 'Домашнее задание',
|
||||
pet_petting: 'Поглаживание', pet_feeding: 'Кормёжка питомца',
|
||||
mood_ecstatic: 'Бонус настроения', correct_answers: 'Тест',
|
||||
test_complete: 'Тест', 'test_90+': 'Тест 90%+', test_perfect: 'Тест 100%',
|
||||
daily_activity: 'Активность дня', daily_goal: 'Цель дня',
|
||||
lesson_complete: 'Урок пройден',
|
||||
};
|
||||
const _ACH_TITLE = new Map(ACHIEVEMENT_DEFS.map(a => [a.slug, a.title]));
|
||||
|
||||
function _xpReasonLabel(reason) {
|
||||
if (!reason) return 'Награда';
|
||||
if (reason.startsWith('achievement:')) {
|
||||
const t = _ACH_TITLE.get(reason.slice('achievement:'.length));
|
||||
return t ? `Достижение «${t}»` : 'Достижение';
|
||||
}
|
||||
if (reason.startsWith('tb:')) return 'Учебник';
|
||||
if (SOURCE_LABELS[reason]) return SOURCE_LABELS[reason];
|
||||
// Уже читаемая фраза (например «Испытание: …») — содержит пробел/кириллицу.
|
||||
if (/[А-Яа-яЁё ]/.test(reason)) return reason;
|
||||
return 'Награда';
|
||||
}
|
||||
|
||||
const BG_SHOP = [
|
||||
{ id:'space', name:'Космос', price:50, desc:'Звёздный простор' },
|
||||
@@ -115,19 +145,11 @@ function getPet(req, res) {
|
||||
weeklyXP.push({ day: d.toLocaleDateString('ru', { weekday: 'short' }), xp: weekMap.get(dateStr) || 0 });
|
||||
}
|
||||
|
||||
const SOURCE_LABELS = {
|
||||
hangman_win: 'Виселица', crossword_win: 'Кроссворд',
|
||||
test_answer: 'Тест', challenge: 'Задание',
|
||||
lab_activity: 'Лаборатория', assignment: 'Домашнее задание',
|
||||
pet_petting: 'Поглаживание', pet_feeding: 'Кормёжка питомца',
|
||||
mood_ecstatic: 'Бонус настроения', correct_answers: 'Тест',
|
||||
test_complete: 'Тест', 'test_90+': 'Тест 90%+', test_perfect: 'Тест 100%',
|
||||
};
|
||||
const rawActivity = db.prepare(
|
||||
"SELECT amount, reason, created_at FROM xp_log WHERE user_id = ? ORDER BY created_at DESC LIMIT 6"
|
||||
).all(req.user.id);
|
||||
const recentActivity = rawActivity.map(r => ({
|
||||
xp: r.amount, label: SOURCE_LABELS[r.reason] || r.reason, at: r.created_at,
|
||||
xp: r.amount, label: _xpReasonLabel(r.reason), at: r.created_at,
|
||||
}));
|
||||
|
||||
const pettingCooldown = user.pet_last_petted
|
||||
|
||||
Reference in New Issue
Block a user