include decay in ComputeMemoryStateResponse (#4102)

* include decay in ComputeMemoryStateResponse

* Add decay attribute to ComputedMemoryState and update Collection methods

* Refactor decay calculation into a helper function for improved readability and maintainability in memory state management

* format & clippy
This commit is contained in:
Jarrett Ye 2025-06-21 01:59:35 +08:00 committed by GitHub
parent b781dfabf5
commit a4c95f5fbd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 25 additions and 11 deletions

View file

@ -450,6 +450,7 @@ message EvaluateParamsResponse {
message ComputeMemoryStateResponse {
optional cards.FsrsMemoryState state = 1;
float desired_retention = 2;
float decay = 3;
}
message FuzzDeltaRequest {

View file

@ -122,6 +122,7 @@ class ComputedMemoryState:
desired_retention: float
stability: float | None = None
difficulty: float | None = None
decay: float | None = None
@dataclass
@ -1189,9 +1190,13 @@ class Collection(DeprecatedNamesMixin):
desired_retention=resp.desired_retention,
stability=resp.state.stability,
difficulty=resp.state.difficulty,
decay=resp.decay,
)
else:
return ComputedMemoryState(desired_retention=resp.desired_retention)
return ComputedMemoryState(
desired_retention=resp.desired_retention,
decay=resp.decay,
)
def fuzz_delta(self, card_id: CardId, interval: int) -> int:
"The delta days of fuzz applied if reviewing the card in v3."

View file

@ -30,6 +30,18 @@ pub struct ComputeMemoryProgress {
pub total_cards: u32,
}
/// Helper function to determine the appropriate decay value based on FSRS
/// parameters
fn get_decay_from_params(params: &[f32]) -> f32 {
if params.is_empty() {
FSRS6_DEFAULT_DECAY // default decay for FSRS-6
} else if params.len() < 21 {
FSRS5_DEFAULT_DECAY // default decay for FSRS-4.5 and FSRS-5
} else {
params[20]
}
}
#[derive(Debug)]
pub(crate) struct UpdateMemoryStateRequest {
pub params: Params,
@ -77,15 +89,7 @@ impl Collection {
.then(|| Rescheduler::new(self))
.transpose()?;
let fsrs = FSRS::new(req.as_ref().map(|w| &w.params[..]).or(Some([].as_slice())))?;
let decay = req.as_ref().map(|w| {
if w.params.is_empty() {
FSRS6_DEFAULT_DECAY // default decay for FSRS-6
} else if w.params.len() < 21 {
FSRS5_DEFAULT_DECAY // default decay for FSRS-4.5 and FSRS-5
} else {
w.params[20]
}
});
let decay = req.as_ref().map(|w| get_decay_from_params(&w.params));
let historical_retention = req.as_ref().map(|w| w.historical_retention);
let items = fsrs_items_for_memory_states(
&fsrs,
@ -190,7 +194,9 @@ impl Collection {
.or_not_found(conf_id)?;
let desired_retention = config.inner.desired_retention;
let historical_retention = config.inner.historical_retention;
let fsrs = FSRS::new(Some(config.fsrs_params()))?;
let params = config.fsrs_params();
let decay = get_decay_from_params(params);
let fsrs = FSRS::new(Some(params))?;
let revlog = self.revlog_for_srs(SearchNode::CardIds(card.id.to_string()))?;
let item = fsrs_item_for_memory_state(
&fsrs,
@ -204,6 +210,7 @@ impl Collection {
Ok(ComputeMemoryStateResponse {
state: card.memory_state.map(Into::into),
desired_retention,
decay,
})
} else {
card.memory_state = None;
@ -211,6 +218,7 @@ impl Collection {
Ok(ComputeMemoryStateResponse {
state: None,
desired_retention,
decay,
})
}
}