aboutsummaryrefslogtreecommitdiff
path: root/karld/src
diff options
context:
space:
mode:
Diffstat (limited to 'karld/src')
-rw-r--r--karld/src/condition.rs9
-rw-r--r--karld/src/helper.rs98
-rw-r--r--karld/src/main.rs91
-rw-r--r--karld/src/schedule.rs5
4 files changed, 170 insertions, 33 deletions
diff --git a/karld/src/condition.rs b/karld/src/condition.rs
index db1cf1d..81f7245 100644
--- a/karld/src/condition.rs
+++ b/karld/src/condition.rs
@@ -1,18 +1,9 @@
use chrono::{Datelike, Duration, NaiveDate, NaiveDateTime, NaiveTime, Timelike};
use karlcommon::{Condition, Property};
-use serde::{Deserialize, Serialize};
use std::cmp::{max, min};
use Direction::*;
use Edge::*;
-#[derive(Debug, Clone, Serialize, Deserialize)]
-pub struct Range<T>(T, T);
-impl<T: PartialOrd + PartialEq> Range<T> {
- pub fn includes(&self, a: T) -> bool {
- a > self.0 && a < self.1
- }
-}
-
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Edge {
Start,
diff --git a/karld/src/helper.rs b/karld/src/helper.rs
new file mode 100644
index 0000000..2e601b0
--- /dev/null
+++ b/karld/src/helper.rs
@@ -0,0 +1,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)
+ }
+}
diff --git a/karld/src/main.rs b/karld/src/main.rs
index 0983554..2d0c9e9 100644
--- a/karld/src/main.rs
+++ b/karld/src/main.rs
@@ -1,12 +1,15 @@
pub mod condition;
+pub mod helper;
pub mod interface;
+pub mod schedule;
use chrono::NaiveDateTime;
use condition::ConditionFind;
use crossbeam_channel::Sender;
+use helper::Overlaps;
use interface::network_loop;
use karlcommon::{
- ClientboundPacket, Condition, Instance, Property, ProtoError, ServerboundPacket, Task,
+ ClientboundPacket, Condition, Instance, Property, ProtoError, Schedule, ServerboundPacket, Task,
};
use log::{debug, info};
use std::{collections::HashMap, sync::RwLock};
@@ -20,11 +23,8 @@ fn main() {
id: 0,
name: "Mittagessen im Februar".to_string(),
description: None,
- tags: vec![],
- priority: 69.0,
- completed: None,
- scheduled: None,
- occurence: Some(Condition::And(vec![
+ tags: vec!["Essen".to_string(), "Unwichtig".to_string()],
+ schedule: Schedule::Condition(Condition::And(vec![
Condition::Equal {
modulus: None,
prop: Property::Monthofyear,
@@ -36,7 +36,37 @@ fn main() {
value: 12,
},
])),
- deadline: None,
+ },
+ );
+ TASKS.write().unwrap().insert(
+ 1,
+ Task {
+ id: 1,
+ name: "Abendessen oder Frühstück".to_string(),
+ description: Some("Nom nom nom".to_string()),
+ tags: vec!["Essen".to_string()],
+ schedule: Schedule::Condition(Condition::Or(vec![
+ Condition::Equal {
+ modulus: None,
+ prop: Property::Hour,
+ value: 18,
+ },
+ Condition::Equal {
+ modulus: None,
+ prop: Property::Hour,
+ value: 7,
+ },
+ ])),
+ },
+ );
+ TASKS.write().unwrap().insert(
+ 2,
+ Task {
+ id: 2,
+ description: None,
+ name: "Wichtiger termin™".to_string(),
+ tags: vec![],
+ schedule: Schedule::Static(1654997366..1655007366),
},
);
network_loop();
@@ -77,25 +107,38 @@ pub fn handle_packet(client: u32, packet: ServerboundPacket, responder: Sender<C
};
let mut ocs = vec![];
- if let Some(o) = &t.occurence {
- let mut time = NaiveDateTime::from_timestamp(range.start.unwrap_or(0), 0);
- let end_time = range.end.map(|e| NaiveDateTime::from_timestamp(e, 0));
- for _ in 0..limit {
- let start = o.find(condition::Edge::Start, condition::Direction::Forward, time);
- let end = o.find(condition::Edge::End, condition::Direction::Forward, time);
- ocs.push(Instance {
- of: t.id,
- at: start.map(|e| e.timestamp())..end.map(|e| e.timestamp()),
- });
- if let Some(s) = end {
- if let Some(e) = end_time {
- if s > e {
- break;
+ match t.schedule {
+ Schedule::Never => (),
+ Schedule::Dynamic { .. } => (), // TODO
+ Schedule::Static(r) => {
+ if range.overlaps(r.clone()) {
+ ocs.push(Instance {
+ of: t.id,
+ at: Some(r.start)..Some(r.end),
+ })
+ }
+ }
+ Schedule::Condition(o) => {
+ let mut time = NaiveDateTime::from_timestamp(range.start.unwrap_or(0), 0);
+ let end_time = range.end.map(|e| NaiveDateTime::from_timestamp(e, 0));
+ for _ in 0..limit {
+ let start =
+ o.find(condition::Edge::Start, condition::Direction::Forward, time);
+ let end = o.find(condition::Edge::End, condition::Direction::Forward, time);
+ ocs.push(Instance {
+ of: t.id,
+ at: start.map(|e| e.timestamp())..end.map(|e| e.timestamp()),
+ });
+ if let Some(s) = end {
+ if let Some(e) = end_time {
+ if s > e {
+ break;
+ }
}
+ time = s;
+ } else {
+ break;
}
- time = s;
- } else {
- break;
}
}
}
diff --git a/karld/src/schedule.rs b/karld/src/schedule.rs
new file mode 100644
index 0000000..1f3c479
--- /dev/null
+++ b/karld/src/schedule.rs
@@ -0,0 +1,5 @@
+
+
+pub fn schedule_dynamic() {
+
+}