Merge pull request #904 from hgiesel/propdue
Streamlining `is:due`, `prop:due`, and the FutureDue graph
This commit is contained in:
commit
97e3bfe1c0
@ -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
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -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(
|
||||||
|
@ -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,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user