Sort FSRSItems by RevlogId for training (#3660)

* Sort FSRSItems by RevlogId for training

* update fsrs-rs v1.5.0
This commit is contained in:
Jarrett Ye 2025-01-08 18:32:00 +08:00 committed by GitHub
parent d7fc98d4d8
commit 58bcab2484
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 15 additions and 12 deletions

4
Cargo.lock generated
View file

@ -1860,9 +1860,9 @@ dependencies = [
[[package]] [[package]]
name = "fsrs" name = "fsrs"
version = "1.4.7" version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61218a50bf5c8da66b62be02f495c5d0b43de52ec37fae036a0e68d4539ff59d" checksum = "738a17a9825de16c23063c5931738e96aacce208a9b0ab54260c6ea2aa6a6feb"
dependencies = [ dependencies = [
"burn", "burn",
"itertools 0.12.1", "itertools 0.12.1",

View file

@ -35,7 +35,7 @@ git = "https://github.com/ankitects/linkcheck.git"
rev = "184b2ca50ed39ca43da13f0b830a463861adb9ca" rev = "184b2ca50ed39ca43da13f0b830a463861adb9ca"
[workspace.dependencies.fsrs] [workspace.dependencies.fsrs]
version = "=1.4.7" version = "=1.5.0"
# git = "https://github.com/open-spaced-repetition/fsrs-rs.git" # git = "https://github.com/open-spaced-repetition/fsrs-rs.git"
# rev = "58ca25ed2bc4bb1dc376208bbcaed7f5a501b941" # rev = "58ca25ed2bc4bb1dc376208bbcaed7f5a501b941"
# path = "../open-spaced-repetition/fsrs-rs" # path = "../open-spaced-repetition/fsrs-rs"

View file

@ -1225,7 +1225,7 @@
}, },
{ {
"name": "fsrs", "name": "fsrs",
"version": "1.4.7", "version": "1.5.0",
"authors": "Open Spaced Repetition", "authors": "Open Spaced Repetition",
"repository": "https://github.com/open-spaced-repetition/fsrs-rs", "repository": "https://github.com/open-spaced-repetition/fsrs-rs",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",

View file

@ -284,7 +284,7 @@ pub(crate) fn fsrs_item_for_memory_state(
ease_factor: f32, ease_factor: f32,
} }
if let Some(mut output) = reviews_for_fsrs(entries, next_day_at, false, ignore_revlogs_before) { if let Some(mut output) = reviews_for_fsrs(entries, next_day_at, false, ignore_revlogs_before) {
let mut item = output.fsrs_items.pop().unwrap(); let mut item = output.fsrs_items.pop().unwrap().1;
if output.revlogs_complete { if output.revlogs_complete {
Ok(Some(FsrsItemForMemoryState { Ok(Some(FsrsItemForMemoryState {
item, item,

View file

@ -237,7 +237,10 @@ fn fsrs_items_for_training(
i.fsrs_items i.fsrs_items
}) })
.collect_vec(); .collect_vec();
revlogs.sort_by_cached_key(|r| r.reviews.len()); // Sort by RevlogId
revlogs.sort_by_key(|(revlog_id, _)| revlog_id.0);
// Extract only the FSRSItems after sorting
let revlogs = revlogs.into_iter().map(|(_, item)| item).collect_vec();
(revlogs, review_count) (revlogs, review_count)
} }
@ -246,7 +249,7 @@ pub(crate) struct ReviewsForFsrs {
/// review entries prior to a card being reset). /// review entries prior to a card being reset).
pub filtered_revlogs: Vec<RevlogEntry>, pub filtered_revlogs: Vec<RevlogEntry>,
/// FSRS items derived from the filtered revlogs. /// FSRS items derived from the filtered revlogs.
pub fsrs_items: Vec<FSRSItem>, pub fsrs_items: Vec<(RevlogId, FSRSItem)>,
/// True if there is enough history to derive memory state from history /// True if there is enough history to derive memory state from history
/// alone. If false, memory state will be derived from SM2. /// alone. If false, memory state will be derived from SM2.
pub revlogs_complete: bool, pub revlogs_complete: bool,
@ -360,11 +363,11 @@ pub(crate) fn reviews_for_fsrs(
let skip = if training { 1 } else { 0 }; let skip = if training { 1 } else { 0 };
// Convert the remaining entries into separate FSRSItems, where each item // Convert the remaining entries into separate FSRSItems, where each item
// contains all reviews done until then. // contains all reviews done until then.
let items: Vec<FSRSItem> = entries let items: Vec<(RevlogId, FSRSItem)> = entries
.iter() .iter()
.enumerate() .enumerate()
.skip(skip) .skip(skip)
.map(|(outer_idx, _)| { .map(|(outer_idx, entry)| {
let reviews = entries let reviews = entries
.iter() .iter()
.take(outer_idx + 1) .take(outer_idx + 1)
@ -374,9 +377,9 @@ pub(crate) fn reviews_for_fsrs(
delta_t: delta_ts[inner_idx], delta_t: delta_ts[inner_idx],
}) })
.collect(); .collect();
FSRSItem { reviews } (entry.id, FSRSItem { reviews })
}) })
.filter(|item| !training || item.reviews.last().unwrap().delta_t > 0) .filter(|(_, item)| !training || item.reviews.last().unwrap().delta_t > 0)
.collect_vec(); .collect_vec();
if items.is_empty() { if items.is_empty() {
None None
@ -445,7 +448,7 @@ pub(crate) mod tests {
ignore_before: TimestampMillis, ignore_before: TimestampMillis,
) -> Option<Vec<FSRSItem>> { ) -> Option<Vec<FSRSItem>> {
reviews_for_fsrs(revlog.to_vec(), NEXT_DAY_AT, training, ignore_before) reviews_for_fsrs(revlog.to_vec(), NEXT_DAY_AT, training, ignore_before)
.map(|i| i.fsrs_items) .map(|i| i.fsrs_items.into_iter().map(|(_, item)| item).collect_vec())
} }
pub(crate) fn convert(revlog: &[RevlogEntry], training: bool) -> Option<Vec<FSRSItem>> { pub(crate) fn convert(revlog: &[RevlogEntry], training: bool) -> Option<Vec<FSRSItem>> {