From bb619b245296424385c2e79bc96a6aa41c4b8073 Mon Sep 17 00:00:00 2001 From: _ <_@_> Date: Tue, 5 Apr 2022 23:58:28 +0000 Subject: [PATCH] :heavy_plus_sign: offset feature --- src/config.rs | 17 +++++++++++++++++ src/main.rs | 11 +++++++++-- src/offset.rs | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 src/offset.rs diff --git a/src/config.rs b/src/config.rs index bc647dc..aa73b9c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -7,6 +7,9 @@ type Result = std::result::Result ; pub struct Config { pub interval_secs: u64, pub prompt: String, + + // Open dev tools in a web browser and run `Math.random () * 2225` + pub offset_secs: u64, } impl Default for Config { @@ -14,6 +17,7 @@ impl Default for Config { Self { interval_secs: 2225, prompt: "Write a journal entry, then hit Tab, Enter to submit it.".into (), + offset_secs: 0, } } } @@ -35,6 +39,11 @@ impl Config { let val = u64::from_str (&val).map_err (|_| CannotParseArg ("--interval-secs "))?; that.interval_secs = val; } + else if arg == "--offset-secs" { + let val = args.next ().ok_or (ParamNeedsArg ("--offset-secs"))?; + let val = u64::from_str (&val).map_err (|_| CannotParseArg ("--offset-secs "))?; + that.offset_secs = val; + } else if arg == "--prompt" { let val = args.next ().ok_or (ParamNeedsArg ("--prompt"))?; that.prompt = val; @@ -44,3 +53,11 @@ impl Config { Ok (that) } } + +#[cfg (test)] +mod test { + #[test] + fn parse () { + + } +} diff --git a/src/main.rs b/src/main.rs index 5fc7228..dfa56c4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,12 +21,13 @@ use tokio::{ io::AsyncWriteExt, time::{ Duration, - interval, + interval_at, }, }; mod config; mod error; +mod offset; use config::Config; use error::Error; @@ -40,7 +41,13 @@ async fn main () -> Result <(), Error> { let app = app::App::default (); tokio::spawn (async move { - let mut i = interval (Duration::from_secs (config.interval_secs)); + let mut i = interval_at ( + offset::get_next_tick ( + config.interval_secs, + config.offset_secs, + ).into (), + Duration::from_secs (config.interval_secs), + ); i.set_missed_tick_behavior (tokio::time::MissedTickBehavior::Skip); loop { diff --git a/src/offset.rs b/src/offset.rs new file mode 100644 index 0000000..60fb9ba --- /dev/null +++ b/src/offset.rs @@ -0,0 +1,33 @@ +use std::{ + time::{ + Duration, + Instant, + SystemTime, + } +}; + +pub fn get_next_tick (interval_secs: u64, offset_secs: u64) -> Instant { + let now_sys = SystemTime::now (); + let now_mono = Instant::now (); + + let phase = get_phase (now_sys, interval_secs, offset_secs); + now_mono.checked_add (Duration::from_millis (interval_secs * 1000 - u64::try_from (phase).unwrap ())).unwrap () +} + +fn get_phase (now: SystemTime, interval_secs: u64, offset_secs: u64) -> u64 { + let ms_since_epoch = now.duration_since (SystemTime::UNIX_EPOCH).unwrap ().as_millis (); + u64::try_from ((ms_since_epoch + u128::from (offset_secs) * 1000) % (u128::from (interval_secs) * 1000)).unwrap () +} + +#[cfg (test)] +mod test { + use super::*; + + #[test] + fn test () { + let now = SystemTime::UNIX_EPOCH.checked_add (Duration::from_secs (1649201544)).unwrap (); + + assert_eq! (get_phase (now, 2225, 0), 394000); + assert_eq! (get_phase (now, 2225, 30), 424000); + } +}