fix(anti-cheat): анти-фарм XP в играх и при повторном завершении урока (Спринт1 #2,#3)
- games: дневной лимит начислений XP за hangman/crossword (DAILY_WIN_CAP=10, счёт по xp_log.reason) — нельзя бесконечно фармить циклом complete. - lessons.markComplete: XP/монеты только при ПЕРВОМ завершении урока (повторные POST больше ничего не начисляют). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -186,6 +186,10 @@ function markComplete(req, res) {
|
||||
const lesson = db.prepare('SELECT * FROM lessons WHERE id = ?').get(req.params.id);
|
||||
if (!lesson) return res.status(404).json({ error: 'Lesson not found' });
|
||||
|
||||
// Награду даём только при ПЕРВОМ завершении (анти-фарм повторными POST).
|
||||
const prev = db.prepare('SELECT completed FROM lesson_progress WHERE user_id = ? AND lesson_id = ?').get(req.user.id, lesson.id);
|
||||
const firstCompletion = !prev || prev.completed !== 1;
|
||||
|
||||
db.prepare(`
|
||||
INSERT INTO lesson_progress (user_id, lesson_id, completed, updated_at)
|
||||
VALUES (?, ?, 1, datetime('now'))
|
||||
@@ -201,7 +205,7 @@ function markComplete(req, res) {
|
||||
WHERE l.course_id = ? AND lp.user_id = ? AND lp.completed = 1
|
||||
`).get(lesson.course_id, req.user.id).n;
|
||||
|
||||
try { onLessonComplete(req.user.id, lesson.course_id); } catch {}
|
||||
if (firstCompletion) { try { onLessonComplete(req.user.id, lesson.course_id); } catch {} }
|
||||
res.json({ ok: true, courseComplete: done >= total && total > 0 });
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user