diff options
Diffstat (limited to 'apps/cassiopeia/src/data.rs')
-rw-r--r-- | apps/cassiopeia/src/data.rs | 159 |
1 files changed, 124 insertions, 35 deletions
diff --git a/apps/cassiopeia/src/data.rs b/apps/cassiopeia/src/data.rs index 7442d699be88..47bb6e35b6e5 100644 --- a/apps/cassiopeia/src/data.rs +++ b/apps/cassiopeia/src/data.rs @@ -4,14 +4,15 @@ //! used to generate new files, and perform various lookups and //! analysis tasks. -use crate::format::LineCfg; -use chrono::{DateTime, Duration, Local, FixedOffset as Offset, NaiveDate}; +use crate::{ + format::{IrItem, IrType, MakeIr}, + Date, Time, +}; +use chrono::{DateTime, Duration, FixedOffset as Offset, Local, NaiveDate}; use std::collections::BTreeMap; #[derive(Debug, Default)] pub struct TimeFile { - /// Raw line buffers to echo back into the file - lines: Vec<LineCfg>, /// A parsed header structure header: BTreeMap<String, String>, /// A parsed session structure @@ -21,70 +22,158 @@ pub struct TimeFile { } impl TimeFile { - pub(crate) fn append(mut self, line: LineCfg) -> Self { - let lo = self.lines.len(); + pub(crate) fn append(&mut self, line: IrItem) { match line { - LineCfg::Header(ref header) => self.header = header.clone(), - LineCfg::Start(Some(time)) => self.sessions.push(Session::start(time, lo)), - LineCfg::Stop(Some(time)) => self.get_last_session().stop(time, lo), - LineCfg::Invoice(Some(date)) => self.invoices.push(Invoice::new(date, lo)), + IrItem { + tt: IrType::Header(ref header), + .. + } => self.header = header.clone(), + IrItem { + tt: IrType::Start(time), + lo, + } => self.sessions.push(Session::start(time.into())), + IrItem { + tt: IrType::Stop(time), + lo, + } => self.get_last_session().unwrap().stop(time.into()), + IrItem { + tt: IrType::Invoice(date), + lo, + } => self.invoices.push(Invoice::new(date.into())), _ => {} } + } - self.lines.push(line); - self + fn get_last_session(&mut self) -> Option<&mut Session> { + self.sessions.last_mut() } - fn get_last_session(&mut self) -> &mut Session { - self.sessions.last_mut().unwrap() + fn get_last_invoice(&mut self) -> Option<&mut Invoice> { + self.invoices.last_mut() } /// Start a new session (optionally 15-minute rounded) - pub fn start(&mut self, round: bool) -> Option<()> { - let now = Local::now(); - + /// + /// This function returns the new session object that will have to + /// be turned into an IR line to be written back into the file + pub(crate) fn start(&mut self, round: bool) -> Option<Session> { + // Check if the last session was closed + match self.get_last_session() { + Some(s) if !s.finished() => return None, + _ => {} + } + + // Create a new time + let now = if round { + Time::now().round() + } else { + Time::now() + }; + + Some(Session::start(now)) + } + + /// Stop the last session that was started, returning a completed + /// session + pub(crate) fn stop(&mut self, round: bool) -> Option<Session> { + match self.get_last_session() { + Some(s) if s.finished() => return None, + None => return None, + _ => {} + } + + // Create a new time + let now = if round { + Time::now().round() + } else { + Time::now() + }; + + self.get_last_session().cloned().map(|mut s| { + s.stop(now); + s + }) + } + + /// Add a new invoice block to the time file + pub(crate) fn invoice(&mut self) -> Option<()> { + let today = Date::today(); + + let last_sess = self.get_last_session().cloned(); + + match self.get_last_invoice() { + // Check if _today_ there has been already an invoice + Some(i) if i.date == today => return None, + + // Check if since the last invoice there has been at least + // _one_ terminated session. + Some(i) + if !last_sess + .map(|s| !s.stop.map(|s| s.after(&i.date)).unwrap_or(false)) + .unwrap_or(false) => + { + return None + } + + // Otherwise, we create an invoice + _ => {} + } + + self.invoices.push(Invoice::new(today)); Some(()) } } -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct Session { - start: DateTime<Offset>, - stop: Option<DateTime<Offset>>, - /// Track the lines this session took place in - lines: (usize, usize), + start: Time, + stop: Option<Time>, } impl Session { /// Create a new session with a start time - fn start(start: DateTime<Offset>, line: usize) -> Self { - Self { - start, - stop: None, - lines: (line, 0), - } + fn start(start: Time) -> Self { + Self { start, stop: None } } /// Finalise a session with a stop time - fn stop(&mut self, stop: DateTime<Offset>, line: usize) { + fn stop(&mut self, stop: Time) { self.stop = Some(stop); - self.lines.1 = line; + } + + /// Check whether this session was already finished + pub fn finished(&self) -> bool { + self.stop.is_some() } /// Get the length of the session, if it was already finished pub fn length(&self) -> Option<Duration> { - self.stop.map(|stop| stop - self.start) + self.stop.as_ref().map(|stop| stop - &self.start) + } +} + +impl MakeIr for Session { + fn make_ir(&self) -> IrType { + match self.stop { + Some(ref time) => IrType::Stop(time.clone()), + None => IrType::Start(self.start.clone()), + } } } #[derive(Debug)] pub struct Invoice { - date: NaiveDate, - line: usize, + date: Date, } impl Invoice { - fn new(date: NaiveDate, line: usize) -> Self { - Self { date, line } + fn new(date: Date) -> Self { + Self { date } + } +} + +impl MakeIr for Invoice { + fn make_ir(&self) -> IrType { + IrType::Invoice(self.date.clone()) } } |