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<()> {
let timing = self.col.timing_today()?;
match kind {
PropertyKind::Due(days) => {
let day = days + (timing.days_elapsed as i32);
write!(
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,
daylrn = CardQueue::DayLearn as u8,
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) => {
@ -292,14 +301,15 @@ impl SqlWriter<'_> {
StateKind::Suspended => write!(self.sql, "c.queue = {}", CardQueue::Suspended as i8),
StateKind::Due => write!(
self.sql,
"(
(c.queue in ({rev},{daylrn}) and c.due <= {today}) or
(c.queue = {lrn} and c.due <= {learncutoff})
)",
"(\
(c.queue in ({rev},{daylrn}) and c.due <= {today}) or \
(c.queue in ({lrn},{previewrepeat}) and c.due <= {learncutoff})\
)",
rev = CardQueue::Review as i8,
daylrn = CardQueue::DayLearn as i8,
today = timing.days_elapsed,
lrn = CardQueue::Learn as i8,
previewrepeat = CardQueue::PreviewRepeat as i8,
learncutoff = TimestampSecs::now().0 + (self.col.learn_ahead_secs() as i64),
),
StateKind::UserBuried => write!(self.sql, "c.queue = {}", CardQueue::UserBuried as i8),
@ -725,8 +735,9 @@ mod test {
assert_eq!(
s(ctx, "prop:due!=-1").0,
format!(
"((c.queue in (2,3) and due != {}))",
timing.days_elapsed - 1
"(((c.queue in (2,3) and c.due != {days}) or (c.queue in (1,4) and ((c.due - {cutoff}) / 86400) != -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 {
const isLearning = (queue: number): boolean =>
[CardQueue.Learn, CardQueue.PreviewRepeat].includes(queue);
const isLearning = (card: pb.BackendProto.Card): boolean =>
[CardQueue.Learn, CardQueue.PreviewRepeat].includes(card.queue);
let haveBacklog = false;
const due = (data.cards as pb.BackendProto.Card[])
.filter(
(c) =>
// reviews
.filter((c: pb.BackendProto.Card) => {
// reviews
return (
[CardQueue.Review, CardQueue.DayLearn].includes(c.queue) ||
// or learning cards due today
(isLearning(c.queue) && c.due < data.nextDayAtSecs)
)
.map((c) => {
if (isLearning(c.queue)) {
return 0;
// or learning cards
isLearning(c)
);
})
.map((c: pb.BackendProto.Card) => {
let dueDay: number;
if (isLearning(c)) {
const offset = c.due - data.nextDayAtSecs;
dueDay = Math.floor(offset / 86_400) + 1;
} else {
// - testing just odue fails on day 1
// - testing just odid fails on lapsed cards that
// have due calculated at regraduation time
const due = c.originalDeckId && c.originalDue ? c.originalDue : c.due;
const dueDay = due - data.daysElapsed;
if (dueDay < 0) {
haveBacklog = true;
}
return dueDay;
dueDay = due - data.daysElapsed;
}
haveBacklog = haveBacklog || dueDay < 0;
return dueDay;
});
const dueCounts = rollup(

View File

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