diff --git a/proto/anki/deck_config.proto b/proto/anki/deck_config.proto index 10b081aed..22ecc8c60 100644 --- a/proto/anki/deck_config.proto +++ b/proto/anki/deck_config.proto @@ -135,7 +135,6 @@ message DeckConfig { bool bury_reviews = 28; bool bury_interday_learning = 29; - bool fsrs_enabled = 36; float desired_retention = 37; // for fsrs bytes other = 255; @@ -179,6 +178,7 @@ message DeckConfigsForUpdate { string card_state_customizer = 6; // only applies to v3 scheduler bool new_cards_ignore_review_limit = 7; + bool fsrs = 8; } message UpdateDeckConfigsRequest { @@ -191,4 +191,5 @@ message UpdateDeckConfigsRequest { string card_state_customizer = 5; DeckConfigsForUpdate.CurrentDeck.Limits limits = 6; bool new_cards_ignore_review_limit = 7; + bool fsrs = 8; } diff --git a/rslib/src/config/bool.rs b/rslib/src/config/bool.rs index 0cf438ffc..bc0823450 100644 --- a/rslib/src/config/bool.rs +++ b/rslib/src/config/bool.rs @@ -37,6 +37,7 @@ pub enum BoolKey { MergeNotetypes, WithScheduling, StopTimerOnAnswer, + Fsrs, #[strum(to_string = "normalize_note_text")] NormalizeNoteText, diff --git a/rslib/src/deckconfig/mod.rs b/rslib/src/deckconfig/mod.rs index 4f6927400..820e4b8ab 100644 --- a/rslib/src/deckconfig/mod.rs +++ b/rslib/src/deckconfig/mod.rs @@ -66,7 +66,6 @@ const DEFAULT_DECK_CONFIG_INNER: DeckConfigInner = DeckConfigInner { bury_new: false, bury_reviews: false, bury_interday_learning: false, - fsrs_enabled: false, fsrs_weights: vec![], desired_retention: 0.9, other: Vec::new(), diff --git a/rslib/src/deckconfig/schema11.rs b/rslib/src/deckconfig/schema11.rs index d8185ce10..4f4b671fa 100644 --- a/rslib/src/deckconfig/schema11.rs +++ b/rslib/src/deckconfig/schema11.rs @@ -68,8 +68,6 @@ pub struct DeckConfSchema11 { #[serde(default)] fsrs_weights: Vec, #[serde(default)] - fsrs_enabled: bool, - #[serde(default)] desired_retention: f32, #[serde(flatten)] @@ -258,7 +256,6 @@ impl Default for DeckConfSchema11 { new_gather_priority: 0, bury_interday_learning: false, fsrs_weights: vec![], - fsrs_enabled: false, desired_retention: 0.9, } } @@ -329,7 +326,6 @@ impl From for DeckConfig { bury_reviews: c.rev.bury, bury_interday_learning: c.bury_interday_learning, fsrs_weights: c.fsrs_weights, - fsrs_enabled: c.fsrs_enabled, desired_retention: c.desired_retention, other: other_bytes, }, @@ -423,7 +419,6 @@ impl From for DeckConfSchema11 { new_gather_priority: i.new_card_gather_priority, bury_interday_learning: i.bury_interday_learning, fsrs_weights: i.fsrs_weights, - fsrs_enabled: i.fsrs_enabled, desired_retention: i.desired_retention, } } @@ -448,7 +443,6 @@ static RESERVED_DECKCONF_KEYS: Set<&'static str> = phf_set! { "newGatherPriority", "fsrsWeights", "desiredRetention", - "fsrsEnabled", }; static RESERVED_DECKCONF_NEW_KEYS: Set<&'static str> = phf_set! { diff --git a/rslib/src/deckconfig/service.rs b/rslib/src/deckconfig/service.rs index 8d49f3506..5ebbf4816 100644 --- a/rslib/src/deckconfig/service.rs +++ b/rslib/src/deckconfig/service.rs @@ -102,6 +102,7 @@ impl From for UpdateDeckConfi card_state_customizer: c.card_state_customizer, limits: c.limits.unwrap_or_default(), new_cards_ignore_review_limit: c.new_cards_ignore_review_limit, + fsrs: c.fsrs, } } } diff --git a/rslib/src/deckconfig/update.rs b/rslib/src/deckconfig/update.rs index ed2be846f..24cda6c57 100644 --- a/rslib/src/deckconfig/update.rs +++ b/rslib/src/deckconfig/update.rs @@ -29,6 +29,7 @@ pub struct UpdateDeckConfigsRequest { pub card_state_customizer: String, pub limits: Limits, pub new_cards_ignore_review_limit: bool, + pub fsrs: bool, } impl Collection { @@ -48,6 +49,7 @@ impl Collection { v3_scheduler: self.get_config_bool(BoolKey::Sched2021), card_state_customizer: self.get_config_string(StringKey::CardStateCustomizer), new_cards_ignore_review_limit: self.get_config_bool(BoolKey::NewCardsIgnoreReviewLimit), + fsrs: self.get_config_bool(BoolKey::Fsrs), }) } @@ -161,6 +163,10 @@ impl Collection { let selected_config = input.configs.last().unwrap(); let mut decks_needing_memory_recompute: HashMap> = Default::default(); + let fsrs_toggled = self.get_config_bool(BoolKey::Fsrs) != input.fsrs; + if fsrs_toggled { + self.set_config_bool_inner(BoolKey::Fsrs, input.fsrs)?; + } for deck in self.storage.get_all_decks()? { if let Ok(normal) = deck.normal() { let deck_id = deck.id; @@ -171,9 +177,6 @@ impl Collection { let previous_order = previous_config .map(|c| c.inner.new_card_insert_order()) .unwrap_or_default(); - let previous_fsrs_on = previous_config - .map(|c| c.inner.fsrs_enabled) - .unwrap_or_default(); let previous_weights = previous_config.map(|c| &c.inner.fsrs_weights); // if a selected (sub)deck, or its old config was removed, update deck to point @@ -200,11 +203,8 @@ impl Collection { } // if weights differ, memory state needs to be recomputed - let current_fsrs_on = current_config - .map(|c| c.inner.fsrs_enabled) - .unwrap_or_default(); let current_weights = current_config.map(|c| &c.inner.fsrs_weights); - if current_fsrs_on != previous_fsrs_on || previous_weights != current_weights { + if fsrs_toggled || previous_weights != current_weights { decks_needing_memory_recompute .entry(current_config_id) .or_default() @@ -220,7 +220,7 @@ impl Collection { .into_iter() .map(|(conf_id, search)| { let weights = configs_after_update.get(&conf_id).and_then(|c| { - if c.inner.fsrs_enabled { + if input.fsrs { Some(c.inner.fsrs_weights.clone()) } else { None @@ -365,6 +365,7 @@ mod test { card_state_customizer: "".to_string(), limits: Limits::default(), new_cards_ignore_review_limit: false, + fsrs: false, }; assert!(!col.update_deck_configs(input.clone())?.changes.had_change()); diff --git a/rslib/src/scheduler/answering/mod.rs b/rslib/src/scheduler/answering/mod.rs index 505c61a60..f191f11ed 100644 --- a/rslib/src/scheduler/answering/mod.rs +++ b/rslib/src/scheduler/answering/mod.rs @@ -351,7 +351,7 @@ impl Collection { .get_deck(card.deck_id)? .or_not_found(card.deck_id)?; let config = self.home_deck_config(deck.config_id(), card.original_deck_id)?; - let fsrs_next_states = if config.inner.fsrs_enabled { + let fsrs_next_states = if self.get_config_bool(BoolKey::Fsrs) { let fsrs = FSRS::new(Some(&config.inner.fsrs_weights))?; let memory_state = if let Some(state) = card.memory_state { Some(MemoryState::from(state)) diff --git a/ts/deck-options/AdvancedOptions.svelte b/ts/deck-options/AdvancedOptions.svelte index d1afe3910..4efcb8854 100644 --- a/ts/deck-options/AdvancedOptions.svelte +++ b/ts/deck-options/AdvancedOptions.svelte @@ -28,6 +28,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html const config = state.currentConfig; const defaults = state.defaults; const cardStateCustomizer = state.cardStateCustomizer; + const fsrs = state.fsrs; const settings = { maximumInterval: { @@ -76,7 +77,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html carousel.to(index); } - $: fsrsClientWarning = $config.fsrsEnabled ? tr.deckConfigFsrsOnAllClients() : ""; + $: fsrsClientWarning = $fsrs ? tr.deckConfigFsrsOnAllClients() : ""; @@ -93,7 +94,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html {#if state.v3Scheduler} - + FSRS @@ -117,7 +118,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html - {#if !$config.fsrsEnabled || !state.v3Scheduler} + {#if !$fsrs || !state.v3Scheduler} = 1 + $fsrs && lastRelearnStepInDays >= 1 ? tr.deckConfigStepsTooLargeForFsrs() : ""; } @@ -106,7 +107,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html - {#if !$config.fsrsEnabled} + {#if !$fsrs} = 1 + $fsrs && lastLearnStepInDays >= 1 ? tr.deckConfigStepsTooLargeForFsrs() : ""; } @@ -118,7 +119,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html - {#if !$config.fsrsEnabled} + {#if !$fsrs} ; readonly v3Scheduler: boolean; readonly newCardsIgnoreReviewLimit: Writable; + readonly fsrs: Writable; private targetDeckId: DeckOptionsId; private configs: ConfigWithCount[]; @@ -79,6 +80,7 @@ export class DeckOptionsState { this.cardStateCustomizer = writable(data.cardStateCustomizer); this.deckLimits = writable(data.currentDeck?.limits ?? createLimits()); this.newCardsIgnoreReviewLimit = writable(data.newCardsIgnoreReviewLimit); + this.fsrs = writable(data.fsrs); // decrement the use count of the starting item, as we'll apply +1 to currently // selected one at display time @@ -205,6 +207,7 @@ export class DeckOptionsState { cardStateCustomizer: get(this.cardStateCustomizer), limits: get(this.deckLimits), newCardsIgnoreReviewLimit: get(this.newCardsIgnoreReviewLimit), + fsrs: get(this.fsrs), }; }