calculate method

FsrsResult calculate({
  1. required FsrsState state,
  2. required FsrsRating rating,
  3. required double elapsedDays,
  4. double targetRetention = 0.9,
})

Schedule a card given its current state, the user's rating, and the number of elapsedDays since last review. targetRetention controls the desired recall probability (default 0.9).

Implementation

FsrsResult calculate({
  required FsrsState state,
  required FsrsRating rating,
  required double elapsedDays,
  double targetRetention = 0.9,
}) {
  final ratingIdx = rating.index; // 0=again, 1=hard, 2=good, 3=easy

  double newStability;
  double newDifficulty;
  FsrsCardState newState;

  if (state.cardState == FsrsCardState.newCard) {
    // First review — use initial stability from parameters.
    newStability = w[ratingIdx];
    newDifficulty = _initDifficulty(ratingIdx);
    newState = rating == FsrsRating.again
        ? FsrsCardState.learning
        : FsrsCardState.review;
  } else if (rating == FsrsRating.again) {
    // Lapse: stability collapses.
    newDifficulty = _nextDifficulty(state.difficulty, ratingIdx);
    newStability = _stabilityAfterLapse(
      state.stability,
      newDifficulty,
      elapsedDays,
    );
    newState = FsrsCardState.relearning;
  } else {
    // Successful recall.
    final retrievability = _retrievability(elapsedDays, state.stability);
    newDifficulty = _nextDifficulty(state.difficulty, ratingIdx);
    newStability = _stabilityAfterRecall(
      state.stability,
      newDifficulty,
      retrievability,
      ratingIdx,
    );
    newState = FsrsCardState.review;
  }

  final interval = _nextInterval(newStability, targetRetention);

  return FsrsResult(
    stability: newStability,
    difficulty: newDifficulty,
    cardState: newState,
    intervalDays: interval,
    elapsedDays: elapsedDays,
    nextReviewAt: DateTime.now().add(Duration(days: interval)),
  );
}