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

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();
}
}
}

Powered by TurnKey Linux.