Evaluate some deltas
This commit is contained in:
parent
0eda941ed7
commit
b8aeb79323
2 changed files with 143 additions and 5 deletions
18
src/eval.rs
18
src/eval.rs
|
|
@ -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>;
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue