diff options
-rw-r--r-- | Cargo.lock | 56 | ||||
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | protocol.d.ts | 40 | ||||
-rw-r--r-- | src/condition.rs | 156 | ||||
-rw-r--r-- | src/lib.rs | 2 | ||||
-rw-r--r-- | src/main.rs | 3 | ||||
-rw-r--r-- | src/occurence.rs | 25 | ||||
-rw-r--r-- | src/protocol.rs | 2 |
8 files changed, 237 insertions, 48 deletions
@@ -29,10 +29,17 @@ dependencies = [ ] [[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] name = "calender-thing" version = "0.1.0" dependencies = [ "anyhow", + "chrono", "crossbeam-channel", "env_logger", "log", @@ -47,6 +54,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] +name = "chrono" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +dependencies = [ + "libc", + "num-integer", + "num-traits", + "time", + "winapi", +] + +[[package]] name = "crossbeam-channel" version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -128,6 +148,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] name = "proc-macro2" version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -220,12 +259,29 @@ dependencies = [ ] [[package]] +name = "time" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +dependencies = [ + "libc", + "wasi", + "winapi", +] + +[[package]] name = "unicode-ident" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" [[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -10,4 +10,5 @@ log = "0.4.17" env_logger = "0.9.0" crossbeam-channel = "0.5.4" serde_json = "1.0.81" +chrono = "0.4.19" diff --git a/protocol.d.ts b/protocol.d.ts index 36bf3e1..0657cdf 100644 --- a/protocol.d.ts +++ b/protocol.d.ts @@ -36,32 +36,34 @@ interface Task { deadline?: Condition, } -/* - { and: [ - { or: [{ dayofweak: 0 }, { dayofweak: 1 }] }, - { weekofmonth: 0 } - { hour: [11, 13] } - ]} +/* + 11:00 - 12:00 every first monday of the month + + and: [ + range: {prop: "hour", min: 11, max: 12}, + equal: {prop: "dayofweek", value: 0}, + equal: {prop: "weekofmonth", value: 0}, + ] */ // should only have one property interface Condition { from: Condition - to: Condition or: Condition[] and: Condition[] - year?: [number, number], - monthofyear?: [number, number], - weekofmonth?: [number, number], - dayofyear?: [number, number], - dayofmonth?: [number, number], - dayofweek?: [number, number], - - hour?: [number, number], - minute?: [number, number], - second?: [number, number], - - unix?: [number, number], + equal?: { prop: Thing, value: number, mod?: number } + range?: { prop: Thing, min: number, max: number, mod?: number } } + +type Thing = "year" + | "monthofyear" + | "weekofmonth" + | "dayofyear" + | "dayofmonth" + | "dayofweek" + | "hour" + | "minute" + | "second" + | "unix"
\ No newline at end of file diff --git a/src/condition.rs b/src/condition.rs new file mode 100644 index 0000000..7a873a8 --- /dev/null +++ b/src/condition.rs @@ -0,0 +1,156 @@ +use std::cmp::{max, min}; + +use chrono::{Datelike, NaiveDate, NaiveDateTime, NaiveTime}; +use serde::{Deserialize, Serialize}; +use Direction::*; +use Edge::*; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum Condition { + From(Box<Condition>), + + Or(Vec<Condition>), + And(Vec<Condition>), + Invert(Box<Condition>), + + Equal { + prop: Property, + value: i32, + modulus: Option<i32>, + }, + Range { + prop: Property, + min: i32, + max: i32, + modulus: Option<i32>, + }, +} + +#[derive(Debug, Clone, Copy, Serialize, Deserialize)] +pub enum Property { + Year, + Monthofyear, + Weekofmonth, + Dayofyear, + Dayofmonth, + Dayofweek, + Hour, + Minute, + Second, + Unix, +} + +#[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)] +pub enum Edge { + Start, + End, +} +#[derive(Debug, Clone, Copy)] +pub enum Direction { + Forward, + Backward, +} + +impl Condition { + pub fn find(&self, edge: Edge, dir: Direction, from: NaiveDateTime) -> Option<NaiveDateTime> { + match self { + Condition::And(_) => todo!(), + Condition::Or(cs) => { + cs.iter() + .filter_map(|c| c.find(edge, dir, from)) + .reduce(match dir { + Forward => min, + Backward => max, + }) + } + Condition::From(c) => todo!(), + Condition::Invert(c) => c.find(edge.invert(), dir, from), + Condition::Equal { + prop, + value, + modulus, + } => { + let geq = match dir { + Forward => |a: i32, b: i32| a >= b, + Backward => |a: i32, b: i32| a < b, + }; + let off = match edge { + Start => 0, + End => 1, + }; + match prop { + Property::Year => { + if geq(from.year(), *value + off) { + None + } else { + Some(NaiveDateTime::new( + NaiveDate::from_ymd(*value + off, 1, 1), + NaiveTime::from_hms(0, 0, 0), + )) + } + } + Property::Monthofyear => todo!(), + Property::Weekofmonth => todo!(), + Property::Dayofyear => todo!(), + Property::Dayofmonth => todo!(), + Property::Dayofweek => todo!(), + Property::Hour => todo!(), + Property::Minute => todo!(), + Property::Second => todo!(), + Property::Unix => todo!(), + } + } + Condition::Range { + prop, + min, + max, + modulus, + } => todo!(), + } + } +} + +impl Edge { + pub fn invert(self) -> Self { + match self { + Edge::Start => Edge::End, + Edge::End => Edge::Start, + } + } +} + +#[cfg(test)] +mod test { + use super::{Condition, Direction, Edge, Property}; + use chrono::NaiveDateTime; + use std::str::FromStr; + + #[test] + fn a() { + let cond = Condition::Equal { + modulus: None, + prop: Property::Year, + value: 2023, + }; + + let dt = NaiveDateTime::from_str("2022-06-07T13:37:48").unwrap(); + assert_eq!( + cond.find(Edge::Start, Direction::Forward, dt).unwrap(), + NaiveDateTime::from_str("2023-01-01T00:00:00").unwrap(), + ); + assert_eq!( + cond.find(Edge::End, Direction::Forward, dt).unwrap(), + NaiveDateTime::from_str("2024-01-01T00:00:00").unwrap(), + ); + assert_eq!(cond.find(Edge::End, Direction::Backward, dt), None); + assert_eq!(cond.find(Edge::Start, Direction::Backward, dt), None); + } +} @@ -1,3 +1,3 @@ pub mod protocol; -pub mod occurence; +pub mod condition; pub mod interface; diff --git a/src/main.rs b/src/main.rs index fb975d6..7a36cb1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,9 @@ -use std::time::Duration; - use calender_thing::{ interface::network_loop, protocol::{ClientboundPacket, ServerboundPacket}, }; use crossbeam_channel::{Receiver, Sender}; +use std::time::Duration; fn main() { let (s, r) = crossbeam_channel::unbounded(); diff --git a/src/occurence.rs b/src/occurence.rs deleted file mode 100644 index 104438a..0000000 --- a/src/occurence.rs +++ /dev/null @@ -1,25 +0,0 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Debug, Serialize, Deserialize)] -pub enum Condition { - And(Vec<Condition>), - Or(Vec<Condition>), - From(Box<Condition>), - To(Box<Condition>), - - Year(Range), - Monthofyear(Range), - Weekofmonth(Range), - Dayofyear(Range), - Dayofmonth(Range), - Dayofweek(Range), - - Hour(Range), - Minute(Range), - Second(Range), - - Unix(Range), -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct Range(u64, u64); diff --git a/src/protocol.rs b/src/protocol.rs index a09f879..e7527eb 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -1,6 +1,6 @@ use serde::{Deserialize, Serialize}; -use crate::occurence::Condition; +use crate::condition::Condition; #[derive(Debug, Serialize, Deserialize)] #[serde(tag = "type", content = "data", rename_all = "snake_case")] |