diff options
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | dome_key_map.h | 2 | ||||
| -rw-r--r-- | src/errors.rs | 10 | ||||
| -rw-r--r-- | src/lib.rs | 5 | ||||
| -rw-r--r-- | src/trial.rs | 86 | 
5 files changed, 104 insertions, 0 deletions
| @@ -14,6 +14,7 @@ getopts = "0.2.18"  libc = "0.2.43"  log = "0.4.5"  objc = "0.2.5" +quick-error = "1.2.2"  serde = "1.0.58"  serde_derive = "1.0.58"  stderrlog = "0.4.1" diff --git a/dome_key_map.h b/dome_key_map.h index a6e44ca..88909f0 100644 --- a/dome_key_map.h +++ b/dome_key_map.h @@ -6,6 +6,8 @@  #include <stdlib.h>  #include <stdbool.h> +#define DAYS_REMAINING 30 +  typedef enum {    HeadphoneButton_Play,    HeadphoneButton_Up, diff --git a/src/errors.rs b/src/errors.rs index beafc9f..5f09c27 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -5,3 +5,13 @@ error_chain! {          Xdg(xdg::BaseDirectoriesError);      }  } + +quick_error! { +    #[derive(Debug, PartialEq)] +    pub enum DurationError { +        NegativeDuration(duration: i32) { +            description("negative duration") +            display("negative duration: '{}'", duration) +        } +    } +} @@ -1,6 +1,7 @@  #![recursion_limit="128"]  extern crate autopilot; +extern crate chrono;  extern crate cocoa;  #[macro_use] @@ -20,6 +21,9 @@ extern crate log;  extern crate objc;  #[macro_use] +extern crate quick_error; + +#[macro_use]  extern crate serde_derive;  extern crate stderrlog;  extern crate toml; @@ -31,6 +35,7 @@ mod config;  mod errors;  mod key_code;  mod parser; +mod trial;  use parser::{Action, HeadphoneButton, MapAction, MapGroup, MapKind}; diff --git a/src/trial.rs b/src/trial.rs new file mode 100644 index 0000000..9604f62 --- /dev/null +++ b/src/trial.rs @@ -0,0 +1,86 @@ +use chrono::{DateTime, Local, TimeZone}; + +use errors::DurationError; + +// Start timestamp on October 1 at 23h +// Trial should be valid until November 1 00h + + +const DAYS_REMAINING: u8 = 30; + +fn days_remaining( +    start: DateTime<Local>, +    now: DateTime<Local>, +    days_available: u8, +) -> Result<u8, DurationError> { +    let duration = (now.date() - start.date()).num_days() as u8; + +    if duration > days_available { +        Err( +            DurationError::NegativeDuration(days_available as i32 - duration as i32) +        ) +    } else { +        Ok(days_available - duration) +    } +} + + +#[cfg(test)] +mod tests { +    use super::*; + +    #[test] +    fn days_remaining_counts_days_remaining_from_start_date() { +        let remaining = days_remaining( +            Local.ymd(2018, 10, 1).and_hms(23, 1, 0), +            Local.ymd(2018, 10, 1).and_hms(23, 30, 0), +            30, +        ); + +        assert_eq!(remaining, Ok(30)); +    } + +    #[test] +    fn days_remaining_with_middle_date() { +        let remaining = days_remaining( +            Local.ymd(2018, 10, 1).and_hms(23, 1, 0), +            Local.ymd(2018, 10, 22).and_hms(15, 0, 0), +            30, +        ); + +        assert_eq!(remaining, Ok(9)); +    } + +    #[test] +    fn days_remaining_on_last_day_is_0() { +        let remaining = days_remaining( +            Local.ymd(2018, 10, 1).and_hms(23, 1, 0), +            Local.ymd(2018, 10, 31).and_hms(23, 30, 0), +            30, +        ); + +        assert_eq!(remaining, Ok(0)); +    } + +    #[test] +    fn days_remaining_on_day_following_last_day_is_negative_duration_error() { +        let remaining = days_remaining( +            Local.ymd(2018, 10, 1).and_hms(23, 1, 0), +            Local.ymd(2018, 11, 1).and_hms(0, 0, 0), +            30, +        ); + +        assert_eq!(remaining, Err(DurationError::NegativeDuration(-1))); +    } + +    #[test] +    fn days_remaining_after_last_day_is_negative_duration_error() { +        let remaining = days_remaining( +            Local.ymd(2018, 10, 1).and_hms(23, 1, 0), +            Local.ymd(2018, 11, 5).and_hms(0, 0, 0), +            30, +        ); + +        assert_eq!(remaining, Err(DurationError::NegativeDuration(-5))); +    } +} | 
