1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
use crate::condition::{ConditionFind, Direction, Edge};
use chrono::{NaiveDate, NaiveDateTime};
use karlcommon::{Schedule, Task};
use std::{collections::HashMap, ops::Range};
pub struct DiscreteCache {
tasks: HashMap<u64, DiscreteCacheTask>,
}
pub struct DiscreteCacheTask {
inner: Task,
cached: Option<Range<NaiveDateTime>>,
cache: Vec<Range<NaiveDateTime>>,
}
impl DiscreteCache {
pub fn new_for(tasks: HashMap<u64, Task>) -> Self {
Self {
tasks: HashMap::from_iter(
tasks
.into_iter()
.map(|(k, v)| (k, DiscreteCacheTask::new(v))),
),
}
}
}
impl DiscreteCacheTask {
pub fn new(inner: Task) -> Self {
Self {
inner,
cached: None,
cache: vec![],
}
}
pub fn find(&mut self, from: NaiveDateTime, dir: Direction) -> Range<Option<NaiveDateTime>> {
assert_eq!(dir, Direction::Forward);
// TODO cache
// if let Some(c) = self.cached {}
match &self.inner.schedule {
Schedule::Condition(o) => {
let start = o.find(Edge::Start, dir, from);
let end = o.find(Edge::End, dir, from);
match (start, end) {
(Some(start), Some(end)) => {
if end < start {
if let Some(start) = o.find(Edge::Start, dir.invert(), from) {
assert!(start < end);
Some(start)..Some(end)
} else {
None..Some(end)
}
} else {
Some(start)..Some(end)
}
}
(None, Some(end)) => {
if let Some(start) = o.find(Edge::Start, dir.invert(), from) {
assert!(start < end);
Some(start)..Some(end)
} else {
None..Some(end)
}
}
(Some(start), None) => Some(start)..None,
(None, None) => None..None,
}
}
Schedule::Never => None..None,
Schedule::Static(_) => None..None, // TODO
Schedule::Dynamic { .. } => None..None, // TODO
}
}
}
pub trait Overlaps<T> {
fn overlaps(&self, v: T) -> bool;
}
impl Overlaps<i64> for Range<i64> {
fn overlaps(&self, v: i64) -> bool {
self.start <= v && v < self.end
}
}
impl Overlaps<i64> for Range<Option<i64>> {
fn overlaps(&self, v: i64) -> bool {
match (self.start, self.end) {
(Some(s), Some(e)) => s <= v && v < e,
(Some(s), None) => s <= v,
(None, Some(e)) => v < e,
(None, None) => false,
}
}
}
impl Overlaps<Range<i64>> for Range<Option<i64>> {
fn overlaps(&self, v: Range<i64>) -> bool {
self.overlaps(v.start) || self.overlaps(v.end)
}
}
|