Merge branch 'main' into workload-with-cards

This commit is contained in:
Luc Mcgrady 2025-08-04 12:31:24 +01:00 committed by GitHub
commit d5089cb331
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 32 additions and 22 deletions

2
Cargo.lock generated
View file

@ -2851,7 +2851,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5"
dependencies = [ dependencies = [
"allocator-api2", "allocator-api2",
"equivalent", "equivalentclone()",
"foldhash", "foldhash",
"serde", "serde",
] ]

View file

@ -407,6 +407,8 @@ message SimulateFsrsReviewRequest {
deck_config.DeckConfig.Config.ReviewCardOrder review_order = 11; deck_config.DeckConfig.Config.ReviewCardOrder review_order = 11;
optional uint32 suspend_after_lapse_count = 12; optional uint32 suspend_after_lapse_count = 12;
float historical_retention = 13; float historical_retention = 13;
uint32 learning_step_count = 14;
uint32 relearning_step_count = 15;
} }
message SimulateFsrsReviewResponse { message SimulateFsrsReviewResponse {

View file

@ -126,8 +126,9 @@ impl Card {
} }
} }
/// This uses card.due and card.ivl to infer the elapsed time. If 'set due /// If last_review_date isn't stored in the card, this uses card.due and
/// date' or an add-on has changed the due date, this won't be accurate. /// card.ivl to infer the elapsed time, which won't be accurate if
/// 'set due date' or an add-on has changed the due date.
pub(crate) fn seconds_since_last_review(&self, timing: &SchedTimingToday) -> Option<u32> { pub(crate) fn seconds_since_last_review(&self, timing: &SchedTimingToday) -> Option<u32> {
if let Some(last_review_time) = self.last_review_time { if let Some(last_review_time) = self.last_review_time {
Some(timing.now.elapsed_secs_since(last_review_time) as u32) Some(timing.now.elapsed_secs_since(last_review_time) as u32)

View file

@ -238,8 +238,8 @@ impl Collection {
learning_step_transitions: p.learning_step_transitions, learning_step_transitions: p.learning_step_transitions,
relearning_step_transitions: p.relearning_step_transitions, relearning_step_transitions: p.relearning_step_transitions,
state_rating_costs: p.state_rating_costs, state_rating_costs: p.state_rating_costs,
learning_step_count: p.learning_step_count, learning_step_count: req.learning_step_count as usize,
relearning_step_count: p.relearning_step_count, relearning_step_count: req.relearning_step_count as usize,
}; };
Ok((config, converted_cards)) Ok((config, converted_cards))

View file

@ -113,6 +113,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
easyDaysPercentages: $config.easyDaysPercentages, easyDaysPercentages: $config.easyDaysPercentages,
reviewOrder: $config.reviewOrder, reviewOrder: $config.reviewOrder,
historicalRetention: $config.historicalRetention, historicalRetention: $config.historicalRetention,
learningStepCount: $config.learnSteps.length,
relearningStepCount: $config.relearnSteps.length,
}); });
const DESIRED_RETENTION_LOW_THRESHOLD = 0.8; const DESIRED_RETENTION_LOW_THRESHOLD = 0.8;
@ -128,7 +130,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
} }
} }
let retentionWorloadInfo: undefined | Promise<GetRetentionWorkloadResponse> = let retentionWorkloadInfo: undefined | Promise<GetRetentionWorkloadResponse> =
undefined; undefined;
let lastParams = [...fsrsParams($config)]; let lastParams = [...fsrsParams($config)];
@ -139,7 +141,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
} }
if ( if (
// If the cache is empty and a request has not yet been made to fill it // If the cache is empty and a request has not yet been made to fill it
!retentionWorloadInfo || !retentionWorkloadInfo ||
// If the parameters have been changed // If the parameters have been changed
lastParams.toString() !== params.toString() lastParams.toString() !== params.toString()
) { ) {
@ -148,12 +150,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
search: defaultparamSearch, search: defaultparamSearch,
}); });
lastParams = [...params]; lastParams = [...params];
retentionWorloadInfo = getRetentionWorkload(request); retentionWorkloadInfo = getRetentionWorkload(request);
} }
const previous = +startingDesiredRetention * 100; const previous = +startingDesiredRetention * 100;
const after = retention * 100; const after = retention * 100;
const resp = await retentionWorloadInfo; const resp = await retentionWorkloadInfo;
const factor = resp.costs[after] / resp.costs[previous]; const factor = resp.costs[after] / resp.costs[previous];
desiredRetentionChangeInfo = tr.deckConfigWorkloadFactorChange({ desiredRetentionChangeInfo = tr.deckConfigWorkloadFactorChange({
@ -218,29 +220,34 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
healthCheck: $healthCheck, healthCheck: $healthCheck,
}); });
const already_optimal = const alreadyOptimal =
(params.length && (params.length &&
params.every( params.every(
(n, i) => n.toFixed(4) === resp.params[i].toFixed(4), (n, i) => n.toFixed(4) === resp.params[i].toFixed(4),
)) || )) ||
resp.params.length === 0; resp.params.length === 0;
let healthCheckMessage = "";
if (resp.healthCheckPassed !== undefined) { if (resp.healthCheckPassed !== undefined) {
if (resp.healthCheckPassed) { healthCheckMessage = resp.healthCheckPassed
setTimeout(() => alert(tr.deckConfigFsrsGoodFit()), 200); ? tr.deckConfigFsrsGoodFit()
} else { : tr.deckConfigFsrsBadFitWarning();
setTimeout( }
() => alert(tr.deckConfigFsrsBadFitWarning()), let alreadyOptimalMessage = "";
200, if (alreadyOptimal) {
); alreadyOptimalMessage = resp.fsrsItems
}
} else if (already_optimal) {
const msg = resp.fsrsItems
? tr.deckConfigFsrsParamsOptimal() ? tr.deckConfigFsrsParamsOptimal()
: tr.deckConfigFsrsParamsNoReviews(); : tr.deckConfigFsrsParamsNoReviews();
setTimeout(() => alert(msg), 200);
} }
if (!already_optimal) { const message = [alreadyOptimalMessage, healthCheckMessage]
.filter((a) => a)
.join("\n\n");
if (message) {
setTimeout(() => alert(message), 200);
}
if (!alreadyOptimal) {
$config.fsrsParams6 = resp.params; $config.fsrsParams6 = resp.params;
setTimeout(() => { setTimeout(() => {
optimized = true; optimized = true;