Skip to content

Commit

Permalink
Merge pull request #453 from tijlleenders/tijl/-/add-simple-without-d…
Browse files Browse the repository at this point in the history
…eadline

Tijl/-/add-simple-without-deadline
  • Loading branch information
tijlleenders authored Mar 23, 2024
2 parents 7eb6fcd + 52d34f3 commit ae3ed65
Show file tree
Hide file tree
Showing 11 changed files with 274 additions and 169 deletions.
43 changes: 15 additions & 28 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
//! quality perception of the ZinZen® projects.
use chrono::NaiveDateTime;
use models::{activity::Activity, calendar::Calendar, goal::Goal, task::FinalTasks};
use models::{calendar::Calendar, goal::Goal, task::FinalTasks};
use serde_wasm_bindgen::{from_value, to_value};
use services::activity_generator;
use services::activity_placer;
Expand Down Expand Up @@ -94,44 +94,31 @@ pub fn run_scheduler(

calendar.add_budgets_from(goals);

//generate and place simple goal activities
let simple_goal_activities =
activity_generator::generate_simple_goal_activities(&calendar, goals);
dbg!(&simple_goal_activities);
let mut base_activities = activity_generator::get_base_activities(&calendar, goals);

let simple_filler_activities =
activity_generator::generate_simple_filler_goal_activities(&calendar, goals);
dbg!(&simple_filler_activities);

//generate and place budget goal activities
let budget_goal_activities: Vec<Activity> =
activity_generator::generate_budget_goal_activities(&calendar, goals);
dbg!(&budget_goal_activities);
dbg!(&calendar);

let activities: Vec<Activity> = [
simple_goal_activities,
simple_filler_activities,
budget_goal_activities,
]
.concat();
activity_placer::place(&mut calendar, activities);
base_activities = activity_placer::place(&mut calendar, base_activities);

calendar.log_impossible_min_day_budgets();

if let Some(get_to_week_min_budget_activities) =
activity_generator::generate_get_to_week_min_budget_activities(&calendar, goals)
{
activity_placer::place(&mut calendar, get_to_week_min_budget_activities);
}
let get_to_week_min_budget_activities =
activity_generator::get_budget_min_week_activities(&calendar, goals);
activity_placer::place(&mut calendar, get_to_week_min_budget_activities);
//TODO: Test that day stays below min when week min being reached so other goals can get to the week min too

calendar.log_impossible_min_week_budgets();

let top_up_week_budget_activities =
activity_generator::generate_top_up_week_budget_activities(&calendar, goals);
activity_generator::get_budget_top_up_week_activities(&calendar, goals);
activity_placer::place(&mut calendar, top_up_week_budget_activities);
//TODO: Test that day stays below min or max when week max being reachd

//TODO: Fit simple budget activities into scheduled budgets?
// No need, as simple budget activities will share the same overlay, but with less hours
// Thus, the flex will always be higher than (or equal to?) the MinDayBudget activities
// So MinDayBudget will get chosen last unless flex is equal and order happens to favor MinDayBudget
// => TODO: order activities before placing?

calendar.log_impossible_base_activities(base_activities);

calendar.print()
}
53 changes: 19 additions & 34 deletions src/models/activity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ pub struct Activity {
pub min_block_size: usize,
pub max_block_size: usize,
pub calendar_overlay: Vec<Option<Weak<Hour>>>,
pub time_budgets: Vec<TimeBudget>,
pub total_duration: usize,
pub duration_left: usize,
pub status: Status,
pub deadline: NaiveDateTime,
}
impl Activity {
pub fn get_compatible_hours_overlay(
Expand Down Expand Up @@ -138,9 +138,10 @@ impl Activity {
//TODO: shouldn't this logic be in creating the activity and then set to min_block_size so we can just use that here?
let offset_size: usize = match self.activity_type {
ActivityType::SimpleGoal => self.total_duration,
ActivityType::Budget => self.min_block_size,
ActivityType::BudgetMinDay => self.min_block_size,
ActivityType::GetToMinWeekBudget => 1,
ActivityType::TopUpWeekBudget => 1,
ActivityType::SimpleFiller => self.total_duration,
};
for offset in 0..offset_size {
match &self.calendar_overlay[hour_index + offset] {
Expand Down Expand Up @@ -178,17 +179,8 @@ impl Activity {
best_scheduling_index_and_conflicts.map(|(best_index, _, size)| (best_index, size))
}

pub(crate) fn get_activities_from_simple_goal(
goal: &Goal,
calendar: &Calendar,
parent_goal: Option<Goal>,
) -> Vec<Activity> {
if goal.children.is_some() || goal.filters.as_ref().is_some() {
return vec![];
}

let (adjusted_goal_start, adjusted_goal_deadline) =
goal.get_adj_start_deadline(calendar, parent_goal);
pub(crate) fn get_simple_activities(goal: &Goal, calendar: &Calendar) -> Vec<Activity> {
let (adjusted_goal_start, adjusted_goal_deadline) = goal.get_adj_start_deadline(calendar);
let mut activities: Vec<Activity> = Vec::with_capacity(1);

if let Some(activity_total_duration) = goal.min_duration {
Expand Down Expand Up @@ -216,10 +208,10 @@ impl Activity {
min_block_size,
max_block_size: min_block_size,
calendar_overlay: compatible_hours_overlay,
time_budgets: vec![],
total_duration: activity_total_duration,
duration_left: activity_total_duration,
status: Status::Unprocessed,
deadline: goal.deadline,
};
dbg!(&activity);
activities.push(activity);
Expand All @@ -228,10 +220,7 @@ impl Activity {
activities
}

pub(crate) fn get_activities_from_budget_goal(
goal: &Goal,
calendar: &Calendar,
) -> Vec<Activity> {
pub(crate) fn get_budget_min_day_activities(goal: &Goal, calendar: &Calendar) -> Vec<Activity> {
if goal.filters.as_ref().is_none() {
return vec![];
}
Expand All @@ -240,8 +229,7 @@ impl Activity {
return vec![];
}
}
let (adjusted_goal_start, adjusted_goal_deadline) =
goal.get_adj_start_deadline(calendar, None);
let (adjusted_goal_start, adjusted_goal_deadline) = goal.get_adj_start_deadline(calendar);
let mut activities: Vec<Activity> = Vec::with_capacity(1);

for day in 0..(adjusted_goal_deadline - adjusted_goal_start).num_days() as u64 {
Expand Down Expand Up @@ -277,15 +265,15 @@ impl Activity {

let activity = Activity {
goal_id: goal.id.clone(),
activity_type: ActivityType::Budget,
activity_type: ActivityType::BudgetMinDay,
title: goal.title.clone(),
min_block_size: adjusted_min_block_size,
max_block_size: config.max_per_day,
calendar_overlay: compatible_hours_overlay,
time_budgets: vec![],
total_duration: adjusted_min_block_size,
duration_left: config.min_per_day,
status: Status::Unprocessed,
deadline: goal.deadline,
};
dbg!(&activity);
activities.push(activity);
Expand Down Expand Up @@ -324,10 +312,10 @@ impl Activity {
min_block_size: 1,
max_block_size: max_hours,
calendar_overlay: compatible_hours_overlay,
time_budgets: vec![],
total_duration: max_hours,
duration_left: max_hours,
status: Status::Unprocessed,
deadline: goal_to_use.deadline,
});

activities
Expand Down Expand Up @@ -363,10 +351,10 @@ impl Activity {
min_block_size: 1,
max_block_size: max_hours,
calendar_overlay: compatible_hours_overlay,
time_budgets: vec![],
total_duration: max_hours,
duration_left: max_hours,
status: Status::Unprocessed,
deadline: goal_to_use.deadline,
});

activities
Expand Down Expand Up @@ -468,6 +456,7 @@ impl Activity {
self.status = Status::Impossible;
}
}

pub(crate) fn release_claims(&mut self) {
let mut empty_overlay: Vec<Option<Weak<Hour>>> =
Vec::with_capacity(self.calendar_overlay.capacity());
Expand All @@ -477,16 +466,11 @@ impl Activity {
self.calendar_overlay = empty_overlay;
}

pub(crate) fn get_filler_activities_from_simple_goal(
goal: &Goal,
calendar: &Calendar,
parent_goal: Option<Goal>,
) -> Vec<Activity> {
pub(crate) fn get_simple_filler_activities(goal: &Goal, calendar: &Calendar) -> Vec<Activity> {
if goal.children.is_none() || goal.filters.as_ref().is_some() {
return vec![];
}
let (adjusted_goal_start, adjusted_goal_deadline) =
goal.get_adj_start_deadline(calendar, parent_goal);
let (adjusted_goal_start, adjusted_goal_deadline) = goal.get_adj_start_deadline(calendar);
let mut activities: Vec<Activity> = Vec::with_capacity(1);

if let Some(activity_total_duration) = goal.min_duration {
Expand All @@ -509,15 +493,15 @@ impl Activity {

let activity = Activity {
goal_id: goal.id.clone(),
activity_type: ActivityType::SimpleGoal,
activity_type: ActivityType::SimpleFiller,
title: goal.title.clone(),
min_block_size,
max_block_size: min_block_size,
calendar_overlay: compatible_hours_overlay,
time_budgets: vec![],
total_duration: activity_total_duration,
duration_left: activity_total_duration,
status: Status::Unprocessed,
deadline: goal.deadline,
};
dbg!(&activity);
activities.push(activity);
Expand All @@ -538,9 +522,10 @@ pub enum Status {
#[derive(Clone, Debug, PartialEq)]
pub enum ActivityType {
SimpleGoal,
Budget,
BudgetMinDay,
GetToMinWeekBudget,
TopUpWeekBudget,
SimpleFiller,
}

impl fmt::Debug for Activity {
Expand Down
3 changes: 2 additions & 1 deletion src/models/budget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ impl Budget {
ActivityType::SimpleGoal => {
budget_cut_off_number = time_budget.min_scheduled;
}
ActivityType::Budget => {
ActivityType::BudgetMinDay => {
budget_cut_off_number = time_budget.min_scheduled;
}
ActivityType::GetToMinWeekBudget => {
Expand All @@ -61,6 +61,7 @@ impl Budget {
ActivityType::TopUpWeekBudget => {
budget_cut_off_number = time_budget.max_scheduled;
}
ActivityType::SimpleFiller => budget_cut_off_number = time_budget.min_scheduled,
}
//figure out how many of the hours in hour_index till hour_index + offset are in the time_budget window
let mut hours_in_time_budget_window = 0;
Expand Down
25 changes: 25 additions & 0 deletions src/models/calendar.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use super::activity::Activity;
use super::budget::{get_time_budgets_from, Budget, TimeBudgetType};
use super::goal::Goal;
use super::task::{DayTasks, FinalTasks, Task};
Expand Down Expand Up @@ -70,6 +71,15 @@ impl Calendar {
date_time_of_index_to_test.weekday()
}

pub fn is_budget(&self, goal_id: String) -> bool {
for budget in self.budgets.iter() {
if budget.participating_goals.contains(&goal_id) {
return true;
}
}
false
}

pub fn get_index_of(&self, date_time: NaiveDateTime) -> usize {
if date_time < self.start_date_time.sub(Duration::days(1))
|| date_time > self.end_date_time.add(Duration::days(1))
Expand Down Expand Up @@ -294,6 +304,21 @@ impl Calendar {
self.impossible_activities.extend(impossible_activities);
}

pub fn log_impossible_base_activities(&mut self, activities: Vec<Activity>) {
for activity in activities {
if activity.status == super::activity::Status::Impossible
&& activity.deadline.year() != 1970
{
self.impossible_activities.push(ImpossibleActivity {
id: activity.goal_id.clone(),
hours_missing: activity.duration_left,
period_start_date_time: self.start_date_time,
period_end_date_time: self.end_date_time,
})
}
}
}

fn impossible_activities(&mut self) -> Vec<ImpossibleActivity> {
let mut impossible_activities = vec![];
for budget in &self.budgets {
Expand Down
18 changes: 1 addition & 17 deletions src/models/goal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,7 @@ pub struct BudgetConfig {
}

impl Goal {
pub fn get_adj_start_deadline(
&self,
calendar: &Calendar,
parent_goal: Option<Goal>,
) -> (NaiveDateTime, NaiveDateTime) {
pub fn get_adj_start_deadline(&self, calendar: &Calendar) -> (NaiveDateTime, 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;
Expand All @@ -60,18 +56,6 @@ impl Goal {
adjusted_goal_deadline = calendar.end_date_time;
}

// Make sure child goal not fall outside of parent goal start and deadline
if let Some(parent_goal) = parent_goal {
// means this is a child goal
if adjusted_goal_start < parent_goal.start {
adjusted_goal_start = parent_goal.start;
}
if adjusted_goal_deadline > parent_goal.deadline && parent_goal.deadline.year() != 1970
{
adjusted_goal_deadline = parent_goal.deadline;
}
}

if self.filters.is_none() {
return (adjusted_goal_start, adjusted_goal_deadline);
}
Expand Down
Loading

0 comments on commit ae3ed65

Please sign in to comment.