feat: implement basic cycle between work and break modes
This commit is contained in:
@@ -0,0 +1 @@
|
||||
tab_spaces = 2
|
||||
+161
-1
@@ -1,3 +1,163 @@
|
||||
const SECONDS_PER_MIN: i64 = 60;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
enum TimerState {
|
||||
Work,
|
||||
Break,
|
||||
Paused,
|
||||
}
|
||||
|
||||
struct Termato {
|
||||
work_mins: i64,
|
||||
break_mins: i64,
|
||||
state: TimerState,
|
||||
prior_state: TimerState,
|
||||
is_running: bool,
|
||||
duration_in_secs: i64,
|
||||
time_remaining_in_sec: i64,
|
||||
}
|
||||
|
||||
impl Termato {
|
||||
fn new(work_mins: i64, break_mins: i64) -> Self {
|
||||
Termato {
|
||||
work_mins,
|
||||
break_mins,
|
||||
state: TimerState::Work,
|
||||
prior_state: TimerState::Work,
|
||||
is_running: false,
|
||||
duration_in_secs: work_mins * SECONDS_PER_MIN,
|
||||
time_remaining_in_sec: break_mins * SECONDS_PER_MIN,
|
||||
}
|
||||
}
|
||||
|
||||
fn toggle_mode(&mut self) {
|
||||
let is_on_break = self.state == TimerState::Break
|
||||
|| (self.state == TimerState::Paused && self.prior_state == TimerState::Break);
|
||||
|
||||
if is_on_break {
|
||||
self.state = TimerState::Work;
|
||||
self.prior_state = TimerState::Work;
|
||||
self.duration_in_secs = self.work_mins * SECONDS_PER_MIN;
|
||||
} else {
|
||||
self.state = TimerState::Break;
|
||||
self.prior_state = TimerState::Break;
|
||||
self.duration_in_secs = self.break_mins * SECONDS_PER_MIN;
|
||||
}
|
||||
|
||||
self.time_remaining_in_sec = self.duration_in_secs;
|
||||
}
|
||||
|
||||
fn tick(&mut self) {
|
||||
if self.is_running && self.time_remaining_in_sec > 0 {
|
||||
self.time_remaining_in_sec -= 1;
|
||||
|
||||
if self.time_remaining_in_sec == 0 {
|
||||
self.toggle_mode();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
let mut termato = Termato::new(1, 1);
|
||||
|
||||
loop {
|
||||
termato.is_running = true;
|
||||
|
||||
termato.tick();
|
||||
|
||||
println!("Time remaining: {}", termato.time_remaining_in_sec);
|
||||
println!("State: {:?}", termato.state);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn termato_when_called_it_should_return_expected_starting_state() {
|
||||
let result = Termato::new(1, 1);
|
||||
|
||||
assert_eq!(result.work_mins, 1);
|
||||
assert_eq!(result.break_mins, 1);
|
||||
assert_eq!(result.state, TimerState::Work);
|
||||
assert_eq!(result.prior_state, TimerState::Work);
|
||||
assert!(!result.is_running);
|
||||
assert_eq!(result.duration_in_secs, 60);
|
||||
assert_eq!(result.time_remaining_in_sec, 60);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn termato_tick_when_called_and_not_running_it_should_do_nothing() {
|
||||
let mut termato = Termato::new(1, 1);
|
||||
|
||||
termato.tick();
|
||||
|
||||
assert_eq!(termato.time_remaining_in_sec, 60);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn termato_tick_when_called_and_no_time_remaining_it_should_do_nothing() {
|
||||
let mut termato = Termato::new(1, 1);
|
||||
termato.is_running = true;
|
||||
termato.time_remaining_in_sec = 0;
|
||||
|
||||
termato.tick();
|
||||
|
||||
assert_eq!(termato.time_remaining_in_sec, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn termato_tick_when_running_and_time_reamining_it_should_reduce_remaining_by_one() {
|
||||
let mut termato = Termato::new(1, 1);
|
||||
termato.is_running = true;
|
||||
|
||||
termato.tick();
|
||||
|
||||
assert_eq!(termato.time_remaining_in_sec, 59);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn termato_tick_when_running_on_work_and_time_remaining_reaches_zero_it_should_toggle_to_break() {
|
||||
let mut termato = Termato::new(1, 2);
|
||||
termato.is_running = true;
|
||||
termato.time_remaining_in_sec = 1;
|
||||
|
||||
termato.tick();
|
||||
|
||||
assert_eq!(termato.state, TimerState::Break);
|
||||
assert_eq!(termato.prior_state, TimerState::Break);
|
||||
assert_eq!(termato.duration_in_secs, 120);
|
||||
assert_eq!(termato.time_remaining_in_sec, 120);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn termato_tick_when_running_on_break_and_time_remaining_reaches_zero_it_should_toggle_to_work() {
|
||||
let mut termato = Termato::new(2, 1);
|
||||
termato.state = TimerState::Break;
|
||||
termato.is_running = true;
|
||||
termato.time_remaining_in_sec = 1;
|
||||
|
||||
termato.tick();
|
||||
|
||||
assert_eq!(termato.state, TimerState::Work);
|
||||
assert_eq!(termato.prior_state, TimerState::Work);
|
||||
assert_eq!(termato.duration_in_secs, 120);
|
||||
assert_eq!(termato.time_remaining_in_sec, 120);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn termato_toggle_mode_when_paused_and_previous_state_is_break_it_should_toggle_to_work() {
|
||||
let mut termato = Termato::new(2, 1);
|
||||
termato.state = TimerState::Paused;
|
||||
termato.prior_state = TimerState::Break;
|
||||
|
||||
termato.toggle_mode();
|
||||
|
||||
assert_eq!(termato.state, TimerState::Work);
|
||||
assert_eq!(termato.prior_state, TimerState::Work);
|
||||
assert_eq!(termato.duration_in_secs, 120);
|
||||
assert_eq!(termato.time_remaining_in_sec, 120);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user