From b248911b0f477173594a60d672b23439943cf5a9 Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Mon, 20 Nov 2023 10:52:13 +1000 Subject: [PATCH] Fix cards showing up due in the past in a filtered deck Caused by using due instead of original_due when card was in learning. I think the original goal of that code was to ignore the learning timestamp and show the next review date instead, but it's both simpler and more intuitive to show the learning date instead. --- rslib/src/card/mod.rs | 3 +++ rslib/src/scheduler/filtered/card.rs | 3 ++- rslib/src/scheduler/timing.rs | 5 +++++ rslib/src/stats/card.rs | 3 ++- rslib/src/stats/graphs/future_due.rs | 12 +++--------- 5 files changed, 15 insertions(+), 11 deletions(-) diff --git a/rslib/src/card/mod.rs b/rslib/src/card/mod.rs index a14f3b176..e74c9b368 100644 --- a/rslib/src/card/mod.rs +++ b/rslib/src/card/mod.rs @@ -213,6 +213,9 @@ impl Card { (self.ease_factor as f32) / 1000.0 } + /// Don't use this in situations where you may be using original_due, since + /// it only applies to the current due date. You may want to use + /// is_unix_epoch_timestap() instead. pub fn is_intraday_learning(&self) -> bool { matches!(self.queue, CardQueue::Learn | CardQueue::PreviewRepeat) } diff --git a/rslib/src/scheduler/filtered/card.rs b/rslib/src/scheduler/filtered/card.rs index bf1ff417b..d67ebcbc7 100644 --- a/rslib/src/scheduler/filtered/card.rs +++ b/rslib/src/scheduler/filtered/card.rs @@ -5,12 +5,13 @@ use super::DeckFilterContext; use crate::card::CardQueue; use crate::card::CardType; use crate::prelude::*; +use crate::scheduler::timing::is_unix_epoch_timestamp; impl Card { pub(crate) fn restore_queue_from_type(&mut self) { self.queue = match self.ctype { CardType::Learn | CardType::Relearn => { - if self.due > 1_000_000_000 { + if is_unix_epoch_timestamp(self.due) { // unix timestamp CardQueue::Learn } else { diff --git a/rslib/src/scheduler/timing.rs b/rslib/src/scheduler/timing.rs index 61b819894..3d79138ce 100644 --- a/rslib/src/scheduler/timing.rs +++ b/rslib/src/scheduler/timing.rs @@ -178,6 +178,11 @@ pub(crate) fn sched_timing_today( } } +/// True if provided due number looks like a seconds-based timestamp. +pub fn is_unix_epoch_timestamp(due: i32) -> bool { + due > 1_000_000_000 +} + #[cfg(test)] mod test { use chrono::FixedOffset; diff --git a/rslib/src/stats/card.rs b/rslib/src/stats/card.rs index c052cd10b..7bc40c51b 100644 --- a/rslib/src/stats/card.rs +++ b/rslib/src/stats/card.rs @@ -7,6 +7,7 @@ use crate::card::CardQueue; use crate::card::CardType; use crate::prelude::*; use crate::revlog::RevlogEntry; +use crate::scheduler::timing::is_unix_epoch_timestamp; impl Collection { pub fn card_stats(&mut self, cid: CardId) -> Result { @@ -81,7 +82,7 @@ impl Collection { } CardType::Review | CardType::Learn | CardType::Relearn => ( { - if due <= 1_000_000_000 { + if !is_unix_epoch_timestamp(due) { let days_remaining = due - (self.timing_today()?.days_elapsed as i32); let mut due = TimestampSecs::now(); due.0 += (days_remaining as i64) * 86_400; diff --git a/rslib/src/stats/graphs/future_due.rs b/rslib/src/stats/graphs/future_due.rs index ff92cd366..ef7da2ad3 100644 --- a/rslib/src/stats/graphs/future_due.rs +++ b/rslib/src/stats/graphs/future_due.rs @@ -6,6 +6,7 @@ use std::collections::HashMap; use anki_proto::stats::graphs_response::FutureDue; use super::GraphsContext; +use crate::scheduler::timing::is_unix_epoch_timestamp; impl GraphsContext { pub(super) fn future_due(&self) -> FutureDue { @@ -15,15 +16,8 @@ impl GraphsContext { if c.queue as i8 <= 0 { continue; } - // The extra original_due check covers lapsed cards, which have their due date - // updated on graduation. - let intraday = c.is_intraday_learning(); - let due = if c.is_filtered() && c.original_due != 0 && !intraday { - c.original_due - } else { - c.due - }; - let due_day = if c.is_intraday_learning() { + let due = c.original_or_current_due(); + let due_day = if is_unix_epoch_timestamp(due) { let offset = due as i64 - self.next_day_start.0; (offset / 86_400) as i32 } else {