diff options
author | metamuffin <yvchraiqi@protonmail.com> | 2022-06-09 22:35:26 +0200 |
---|---|---|
committer | metamuffin <yvchraiqi@protonmail.com> | 2022-06-09 22:35:26 +0200 |
commit | f8edbf82aa2a0a7da8808bc2e196e9f219238467 (patch) | |
tree | 8022d292fd4a131dc19c7883ab085549dd2c1820 /src | |
parent | 20030e38a921d2ba00ba7b67d0e466aafd591b4d (diff) | |
download | karlender-f8edbf82aa2a0a7da8808bc2e196e9f219238467.tar karlender-f8edbf82aa2a0a7da8808bc2e196e9f219238467.tar.bz2 karlender-f8edbf82aa2a0a7da8808bc2e196e9f219238467.tar.zst |
basic conditions
Diffstat (limited to 'src')
-rw-r--r-- | src/condition.rs | 287 | ||||
-rw-r--r-- | src/lib.rs | 3 | ||||
-rw-r--r-- | src/main.rs | 10 |
3 files changed, 261 insertions, 39 deletions
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() { |