feat(tasks): generate tree from iterator
This commit is contained in:
parent
85b923edc8
commit
619bcfbbad
72
src/tasks.rs
72
src/tasks.rs
|
@ -151,28 +151,8 @@ impl Tasks {
|
||||||
pub(crate) fn len(&self) -> usize { self.tasks.len() }
|
pub(crate) fn len(&self) -> usize { self.tasks.len() }
|
||||||
|
|
||||||
/// Ids of all subtasks recursively found for id, including itself
|
/// Ids of all subtasks recursively found for id, including itself
|
||||||
fn get_task_tree<'a>(&'a self, id: &'a EventId) -> Vec<&'a EventId> {
|
pub(crate) fn get_task_tree<'a>(&'a self, id: &'a EventId) -> ChildIterator {
|
||||||
let mut children = Vec::with_capacity(32);
|
ChildIterator::from(&self.tasks, id)
|
||||||
let mut index = 0;
|
|
||||||
|
|
||||||
children.push(id);
|
|
||||||
while index < children.len() {
|
|
||||||
let id = children[index];
|
|
||||||
if let Some(task) = self.tasks.get(&id) {
|
|
||||||
children.reserve(task.children.len());
|
|
||||||
children.extend(task.children.iter());
|
|
||||||
} else {
|
|
||||||
// Unknown task, can still find children
|
|
||||||
for task in self.tasks.values() {
|
|
||||||
if task.parent_id().is_some_and(|i| i == id) {
|
|
||||||
children.push(task.get_id());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
index += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
children
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn all_hashtags(&self) -> impl Iterator<Item=&str> {
|
pub(crate) fn all_hashtags(&self) -> impl Iterator<Item=&str> {
|
||||||
|
@ -237,7 +217,7 @@ impl Tasks {
|
||||||
fn total_time_tracked(&self, id: EventId) -> u64 {
|
fn total_time_tracked(&self, id: EventId) -> u64 {
|
||||||
let mut total = 0;
|
let mut total = 0;
|
||||||
|
|
||||||
let children = self.get_task_tree(&id);
|
let children = self.get_task_tree(&id).get_all();
|
||||||
for user in self.history.values() {
|
for user in self.history.values() {
|
||||||
total += TimesTracked::from(user, &children).into_iter().sum::<Duration>().as_secs();
|
total += TimesTracked::from(user, &children).into_iter().sum::<Duration>().as_secs();
|
||||||
}
|
}
|
||||||
|
@ -978,6 +958,52 @@ impl Iterator for TimesTracked<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Breadth-First Iterator over Tasks and recursive children
|
||||||
|
struct ChildIterator<'a> {
|
||||||
|
tasks: &'a TaskMap,
|
||||||
|
queue: Vec<&'a EventId>,
|
||||||
|
index: usize,
|
||||||
|
}
|
||||||
|
impl<'a> ChildIterator<'a> {
|
||||||
|
fn from(tasks: &'a TaskMap, id: &'a EventId) -> Self {
|
||||||
|
let mut queue = Vec::with_capacity(30);
|
||||||
|
queue.push(id);
|
||||||
|
ChildIterator {
|
||||||
|
tasks,
|
||||||
|
queue,
|
||||||
|
index: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_all(mut self) -> Vec<&'a EventId> {
|
||||||
|
while self.next().is_some() {}
|
||||||
|
self.queue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'a> Iterator for ChildIterator<'a> {
|
||||||
|
type Item = &'a EventId;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
if self.index >= self.queue.len() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let id = self.queue[self.index];
|
||||||
|
if let Some(task) = self.tasks.get(&id) {
|
||||||
|
self.queue.reserve(task.children.len());
|
||||||
|
self.queue.extend(task.children.iter());
|
||||||
|
} else {
|
||||||
|
// Unknown task, can still find children
|
||||||
|
for task in self.tasks.values() {
|
||||||
|
if task.parent_id().is_some_and(|i| i == id) {
|
||||||
|
self.queue.push(task.get_id());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.index += 1;
|
||||||
|
Some(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct ParentIterator<'a> {
|
struct ParentIterator<'a> {
|
||||||
tasks: &'a TaskMap,
|
tasks: &'a TaskMap,
|
||||||
|
|
Loading…
Reference in New Issue