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-evaluate-button = Evaluate
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-steps-too-large-for-fsrs = When FSRS is enabled, steps of 1 day or more are not recommended.
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
values will greatly increase your workload, and lower values can be demoralizing when you forget
a lot of material.
deck-config-sm2-retention-tooltip =
If your actual retention before switching to FSRS was significantly different from 0.9, adjusting
this value will allow Anki to better estimate your memory state when it encounters cards that are
missing review logs. Since review logs typically won't be missing unless you explicitly deleted them
to free up space, most users will not need to adjust this.
deck-config-historical-retention-tooltip =
When some of your review history is missing, FSRS needs to fill in the gaps. By default, it will
assume that when you did those old reviews, you remembered 90% of the material. If your old retention
was appreciably higher or lower than 90%, adjusting this option will allow FSRS to better approximate
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 =
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

View file

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

View file

@ -75,7 +75,7 @@ const DEFAULT_DECK_CONFIG_INNER: DeckConfigInner = DeckConfigInner {
fsrs_weights: vec![],
desired_retention: 0.9,
other: Vec::new(),
sm2_retention: 0.9,
historical_retention: 0.9,
weight_search: 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.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) {

View file

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

View file

@ -263,7 +263,7 @@ impl Collection {
desired_retention: c.inner.desired_retention,
max_interval: c.inner.maximum_review_interval,
reschedule: req.fsrs_reschedule,
sm2_retention: c.inner.sm2_retention,
historical_retention: c.inner.historical_retention,
})
} else {
None

View file

@ -382,10 +382,10 @@ impl Collection {
&fsrs,
revlog,
timing.next_day_at,
config.inner.sm2_retention,
config.inner.historical_retention,
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
.storage

View file

@ -32,7 +32,7 @@ pub struct ComputeMemoryProgress {
pub(crate) struct UpdateMemoryStateRequest {
pub weights: Weights,
pub desired_retention: f32,
pub sm2_retention: f32,
pub historical_retention: f32,
pub max_interval: u32,
pub reschedule: bool,
}
@ -70,12 +70,12 @@ impl Collection {
None
};
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(
&fsrs,
revlog,
timing.next_day_at,
sm2_retention.unwrap_or(0.9),
historical_retention.unwrap_or(0.9),
ignore_before,
)?;
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 original = card.clone();
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;
// if rescheduling
if let Some(reviews) = &last_revlog_info {
@ -153,17 +153,17 @@ impl Collection {
.get_deck_config(conf_id)?
.or_not_found(conf_id)?;
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 revlog = self.revlog_for_srs(SearchNode::CardIds(card.id.to_string()))?;
let item = single_card_revlog_to_item(
&fsrs,
revlog,
self.timing_today()?.next_day_at,
sm2_retention,
historical_retention,
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 {
state: card.memory_state.map(Into::into),
desired_retention,
@ -176,7 +176,7 @@ impl Card {
&mut self,
fsrs: &FSRS,
item: Option<FsrsItemWithStartingState>,
sm2_retention: f32,
historical_retention: f32,
) -> Result<()> {
let memory_state = if let Some(i) = item {
Some(fsrs.memory_state(i.item, i.starting_state)?)
@ -187,7 +187,7 @@ impl Card {
Some(fsrs.memory_state_from_sm2(
self.ease_factor(),
self.interval as f32,
sm2_retention,
historical_retention,
)?)
};
self.memory_state = memory_state.map(Into::into);
@ -209,7 +209,7 @@ pub(crate) fn fsrs_items_for_memory_state(
fsrs: &FSRS,
revlogs: Vec<RevlogEntry>,
next_day_at: TimestampSecs,
sm2_retention: f32,
historical_retention: f32,
ignore_revlogs_before: TimestampMillis,
) -> Result<Vec<(CardId, Option<FsrsItemWithStartingState>)>> {
revlogs
@ -223,7 +223,7 @@ pub(crate) fn fsrs_items_for_memory_state(
fsrs,
group.collect(),
next_day_at,
sm2_retention,
historical_retention,
ignore_revlogs_before,
)?,
))
@ -277,7 +277,7 @@ pub(crate) fn single_card_revlog_to_item(
fsrs: &FSRS,
entries: Vec<RevlogEntry>,
next_day_at: TimestampSecs,
sm2_retention: f32,
historical_retention: f32,
ignore_revlogs_before: TimestampMillis,
) -> Result<Option<FsrsItemWithStartingState>> {
struct FirstReview {
@ -310,7 +310,7 @@ pub(crate) fn single_card_revlog_to_item(
let starting_state = fsrs.memory_state_from_sm2(
first_review.ease_factor,
first_review.interval,
sm2_retention,
historical_retention,
)?;
item.reviews.remove(0);
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(),
url: HelpPage.DeckOptions.maximumInterval,
},
sm2Retention: {
title: tr.deckConfigSm2Retention(),
help: tr.deckConfigSm2RetentionTooltip(),
historicalRetention: {
title: tr.deckConfigHistoricalRetention(),
help: tr.deckConfigHistoricalRetentionTooltip(),
sched: HelpItemScheduler.FSRS,
},
startingEase: {
@ -201,16 +201,18 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</Item>
{:else}
<SpinBoxFloatRow
bind:value={$config.sm2Retention}
defaultValue={defaults.sm2Retention}
bind:value={$config.historicalRetention}
defaultValue={defaults.historicalRetention}
min={0.5}
max={1.0}
>
<SettingTitle
on:click={() =>
openHelpModal(Object.keys(settings).indexOf("sm2Retention"))}
openHelpModal(
Object.keys(settings).indexOf("historicalRetention"),
)}
>
{tr.deckConfigSm2Retention()}
{tr.deckConfigHistoricalRetention()}
</SettingTitle>
</SpinBoxFloatRow>
{/if}