use std::collections::BTreeMap;
use serde::{Deserialize, Serialize};
use crate::task::Task;
pub const PUEUE_DEFAULT_GROUP: &str = "default";
#[derive(PartialEq, Eq, Clone, Debug, Copy, Deserialize, Serialize)]
pub enum GroupStatus {
Running,
Paused,
Reset,
}
#[derive(PartialEq, Eq, Clone, Debug, Deserialize, Serialize)]
pub struct Group {
pub status: GroupStatus,
pub parallel_tasks: usize,
}
#[derive(Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
pub struct State {
pub tasks: BTreeMap<usize, Task>,
pub groups: BTreeMap<String, Group>,
}
impl Clone for State {
fn clone(&self) -> Self {
State {
tasks: self.tasks.clone(),
groups: self.groups.clone(),
}
}
}
#[derive(Debug, Default)]
pub struct FilteredTasks {
pub matching_ids: Vec<usize>,
pub non_matching_ids: Vec<usize>,
}
impl State {
pub fn new() -> State {
Self::default()
}
pub fn add_task(&mut self, mut task: Task) -> usize {
let next_id = match self.tasks.keys().max() {
None => 0,
Some(id) => id + 1,
};
task.id = next_id;
self.tasks.insert(next_id, task);
next_id
}
pub fn task_ids_in_group(&self, group: &str) -> Vec<usize> {
self.tasks
.iter()
.filter(|(_, task)| task.group.eq(group))
.map(|(id, _)| *id)
.collect()
}
pub fn filter_tasks<F>(&self, condition: F, task_ids: Option<Vec<usize>>) -> FilteredTasks
where
F: Fn(&Task) -> bool,
{
let task_ids = match task_ids {
Some(ids) => ids,
None => self.tasks.keys().cloned().collect(),
};
self.filter_task_ids(condition, task_ids)
}
pub fn filter_tasks_of_group<F>(&self, condition: F, group: &str) -> FilteredTasks
where
F: Fn(&Task) -> bool,
{
if !self.groups.contains_key(group) {
return FilteredTasks::default();
}
let task_ids = self
.tasks
.iter()
.filter(|(_, task)| task.group == group)
.map(|(id, _)| *id)
.collect();
self.filter_task_ids(condition, task_ids)
}
fn filter_task_ids<F>(&self, condition: F, task_ids: Vec<usize>) -> FilteredTasks
where
F: Fn(&Task) -> bool,
{
let mut matching_ids = Vec::new();
let mut non_matching_ids = Vec::new();
for task_id in task_ids.iter() {
match self.tasks.get(task_id) {
None => {
non_matching_ids.push(*task_id);
continue;
}
Some(task) => {
if condition(task) {
matching_ids.push(*task_id);
} else {
non_matching_ids.push(*task_id);
}
}
};
}
FilteredTasks {
matching_ids,
non_matching_ids,
}
}
}