Evaluate some deltas

This commit is contained in:
Joscha 2021-12-03 20:17:49 +00:00
parent 0eda941ed7
commit b8aeb79323
2 changed files with 143 additions and 5 deletions

View file

@ -3,7 +3,7 @@ use std::result;
use chrono::{Datelike, NaiveDate};
use crate::files::commands::{Birthday, Command, DoneDate, Note, Spec, Task};
use crate::files::commands::{Birthday, Command, DoneDate, Note, Span, Spec, Task, Time};
use crate::files::{Files, Source, SourcedCommand};
use self::entry::EntryMap;
@ -16,10 +16,20 @@ mod entry;
mod formula_spec;
mod range;
#[derive(Debug, thiserror::Error)]
#[derive(Debug)]
pub enum Error {
#[error("TODO")]
Todo,
DeltaInvalidStep {
span: Span,
start: NaiveDate,
start_time: Option<Time>,
prev: NaiveDate,
prev_time: Option<Time>,
},
DeltaNoTime {
span: Span,
start: NaiveDate,
prev: NaiveDate,
},
}
type Result<T> = result::Result<T, Error>;

View file

@ -1,6 +1,10 @@
use std::cmp::Ordering;
use crate::files::commands::{self, Spanned, Time, Weekday};
use chrono::{Datelike, Duration, NaiveDate};
use crate::files::commands::{self, Span, Spanned, Time, Weekday};
use super::{Error, Result};
/// Like [`commands::DeltaStep`] but includes a new constructor,
/// [`DeltaStep::Time`].
@ -137,6 +141,122 @@ impl From<&commands::Delta> for Delta {
}
}
struct DeltaEval {
start: NaiveDate,
start_time: Option<Time>,
curr: NaiveDate,
curr_time: Option<Time>,
}
impl DeltaEval {
fn new(start: NaiveDate, start_time: Option<Time>) -> Self {
Self {
start,
start_time,
curr: start,
curr_time: start_time,
}
}
fn err_step(&self, span: Span) -> Error {
Error::DeltaInvalidStep {
span,
start: self.start,
start_time: self.start_time,
prev: self.curr,
prev_time: self.curr_time,
}
}
fn err_time(&self, span: Span) -> Error {
Error::DeltaNoTime {
span,
start: self.start,
prev: self.curr,
}
}
fn apply(&mut self, step: &Spanned<DeltaStep>) -> Result<()> {
match step.value {
DeltaStep::Year(n) => self.step_year(step.span, n),
DeltaStep::Month(n) => self.step_month(step.span, n),
DeltaStep::MonthReverse(n) => self.step_month_reverse(step.span, n),
DeltaStep::Day(n) => self.step_day(step.span, n),
DeltaStep::Week(n) => self.step_week(step.span, n),
DeltaStep::Hour(n) => self.step_hour(step.span, n),
DeltaStep::Minute(n) => self.step_minute(step.span, n),
DeltaStep::Weekday(n, wd) => self.step_weekday(step.span, n, wd),
DeltaStep::Time(time) => self.step_time(step.span, time),
}
}
fn step_year(&mut self, span: Span, amount: i32) -> Result<()> {
let curr = self.curr;
match NaiveDate::from_ymd_opt(curr.year() + amount, curr.month(), curr.day()) {
None => Err(self.err_step(span)),
Some(next) => {
self.curr = next;
Ok(())
}
}
}
fn step_month(&mut self, span: Span, amount: i32) -> Result<()> {
let month0 = self.curr.month0() as i32 + amount;
let year = self.curr.year() + month0.div_euclid(12);
let month0 = month0.rem_euclid(12) as u32;
match NaiveDate::from_ymd_opt(year, month0 + 1, self.curr.day()) {
None => Err(self.err_step(span)),
Some(next) => {
self.curr = next;
Ok(())
}
}
}
fn step_month_reverse(&mut self, span: Span, amount: i32) -> Result<()> {
todo!()
}
fn step_day(&mut self, span: Span, amount: i32) -> Result<()> {
let delta = Duration::days(amount.into());
match self.curr.checked_add_signed(delta) {
None => Err(self.err_step(span)),
Some(next) => {
self.curr = next;
Ok(())
}
}
}
fn step_week(&mut self, span: Span, amount: i32) -> Result<()> {
let delta = Duration::days((7 * amount).into());
match self.curr.checked_add_signed(delta) {
None => Err(self.err_step(span)),
Some(next) => {
self.curr = next;
Ok(())
}
}
}
fn step_hour(&mut self, span: Span, amount: i32) -> Result<()> {
todo!()
}
fn step_minute(&mut self, span: Span, amount: i32) -> Result<()> {
todo!()
}
fn step_weekday(&mut self, span: Span, amount: i32, weekday: Weekday) -> Result<()> {
todo!()
}
fn step_time(&mut self, span: Span, time: Time) -> Result<()> {
todo!()
}
}
impl Delta {
pub fn lower_bound(&self) -> i32 {
self.steps.iter().map(|step| step.value.lower_bound()).sum()
@ -145,4 +265,12 @@ impl Delta {
pub fn upper_bound(&self) -> i32 {
self.steps.iter().map(|step| step.value.upper_bound()).sum()
}
pub fn apply(&self, start: (NaiveDate, Option<Time>)) -> Result<(NaiveDate, Option<Time>)> {
let mut eval = DeltaEval::new(start.0, start.1);
for step in &self.steps {
eval.apply(step)?;
}
Ok((eval.curr, eval.curr_time))
}
}