From 62df837cf73ce792a5f1f4ec51ba128ace8abd43 Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Sat, 2 Aug 2025 13:37:44 +0100 Subject: [PATCH] https://github.com/open-spaced-repetition/fsrs-rs/pull/355 --- Cargo.lock | 47 +++++++++++++-------------- Cargo.toml | 6 ++-- rslib/src/deckconfig/service.rs | 15 ++++++++- rslib/src/scheduler/fsrs/simulator.rs | 17 ++++++---- 4 files changed, 51 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f698a4ce4..dc511ce11 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -130,7 +130,7 @@ dependencies = [ "prost", "prost-reflect", "pulldown-cmark 0.13.0", - "rand 0.9.1", + "rand 0.9.2", "rayon", "regex", "reqwest 0.12.20", @@ -144,7 +144,7 @@ dependencies = [ "serde_tuple", "sha1", "snafu", - "strum 0.27.1", + "strum 0.27.2", "syn 2.0.103", "tempfile", "tokio", @@ -220,7 +220,7 @@ dependencies = [ "prost-types", "serde", "snafu", - "strum 0.27.1", + "strum 0.27.2", ] [[package]] @@ -706,7 +706,7 @@ dependencies = [ "log", "num-traits", "portable-atomic-util", - "rand 0.9.1", + "rand 0.9.2", "rmp-serde", "serde", "serde_json", @@ -732,7 +732,7 @@ dependencies = [ "hashbrown 0.15.4", "log", "num-traits", - "rand 0.9.1", + "rand 0.9.2", "serde", "spin 0.10.0", "text_placeholder", @@ -762,12 +762,12 @@ dependencies = [ "csv", "derive-new 0.7.0", "dirs 6.0.0", - "rand 0.9.1", + "rand 0.9.2", "rmp-serde", "sanitize-filename 0.6.0", "serde", "serde_json", - "strum 0.27.1", + "strum 0.27.2", "tempfile", "thiserror 2.0.12", ] @@ -817,7 +817,7 @@ dependencies = [ "num-traits", "paste", "portable-atomic-util", - "rand 0.9.1", + "rand 0.9.2", "seq-macro", "spin 0.10.0", ] @@ -865,7 +865,7 @@ dependencies = [ "half", "hashbrown 0.15.4", "num-traits", - "rand 0.9.1", + "rand 0.9.2", "rand_distr", "serde", "serde_bytes", @@ -959,7 +959,7 @@ dependencies = [ "memmap2", "num-traits", "num_cpus", - "rand 0.9.1", + "rand 0.9.2", "rand_distr", "rayon", "safetensors", @@ -1403,7 +1403,7 @@ dependencies = [ "log", "num-traits", "portable-atomic", - "rand 0.9.1", + "rand 0.9.2", "sanitize-filename 0.5.0", "serde", "serde_json", @@ -2214,20 +2214,19 @@ dependencies = [ [[package]] name = "fsrs" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f590cfcbe25079bb54a39900f45e6e308935bd6067249ce00d265b280465cde2" +version = "5.0.1" +source = "git+https://github.com/open-spaced-repetition/fsrs-rs.git?branch=Feat/estimate-workload-for-cards#03e83fa66d86a4f60a2bb2e920b9c5cae9106b9d" dependencies = [ "burn", "itertools 0.14.0", "log", "ndarray", "priority-queue", - "rand 0.9.1", + "rand 0.9.2", "rayon", "serde", "snafu", - "strum 0.27.1", + "strum 0.27.2", ] [[package]] @@ -2804,7 +2803,7 @@ dependencies = [ "cfg-if", "crunchy", "num-traits", - "rand 0.9.1", + "rand 0.9.2", "rand_distr", "serde", ] @@ -3658,7 +3657,7 @@ dependencies = [ "linkcheck", "regex", "reqwest 0.12.20", - "strum 0.27.1", + "strum 0.27.2", "tokio", ] @@ -5096,7 +5095,7 @@ dependencies = [ "bytes", "getrandom 0.3.3", "lru-slab", - "rand 0.9.1", + "rand 0.9.2", "ring", "rustc-hash 2.1.1", "rustls", @@ -5150,9 +5149,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.3", @@ -5203,7 +5202,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8615d50dcf34fa31f7ab52692afec947c4dd0ab803cc87cb3b0b4570ff7463" dependencies = [ "num-traits", - "rand 0.9.1", + "rand 0.9.2", ] [[package]] @@ -6113,9 +6112,9 @@ dependencies = [ [[package]] name = "strum" -version = "0.27.1" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" dependencies = [ "strum_macros 0.27.1", ] diff --git a/Cargo.toml b/Cargo.toml index f62a71023..0e866defe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,9 +33,9 @@ git = "https://github.com/ankitects/linkcheck.git" rev = "184b2ca50ed39ca43da13f0b830a463861adb9ca" [workspace.dependencies.fsrs] -version = "5.0.0" -# git = "https://github.com/open-spaced-repetition/fsrs-rs.git" -# branch = "Refactor/expected_workload_via_dp" +# version = "5.0.1" +git = "https://github.com/open-spaced-repetition/fsrs-rs.git" +branch = "Feat/estimate-workload-for-cards" # rev = "a7f7efc10f0a26b14ee348cc7402155685f2a24f" # path = "../open-spaced-repetition/fsrs-rs" diff --git a/rslib/src/deckconfig/service.rs b/rslib/src/deckconfig/service.rs index 8cc33fc3a..f280588be 100644 --- a/rslib/src/deckconfig/service.rs +++ b/rslib/src/deckconfig/service.rs @@ -103,6 +103,7 @@ impl crate::services::DeckConfigService for Collection { &mut self, input: anki_proto::deck_config::GetRetentionWorkloadRequest, ) -> Result { + let days_elapsed = self.timing_today().unwrap().days_elapsed as i32; let guard = self.search_cards_into_table(&input.search, crate::search::SortMode::NoOrder)?; @@ -112,12 +113,24 @@ impl crate::services::DeckConfigService for Collection { .get_revlog_entries_for_searched_cards_in_card_order()?; let config = guard.col.get_optimal_retention_parameters(revlogs)?; + let cards = guard + .col + .storage + .all_searched_cards()? + .into_iter() + .filter_map(|c| crate::card::Card::convert(c.clone(), days_elapsed, c.memory_state?.clone())) + .collect::>(); let costs = (70u32..=99u32) .map(|dr| { Ok(( dr, - fsrs::expected_workload(&input.w, dr as f32 / 100., &config)?, + fsrs::expected_workload_with_existing_cards( + &input.w, + dr as f32 / 100., + &config, + &cards, + )?, )) }) .collect::>>()?; diff --git a/rslib/src/scheduler/fsrs/simulator.rs b/rslib/src/scheduler/fsrs/simulator.rs index 3b173939b..c782530cd 100644 --- a/rslib/src/scheduler/fsrs/simulator.rs +++ b/rslib/src/scheduler/fsrs/simulator.rs @@ -121,6 +121,12 @@ fn create_review_priority_fn( } } +pub(crate) fn is_included_card(c: &Card) -> bool { + c.queue != CardQueue::Suspended + && c.queue != CardQueue::PreviewRepeat + && c.ctype != CardType::New +} + impl Collection { pub fn simulate_request_to_config( &mut self, @@ -133,11 +139,6 @@ impl Collection { .get_revlog_entries_for_searched_cards_in_card_order()?; let mut cards = guard.col.storage.all_searched_cards()?; drop(guard); - fn is_included_card(c: &Card) -> bool { - c.queue != CardQueue::Suspended - && c.queue != CardQueue::PreviewRepeat - && c.ctype != CardType::New - } // calculate any missing memory state for c in &mut cards { if is_included_card(c) && c.memory_state.is_none() { @@ -306,7 +307,11 @@ impl Collection { } impl Card { - fn convert(card: Card, days_elapsed: i32, memory_state: FsrsMemoryState) -> Option { + pub(crate) fn convert( + card: Card, + days_elapsed: i32, + memory_state: FsrsMemoryState, + ) -> Option { match card.queue { CardQueue::DayLearn | CardQueue::Review => { let due = card.original_or_current_due();