Fix extract_fsrs_retrievabilty()

- Need to use fuzzed interval to accurately determine elapsed days
- saturating_sub on an i32 is not useful
This commit is contained in:
Damien Elmes 2023-09-25 14:40:44 +10:00
parent 3c62a8345a
commit da0e42ea03
3 changed files with 10 additions and 11 deletions

View File

@ -377,7 +377,7 @@ fn card_order_from_sort_column(column: Column, timing: SchedTimingToday) -> Cow<
Column::Stability => "extract_fsrs_variable(c.data, 's') desc".into(),
Column::Difficulty => "extract_fsrs_variable(c.data, 'd') desc".into(),
Column::Retrievability => format!(
"extract_fsrs_retrievability(c.data, c.due, {})",
"extract_fsrs_retrievability(c.data, c.due, c.ivl, {})",
timing.days_elapsed
)
.into(),

View File

@ -383,7 +383,7 @@ impl SqlWriter<'_> {
let elap = self.col.timing_today()?.days_elapsed;
write!(
self.sql,
"extract_fsrs_retrievability(c.data, c.due, {elap}) {op} {r}"
"extract_fsrs_retrievability(c.data, c.due, c.ivl, {elap}) {op} {r}"
)
.unwrap()
}

View File

@ -265,15 +265,15 @@ fn add_extract_fsrs_variable(db: &Connection) -> rusqlite::Result<()> {
)
}
/// eg. extract_fsrs_retrievability(card.data, card.due, timing.days_elapsed) ->
/// float | null
/// eg. extract_fsrs_retrievability(card.data, card.due, card.ivl,
/// timing.days_elapsed) -> float | null
fn add_extract_fsrs_retrievability(db: &Connection) -> rusqlite::Result<()> {
db.create_scalar_function(
"extract_fsrs_retrievability",
3,
4,
FunctionFlags::SQLITE_DETERMINISTIC,
move |ctx| {
assert_eq!(ctx.len(), 3, "called with unexpected number of arguments");
assert_eq!(ctx.len(), 4, "called with unexpected number of arguments");
let Ok(card_data) = ctx.get_raw(0).as_str() else {
return Ok(None);
@ -289,15 +289,14 @@ fn add_extract_fsrs_retrievability(db: &Connection) -> rusqlite::Result<()> {
// learning card
return Ok(None);
}
let Ok(days_elapsed) = ctx.get_raw(2).as_i64() else {
let Ok(ivl) = ctx.get_raw(2).as_i64() else {
return Ok(None);
};
let Some(stability) = card_data.fsrs_stability else {
let Ok(days_elapsed) = ctx.get_raw(3).as_i64() else {
return Ok(None);
};
let review_day = due.saturating_sub(stability as i64);
let days_elapsed = days_elapsed.saturating_sub(review_day) as u32;
let review_day = (due.max(0) as u32).saturating_sub(ivl as u32);
let days_elapsed = (days_elapsed.max(0) as u32).saturating_sub(review_day);
Ok(card_data.memory_state().map(|state| {
FSRS::new(None)
.unwrap()