From dc8a687b3317e657c87dc4357f582a89c4a064f3 Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Sun, 13 Jul 2025 09:53:03 +0100 Subject: [PATCH] backend part --- proto/anki/scheduler.proto | 6 ++++++ rslib/src/scheduler/fsrs/simulator.rs | 26 ++++++++++++++++++++++++++ rslib/src/scheduler/service/mod.rs | 8 ++++++++ 3 files changed, 40 insertions(+) diff --git a/proto/anki/scheduler.proto b/proto/anki/scheduler.proto index 1294b4543..56ad389ee 100644 --- a/proto/anki/scheduler.proto +++ b/proto/anki/scheduler.proto @@ -55,6 +55,8 @@ service SchedulerService { returns (ComputeOptimalRetentionResponse); rpc SimulateFsrsReview(SimulateFsrsReviewRequest) returns (SimulateFsrsReviewResponse); + rpc SimulateFsrsWorkload(SimulateFsrsReviewRequest) + returns (SimulateFsrsWorkloadResponse); rpc EvaluateParams(EvaluateParamsRequest) returns (EvaluateParamsResponse); rpc EvaluateParamsLegacy(EvaluateParamsLegacyRequest) returns (EvaluateParamsResponse); @@ -414,6 +416,10 @@ message SimulateFsrsReviewResponse { repeated float daily_time_cost = 4; } +message SimulateFsrsWorkloadResponse { + map dr_workload = 1; +} + message ComputeOptimalRetentionResponse { float optimal_retention = 1; } diff --git a/rslib/src/scheduler/fsrs/simulator.rs b/rslib/src/scheduler/fsrs/simulator.rs index e032ecaf3..99ca42989 100644 --- a/rslib/src/scheduler/fsrs/simulator.rs +++ b/rslib/src/scheduler/fsrs/simulator.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; // Copyright: Ankitects Pty Ltd and contributors // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html use std::sync::Arc; @@ -6,6 +7,7 @@ use anki_proto::deck_config::deck_config::config::ReviewCardOrder; use anki_proto::deck_config::deck_config::config::ReviewCardOrder::*; use anki_proto::scheduler::SimulateFsrsReviewRequest; use anki_proto::scheduler::SimulateFsrsReviewResponse; +use anki_proto::scheduler::SimulateFsrsWorkloadResponse; use fsrs::simulate; use fsrs::PostSchedulingFn; use fsrs::ReviewPriorityFn; @@ -267,6 +269,30 @@ impl Collection { daily_time_cost: result.cost_per_day, }) } + + pub fn simulate_workload( + &mut self, + req: SimulateFsrsReviewRequest, + ) -> Result { + let (config, cards) = self.simulate_request_to_config(&req)?; + let dr_workload = (70u32..=99u32) + .map(|dr| { + let result = simulate( + &config, + &req.params, + dr as f32 / 100., + None, + Some(cards.clone()), + )?; + Ok(( + dr, + result.memorized_cnt_per_day.last().unwrap_or(&0.) + / result.cost_per_day.iter().sum::(), + )) + }) + .collect::>>()?; + Ok(SimulateFsrsWorkloadResponse { dr_workload }) + } } impl Card { diff --git a/rslib/src/scheduler/service/mod.rs b/rslib/src/scheduler/service/mod.rs index 43d694e4f..9f42a79f7 100644 --- a/rslib/src/scheduler/service/mod.rs +++ b/rslib/src/scheduler/service/mod.rs @@ -16,6 +16,7 @@ use anki_proto::scheduler::FuzzDeltaResponse; use anki_proto::scheduler::GetOptimalRetentionParametersResponse; use anki_proto::scheduler::SimulateFsrsReviewRequest; use anki_proto::scheduler::SimulateFsrsReviewResponse; +use anki_proto::scheduler::SimulateFsrsWorkloadResponse; use fsrs::ComputeParametersInput; use fsrs::FSRSItem; use fsrs::FSRSReview; @@ -283,6 +284,13 @@ impl crate::services::SchedulerService for Collection { self.simulate_review(input) } + fn simulate_fsrs_workload( + &mut self, + input: SimulateFsrsReviewRequest, + ) -> Result { + self.simulate_workload(input) + } + fn compute_optimal_retention( &mut self, input: SimulateFsrsReviewRequest,