use chrono::{DateTime, Utc};
use crate::types::{Action, Event};
#[derive(Debug, Default, PartialEq)]
pub struct Scheduler {
future_events: Vec<Event>,
events: Vec<Event>,
}
impl Scheduler {
pub fn new() -> Self {
Self {
future_events: Vec::new(),
events: Vec::new(),
}
}
pub fn has_future_events(&self) -> bool {
!self.future_events.is_empty()
}
pub fn schedule_on(&mut self, timestamp: DateTime<Utc>) {
let event = Event::new(Action::On, timestamp);
self.future_events.push(event);
}
pub fn schedule_off(&mut self, timestamp: DateTime<Utc>) {
let event = Event::new(Action::Off, timestamp);
self.future_events.push(event);
}
pub fn schedule_read(&mut self, timestamp: DateTime<Utc>) {
let event = Event::new(Action::Read, timestamp);
self.future_events.push(event);
}
pub fn attempt_execution(&mut self, time: DateTime<Utc>) -> Option<Event> {
if let Some(index) = self.future_events.iter().position(|e| e.should_execute(time)) {
let event = self.future_events.remove(index);
self.events.push(event.clone());
Some(event)
} else {
None
}
}
pub fn get_future_events(&self) -> &Vec<Event> {
&self.future_events
}
}
#[cfg(test)]
mod tests {
use chrono::TimeZone;
use super::*;
#[test]
fn test_new() {
let scheduler = Scheduler::new();
assert_eq!(scheduler.has_future_events(), false);
}
#[test]
fn test_schedule_on() {
let mut scheduler = Scheduler::new();
let timestamp = Utc.with_ymd_and_hms(2023, 1, 1, 0, 0, 0)
.unwrap();
scheduler.schedule_on(timestamp);
assert_eq!(scheduler.has_future_events(), true);
}
#[test]
fn test_schedule_off() {
let mut scheduler = Scheduler::new();
let timestamp = Utc.with_ymd_and_hms(2023, 1, 1, 0, 0, 0)
.unwrap();
scheduler.schedule_off(timestamp);
assert_eq!(scheduler.has_future_events(), true);
}
#[test]
fn test_schedule_read() {
let mut scheduler = Scheduler::new();
let timestamp = Utc.with_ymd_and_hms(2023, 1, 1, 0, 0, 0)
.unwrap();
scheduler.schedule_read(timestamp);
assert_eq!(scheduler.has_future_events(), true);
}
#[test]
fn test_attempt_execution() {
let mut scheduler = Scheduler::new();
let timestamp = Utc.with_ymd_and_hms(2023, 1, 1, 0, 0, 0)
.unwrap();
scheduler.schedule_on(timestamp);
let timestamp = Utc.with_ymd_and_hms(2023, 1, 1, 0, 0, 1)
.unwrap();
let event = scheduler.attempt_execution(timestamp);
assert!(event.is_some());
assert_eq!(event.unwrap().get_action(), Action::On);
assert_eq!(scheduler.has_future_events(), false);
assert_eq!(scheduler.events.len(), 1);
let timestamp = Utc.with_ymd_and_hms(2023, 1, 1, 0, 1, 0)
.unwrap();
scheduler.schedule_off(timestamp);
let timestamp = Utc.with_ymd_and_hms(2023, 1, 1, 0, 3, 0)
.unwrap();
scheduler.schedule_on(timestamp);
let timestamp = Utc.with_ymd_and_hms(2023, 1, 1, 0, 2, 0)
.unwrap();
let event = scheduler.attempt_execution(timestamp);
assert!(event.is_some());
assert_eq!(event.unwrap().get_action(), Action::Off);
assert_eq!(scheduler.has_future_events(), true);
assert_eq!(scheduler.events.len(), 2);
let timestamp = Utc.with_ymd_and_hms(2023, 1, 1, 0, 4, 0)
.unwrap();
let event = scheduler.attempt_execution(timestamp);
assert!(event.is_some());
assert_eq!(event.unwrap().get_action(), Action::On);
assert_eq!(scheduler.has_future_events(), false);
assert_eq!(scheduler.events.len(), 3);
}
}