Shift FSRS optimization into top level; shown optimize all tip after 30 days

This commit is contained in:
Damien Elmes 2024-03-17 17:46:12 +07:00
parent 5eafd82521
commit e9d3b46d47
5 changed files with 57 additions and 39 deletions

View file

@ -202,6 +202,7 @@ message DeckConfigsForUpdate {
bool new_cards_ignore_review_limit = 7;
bool fsrs = 8;
bool apply_all_parent_limits = 9;
uint32 days_since_last_fsrs_optimize = 10;
}
enum UpdateDeckConfigsMode {

View file

@ -10,6 +10,7 @@ use crate::prelude::*;
pub enum I32ConfigKey {
CsvDuplicateResolution,
MatchScope,
LastFsrsOptimize,
}
impl Collection {

View file

@ -14,6 +14,7 @@ use anki_proto::deck_config::UpdateDeckConfigsMode;
use anki_proto::decks::deck::normal::DayLimit;
use fsrs::DEFAULT_PARAMETERS;
use crate::config::I32ConfigKey;
use crate::config::StringKey;
use crate::decks::NormalDeck;
use crate::prelude::*;
@ -47,6 +48,14 @@ impl Collection {
) -> Result<anki_proto::deck_config::DeckConfigsForUpdate> {
let mut defaults = DeckConfig::default();
defaults.inner.fsrs_weights = DEFAULT_PARAMETERS.into();
let last_optimize = self.get_config_i32(I32ConfigKey::LastFsrsOptimize) as u32;
let days_since_last_fsrs_optimize = if last_optimize > 0 {
self.timing_today()?
.days_elapsed
.saturating_sub(last_optimize)
} else {
0
};
Ok(anki_proto::deck_config::DeckConfigsForUpdate {
all_config: self.get_deck_config_with_extra_for_update()?,
current_deck: Some(self.get_current_deck_for_update(deck)?),
@ -59,6 +68,7 @@ impl Collection {
new_cards_ignore_review_limit: self.get_config_bool(BoolKey::NewCardsIgnoreReviewLimit),
apply_all_parent_limits: self.get_config_bool(BoolKey::ApplyAllParentLimits),
fsrs: self.get_config_bool(BoolKey::Fsrs),
days_since_last_fsrs_optimize,
})
}
@ -354,6 +364,8 @@ impl Collection {
println!("{}: {}", config.name, err)
}
}
let today = self.timing_today()?.days_elapsed as i32;
self.set_config_i32_inner(I32ConfigKey::LastFsrsOptimize, today)?;
}
Ok(())
}

View file

@ -35,6 +35,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
const config = state.currentConfig;
const defaults = state.defaults;
const fsrsReschedule = state.fsrsReschedule;
const daysSinceLastOptimization = state.daysSinceLastOptimization;
$: lastOptimizationWarning =
$daysSinceLastOptimization > 30 ? tr.deckConfigOptimizeAllTip() : "";
let computeWeightsProgress: ComputeWeightsProgress | undefined;
let computingWeights = false;
@ -300,46 +304,44 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</div>
<div class="m-2">
<details>
<summary>{tr.deckConfigComputeOptimalWeights()}</summary>
<input
bind:value={$config.weightSearch}
placeholder={defaultWeightSearch}
class="w-100 mb-1"
/>
<button
class="btn {computingWeights ? 'btn-warning' : 'btn-primary'}"
disabled={!computingWeights && computing}
on:click={() => computeWeights()}
>
{#if computingWeights}
{tr.actionsCancel()}
{:else}
{tr.deckConfigOptimizeButton()}
{/if}
</button>
<button
class="btn {checkingWeights ? 'btn-warning' : 'btn-primary'}"
disabled={!checkingWeights && computing}
on:click={() => checkWeights()}
>
{#if checkingWeights}
{tr.actionsCancel()}
{:else}
{tr.deckConfigEvaluateButton()}
{/if}
</button>
<DateInput bind:date={$config.ignoreRevlogsBeforeDate}>
<SettingTitle on:click={() => openHelpModal("ignoreBefore")}>
{tr.deckConfigIgnoreBefore()}
</SettingTitle>
</DateInput>
{#if computingWeights || checkingWeights}<div>
{computeWeightsProgressString}
</div>{/if}
<b>{tr.deckConfigComputeOptimalWeights()}</b>
<input
bind:value={$config.weightSearch}
placeholder={defaultWeightSearch}
class="w-100 mb-1"
/>
<button
class="btn {computingWeights ? 'btn-warning' : 'btn-primary'}"
disabled={!computingWeights && computing}
on:click={() => computeWeights()}
>
{#if computingWeights}
{tr.actionsCancel()}
{:else}
{tr.deckConfigOptimizeButton()}
{/if}
</button>
<button
class="btn {checkingWeights ? 'btn-warning' : 'btn-primary'}"
disabled={!checkingWeights && computing}
on:click={() => checkWeights()}
>
{#if checkingWeights}
{tr.actionsCancel()}
{:else}
{tr.deckConfigEvaluateButton()}
{/if}
</button>
<DateInput bind:date={$config.ignoreRevlogsBeforeDate}>
<SettingTitle on:click={() => openHelpModal("ignoreBefore")}>
{tr.deckConfigIgnoreBefore()}
</SettingTitle>
</DateInput>
{#if computingWeights || checkingWeights}<div>
{computeWeightsProgressString}
</div>{/if}
<div>{tr.deckConfigOptimizeAllTip()}</div>
</details>
<Warning warning={lastOptimizationWarning} className="alert-warning" />
</div>
<div class="m-2">

View file

@ -45,6 +45,7 @@ export class DeckOptionsState {
readonly applyAllParentLimits: Writable<boolean>;
readonly fsrs: Writable<boolean>;
readonly fsrsReschedule: Writable<boolean> = writable(false);
readonly daysSinceLastOptimization: Writable<number>;
readonly currentPresetName: Writable<string>;
private targetDeckId: DeckOptionsId;
@ -78,6 +79,7 @@ export class DeckOptionsState {
this.newCardsIgnoreReviewLimit = writable(data.newCardsIgnoreReviewLimit);
this.applyAllParentLimits = writable(data.applyAllParentLimits);
this.fsrs = writable(data.fsrs);
this.daysSinceLastOptimization = writable(data.daysSinceLastFsrsOptimize);
// decrement the use count of the starting item, as we'll apply +1 to currently
// selected one at display time