mirror of
https://github.com/ankitects/anki.git
synced 2025-09-19 06:22:22 -04:00
Use first >= 1d interval for starting memory state (#3959)
When a filtered revlog history begins with one or more < 1d intervals (for example, because it starts in the middle of a sequence of relearning steps), use the first >= 1d interval to calculate the initial memory state. Bug report thread: https://forums.ankiweb.net/t/fsrs-stability-when-first-non-ignored-revlog-has-a-relearning-interval/59894
This commit is contained in:
parent
57ecfbe562
commit
bcb28f0a85
1 changed files with 27 additions and 1 deletions
|
@ -313,9 +313,12 @@ pub(crate) fn reviews_for_fsrs(
|
||||||
if entry.review_kind == RevlogReviewKind::Filtered && entry.ease_factor == 0 {
|
if entry.review_kind == RevlogReviewKind::Filtered && entry.ease_factor == 0 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
// For incomplete review histories, initial memory state is based on the first
|
||||||
|
// user-graded review after the cutoff date with interval >= 1d.
|
||||||
let within_cutoff = entry.id.0 > ignore_revlogs_before.0;
|
let within_cutoff = entry.id.0 > ignore_revlogs_before.0;
|
||||||
let user_graded = matches!(entry.button_chosen, 1..=4);
|
let user_graded = matches!(entry.button_chosen, 1..=4);
|
||||||
if user_graded && within_cutoff {
|
let interday = entry.interval >= 1 || entry.interval <= -86400;
|
||||||
|
if user_graded && within_cutoff && interday {
|
||||||
first_user_grade_idx = Some(index);
|
first_user_grade_idx = Some(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -477,6 +480,7 @@ pub(crate) mod tests {
|
||||||
review_kind,
|
review_kind,
|
||||||
id: days_ago_ms(days_ago).into(),
|
id: days_ago_ms(days_ago).into(),
|
||||||
button_chosen: 3,
|
button_chosen: 3,
|
||||||
|
interval: 1,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -711,6 +715,28 @@ pub(crate) mod tests {
|
||||||
assert_eq!(convert_ignore_before(revlogs, true, days_ago_ms(9)), None);
|
assert_eq!(convert_ignore_before(revlogs, true, days_ago_ms(9)), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn skip_initial_relearning_steps() {
|
||||||
|
let revlogs = &[
|
||||||
|
revlog(RevlogReviewKind::Review, 10),
|
||||||
|
RevlogEntry {
|
||||||
|
button_chosen: 1, // Again
|
||||||
|
interval: -600,
|
||||||
|
..revlog(RevlogReviewKind::Review, 8)
|
||||||
|
},
|
||||||
|
revlog(RevlogReviewKind::Relearning, 8),
|
||||||
|
revlog(RevlogReviewKind::Review, 6),
|
||||||
|
];
|
||||||
|
// | = Ignore before
|
||||||
|
// A = Again
|
||||||
|
// X = Relearning
|
||||||
|
// R | A X R
|
||||||
|
assert_eq!(
|
||||||
|
convert_ignore_before(revlogs, false, days_ago_ms(9)),
|
||||||
|
fsrs_items!([review(0)], [review(0), review(2)])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ignore_before_date_between_learning_steps_when_reviewing() {
|
fn ignore_before_date_between_learning_steps_when_reviewing() {
|
||||||
let revlogs = &[
|
let revlogs = &[
|
||||||
|
|
Loading…
Reference in a new issue