support generating a due tree for a different date

This commit is contained in:
Damien Elmes 2020-06-05 09:38:31 +10:00
parent 4a69b55a90
commit fee6cdff22
6 changed files with 37 additions and 15 deletions

View file

@ -528,6 +528,7 @@ message SchedTimingTodayOut {
message DeckTreeIn { message DeckTreeIn {
bool include_counts = 1; bool include_counts = 1;
int64 top_deck_id = 2; int64 top_deck_id = 2;
int32 today_delta = 3;
} }
message DeckTreeNode { message DeckTreeNode {

View file

@ -140,7 +140,9 @@ class DeckManager:
return from_json_bytes(self.col.backend.new_deck_legacy(filtered)) return from_json_bytes(self.col.backend.new_deck_legacy(filtered))
def deck_tree(self) -> pb.DeckTreeNode: def deck_tree(self) -> pb.DeckTreeNode:
return self.col.backend.deck_tree(include_counts=False, top_deck_id=0) return self.col.backend.deck_tree(
include_counts=False, top_deck_id=0, today_delta=0
)
@classmethod @classmethod
def find_deck_in_tree( def find_deck_in_tree(

View file

@ -224,7 +224,9 @@ order by due"""
def deck_due_tree(self, top_deck_id: int = 0) -> DeckTreeNode: def deck_due_tree(self, top_deck_id: int = 0) -> DeckTreeNode:
"""Returns a tree of decks with counts. """Returns a tree of decks with counts.
If top_deck_id provided, counts are limited to that node.""" If top_deck_id provided, counts are limited to that node."""
return self.col.backend.deck_tree(include_counts=True, top_deck_id=top_deck_id) return self.col.backend.deck_tree(
include_counts=True, top_deck_id=top_deck_id, today_delta=0
)
# Getting the next card # Getting the next card
########################################################################## ##########################################################################

View file

@ -476,7 +476,14 @@ impl BackendService for Backend {
} else { } else {
None None
}; };
self.with_col(|col| col.deck_tree(input.include_counts, lim)) self.with_col(|col| {
let today = if input.include_counts {
Some(col.current_due_day(input.today_delta)?)
} else {
None
};
col.deck_tree(today, lim)
})
} }
fn deck_tree_legacy(&mut self, _input: pb::Empty) -> BackendResult<pb::Json> { fn deck_tree_legacy(&mut self, _input: pb::Empty) -> BackendResult<pb::Json> {

View file

@ -209,11 +209,16 @@ impl From<DeckTreeNode> for LegacyDueCounts {
} }
impl Collection { impl Collection {
/// Get the deck tree, optionally populating it with due counts. /// Get the deck tree.
/// If today is provided, due counts for the provided day will be populated.
/// If top_deck_id is provided, only the node starting at the provided deck ID will /// If top_deck_id is provided, only the node starting at the provided deck ID will
/// have the counts populated. Currently the entire tree is returned in this case, but /// have the counts populated. Currently the entire tree is returned in this case, but
/// this may change in the future. /// this may change in the future.
pub fn deck_tree(&mut self, counts: bool, top_deck_id: Option<DeckID>) -> Result<DeckTreeNode> { pub fn deck_tree(
&mut self,
today: Option<u32>,
top_deck_id: Option<DeckID>,
) -> Result<DeckTreeNode> {
let names = self.storage.get_all_deck_names()?; let names = self.storage.get_all_deck_names()?;
let mut tree = deck_names_to_tree(names); let mut tree = deck_names_to_tree(names);
@ -224,12 +229,12 @@ impl Collection {
.map(|d| (d.id, d)) .map(|d| (d.id, d))
.collect(); .collect();
add_collapsed_and_filtered(&mut tree, &decks_map, !counts); add_collapsed_and_filtered(&mut tree, &decks_map, today.is_none());
if self.default_deck_is_empty()? { if self.default_deck_is_empty()? {
hide_default_deck(&mut tree); hide_default_deck(&mut tree);
} }
if counts { if let Some(today) = today {
let limit = top_deck_id.and_then(|did| { let limit = top_deck_id.and_then(|did| {
if let Some(deck) = decks_map.get(&did) { if let Some(deck) = decks_map.get(&did) {
Some(deck.name.as_str()) Some(deck.name.as_str())
@ -238,7 +243,6 @@ impl Collection {
} }
}); });
let counts = self.due_counts(limit)?; let counts = self.due_counts(limit)?;
let today = self.timing_today()?.days_elapsed;
let dconf: HashMap<_, _> = self let dconf: HashMap<_, _> = self
.storage .storage
.all_deck_config()? .all_deck_config()?
@ -260,12 +264,14 @@ impl Collection {
pub fn current_deck_tree(&mut self) -> Result<Option<DeckTreeNode>> { pub fn current_deck_tree(&mut self) -> Result<Option<DeckTreeNode>> {
let target = self.get_current_deck_id(); let target = self.get_current_deck_id();
let tree = self.deck_tree(true, Some(target))?; let today = self.current_due_day(0)?;
let tree = self.deck_tree(Some(today), Some(target))?;
Ok(get_subnode(tree, target)) Ok(get_subnode(tree, target))
} }
pub(crate) fn legacy_deck_tree(&mut self) -> Result<LegacyDueCounts> { pub(crate) fn legacy_deck_tree(&mut self) -> Result<LegacyDueCounts> {
let tree = self.deck_tree(true, None)?; let today = self.current_due_day(0)?;
let tree = self.deck_tree(Some(today), None)?;
Ok(LegacyDueCounts::from(tree)) Ok(LegacyDueCounts::from(tree))
} }
@ -303,7 +309,7 @@ mod test {
col.get_or_create_normal_deck("2::c::A")?; col.get_or_create_normal_deck("2::c::A")?;
col.get_or_create_normal_deck("3")?; col.get_or_create_normal_deck("3")?;
let tree = col.deck_tree(false, None)?; let tree = col.deck_tree(None, None)?;
assert_eq!(tree.children.len(), 3); assert_eq!(tree.children.len(), 3);
@ -326,7 +332,7 @@ mod test {
col.storage.remove_deck(col.get_deck_id("2")?.unwrap())?; col.storage.remove_deck(col.get_deck_id("2")?.unwrap())?;
col.storage.remove_deck(col.get_deck_id("2::3")?.unwrap())?; col.storage.remove_deck(col.get_deck_id("2::3")?.unwrap())?;
let tree = col.deck_tree(false, None)?; let tree = col.deck_tree(None, None)?;
assert_eq!(tree.children.len(), 1); assert_eq!(tree.children.len(), 1);
Ok(()) Ok(())
@ -345,7 +351,7 @@ mod test {
note.fields[0] = "{{c1::}} {{c2::}} {{c3::}} {{c4::}}".into(); note.fields[0] = "{{c1::}} {{c2::}} {{c3::}} {{c4::}}".into();
col.add_note(&mut note, child_deck.id)?; col.add_note(&mut note, child_deck.id)?;
let tree = col.deck_tree(true, None)?; let tree = col.deck_tree(Some(0), None)?;
assert_eq!(tree.children[0].new_count, 4); assert_eq!(tree.children[0].new_count, 4);
assert_eq!(tree.children[0].children[0].new_count, 4); assert_eq!(tree.children[0].children[0].new_count, 4);
@ -356,7 +362,7 @@ mod test {
col.add_or_update_deck(&mut parent_deck)?; col.add_or_update_deck(&mut parent_deck)?;
// with the default limit of 20, there should still be 4 due // with the default limit of 20, there should still be 4 due
let tree = col.deck_tree(true, None)?; let tree = col.deck_tree(Some(0), None)?;
assert_eq!(tree.children[0].new_count, 4); assert_eq!(tree.children[0].new_count, 4);
assert_eq!(tree.children[0].children[0].new_count, 4); assert_eq!(tree.children[0].children[0].new_count, 4);
@ -365,7 +371,7 @@ mod test {
conf.inner.new_per_day = 4; conf.inner.new_per_day = 4;
col.add_or_update_deck_config(&mut conf, false)?; col.add_or_update_deck_config(&mut conf, false)?;
let tree = col.deck_tree(true, None)?; let tree = col.deck_tree(Some(0), None)?;
assert_eq!(tree.children[0].new_count, 3); assert_eq!(tree.children[0].new_count, 3);
assert_eq!(tree.children[0].children[0].new_count, 3); assert_eq!(tree.children[0].children[0].new_count, 3);

View file

@ -18,6 +18,10 @@ impl Collection {
self.timing_for_timestamp(TimestampSecs::now()) self.timing_for_timestamp(TimestampSecs::now())
} }
pub fn current_due_day(&mut self, delta: i32) -> Result<u32> {
Ok(((self.timing_today()?.days_elapsed as i32) + delta).max(0) as u32)
}
pub(crate) fn timing_for_timestamp(&mut self, now: TimestampSecs) -> Result<SchedTimingToday> { pub(crate) fn timing_for_timestamp(&mut self, now: TimestampSecs) -> Result<SchedTimingToday> {
let local_offset = if self.server { let local_offset = if self.server {
self.get_local_mins_west() self.get_local_mins_west()