support deck-specific desired retention when rescheduling

This commit is contained in:
Jarrett Ye 2025-07-20 13:56:56 +08:00
parent 50b3da74f0
commit f788915ea1
No known key found for this signature in database
GPG key ID: EBFC55E0C1A352BB
2 changed files with 17 additions and 6 deletions

View file

@ -212,10 +212,13 @@ impl Collection {
if fsrs_toggled { if fsrs_toggled {
self.set_config_bool_inner(BoolKey::Fsrs, req.fsrs)?; self.set_config_bool_inner(BoolKey::Fsrs, req.fsrs)?;
} }
let mut deck_desired_retention: HashMap<DeckId, f32> = Default::default();
for deck in self.storage.get_all_decks()? { for deck in self.storage.get_all_decks()? {
if let Ok(normal) = deck.normal() { if let Ok(normal) = deck.normal() {
let deck_id = deck.id; let deck_id = deck.id;
if let Some(desired_retention) = normal.desired_retention {
deck_desired_retention.insert(deck_id, desired_retention);
}
// previous order & params // previous order & params
let previous_config_id = DeckConfigId(normal.config_id); let previous_config_id = DeckConfigId(normal.config_id);
let previous_config = configs_before_update.get(&previous_config_id); let previous_config = configs_before_update.get(&previous_config_id);
@ -277,10 +280,11 @@ impl Collection {
if req.fsrs { if req.fsrs {
Some(UpdateMemoryStateRequest { Some(UpdateMemoryStateRequest {
params: c.fsrs_params().clone(), params: c.fsrs_params().clone(),
desired_retention: c.inner.desired_retention, preset_desired_retention: c.inner.desired_retention,
max_interval: c.inner.maximum_review_interval, max_interval: c.inner.maximum_review_interval,
reschedule: req.fsrs_reschedule, reschedule: req.fsrs_reschedule,
historical_retention: c.inner.historical_retention, historical_retention: c.inner.historical_retention,
deck_desired_retention: deck_desired_retention.clone(),
}) })
} else { } else {
None None

View file

@ -45,10 +45,11 @@ pub(crate) fn get_decay_from_params(params: &[f32]) -> f32 {
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct UpdateMemoryStateRequest { pub(crate) struct UpdateMemoryStateRequest {
pub params: Params, pub params: Params,
pub desired_retention: f32, pub preset_desired_retention: f32,
pub historical_retention: f32, pub historical_retention: f32,
pub max_interval: u32, pub max_interval: u32,
pub reschedule: bool, pub reschedule: bool,
pub deck_desired_retention: HashMap<DeckId, f32>,
} }
pub(crate) struct UpdateMemoryStateEntry { pub(crate) struct UpdateMemoryStateEntry {
@ -98,7 +99,8 @@ impl Collection {
historical_retention.unwrap_or(0.9), historical_retention.unwrap_or(0.9),
ignore_before, ignore_before,
)?; )?;
let desired_retention = req.as_ref().map(|w| w.desired_retention); let preset_desired_retention =
req.as_ref().map(|w| w.preset_desired_retention).unwrap();
let mut progress = self.new_progress_handler::<ComputeMemoryProgress>(); let mut progress = self.new_progress_handler::<ComputeMemoryProgress>();
progress.update(false, |s| s.total_cards = items.len() as u32)?; progress.update(false, |s| s.total_cards = items.len() as u32)?;
for (idx, (card_id, item)) in items.into_iter().enumerate() { for (idx, (card_id, item)) in items.into_iter().enumerate() {
@ -109,7 +111,12 @@ impl Collection {
// Store decay and desired retention in the card so that add-ons, card info, // Store decay and desired retention in the card so that add-ons, card info,
// stats and browser search/sorts don't need to access the deck config. // stats and browser search/sorts don't need to access the deck config.
// Unlike memory states, scheduler doesn't use decay and dr stored in the card. // Unlike memory states, scheduler doesn't use decay and dr stored in the card.
card.desired_retention = desired_retention; let deck_id = card.original_or_current_deck_id();
let desired_retention = *req
.deck_desired_retention
.get(&deck_id)
.unwrap_or(&preset_desired_retention);
card.desired_retention = Some(desired_retention);
card.decay = decay; card.decay = decay;
if let Some(item) = item { if let Some(item) = item {
card.set_memory_state(&fsrs, Some(item), historical_retention.unwrap())?; card.set_memory_state(&fsrs, Some(item), historical_retention.unwrap())?;
@ -132,7 +139,7 @@ impl Collection {
let original_interval = card.interval; let original_interval = card.interval;
let interval = fsrs.next_interval( let interval = fsrs.next_interval(
Some(state.stability), Some(state.stability),
desired_retention.unwrap(), desired_retention,
0, 0,
); );
card.interval = rescheduler card.interval = rescheduler