import '../models/question.dart'; /// Handles spaced repetition logic for known questions. class SpacedRepetition { /// Base probability for known questions (very low). static const double baseKnownProbability = 0.01; /// Maximum probability for known questions. static const double maxKnownProbability = 0.15; /// Calculates the probability weight for a known question based on /// how long it's been since it was last seen. /// /// [lastAttemptIndex] is the last attempt where the question was seen. /// [currentAttemptIndex] is the current global attempt index. static double calculateKnownQuestionWeight({ required int lastAttemptIndex, required int currentAttemptIndex, }) { if (lastAttemptIndex < 0) { // Never seen before, use base probability return baseKnownProbability; } final attemptsSinceLastSeen = currentAttemptIndex - lastAttemptIndex; // Probability increases with attempts since last seen // Formula: base + (min(attemptsSinceLastSeen / 20, 1) * (max - base)) final progress = (attemptsSinceLastSeen / 20.0).clamp(0.0, 1.0); final probability = baseKnownProbability + (progress * (maxKnownProbability - baseKnownProbability)); return probability; } /// Gets the weight for a question considering its known status and /// last attempt index. static double getQuestionWeight({ required Question question, required int currentAttemptIndex, required double basePriorityWeight, }) { if (question.isKnown) { // Known questions use spaced repetition probability return calculateKnownQuestionWeight( lastAttemptIndex: question.lastAttemptIndex, currentAttemptIndex: currentAttemptIndex, ) * basePriorityWeight; } else { // Unknown questions use priority-based weight // Priority points + 1 to ensure non-zero weight return (question.priorityPoints + 1).toDouble(); } } }