use chrono::{DateTime, Duration, Local};
use std::{default::Default, mem};
#[derive(Debug)]
pub struct StopwatchData {
pub elapsed: Duration,
pub pause_moments: Vec<DateTime<Local>>, pub start_moments: Vec<DateTime<Local>>, pub lap_moments: Vec<DateTime<Local>>, pub laps: Vec<Duration>, }
impl Default for StopwatchData {
fn default() -> Self {
Self {
elapsed: Duration::zero(),
start_moments: Vec::new(),
pause_moments: Vec::new(),
lap_moments: Vec::new(),
laps: Vec::new(),
}
}
}
impl StopwatchData {
fn new() -> Self {
Self::default()
}
pub fn start(&self) -> DateTime<Local> {
self.start_moments[0]
}
pub fn stop(&self) -> DateTime<Local> {
self.pause_moments[self.pause_moments.len() - 1]
}
}
#[derive(Debug)]
pub struct Stopwatch {
pub lap_elapsed: Duration, pub paused: bool,
pub data: StopwatchData,
}
impl Default for Stopwatch {
fn default() -> Self {
Self {
lap_elapsed: Duration::zero(),
paused: true, data: StopwatchData::new(),
}
}
}
impl Stopwatch {
pub fn new() -> Self {
Self::default()
}
pub fn read(&self) -> Duration {
if self.paused {
self.data.elapsed
} else {
self.data.elapsed + (Local::now() - self.last_start())
}
}
pub fn pause_or_resume(&mut self) {
if self.paused {
self.resume();
} else {
self.pause();
}
}
pub fn lap(&mut self) -> Option<Duration> {
if self.paused {
None
} else {
let moment = Local::now();
let lap = self.read_lap_elapsed(moment);
self.data.lap_moments.push(moment);
self.data.laps.push(lap);
self.lap_elapsed = Duration::zero();
Some(lap)
}
}
pub fn stop(&mut self) -> StopwatchData {
let moment = Local::now();
let lap = self.read_lap_elapsed(moment);
self.data.lap_moments.push(moment);
self.data.laps.push(lap);
self.lap_elapsed = Duration::zero();
self.data.pause_moments.push(moment);
self.data.elapsed = self.data.elapsed + (moment - self.last_start());
self.paused = true;
let data = mem::replace(&mut self.data, StopwatchData::new());
data
}
fn read_lap_elapsed(&self, moment: DateTime<Local>) -> Duration {
self.lap_elapsed
+ if self.lap_elapsed == Duration::zero() && !self.data.lap_moments.is_empty() {
moment - self.last_lap()
} else {
moment - self.last_start()
}
}
fn last_start(&self) -> DateTime<Local> {
self.data.start_moments[self.data.start_moments.len() - 1]
}
fn last_lap(&self) -> DateTime<Local> {
self.data.lap_moments[self.data.lap_moments.len() - 1]
}
pub fn pause(&mut self) {
let moment = Local::now();
self.data.pause_moments.push(moment);
self.data.elapsed = self.data.elapsed + (moment - self.last_start());
self.lap_elapsed = self.read_lap_elapsed(moment);
self.paused = true;
}
pub fn resume(&mut self) {
self.data.start_moments.push(Local::now());
self.paused = false;
}
}