aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--protocol.d.ts2
-rw-r--r--src/condition.rs287
-rw-r--r--src/lib.rs3
-rw-r--r--src/main.rs10
4 files changed, 261 insertions, 41 deletions
diff --git a/protocol.d.ts b/protocol.d.ts
index 0657cdf..16f45d8 100644
--- a/protocol.d.ts
+++ b/protocol.d.ts
@@ -20,8 +20,6 @@ interface DownloadResponse {
data: { tasks: Task[] }
}
-
-
interface Task {
name: string,
description: string,
diff --git a/src/condition.rs b/src/condition.rs
index 7a873a8..c7be56c 100644
--- a/src/condition.rs
+++ b/src/condition.rs
@@ -1,6 +1,6 @@
use std::cmp::{max, min};
-use chrono::{Datelike, NaiveDate, NaiveDateTime, NaiveTime};
+use chrono::{Datelike, Duration, NaiveDate, NaiveDateTime, NaiveTime, Timelike};
use serde::{Deserialize, Serialize};
use Direction::*;
use Edge::*;
@@ -15,14 +15,14 @@ pub enum Condition {
Equal {
prop: Property,
- value: i32,
- modulus: Option<i32>,
+ value: i64,
+ modulus: Option<i64>,
},
Range {
prop: Property,
- min: i32,
- max: i32,
- modulus: Option<i32>,
+ min: i64,
+ max: i64,
+ modulus: Option<i64>,
},
}
@@ -48,21 +48,59 @@ impl<T: PartialOrd + PartialEq> Range<T> {
}
}
-#[derive(Debug, Clone, Copy)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Edge {
Start,
End,
}
-#[derive(Debug, Clone, Copy)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Direction {
Forward,
Backward,
}
impl Condition {
- pub fn find(&self, edge: Edge, dir: Direction, from: NaiveDateTime) -> Option<NaiveDateTime> {
+ pub fn find(
+ &self,
+ edge: Edge,
+ dir: Direction,
+ mut from: NaiveDateTime,
+ ) -> Option<NaiveDateTime> {
match self {
- Condition::And(_) => todo!(),
+ Condition::And(cs) => loop {
+ // TODO improve efficiency for backward search
+ let last_start = cs
+ .iter()
+ .map(|c| c.find(Start, dir, from))
+ .reduce(|a, b| Some(max(a?, b?)))?;
+ let first_end =
+ cs.iter()
+ .map(|c| c.find(End, dir, from))
+ .reduce(|a, b| match a {
+ Some(a) => match b {
+ Some(b) => Some(min(a, b)),
+ None => None,
+ },
+ None => None,
+ })?;
+ match last_start {
+ Some(start) => match first_end {
+ Some(end) => {
+ if end > start {
+ break Some(match edge {
+ Start => start,
+ End => end,
+ });
+ } else {
+ println!("{:?} {:?}", start, end);
+ from = start - Duration::seconds(10); // TODO proper fix
+ }
+ }
+ None => break Some(start),
+ },
+ None => break None,
+ }
+ },
Condition::Or(cs) => {
cs.iter()
.filter_map(|c| c.find(edge, dir, from))
@@ -71,48 +109,177 @@ impl Condition {
Backward => max,
})
}
- Condition::From(c) => todo!(),
+ Condition::From(_c) => todo!(),
Condition::Invert(c) => c.find(edge.invert(), dir, from),
Condition::Equal {
prop,
value,
- modulus,
+ modulus: _,
} => {
- let geq = match dir {
- Forward => |a: i32, b: i32| a >= b,
- Backward => |a: i32, b: i32| a < b,
- };
- let off = match edge {
+ let value = *value;
+ let off: i64 = match edge {
Start => 0,
End => 1,
};
+ let dir_off = match dir {
+ Forward => 0,
+ Backward => -1,
+ };
match prop {
Property::Year => {
- if geq(from.year(), *value + off) {
+ let geq = match dir {
+ Forward => |a, b| a >= b,
+ Backward => |a, b| a < b,
+ };
+
+ if geq(from.year(), (value + off) as i32) {
None
} else {
Some(NaiveDateTime::new(
- NaiveDate::from_ymd(*value + off, 1, 1),
+ NaiveDate::from_ymd((value + off) as i32, 1, 1),
+ NaiveTime::from_hms(0, 0, 0),
+ ))
+ }
+ }
+ Property::Monthofyear => {
+ let rollover = (value + off) / 12;
+ let value = (value + off) % 12;
+ // month still coming for this year
+ if from.month0() < value as u32 {
+ Some(NaiveDateTime::new(
+ NaiveDate::from_ymd(
+ from.year() + (rollover + dir_off) as i32,
+ value as u32 + 1,
+ 1,
+ ),
+ NaiveTime::from_hms(0, 0, 0),
+ ))
+ } else {
+ println!(
+ "{:?}",
+ (
+ from.year() + (rollover + dir_off + 1) as i32,
+ value as u32 + 1,
+ rollover,
+ dir_off
+ )
+ );
+ Some(NaiveDateTime::new(
+ NaiveDate::from_ymd(
+ from.year() + (rollover + dir_off + 1) as i32,
+ value as u32 + 1,
+ 1,
+ ),
NaiveTime::from_hms(0, 0, 0),
))
}
}
- Property::Monthofyear => todo!(),
Property::Weekofmonth => todo!(),
- Property::Dayofyear => todo!(),
- Property::Dayofmonth => todo!(),
+ Property::Dayofyear => {
+ todo!()
+ }
+ Property::Dayofmonth => {
+ // let mut target = NaiveDateTime::new(
+ // NaiveDate::from_ymd(from.year(), from.month(), value as u32),
+ // NaiveTime::from_hms(0, 0, 0),
+ // );
+ // if edge == End {
+ // target += Duration::days(1)
+ // }
+ // fn increment_month(d: NaiveDateTime) -> NaiveDateTime {
+ // NaiveDateTime::new(
+ // NaiveDate::from_ymd(
+ // d.year() + (d.month() as i32 / 12),
+ // (d.month() + 1) % 12,
+ // d.day(),
+ // ),
+ // NaiveTime::from_hms(d.hour(), d.minute(), d.second()),
+ // )
+ // }
+ // let dir_off = match dir {
+ // Forward => |d| d,
+ // Backward => increment_month,
+ // };
+ // if target > from {
+ // Some(dir_off(target))
+ // } else {
+ // Some(increment_month(dir_off(target)))
+ // }
+ todo!()
+ }
Property::Dayofweek => todo!(),
- Property::Hour => todo!(),
- Property::Minute => todo!(),
- Property::Second => todo!(),
- Property::Unix => todo!(),
+ Property::Hour => {
+ let mut target = NaiveDateTime::new(
+ NaiveDate::from_ymd(from.year(), from.month(), from.day()),
+ NaiveTime::from_hms(value as u32, 0, 0),
+ );
+ if edge == End {
+ target += Duration::hours(1)
+ }
+ let dir_off = match dir {
+ Forward => Duration::zero(),
+ Backward => Duration::days(-1),
+ };
+ if target > from {
+ Some(target + dir_off)
+ } else {
+ Some(target + dir_off + Duration::days(1))
+ }
+ }
+ Property::Minute => {
+ let mut target = NaiveDateTime::new(
+ NaiveDate::from_ymd(from.year(), from.month(), from.day()),
+ NaiveTime::from_hms(from.hour(), value as u32, 0),
+ );
+ if edge == End {
+ target += Duration::minutes(1)
+ }
+ let dir_off = match dir {
+ Forward => Duration::zero(),
+ Backward => Duration::hours(-1),
+ };
+ if target > from {
+ Some(target + dir_off)
+ } else {
+ Some(target + dir_off + Duration::hours(1))
+ }
+ }
+ Property::Second => {
+ let mut target = NaiveDateTime::new(
+ NaiveDate::from_ymd(from.year(), from.month(), from.day()),
+ NaiveTime::from_hms(from.hour(), from.minute(), value as u32),
+ );
+ if edge == End {
+ target += Duration::seconds(1)
+ }
+ let dir_off = match dir {
+ Forward => Duration::zero(),
+ Backward => Duration::minutes(-1),
+ };
+ if target > from {
+ Some(target + dir_off)
+ } else {
+ Some(target + dir_off + Duration::minutes(1))
+ }
+ }
+ Property::Unix => {
+ let geq = match dir {
+ Forward => |a, b| a >= b,
+ Backward => |a, b| a < b,
+ };
+ if geq(from.timestamp(), (value + off) as i64) {
+ None
+ } else {
+ Some(NaiveDateTime::from_timestamp(value, 0))
+ }
+ }
}
}
Condition::Range {
- prop,
- min,
- max,
- modulus,
+ prop: _,
+ min: _,
+ max: _,
+ modulus: _,
} => todo!(),
}
}
@@ -130,11 +297,39 @@ impl Edge {
#[cfg(test)]
mod test {
use super::{Condition, Direction, Edge, Property};
- use chrono::NaiveDateTime;
+ use chrono::{NaiveDateTime, Utc};
use std::str::FromStr;
+ use Direction::*;
+ use Edge::*;
+
+ #[test]
+ fn blub() {
+ let cond = Condition::And(vec![
+ Condition::Equal {
+ modulus: None,
+ prop: Property::Monthofyear,
+ value: 1,
+ },
+ Condition::Equal {
+ modulus: None,
+ prop: Property::Hour,
+ value: 12,
+ },
+ ]);
+ // let cond = Condition::Equal {
+ // modulus: None,
+ // prop: Property::Hour,
+ // value: 12,
+ // };
+ let dt = Utc::now().naive_utc();
+ println!("START FORWARD => {:?}", cond.find(Start, Forward, dt));
+ println!("END FORWARD => {:?}", cond.find(End, Forward, dt));
+ println!("START BACKWARD => {:?}", cond.find(Start, Backward, dt));
+ println!("END BACKWARD => {:?}", cond.find(End, Backward, dt));
+ }
#[test]
- fn a() {
+ fn year_equal() {
let cond = Condition::Equal {
modulus: None,
prop: Property::Year,
@@ -153,4 +348,32 @@ mod test {
assert_eq!(cond.find(Edge::End, Direction::Backward, dt), None);
assert_eq!(cond.find(Edge::Start, Direction::Backward, dt), None);
}
+
+ #[test]
+ fn month_equal() {
+ let cond = Condition::Equal {
+ modulus: None,
+ prop: Property::Monthofyear,
+ value: 3,
+ };
+
+ let dt = NaiveDateTime::from_str("2022-06-07T13:37:48").unwrap();
+
+ assert_eq!(
+ cond.find(Edge::Start, Direction::Forward, dt),
+ Some(NaiveDateTime::from_str("2023-04-01T00:00:00").unwrap())
+ );
+ assert_eq!(
+ cond.find(Edge::End, Direction::Forward, dt),
+ Some(NaiveDateTime::from_str("2023-05-01T00:00:00").unwrap())
+ );
+ assert_eq!(
+ cond.find(Edge::Start, Direction::Backward, dt),
+ Some(NaiveDateTime::from_str("2022-04-01T00:00:00").unwrap())
+ );
+ assert_eq!(
+ cond.find(Edge::End, Direction::Backward, dt),
+ Some(NaiveDateTime::from_str("2022-05-01T00:00:00").unwrap())
+ );
+ }
}
diff --git a/src/lib.rs b/src/lib.rs
deleted file mode 100644
index d9d2e29..0000000
--- a/src/lib.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-pub mod protocol;
-pub mod condition;
-pub mod interface;
diff --git a/src/main.rs b/src/main.rs
index 7a36cb1..d237df0 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,8 +1,10 @@
-use calender_thing::{
- interface::network_loop,
- protocol::{ClientboundPacket, ServerboundPacket},
-};
+pub mod condition;
+pub mod interface;
+pub mod protocol;
+
use crossbeam_channel::{Receiver, Sender};
+use interface::network_loop;
+use protocol::{ClientboundPacket, ServerboundPacket};
use std::time::Duration;
fn main() {