You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
57 lines
1.9 KiB
57 lines
1.9 KiB
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();
|
|
}
|
|
}
|
|
}
|
|
|