From da0e42ea0374f8d18c3cd1b893e4511b1c032f0f Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Mon, 25 Sep 2023 14:40:44 +1000 Subject: [PATCH] Fix extract_fsrs_retrievabilty() - Need to use fuzzed interval to accurately determine elapsed days - saturating_sub on an i32 is not useful --- rslib/src/search/mod.rs | 2 +- rslib/src/search/sqlwriter.rs | 2 +- rslib/src/storage/sqlite.rs | 17 ++++++++--------- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/rslib/src/search/mod.rs b/rslib/src/search/mod.rs index 5fe7a0195..5d983defc 100644 --- a/rslib/src/search/mod.rs +++ b/rslib/src/search/mod.rs @@ -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(), diff --git a/rslib/src/search/sqlwriter.rs b/rslib/src/search/sqlwriter.rs index 639c55b73..fd1456f5d 100644 --- a/rslib/src/search/sqlwriter.rs +++ b/rslib/src/search/sqlwriter.rs @@ -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() } diff --git a/rslib/src/storage/sqlite.rs b/rslib/src/storage/sqlite.rs index 30390a954..216837e69 100644 --- a/rslib/src/storage/sqlite.rs +++ b/rslib/src/storage/sqlite.rs @@ -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()