diff --git a/Cargo.lock b/Cargo.lock index 86787124a..079b85695 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2213,9 +2213,8 @@ dependencies = [ [[package]] name = "fsrs" -version = "4.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1f3a8c3df2c324ebab71461178fe8c1fe2d7373cf603f312b652befd026f06d" +version = "5.0.0" +source = "git+https://github.com/open-spaced-repetition/fsrs-rs.git?branch=Refactor/expected_workload_via_dp#808bd715b302ccdda26a2d29c7566270e7be3bb3" dependencies = [ "burn", "itertools 0.14.0", diff --git a/Cargo.toml b/Cargo.toml index 2ff29cd1a..212c79ea1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,8 +33,9 @@ git = "https://github.com/ankitects/linkcheck.git" rev = "184b2ca50ed39ca43da13f0b830a463861adb9ca" [workspace.dependencies.fsrs] -version = "4.1.1" -# git = "https://github.com/open-spaced-repetition/fsrs-rs.git" +# version = "4.1.1" +git = "https://github.com/open-spaced-repetition/fsrs-rs.git" +branch = "Refactor/expected_workload_via_dp" # rev = "a7f7efc10f0a26b14ee348cc7402155685f2a24f" # path = "../open-spaced-repetition/fsrs-rs" diff --git a/rslib/src/deckconfig/service.rs b/rslib/src/deckconfig/service.rs index 21bcfd676..ba2bba3a1 100644 --- a/rslib/src/deckconfig/service.rs +++ b/rslib/src/deckconfig/service.rs @@ -103,43 +103,15 @@ impl crate::services::DeckConfigService for Collection { &mut self, input: anki_proto::deck_config::GetRetentionWorkloadRequest, ) -> Result { - const LEARN_SPAN: usize = 365; - const TERMINATION_PROB: f32 = 1e-5; - // the default values are from https://github.com/open-spaced-repetition/Anki-button-usage/blob/881009015c2a85ac911021d76d0aacb124849937/analysis.ipynb - const DEFAULT_LEARN_COST: f32 = 19.4698; - const DEFAULT_PASS_COST: f32 = 7.8454; - const DEFAULT_FAIL_COST: f32 = 23.185; - const DEFAULT_INITIAL_PASS_RATE: f32 = 0.7645; - let guard = self.search_cards_into_table(&input.search, crate::search::SortMode::NoOrder)?; - let costs = guard.col.storage.get_costs_for_retention()?; + + let revlogs = guard + .col + .storage + .get_revlog_entries_for_searched_cards_in_card_order()?; - fn smoothing(obs: f32, default: f32, count: u32) -> f32 { - let alpha = count as f32 / (50.0 + count as f32); - obs * alpha + default * (1.0 - alpha) - } - - let cost_success = smoothing( - costs.average_pass_time_ms / 1000.0, - DEFAULT_PASS_COST, - costs.pass_count, - ); - let cost_failure = smoothing( - costs.average_fail_time_ms / 1000.0, - DEFAULT_FAIL_COST, - costs.fail_count, - ); - let cost_learn = smoothing( - costs.average_learn_time_ms / 1000.0, - DEFAULT_LEARN_COST, - costs.learn_count, - ); - let initial_pass_rate = smoothing( - costs.initial_pass_rate, - DEFAULT_INITIAL_PASS_RATE, - costs.pass_count, - ); + let config = guard.col.get_optimal_retention_parameters(revlogs)?; let costs = (70u32..=99u32) .map(|dr| { @@ -148,12 +120,7 @@ impl crate::services::DeckConfigService for Collection { fsrs::expected_workload( &input.w, dr as f32 / 100., - LEARN_SPAN, - cost_success, - cost_failure, - cost_learn, - initial_pass_rate, - TERMINATION_PROB, + &config )?, )) })