aboutsummaryrefslogtreecommitdiff
path: root/apps/cassiopeia/src/data.rs
diff options
context:
space:
mode:
Diffstat (limited to 'apps/cassiopeia/src/data.rs')
-rw-r--r--apps/cassiopeia/src/data.rs159
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())
}
}