// Répétition espacée — SM-2 (SuperMemo-2), documenté dans docs/learning-science-strategy.md. // Qualités : 2 = Encore (échec), 3 = Difficile, 4 = Bien, 5 = Facile. export type CardState = { ef: number; // facteur de facilité intervalDays: number; reps: number; lapses: number; }; export type ReviewQuality = 2 | 3 | 4 | 5; export function initialCardState(): CardState { return { ef: 2.5, intervalDays: 0, reps: 0, lapses: 0 }; } export function reviewCard(state: CardState, q: ReviewQuality): CardState & { dueInDays: number } { let { ef, intervalDays, reps, lapses } = state; // Mise à jour du facteur de facilité (formule SM-2) ef = ef + (0.1 - (5 - q) * (0.08 + (5 - q) * 0.02)); if (ef < 1.3) ef = 1.3; if (q < 3) { // Échec : la carte repart au début, revue dans la journée reps = 0; lapses += 1; intervalDays = 0; return { ef, intervalDays, reps, lapses, dueInDays: 0 }; } reps += 1; if (reps === 1) intervalDays = 1; else if (reps === 2) intervalDays = 6; else intervalDays = Math.round(intervalDays * ef); // « Difficile » raccourcit l'intervalle ; « Facile » l'allonge légèrement if (q === 3) intervalDays = Math.max(1, Math.round(intervalDays * 0.8)); if (q === 5) intervalDays = Math.round(intervalDays * 1.15); if (intervalDays > 365) intervalDays = 365; return { ef, intervalDays, reps, lapses, dueInDays: intervalDays }; }