use chrono::{Datelike, NaiveDateTime};
use serde::Deserialize;
use super::calendar::Calendar;
#[derive(Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct Goal {
pub id: String,
#[serde(default)]
pub start: NaiveDateTime,
#[serde(default)]
pub deadline: Option<NaiveDateTime>,
pub min_duration: Option<usize>,
pub title: String,
pub budget_id: Option<String>,
pub not_on: Option<Vec<Slot>>,
}
#[derive(Deserialize, Debug, Clone)]
pub struct Slot {
pub start: NaiveDateTime,
pub end: NaiveDateTime,
}
impl Goal {
pub fn get_adj_start_deadline(
&self,
calendar: &Calendar,
) -> (NaiveDateTime, Option<NaiveDateTime>) {
let mut adjusted_goal_start = self.start;
if self.start.year() == 1970 || self.start < calendar.start_date_time {
adjusted_goal_start = calendar.start_date_time;
}
(adjusted_goal_start, self.deadline)
}
}
#[derive(Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct Budget {
pub id: String,
#[serde(default)]
pub title: Option<String>,
pub min_per_week: usize,
pub max_per_week: usize,
pub periods: Vec<BudgetPeriod>,
}
#[derive(Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct BudgetPeriod {
#[serde(default)]
pub id: Option<String>,
pub on_days: Vec<chrono::Weekday>,
pub window: PeriodWindow,
pub min_for_period: usize,
pub max_for_period: usize,
}
#[derive(Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct PeriodWindow {
pub after_time: usize,
pub before_time: usize,
}
impl Budget {
pub fn soft_period_mins_exceed_week_max(&self) -> bool {
let mut sum = 0usize;
for period in &self.periods {
sum = sum.saturating_add(period.min_for_period);
}
sum > self.max_per_week
}
}