Merge pull request #904 from hgiesel/propdue

Streamlining `is:due`, `prop:due`, and the FutureDue graph
This commit is contained in:
Damien Elmes 2021-01-08 16:34:53 +10:00 committed by GitHub
commit 97e3bfe1c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 42 additions and 26 deletions

View File

@ -235,16 +235,25 @@ impl SqlWriter<'_> {
fn write_prop(&mut self, op: &str, kind: &PropertyKind) -> Result<()> { fn write_prop(&mut self, op: &str, kind: &PropertyKind) -> Result<()> {
let timing = self.col.timing_today()?; let timing = self.col.timing_today()?;
match kind { match kind {
PropertyKind::Due(days) => { PropertyKind::Due(days) => {
let day = days + (timing.days_elapsed as i32); let day = days + (timing.days_elapsed as i32);
write!( write!(
self.sql, self.sql,
"(c.queue in ({rev},{daylrn}) and due {op} {day})", // SQL does integer division if both parameters are integers
"(\
(c.queue in ({rev},{daylrn}) and c.due {op} {day}) or \
(c.queue in ({lrn},{previewrepeat}) and ((c.due - {cutoff}) / 86400) {op} {days})\
)",
rev = CardQueue::Review as u8, rev = CardQueue::Review as u8,
daylrn = CardQueue::DayLearn as u8, daylrn = CardQueue::DayLearn as u8,
op = op, op = op,
day = day day = day,
lrn = CardQueue::Learn as i8,
previewrepeat = CardQueue::PreviewRepeat as i8,
cutoff = timing.next_day_at,
days = days
) )
} }
PropertyKind::Position(pos) => { PropertyKind::Position(pos) => {
@ -292,14 +301,15 @@ impl SqlWriter<'_> {
StateKind::Suspended => write!(self.sql, "c.queue = {}", CardQueue::Suspended as i8), StateKind::Suspended => write!(self.sql, "c.queue = {}", CardQueue::Suspended as i8),
StateKind::Due => write!( StateKind::Due => write!(
self.sql, self.sql,
"( "(\
(c.queue in ({rev},{daylrn}) and c.due <= {today}) or (c.queue in ({rev},{daylrn}) and c.due <= {today}) or \
(c.queue = {lrn} and c.due <= {learncutoff}) (c.queue in ({lrn},{previewrepeat}) and c.due <= {learncutoff})\
)", )",
rev = CardQueue::Review as i8, rev = CardQueue::Review as i8,
daylrn = CardQueue::DayLearn as i8, daylrn = CardQueue::DayLearn as i8,
today = timing.days_elapsed, today = timing.days_elapsed,
lrn = CardQueue::Learn as i8, lrn = CardQueue::Learn as i8,
previewrepeat = CardQueue::PreviewRepeat as i8,
learncutoff = TimestampSecs::now().0 + (self.col.learn_ahead_secs() as i64), learncutoff = TimestampSecs::now().0 + (self.col.learn_ahead_secs() as i64),
), ),
StateKind::UserBuried => write!(self.sql, "c.queue = {}", CardQueue::UserBuried as i8), StateKind::UserBuried => write!(self.sql, "c.queue = {}", CardQueue::UserBuried as i8),
@ -725,8 +735,9 @@ mod test {
assert_eq!( assert_eq!(
s(ctx, "prop:due!=-1").0, s(ctx, "prop:due!=-1").0,
format!( format!(
"((c.queue in (2,3) and due != {}))", "(((c.queue in (2,3) and c.due != {days}) or (c.queue in (1,4) and ((c.due - {cutoff}) / 86400) != -1)))",
timing.days_elapsed - 1 days = timing.days_elapsed - 1,
cutoff = timing.next_day_at
) )
); );

View File

@ -23,31 +23,36 @@ export interface GraphData {
} }
export function gatherData(data: pb.BackendProto.GraphsOut): GraphData { export function gatherData(data: pb.BackendProto.GraphsOut): GraphData {
const isLearning = (queue: number): boolean => const isLearning = (card: pb.BackendProto.Card): boolean =>
[CardQueue.Learn, CardQueue.PreviewRepeat].includes(queue); [CardQueue.Learn, CardQueue.PreviewRepeat].includes(card.queue);
let haveBacklog = false; let haveBacklog = false;
const due = (data.cards as pb.BackendProto.Card[]) const due = (data.cards as pb.BackendProto.Card[])
.filter( .filter((c: pb.BackendProto.Card) => {
(c) => // reviews
// reviews return (
[CardQueue.Review, CardQueue.DayLearn].includes(c.queue) || [CardQueue.Review, CardQueue.DayLearn].includes(c.queue) ||
// or learning cards due today // or learning cards
(isLearning(c.queue) && c.due < data.nextDayAtSecs) isLearning(c)
) );
.map((c) => { })
if (isLearning(c.queue)) { .map((c: pb.BackendProto.Card) => {
return 0; let dueDay: number;
if (isLearning(c)) {
const offset = c.due - data.nextDayAtSecs;
dueDay = Math.floor(offset / 86_400) + 1;
} else { } else {
// - testing just odue fails on day 1 // - testing just odue fails on day 1
// - testing just odid fails on lapsed cards that // - testing just odid fails on lapsed cards that
// have due calculated at regraduation time // have due calculated at regraduation time
const due = c.originalDeckId && c.originalDue ? c.originalDue : c.due; const due = c.originalDeckId && c.originalDue ? c.originalDue : c.due;
const dueDay = due - data.daysElapsed; dueDay = due - data.daysElapsed;
if (dueDay < 0) {
haveBacklog = true;
}
return dueDay;
} }
haveBacklog = haveBacklog || dueDay < 0;
return dueDay;
}); });
const dueCounts = rollup( const dueCounts = rollup(

View File

@ -151,8 +151,8 @@ export function dayLabel(i18n: I18n, daysStart: number, daysEnd: number): string
}); });
} else { } else {
return i18n.tr(i18n.TR.STATISTICS_DAYS_AGO_RANGE, { return i18n.tr(i18n.TR.STATISTICS_DAYS_AGO_RANGE, {
daysStart: Math.abs(daysEnd), daysStart: Math.abs(daysEnd - 1),
daysEnd: -daysStart - 1, daysEnd: -daysStart,
}); });
} }
} }