import { ReviewLog } from '../models/ReviewLog.js'; import { StudyItem } from '../models/StudyItem.js'; import { getDaysDiff, getSRSDate } from '../utils/dateUtils.js'; export const processReview = async (user, subjectId, success) => { if (!user.stats) user.stats = { totalReviews: 0, correctReviews: 0, currentStreak: 0, maxStreak: 0 }; user.stats.totalReviews += 1; if (success) user.stats.correctReviews += 1; const todayStr = new Date().toISOString().split('T')[0]; const lastStudyStr = user.stats.lastStudyDate; if (lastStudyStr !== todayStr) { if (!lastStudyStr) { user.stats.currentStreak = 1; } else { const diff = getDaysDiff(lastStudyStr, todayStr); if (diff === 1) { user.stats.currentStreak += 1; } else if (diff > 1) { const lastFreeze = user.stats.lastFreezeDate ? new Date(user.stats.lastFreezeDate) : null; let daysSinceFreeze = 999; if (lastFreeze) daysSinceFreeze = getDaysDiff(lastFreeze.toISOString().split('T')[0], todayStr); const canUseShield = daysSinceFreeze >= 7; if (canUseShield && diff === 2) { console.log(`User ${user._id} saved by Zen Shield!`); user.stats.lastFreezeDate = new Date(); user.stats.currentStreak += 1; } else { user.stats.currentStreak = 1; } } } user.stats.lastStudyDate = todayStr; if (user.stats.currentStreak > user.stats.maxStreak) user.stats.maxStreak = user.stats.currentStreak; } await user.save(); await ReviewLog.findOneAndUpdate( { userId: user._id, date: todayStr }, { $inc: { count: 1 } }, { upsert: true, new: true } ); const item = await StudyItem.findOne({ userId: user._id, wkSubjectId: subjectId }); if (!item) throw new Error('Item not found'); if (!item.stats) item.stats = { correct: 0, total: 0 }; item.stats.total += 1; if (success) item.stats.correct += 1; if (success) { const nextLevel = Math.min(item.srsLevel + 1, 10); item.srsLevel = nextLevel; item.nextReview = getSRSDate(nextLevel); } else { item.srsLevel = Math.max(1, item.srsLevel - 1); item.nextReview = Date.now(); } await item.save(); return { nextReview: item.nextReview, srsLevel: item.srsLevel }; }; export const getQueue = async (user, limit = 100, sortMode) => { const query = { userId: user._id, srsLevel: { $lt: 10, $gt: 0 }, nextReview: { $lte: new Date() } }; let dueItems; if (sortMode === 'priority') { dueItems = await StudyItem.find(query).sort({ srsLevel: 1, level: 1 }).limit(limit); } else { dueItems = await StudyItem.find(query).limit(limit); for (let i = dueItems.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [dueItems[i], dueItems[j]] = [dueItems[j], dueItems[i]]; } } return dueItems; }; export const getLessonQueue = async (user, limit = 100) => { const query = { userId: user._id, srsLevel: 0 }; return await StudyItem.find(query).sort({ level: 1, wkSubjectId: 1 }).limit(limit); }; export const processLesson = async (user, subjectId) => { const item = await StudyItem.findOne({ userId: user._id, wkSubjectId: subjectId }); if (!item) throw new Error('Item not found'); item.srsLevel = 1; item.nextReview = getSRSDate(1); await item.save(); return { success: true, item }; };