rename sm2 retention to historical retention (#3101)

* rename sm2 retention to historical retention

* ninja format

* keep sm2_retention in DeckConfSchema11

* update wording

* Update schema11.rs
This commit is contained in:
Jarrett Ye 2024-03-29 17:34:26 +08:00 committed by GitHub
parent c1877f9df6
commit 15506328e9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 50 additions and 34 deletions

View file

@ -350,7 +350,7 @@ deck-config-ignore-before = Ignore reviews before
deck-config-optimize-all-tip = You can optimize all presets at once by using the dropdown button next to "Save". deck-config-optimize-all-tip = You can optimize all presets at once by using the dropdown button next to "Save".
deck-config-evaluate-button = Evaluate deck-config-evaluate-button = Evaluate
deck-config-desired-retention = Desired retention deck-config-desired-retention = Desired retention
deck-config-sm2-retention = SM2 retention deck-config-historical-retention = Historical Retention
deck-config-smaller-is-better = Smaller numbers indicate a better fit to your review history. deck-config-smaller-is-better = Smaller numbers indicate a better fit to your review history.
deck-config-steps-too-large-for-fsrs = When FSRS is enabled, steps of 1 day or more are not recommended. deck-config-steps-too-large-for-fsrs = When FSRS is enabled, steps of 1 day or more are not recommended.
deck-config-get-params = Get Params deck-config-get-params = Get Params
@ -377,11 +377,19 @@ deck-config-desired-retention-tooltip =
less frequently, and you will forget more of them. Be conservative when adjusting this - higher less frequently, and you will forget more of them. Be conservative when adjusting this - higher
values will greatly increase your workload, and lower values can be demoralizing when you forget values will greatly increase your workload, and lower values can be demoralizing when you forget
a lot of material. a lot of material.
deck-config-sm2-retention-tooltip = deck-config-historical-retention-tooltip =
If your actual retention before switching to FSRS was significantly different from 0.9, adjusting When some of your review history is missing, FSRS needs to fill in the gaps. By default, it will
this value will allow Anki to better estimate your memory state when it encounters cards that are assume that when you did those old reviews, you remembered 90% of the material. If your old retention
missing review logs. Since review logs typically won't be missing unless you explicitly deleted them was appreciably higher or lower than 90%, adjusting this option will allow FSRS to better approximate
to free up space, most users will not need to adjust this. the missing reviews.
Your review history may be incomplete for two reasons:
1. Because you've used the 'ignore reviews before' option.
2. Because you previously deleted review logs to free up space, or imported material from a different
SRS program.
The latter is quite rare, so unless you've used the former option, you probably don't need to adjust
this setting.
deck-config-weights-tooltip = deck-config-weights-tooltip =
FSRS parameters affect how cards are scheduled. Anki will start with default parameters. Once FSRS parameters affect how cards are scheduled. Anki will start with default parameters. Once
you've accumulated 1000+ reviews, you can use the option below to optimize the parameters to best you've accumulated 1000+ reviews, you can use the option below to optimize the parameters to best

View file

@ -157,7 +157,7 @@ message DeckConfig {
string ignore_revlogs_before_date = 46; string ignore_revlogs_before_date = 46;
// used for fsrs_reschedule in the past // used for fsrs_reschedule in the past
reserved 39; reserved 39;
float sm2_retention = 40; float historical_retention = 40;
string weight_search = 45; string weight_search = 45;
bytes other = 255; bytes other = 255;

View file

@ -75,7 +75,7 @@ const DEFAULT_DECK_CONFIG_INNER: DeckConfigInner = DeckConfigInner {
fsrs_weights: vec![], fsrs_weights: vec![],
desired_retention: 0.9, desired_retention: 0.9,
other: Vec::new(), other: Vec::new(),
sm2_retention: 0.9, historical_retention: 0.9,
weight_search: String::new(), weight_search: String::new(),
ignore_revlogs_before_date: String::new(), ignore_revlogs_before_date: String::new(),
}; };
@ -282,7 +282,12 @@ pub(crate) fn ensure_deck_config_values_valid(config: &mut DeckConfigInner) {
0.7, 0.7,
0.99, 0.99,
); );
ensure_f32_valid(&mut config.sm2_retention, default.sm2_retention, 0.7, 0.97) ensure_f32_valid(
&mut config.historical_retention,
default.historical_retention,
0.7,
0.97,
)
} }
fn ensure_f32_valid(val: &mut f32, default: f32, min: f32, max: f32) { fn ensure_f32_valid(val: &mut f32, default: f32, min: f32, max: f32) {

View file

@ -86,6 +86,7 @@ pub struct DeckConfSchema11 {
#[serde(default = "wait_for_audio_default")] #[serde(default = "wait_for_audio_default")]
wait_for_audio: bool, wait_for_audio: bool,
#[serde(default)] #[serde(default)]
/// historical retention
sm2_retention: f32, sm2_retention: f32,
#[serde(default)] #[serde(default)]
weight_search: String, weight_search: String,
@ -373,7 +374,7 @@ impl From<DeckConfSchema11> for DeckConfig {
fsrs_weights: c.fsrs_weights, fsrs_weights: c.fsrs_weights,
ignore_revlogs_before_date: c.ignore_revlogs_before_date, ignore_revlogs_before_date: c.ignore_revlogs_before_date,
desired_retention: c.desired_retention, desired_retention: c.desired_retention,
sm2_retention: c.sm2_retention, historical_retention: c.sm2_retention,
weight_search: c.weight_search, weight_search: c.weight_search,
other: other_bytes, other: other_bytes,
}, },
@ -479,7 +480,7 @@ impl From<DeckConfig> for DeckConfSchema11 {
bury_interday_learning: i.bury_interday_learning, bury_interday_learning: i.bury_interday_learning,
fsrs_weights: i.fsrs_weights, fsrs_weights: i.fsrs_weights,
desired_retention: i.desired_retention, desired_retention: i.desired_retention,
sm2_retention: i.sm2_retention, sm2_retention: i.historical_retention,
weight_search: i.weight_search, weight_search: i.weight_search,
ignore_revlogs_before_date: i.ignore_revlogs_before_date, ignore_revlogs_before_date: i.ignore_revlogs_before_date,
} }

View file

@ -263,7 +263,7 @@ impl Collection {
desired_retention: c.inner.desired_retention, 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,
sm2_retention: c.inner.sm2_retention, historical_retention: c.inner.historical_retention,
}) })
} else { } else {
None None

View file

@ -382,10 +382,10 @@ impl Collection {
&fsrs, &fsrs,
revlog, revlog,
timing.next_day_at, timing.next_day_at,
config.inner.sm2_retention, config.inner.historical_retention,
ignore_revlogs_before_ms_from_config(&config)?, ignore_revlogs_before_ms_from_config(&config)?,
)?; )?;
card.set_memory_state(&fsrs, item, config.inner.sm2_retention)?; card.set_memory_state(&fsrs, item, config.inner.historical_retention)?;
} }
let days_elapsed = self let days_elapsed = self
.storage .storage

View file

@ -32,7 +32,7 @@ pub struct ComputeMemoryProgress {
pub(crate) struct UpdateMemoryStateRequest { pub(crate) struct UpdateMemoryStateRequest {
pub weights: Weights, pub weights: Weights,
pub desired_retention: f32, pub desired_retention: f32,
pub sm2_retention: f32, pub historical_retention: f32,
pub max_interval: u32, pub max_interval: u32,
pub reschedule: bool, pub reschedule: bool,
} }
@ -70,12 +70,12 @@ impl Collection {
None None
}; };
let fsrs = FSRS::new(req.as_ref().map(|w| &w.weights[..]).or(Some([].as_slice())))?; let fsrs = FSRS::new(req.as_ref().map(|w| &w.weights[..]).or(Some([].as_slice())))?;
let sm2_retention = req.as_ref().map(|w| w.sm2_retention); let historical_retention = req.as_ref().map(|w| w.historical_retention);
let items = fsrs_items_for_memory_state( let items = fsrs_items_for_memory_state(
&fsrs, &fsrs,
revlog, revlog,
timing.next_day_at, timing.next_day_at,
sm2_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 desired_retention = req.as_ref().map(|w| w.desired_retention);
@ -86,7 +86,7 @@ impl Collection {
let mut card = self.storage.get_card(card_id)?.or_not_found(card_id)?; let mut card = self.storage.get_card(card_id)?.or_not_found(card_id)?;
let original = card.clone(); let original = card.clone();
if let Some(req) = &req { if let Some(req) = &req {
card.set_memory_state(&fsrs, item, sm2_retention.unwrap())?; card.set_memory_state(&fsrs, item, historical_retention.unwrap())?;
card.desired_retention = desired_retention; card.desired_retention = desired_retention;
// if rescheduling // if rescheduling
if let Some(reviews) = &last_revlog_info { if let Some(reviews) = &last_revlog_info {
@ -153,17 +153,17 @@ impl Collection {
.get_deck_config(conf_id)? .get_deck_config(conf_id)?
.or_not_found(conf_id)?; .or_not_found(conf_id)?;
let desired_retention = config.inner.desired_retention; let desired_retention = config.inner.desired_retention;
let sm2_retention = config.inner.sm2_retention; let historical_retention = config.inner.historical_retention;
let fsrs = FSRS::new(Some(&config.inner.fsrs_weights))?; let fsrs = FSRS::new(Some(&config.inner.fsrs_weights))?;
let revlog = self.revlog_for_srs(SearchNode::CardIds(card.id.to_string()))?; let revlog = self.revlog_for_srs(SearchNode::CardIds(card.id.to_string()))?;
let item = single_card_revlog_to_item( let item = single_card_revlog_to_item(
&fsrs, &fsrs,
revlog, revlog,
self.timing_today()?.next_day_at, self.timing_today()?.next_day_at,
sm2_retention, historical_retention,
ignore_revlogs_before_ms_from_config(&config)?, ignore_revlogs_before_ms_from_config(&config)?,
)?; )?;
card.set_memory_state(&fsrs, item, sm2_retention)?; card.set_memory_state(&fsrs, item, historical_retention)?;
Ok(ComputeMemoryStateResponse { Ok(ComputeMemoryStateResponse {
state: card.memory_state.map(Into::into), state: card.memory_state.map(Into::into),
desired_retention, desired_retention,
@ -176,7 +176,7 @@ impl Card {
&mut self, &mut self,
fsrs: &FSRS, fsrs: &FSRS,
item: Option<FsrsItemWithStartingState>, item: Option<FsrsItemWithStartingState>,
sm2_retention: f32, historical_retention: f32,
) -> Result<()> { ) -> Result<()> {
let memory_state = if let Some(i) = item { let memory_state = if let Some(i) = item {
Some(fsrs.memory_state(i.item, i.starting_state)?) Some(fsrs.memory_state(i.item, i.starting_state)?)
@ -187,7 +187,7 @@ impl Card {
Some(fsrs.memory_state_from_sm2( Some(fsrs.memory_state_from_sm2(
self.ease_factor(), self.ease_factor(),
self.interval as f32, self.interval as f32,
sm2_retention, historical_retention,
)?) )?)
}; };
self.memory_state = memory_state.map(Into::into); self.memory_state = memory_state.map(Into::into);
@ -209,7 +209,7 @@ pub(crate) fn fsrs_items_for_memory_state(
fsrs: &FSRS, fsrs: &FSRS,
revlogs: Vec<RevlogEntry>, revlogs: Vec<RevlogEntry>,
next_day_at: TimestampSecs, next_day_at: TimestampSecs,
sm2_retention: f32, historical_retention: f32,
ignore_revlogs_before: TimestampMillis, ignore_revlogs_before: TimestampMillis,
) -> Result<Vec<(CardId, Option<FsrsItemWithStartingState>)>> { ) -> Result<Vec<(CardId, Option<FsrsItemWithStartingState>)>> {
revlogs revlogs
@ -223,7 +223,7 @@ pub(crate) fn fsrs_items_for_memory_state(
fsrs, fsrs,
group.collect(), group.collect(),
next_day_at, next_day_at,
sm2_retention, historical_retention,
ignore_revlogs_before, ignore_revlogs_before,
)?, )?,
)) ))
@ -277,7 +277,7 @@ pub(crate) fn single_card_revlog_to_item(
fsrs: &FSRS, fsrs: &FSRS,
entries: Vec<RevlogEntry>, entries: Vec<RevlogEntry>,
next_day_at: TimestampSecs, next_day_at: TimestampSecs,
sm2_retention: f32, historical_retention: f32,
ignore_revlogs_before: TimestampMillis, ignore_revlogs_before: TimestampMillis,
) -> Result<Option<FsrsItemWithStartingState>> { ) -> Result<Option<FsrsItemWithStartingState>> {
struct FirstReview { struct FirstReview {
@ -310,7 +310,7 @@ pub(crate) fn single_card_revlog_to_item(
let starting_state = fsrs.memory_state_from_sm2( let starting_state = fsrs.memory_state_from_sm2(
first_review.ease_factor, first_review.ease_factor,
first_review.interval, first_review.interval,
sm2_retention, historical_retention,
)?; )?;
item.reviews.remove(0); item.reviews.remove(0);
if item.reviews.is_empty() { if item.reviews.is_empty() {

View file

@ -33,9 +33,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
help: tr.deckConfigMaximumIntervalTooltip(), help: tr.deckConfigMaximumIntervalTooltip(),
url: HelpPage.DeckOptions.maximumInterval, url: HelpPage.DeckOptions.maximumInterval,
}, },
sm2Retention: { historicalRetention: {
title: tr.deckConfigSm2Retention(), title: tr.deckConfigHistoricalRetention(),
help: tr.deckConfigSm2RetentionTooltip(), help: tr.deckConfigHistoricalRetentionTooltip(),
sched: HelpItemScheduler.FSRS, sched: HelpItemScheduler.FSRS,
}, },
startingEase: { startingEase: {
@ -201,16 +201,18 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</Item> </Item>
{:else} {:else}
<SpinBoxFloatRow <SpinBoxFloatRow
bind:value={$config.sm2Retention} bind:value={$config.historicalRetention}
defaultValue={defaults.sm2Retention} defaultValue={defaults.historicalRetention}
min={0.5} min={0.5}
max={1.0} max={1.0}
> >
<SettingTitle <SettingTitle
on:click={() => on:click={() =>
openHelpModal(Object.keys(settings).indexOf("sm2Retention"))} openHelpModal(
Object.keys(settings).indexOf("historicalRetention"),
)}
> >
{tr.deckConfigSm2Retention()} {tr.deckConfigHistoricalRetention()}
</SettingTitle> </SettingTitle>
</SpinBoxFloatRow> </SpinBoxFloatRow>
{/if} {/if}