refactor single_card_revlog_to_item(s)

This commit is contained in:
Jarrett Ye 2024-12-15 19:40:57 +08:00
parent e04b382666
commit e6e7a58300
No known key found for this signature in database
GPG key ID: EBFC55E0C1A352BB
2 changed files with 29 additions and 46 deletions

View file

@ -284,20 +284,7 @@ pub(crate) fn single_card_revlog_to_item(
interval: f32, interval: f32,
ease_factor: f32, ease_factor: f32,
} }
let first_review = entries if let Some((mut items, revlogs_complete, _, filtered_entries)) =
.iter()
// ignore manual and rescheduled revlogs and revlogs before the cutoff
.find(|e| e.button_chosen > 0 && e.id.0 >= ignore_revlogs_before.0)
.map(|e| FirstReview {
interval: e.interval.max(1) as f32,
ease_factor: if e.ease_factor == 0 {
2500
} else {
e.ease_factor
} as f32
/ 1000.0,
});
if let Some((mut items, revlogs_complete, _)) =
single_card_revlog_to_items(entries, next_day_at, false, ignore_revlogs_before) single_card_revlog_to_items(entries, next_day_at, false, ignore_revlogs_before)
{ {
let mut item = items.pop().unwrap(); let mut item = items.pop().unwrap();
@ -306,7 +293,16 @@ pub(crate) fn single_card_revlog_to_item(
item, item,
starting_state: None, starting_state: None,
})) }))
} else if let Some(first_review) = first_review { } else if let Some(first_non_manual_entry) = filtered_entries.first() {
let first_review = FirstReview {
interval: first_non_manual_entry.interval.max(1) as f32,
ease_factor: if first_non_manual_entry.ease_factor == 0 {
2500
} else {
first_non_manual_entry.ease_factor
} as f32
/ 1000.0,
};
// the revlog has been truncated, but not fully // the revlog has been truncated, but not fully
let mut starting_state = fsrs.memory_state_from_sm2( let mut starting_state = fsrs.memory_state_from_sm2(
first_review.ease_factor, first_review.ease_factor,
@ -318,14 +314,10 @@ pub(crate) fn single_card_revlog_to_item(
starting_state.difficulty = (first_review.ease_factor - 0.1) * 9.0 + 1.0; starting_state.difficulty = (first_review.ease_factor - 0.1) * 9.0 + 1.0;
} }
item.reviews.remove(0); item.reviews.remove(0);
if item.reviews.is_empty() { Ok(Some(FsrsItemWithStartingState {
Ok(None) item,
} else { starting_state: Some(starting_state),
Ok(Some(FsrsItemWithStartingState { }))
item,
starting_state: Some(starting_state),
}))
}
} else { } else {
// only manual and rescheduled revlogs; treat like empty // only manual and rescheduled revlogs; treat like empty
Ok(None) Ok(None)

View file

@ -258,13 +258,17 @@ pub(crate) fn single_card_revlog_to_items(
next_day_at: TimestampSecs, next_day_at: TimestampSecs,
training: bool, training: bool,
ignore_revlogs_before: TimestampMillis, ignore_revlogs_before: TimestampMillis,
) -> Option<(Vec<FSRSItem>, bool, usize)> { ) -> Option<(Vec<FSRSItem>, bool, usize, Vec<RevlogEntry>)> {
let mut first_of_last_learn_entries = None; let mut first_of_last_learn_entries = None;
let mut first_relearn_entries = None;
let mut non_manual_entries = None; let mut non_manual_entries = None;
let mut revlogs_complete = false; let mut revlogs_complete = false;
for (index, entry) in entries.iter().enumerate().rev() { for (index, entry) in entries.iter().enumerate().rev() {
if matches!(entry.button_chosen, 1..=4) { if matches!(entry.button_chosen, 1..=4) {
non_manual_entries = Some(entry); non_manual_entries = Some(index);
if entry.review_kind == RevlogReviewKind::Relearning {
first_relearn_entries = Some(index);
}
} }
if matches!( if matches!(
(entry.review_kind, entry.button_chosen), (entry.review_kind, entry.button_chosen),
@ -295,18 +299,6 @@ pub(crate) fn single_card_revlog_to_items(
} }
} }
} }
if !revlogs_complete {
revlogs_complete = matches!(
entries.first(),
Some(RevlogEntry {
review_kind: RevlogReviewKind::Manual,
..
}) | Some(RevlogEntry {
review_kind: RevlogReviewKind::Rescheduled,
..
})
);
}
if training { if training {
// While training ignore the entire card if the first learning step of the last // While training ignore the entire card if the first learning step of the last
// group of learning steps is before the ignore_revlogs_before date // group of learning steps is before the ignore_revlogs_before date
@ -333,14 +325,7 @@ pub(crate) fn single_card_revlog_to_items(
} }
} }
} }
let first_relearn = entries if let Some(idx) = first_of_last_learn_entries.or(first_relearn_entries) {
.iter()
.enumerate()
.find(|(_idx, e)| {
e.id.0 > ignore_revlogs_before.0 && e.review_kind == RevlogReviewKind::Relearning
})
.map(|(idx, _)| idx);
if let Some(idx) = first_of_last_learn_entries.or(first_relearn) {
// start from the (re)learning step // start from the (re)learning step
if idx > 0 { if idx > 0 {
entries.drain(..idx); entries.drain(..idx);
@ -348,6 +333,12 @@ pub(crate) fn single_card_revlog_to_items(
} else if training { } else if training {
// when training, we ignore cards that don't have any learning steps // when training, we ignore cards that don't have any learning steps
return None; return None;
} else if let Some(idx) = non_manual_entries {
// if there are no (re)learning entries but there are non-manual entries,
// we ignore all entries before the first non-manual entry
if idx > 0 {
entries.drain(..idx);
}
} }
// Filter out unwanted entries // Filter out unwanted entries
@ -393,7 +384,7 @@ pub(crate) fn single_card_revlog_to_items(
if items.is_empty() { if items.is_empty() {
None None
} else { } else {
Some((items, revlogs_complete, entries.len())) Some((items, revlogs_complete, entries.len(), entries))
} }
} }