From 8e98edd3e06190ea4f21c73cebb229e7059ba9b0 Mon Sep 17 00:00:00 2001 From: Tijl Leenders Date: Tue, 19 Mar 2024 21:19:27 +0100 Subject: [PATCH 01/29] add failing test case --- .../simple-without-deadline/expected.json | 26 +++++++++ .../stable/simple-without-deadline/input.json | 19 ++++++ .../simple-without-deadline/observed.json | 58 +++++++++++++++++++ 3 files changed, 103 insertions(+) create mode 100644 tests/jsons/stable/simple-without-deadline/expected.json create mode 100644 tests/jsons/stable/simple-without-deadline/input.json create mode 100644 tests/jsons/stable/simple-without-deadline/observed.json diff --git a/tests/jsons/stable/simple-without-deadline/expected.json b/tests/jsons/stable/simple-without-deadline/expected.json new file mode 100644 index 00000000..600e0def --- /dev/null +++ b/tests/jsons/stable/simple-without-deadline/expected.json @@ -0,0 +1,26 @@ +{ + "scheduled": [ + { + "day": "2022-01-01", + "tasks": [ + { + "taskid": 0, + "goalid": "free", + "title": "free", + "duration": 23, + "start": "2022-01-01T00:00:00", + "deadline": "2022-01-01T23:00:00" + }, + { + "taskid": 1, + "goalid": "1", + "title": "watch the stars", + "duration": 1, + "start": "2022-01-01T23:00:00", + "deadline": "2022-01-02T23:00:00" + } + ] + } + ], + "impossible": [] +} \ No newline at end of file diff --git a/tests/jsons/stable/simple-without-deadline/input.json b/tests/jsons/stable/simple-without-deadline/input.json new file mode 100644 index 00000000..38f7cf0c --- /dev/null +++ b/tests/jsons/stable/simple-without-deadline/input.json @@ -0,0 +1,19 @@ + { + "startDate": "2022-01-01T00:00:00", + "endDate": "2022-01-02T00:00:00", + "goals": [ + { + "id": "1", + "title": "watch the stars", + "minDuration": 1, + "start": "2022-01-01T23:00:00", + "deadline": "2022-01-02T00:00:00" + }, + { + "id": "2", + "title": "do someday", + "minDuration": 1, + "start": "2022-01-01T23:00:00" + } + ] + } \ No newline at end of file diff --git a/tests/jsons/stable/simple-without-deadline/observed.json b/tests/jsons/stable/simple-without-deadline/observed.json new file mode 100644 index 00000000..5f66bc55 --- /dev/null +++ b/tests/jsons/stable/simple-without-deadline/observed.json @@ -0,0 +1,58 @@ +{ + "scheduled": [ + { + "day": "2022-01-01", + "tasks": [ + { + "taskid": 0, + "goalid": "free", + "title": "free", + "duration": 10, + "start": "2022-01-01T00:00:00", + "deadline": "2022-01-01T10:00:00" + }, + { + "taskid": 1, + "goalid": "2", + "title": "dentist", + "duration": 1, + "start": "2022-01-01T10:00:00", + "deadline": "2022-01-01T11:00:00" + }, + { + "taskid": 2, + "goalid": "1", + "title": "shopping", + "duration": 1, + "start": "2022-01-01T11:00:00", + "deadline": "2022-01-01T12:00:00" + }, + { + "taskid": 3, + "goalid": "free", + "title": "free", + "duration": 1, + "start": "2022-01-01T12:00:00", + "deadline": "2022-01-01T13:00:00" + }, + { + "taskid": 4, + "goalid": "3", + "title": "exercise", + "duration": 1, + "start": "2022-01-01T13:00:00", + "deadline": "2022-01-01T14:00:00" + }, + { + "taskid": 5, + "goalid": "free", + "title": "free", + "duration": 10, + "start": "2022-01-01T14:00:00", + "deadline": "2022-01-02T00:00:00" + } + ] + } + ], + "impossible": [] +} \ No newline at end of file From ed18dc681f1f8a319a447158f8e6fe63e8e8dd80 Mon Sep 17 00:00:00 2001 From: Tijl Leenders Date: Fri, 22 Mar 2024 13:15:04 +0100 Subject: [PATCH 02/29] fix expectation makes test pass --- .../simple-without-deadline/expected.json | 2 +- .../simple-without-deadline/observed.json | 40 ++----------------- 2 files changed, 5 insertions(+), 37 deletions(-) diff --git a/tests/jsons/stable/simple-without-deadline/expected.json b/tests/jsons/stable/simple-without-deadline/expected.json index 600e0def..0d5865ba 100644 --- a/tests/jsons/stable/simple-without-deadline/expected.json +++ b/tests/jsons/stable/simple-without-deadline/expected.json @@ -17,7 +17,7 @@ "title": "watch the stars", "duration": 1, "start": "2022-01-01T23:00:00", - "deadline": "2022-01-02T23:00:00" + "deadline": "2022-01-02T00:00:00" } ] } diff --git a/tests/jsons/stable/simple-without-deadline/observed.json b/tests/jsons/stable/simple-without-deadline/observed.json index 5f66bc55..0d5865ba 100644 --- a/tests/jsons/stable/simple-without-deadline/observed.json +++ b/tests/jsons/stable/simple-without-deadline/observed.json @@ -7,48 +7,16 @@ "taskid": 0, "goalid": "free", "title": "free", - "duration": 10, + "duration": 23, "start": "2022-01-01T00:00:00", - "deadline": "2022-01-01T10:00:00" + "deadline": "2022-01-01T23:00:00" }, { "taskid": 1, - "goalid": "2", - "title": "dentist", - "duration": 1, - "start": "2022-01-01T10:00:00", - "deadline": "2022-01-01T11:00:00" - }, - { - "taskid": 2, "goalid": "1", - "title": "shopping", - "duration": 1, - "start": "2022-01-01T11:00:00", - "deadline": "2022-01-01T12:00:00" - }, - { - "taskid": 3, - "goalid": "free", - "title": "free", + "title": "watch the stars", "duration": 1, - "start": "2022-01-01T12:00:00", - "deadline": "2022-01-01T13:00:00" - }, - { - "taskid": 4, - "goalid": "3", - "title": "exercise", - "duration": 1, - "start": "2022-01-01T13:00:00", - "deadline": "2022-01-01T14:00:00" - }, - { - "taskid": 5, - "goalid": "free", - "title": "free", - "duration": 10, - "start": "2022-01-01T14:00:00", + "start": "2022-01-01T23:00:00", "deadline": "2022-01-02T00:00:00" } ] From 6a350bd2a50f028479066ab78378cd6281554426 Mon Sep 17 00:00:00 2001 From: Tijl Leenders Date: Fri, 22 Mar 2024 14:42:53 +0100 Subject: [PATCH 03/29] improve test to hit both branches --- tests/jsons/stable/simple-without-deadline/input.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/jsons/stable/simple-without-deadline/input.json b/tests/jsons/stable/simple-without-deadline/input.json index 38f7cf0c..2e6998d9 100644 --- a/tests/jsons/stable/simple-without-deadline/input.json +++ b/tests/jsons/stable/simple-without-deadline/input.json @@ -14,6 +14,13 @@ "title": "do someday", "minDuration": 1, "start": "2022-01-01T23:00:00" + }, + { + "id": "3", + "title": "impossible_goal", + "minDuration": 1, + "start": "2022-01-01T23:00:00", + "deadline": "2022-01-02T00:00:00" } ] } \ No newline at end of file From 546fb70aa20ca197017f0818639e80f8e47ac273 Mon Sep 17 00:00:00 2001 From: Tijl Leenders Date: Fri, 22 Mar 2024 14:46:28 +0100 Subject: [PATCH 04/29] update expectation for improved test --- tests/jsons/stable/simple-without-deadline/expected.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/jsons/stable/simple-without-deadline/expected.json b/tests/jsons/stable/simple-without-deadline/expected.json index 0d5865ba..ed41143d 100644 --- a/tests/jsons/stable/simple-without-deadline/expected.json +++ b/tests/jsons/stable/simple-without-deadline/expected.json @@ -22,5 +22,12 @@ ] } ], - "impossible": [] + "impossible": [ + { + "id": "3", + "hoursMissing": 1, + "periodStartDateTime": "2022-01-01T00:00:00", + "periodEndDateTime": "2022-01-02T00:00:00" + } + ] } \ No newline at end of file From 533f6584f03da8567c275ee15e6ec5d180f9b7b7 Mon Sep 17 00:00:00 2001 From: Tijl Leenders Date: Fri, 22 Mar 2024 14:47:18 +0100 Subject: [PATCH 05/29] check if impossible based on activity.deadline --- src/lib.rs | 7 +++++-- src/models/activity.rs | 6 ++++++ src/models/calendar.rs | 16 ++++++++++++++++ src/services/activity_placer.rs | 4 ++-- .../stable/simple-without-deadline/observed.json | 9 ++++++++- 5 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 923e5eb5..a505f971 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -109,13 +109,14 @@ pub fn run_scheduler( dbg!(&budget_goal_activities); dbg!(&calendar); - let activities: Vec = [ + let mut activities: Vec = [ simple_goal_activities, simple_filler_activities, budget_goal_activities, ] .concat(); - activity_placer::place(&mut calendar, activities); + activities = activity_placer::place(&mut calendar, activities) + .expect("should get activities back from placer"); calendar.log_impossible_min_day_budgets(); @@ -133,5 +134,7 @@ pub fn run_scheduler( activity_placer::place(&mut calendar, top_up_week_budget_activities); //TODO: Test that day stays below min or max when week max being reachd + calendar.log_impossible_simple_activities(activities); + calendar.print() } diff --git a/src/models/activity.rs b/src/models/activity.rs index 9e0a53eb..4befc3f1 100644 --- a/src/models/activity.rs +++ b/src/models/activity.rs @@ -25,6 +25,7 @@ pub struct Activity { pub total_duration: usize, pub duration_left: usize, pub status: Status, + pub deadline: NaiveDateTime, } impl Activity { pub fn get_compatible_hours_overlay( @@ -220,6 +221,7 @@ impl Activity { total_duration: activity_total_duration, duration_left: activity_total_duration, status: Status::Unprocessed, + deadline: goal.deadline, }; dbg!(&activity); activities.push(activity); @@ -286,6 +288,7 @@ impl Activity { total_duration: adjusted_min_block_size, duration_left: config.min_per_day, status: Status::Unprocessed, + deadline: goal.deadline, }; dbg!(&activity); activities.push(activity); @@ -328,6 +331,7 @@ impl Activity { total_duration: max_hours, duration_left: max_hours, status: Status::Unprocessed, + deadline: goal_to_use.deadline, }); activities @@ -367,6 +371,7 @@ impl Activity { total_duration: max_hours, duration_left: max_hours, status: Status::Unprocessed, + deadline: goal_to_use.deadline, }); activities @@ -518,6 +523,7 @@ impl Activity { total_duration: activity_total_duration, duration_left: activity_total_duration, status: Status::Unprocessed, + deadline: goal.deadline, }; dbg!(&activity); activities.push(activity); diff --git a/src/models/calendar.rs b/src/models/calendar.rs index b982b18d..0a91579d 100644 --- a/src/models/calendar.rs +++ b/src/models/calendar.rs @@ -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}; @@ -294,6 +295,21 @@ impl Calendar { self.impossible_activities.extend(impossible_activities); } + pub fn log_impossible_simple_activities(&mut self, activities: Vec) { + 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 { let mut impossible_activities = vec![]; for budget in &self.budgets { diff --git a/src/services/activity_placer.rs b/src/services/activity_placer.rs index 2a78fb39..4ad2cde0 100644 --- a/src/services/activity_placer.rs +++ b/src/services/activity_placer.rs @@ -5,7 +5,7 @@ use crate::models::{ calendar::{Calendar, Hour, ImpossibleActivity}, }; -pub fn place(calendar: &mut Calendar, mut activities: Vec) -> Option<()> { +pub fn place(calendar: &mut Calendar, mut activities: Vec) -> Option> { loop { for activity in activities.iter_mut() { activity.update_overlay_with(&calendar.budgets); @@ -79,7 +79,7 @@ pub fn place(calendar: &mut Calendar, mut activities: Vec) -> Option<( dbg!(&calendar); } dbg!(&calendar); - Some(()) + Some(activities) } fn find_act_index_to_schedule(activities: &[Activity]) -> Option { diff --git a/tests/jsons/stable/simple-without-deadline/observed.json b/tests/jsons/stable/simple-without-deadline/observed.json index 0d5865ba..ed41143d 100644 --- a/tests/jsons/stable/simple-without-deadline/observed.json +++ b/tests/jsons/stable/simple-without-deadline/observed.json @@ -22,5 +22,12 @@ ] } ], - "impossible": [] + "impossible": [ + { + "id": "3", + "hoursMissing": 1, + "periodStartDateTime": "2022-01-01T00:00:00", + "periodEndDateTime": "2022-01-02T00:00:00" + } + ] } \ No newline at end of file From 07ed918e7751e52f425f2562efaf9b6ed6e590de Mon Sep 17 00:00:00 2001 From: Tijl Leenders Date: Fri, 22 Mar 2024 15:04:22 +0100 Subject: [PATCH 06/29] place simple activities without deadline last? --- src/lib.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index a505f971..c59dd932 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -52,6 +52,7 @@ //! ZinZen® trademark is a tool to protect the ZinZen® identity and the //! quality perception of the ZinZen® projects. +use chrono::Datelike; use chrono::NaiveDateTime; use models::{activity::Activity, calendar::Calendar, goal::Goal, task::FinalTasks}; use serde_wasm_bindgen::{from_value, to_value}; @@ -95,10 +96,18 @@ pub fn run_scheduler( calendar.add_budgets_from(goals); //generate and place simple goal activities - let simple_goal_activities = + let mut simple_goal_activities = activity_generator::generate_simple_goal_activities(&calendar, goals); dbg!(&simple_goal_activities); + let mut simple_goal_activities_without_deadline: Vec = vec![]; + for activity in simple_goal_activities.iter() { + if activity.deadline.year() == 1970 { + simple_goal_activities_without_deadline.push(activity.clone()); + } + } + simple_goal_activities.retain(|a| a.deadline.year() != 1970); + let simple_filler_activities = activity_generator::generate_simple_filler_goal_activities(&calendar, goals); dbg!(&simple_filler_activities); @@ -136,5 +145,7 @@ pub fn run_scheduler( calendar.log_impossible_simple_activities(activities); + _ = activity_placer::place(&mut calendar, simple_goal_activities_without_deadline); + calendar.print() } From 600fed77d7b083d66c1a71d4f0ba88f9aa9bd784 Mon Sep 17 00:00:00 2001 From: Tijl Leenders Date: Fri, 22 Mar 2024 15:53:35 +0100 Subject: [PATCH 07/29] check that order shouldn't matter --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index c59dd932..59212e32 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -143,9 +143,9 @@ pub fn run_scheduler( activity_placer::place(&mut calendar, top_up_week_budget_activities); //TODO: Test that day stays below min or max when week max being reachd - calendar.log_impossible_simple_activities(activities); - _ = activity_placer::place(&mut calendar, simple_goal_activities_without_deadline); + calendar.log_impossible_simple_activities(activities); + calendar.print() } From a24b18f78055aa34d920cbdf46d6fce2e6791ec5 Mon Sep 17 00:00:00 2001 From: Tijl Leenders Date: Sat, 23 Mar 2024 06:07:22 +0100 Subject: [PATCH 08/29] add ActivityType SimpleFiller --- src/models/activity.rs | 9 +++++++-- src/models/budget.rs | 1 + src/models/calendar.rs | 9 +++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/models/activity.rs b/src/models/activity.rs index 4befc3f1..4ee49764 100644 --- a/src/models/activity.rs +++ b/src/models/activity.rs @@ -142,6 +142,7 @@ impl Activity { ActivityType::Budget => 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] { @@ -184,7 +185,10 @@ impl Activity { calendar: &Calendar, parent_goal: Option, ) -> Vec { - if goal.children.is_some() || goal.filters.as_ref().is_some() { + if goal.children.is_some() + || goal.filters.as_ref().is_some() + || calendar.is_budget(goal.id.clone()) + { return vec![]; } @@ -514,7 +518,7 @@ 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, @@ -547,6 +551,7 @@ pub enum ActivityType { Budget, GetToMinWeekBudget, TopUpWeekBudget, + SimpleFiller, } impl fmt::Debug for Activity { diff --git a/src/models/budget.rs b/src/models/budget.rs index 80f4852d..49df3973 100644 --- a/src/models/budget.rs +++ b/src/models/budget.rs @@ -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; diff --git a/src/models/calendar.rs b/src/models/calendar.rs index 0a91579d..0174f811 100644 --- a/src/models/calendar.rs +++ b/src/models/calendar.rs @@ -71,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)) From 9eb44390473f2ef5f11a30c3a573fef46d6b9a29 Mon Sep 17 00:00:00 2001 From: Tijl Leenders Date: Sat, 23 Mar 2024 06:17:19 +0100 Subject: [PATCH 09/29] extract method to clean up run_scheduler --- src/lib.rs | 34 ++---------------------------- src/services/activity_generator.rs | 31 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 32 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 59212e32..7ef49edf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -52,9 +52,8 @@ //! ZinZen® trademark is a tool to protect the ZinZen® identity and the //! quality perception of the ZinZen® projects. -use chrono::Datelike; 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; @@ -95,35 +94,8 @@ pub fn run_scheduler( calendar.add_budgets_from(goals); - //generate and place simple goal activities - let mut simple_goal_activities = - activity_generator::generate_simple_goal_activities(&calendar, goals); - dbg!(&simple_goal_activities); + let mut activities = activity_generator::generate_activities(&calendar, goals); - let mut simple_goal_activities_without_deadline: Vec = vec![]; - for activity in simple_goal_activities.iter() { - if activity.deadline.year() == 1970 { - simple_goal_activities_without_deadline.push(activity.clone()); - } - } - simple_goal_activities.retain(|a| a.deadline.year() != 1970); - - 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_generator::generate_budget_goal_activities(&calendar, goals); - dbg!(&budget_goal_activities); - dbg!(&calendar); - - let mut activities: Vec = [ - simple_goal_activities, - simple_filler_activities, - budget_goal_activities, - ] - .concat(); activities = activity_placer::place(&mut calendar, activities) .expect("should get activities back from placer"); @@ -143,8 +115,6 @@ pub fn run_scheduler( activity_placer::place(&mut calendar, top_up_week_budget_activities); //TODO: Test that day stays below min or max when week max being reachd - _ = activity_placer::place(&mut calendar, simple_goal_activities_without_deadline); - calendar.log_impossible_simple_activities(activities); calendar.print() diff --git a/src/services/activity_generator.rs b/src/services/activity_generator.rs index d772fab2..966d07c2 100644 --- a/src/services/activity_generator.rs +++ b/src/services/activity_generator.rs @@ -1,4 +1,5 @@ use crate::models::{activity::Activity, budget::TimeBudgetType, calendar::Calendar, goal::Goal}; +use chrono::Datelike; pub fn generate_simple_goal_activities(calendar: &Calendar, goals: &[Goal]) -> Vec { goals @@ -115,3 +116,33 @@ pub fn generate_top_up_week_budget_activities( dbg!(&top_up_activities); top_up_activities } + +pub(crate) fn generate_activities(calendar: &Calendar, goals: &[Goal]) -> Vec { + //generate and place simple goal activities + let mut simple_goal_activities = generate_simple_goal_activities(&calendar, goals); + dbg!(&simple_goal_activities); + + let mut simple_goal_activities_without_deadline: Vec = vec![]; + for activity in simple_goal_activities.iter() { + if activity.deadline.year() == 1970 { + simple_goal_activities_without_deadline.push(activity.clone()); + } + } + simple_goal_activities.retain(|a| a.deadline.year() != 1970); + + let simple_filler_activities = generate_simple_filler_goal_activities(&calendar, goals); + dbg!(&simple_filler_activities); + + //generate and place budget goal activities + let budget_goal_activities: Vec = generate_budget_goal_activities(&calendar, goals); + dbg!(&budget_goal_activities); + dbg!(&calendar); + + [ + simple_goal_activities, + simple_filler_activities, + budget_goal_activities, + simple_goal_activities_without_deadline, + ] + .concat() +} From 33ea74f03eea71eb2c61093ef44698cb1530aa0d Mon Sep 17 00:00:00 2001 From: Tijl Leenders Date: Sat, 23 Mar 2024 06:21:33 +0100 Subject: [PATCH 10/29] clean up verbosity from unnecessary option --- src/lib.rs | 8 +++----- src/services/activity_generator.rs | 7 ++++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 7ef49edf..a02df4b6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -101,11 +101,9 @@ pub fn run_scheduler( 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::generate_get_to_week_min_budget_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(); diff --git a/src/services/activity_generator.rs b/src/services/activity_generator.rs index 966d07c2..01dce0f2 100644 --- a/src/services/activity_generator.rs +++ b/src/services/activity_generator.rs @@ -51,7 +51,7 @@ pub fn generate_budget_goal_activities(calendar: &Calendar, goals: &[Goal]) -> V pub fn generate_get_to_week_min_budget_activities( calendar: &Calendar, goals: &[Goal], -) -> Option> { +) -> Vec { let mut get_to_week_min_budget_activities = vec![]; for budget in &calendar.budgets { let mut is_min_week_reached = true; @@ -71,7 +71,8 @@ pub fn generate_get_to_week_min_budget_activities( } else { let goal_to_use: &Goal = goals .iter() - .find(|g| g.id.eq(&budget.originating_goal_id))?; + .find(|g| g.id.eq(&budget.originating_goal_id)) + .unwrap(); for time_budget in &budget.time_budgets { if time_budget.time_budget_type == TimeBudgetType::Day && time_budget.scheduled == time_budget.min_scheduled @@ -89,7 +90,7 @@ pub fn generate_get_to_week_min_budget_activities( } } dbg!(&get_to_week_min_budget_activities); - Some(get_to_week_min_budget_activities) + get_to_week_min_budget_activities } pub fn generate_top_up_week_budget_activities( From ad542b01a22224eed245462adb71bfcb00aabad2 Mon Sep 17 00:00:00 2001 From: Tijl Leenders Date: Sat, 23 Mar 2024 06:39:41 +0100 Subject: [PATCH 11/29] clippy needless borrow --- src/services/activity_generator.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/services/activity_generator.rs b/src/services/activity_generator.rs index 01dce0f2..7a7c639d 100644 --- a/src/services/activity_generator.rs +++ b/src/services/activity_generator.rs @@ -120,7 +120,7 @@ pub fn generate_top_up_week_budget_activities( pub(crate) fn generate_activities(calendar: &Calendar, goals: &[Goal]) -> Vec { //generate and place simple goal activities - let mut simple_goal_activities = generate_simple_goal_activities(&calendar, goals); + let mut simple_goal_activities = generate_simple_goal_activities(calendar, goals); dbg!(&simple_goal_activities); let mut simple_goal_activities_without_deadline: Vec = vec![]; @@ -131,11 +131,11 @@ pub(crate) fn generate_activities(calendar: &Calendar, goals: &[Goal]) -> Vec = generate_budget_goal_activities(&calendar, goals); + let budget_goal_activities: Vec = generate_budget_goal_activities(calendar, goals); dbg!(&budget_goal_activities); dbg!(&calendar); From e643e82a19ebd8eda6f9afbfe04f13e945b97bf0 Mon Sep 17 00:00:00 2001 From: Tijl Leenders Date: Sat, 23 Mar 2024 06:40:34 +0100 Subject: [PATCH 12/29] rename ActivityType to BudgetMinDay --- src/models/activity.rs | 6 +++--- src/models/budget.rs | 2 +- src/services/activity_placer.rs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/models/activity.rs b/src/models/activity.rs index 4ee49764..48aecb95 100644 --- a/src/models/activity.rs +++ b/src/models/activity.rs @@ -139,7 +139,7 @@ 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, @@ -283,7 +283,7 @@ 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, @@ -548,7 +548,7 @@ pub enum Status { #[derive(Clone, Debug, PartialEq)] pub enum ActivityType { SimpleGoal, - Budget, + BudgetMinDay, GetToMinWeekBudget, TopUpWeekBudget, SimpleFiller, diff --git a/src/models/budget.rs b/src/models/budget.rs index 49df3973..85221b1d 100644 --- a/src/models/budget.rs +++ b/src/models/budget.rs @@ -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 => { diff --git a/src/services/activity_placer.rs b/src/services/activity_placer.rs index 4ad2cde0..c98c1320 100644 --- a/src/services/activity_placer.rs +++ b/src/services/activity_placer.rs @@ -41,7 +41,7 @@ pub fn place(calendar: &mut Calendar, mut activities: Vec) -> Option Date: Sat, 23 Mar 2024 07:23:45 +0100 Subject: [PATCH 13/29] stub parallel function --- src/services/activity_generator.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/services/activity_generator.rs b/src/services/activity_generator.rs index 7a7c639d..65c4e1e5 100644 --- a/src/services/activity_generator.rs +++ b/src/services/activity_generator.rs @@ -118,6 +118,24 @@ pub fn generate_top_up_week_budget_activities( top_up_activities } +pub(crate) fn gen_activities(calendar: &Calendar, goals: &[Goal]) -> Vec { + let mut activities: Vec = vec![]; + // for goal in goals { + // if goal.children.is_none() { + // if goal.budget_config.is_some() { + // activities.append(&mut Activity::get_activities_from_budget_goal( + // goal, calendar, + // )); + // } else { + // activities.append(&mut Activity::get_activities_from_simple_goal( + // goal, calendar, + // )); + // } + // } + // } + activities +} + pub(crate) fn generate_activities(calendar: &Calendar, goals: &[Goal]) -> Vec { //generate and place simple goal activities let mut simple_goal_activities = generate_simple_goal_activities(calendar, goals); From ca94089abba72026f729fc5a322825e0959e8bed Mon Sep 17 00:00:00 2001 From: Tijl Leenders Date: Sat, 23 Mar 2024 07:28:26 +0100 Subject: [PATCH 14/29] assume start/deadline consistent in tree --- src/models/activity.rs | 11 +++-------- src/models/goal.rs | 18 +----------------- src/services/activity_generator.rs | 12 ++---------- 3 files changed, 6 insertions(+), 35 deletions(-) diff --git a/src/models/activity.rs b/src/models/activity.rs index 48aecb95..22fdbab0 100644 --- a/src/models/activity.rs +++ b/src/models/activity.rs @@ -183,7 +183,6 @@ impl Activity { pub(crate) fn get_activities_from_simple_goal( goal: &Goal, calendar: &Calendar, - parent_goal: Option, ) -> Vec { if goal.children.is_some() || goal.filters.as_ref().is_some() @@ -192,8 +191,7 @@ impl Activity { 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 = Vec::with_capacity(1); if let Some(activity_total_duration) = goal.min_duration { @@ -246,8 +244,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 = Vec::with_capacity(1); for day in 0..(adjusted_goal_deadline - adjusted_goal_start).num_days() as u64 { @@ -489,13 +486,11 @@ impl Activity { pub(crate) fn get_filler_activities_from_simple_goal( goal: &Goal, calendar: &Calendar, - parent_goal: Option, ) -> Vec { 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 = Vec::with_capacity(1); if let Some(activity_total_duration) = goal.min_duration { diff --git a/src/models/goal.rs b/src/models/goal.rs index e4b71ec7..3bb3ebb3 100644 --- a/src/models/goal.rs +++ b/src/models/goal.rs @@ -46,11 +46,7 @@ pub struct BudgetConfig { } impl Goal { - pub fn get_adj_start_deadline( - &self, - calendar: &Calendar, - parent_goal: Option, - ) -> (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; @@ -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); } diff --git a/src/services/activity_generator.rs b/src/services/activity_generator.rs index 65c4e1e5..b089dd28 100644 --- a/src/services/activity_generator.rs +++ b/src/services/activity_generator.rs @@ -4,9 +4,7 @@ use chrono::Datelike; pub fn generate_simple_goal_activities(calendar: &Calendar, goals: &[Goal]) -> Vec { goals .iter() - .flat_map(|goal| { - Activity::get_activities_from_simple_goal(goal, calendar, goal.get_parent_goal(goals)) - }) + .flat_map(|goal| Activity::get_activities_from_simple_goal(goal, calendar)) .collect::>() } @@ -16,13 +14,7 @@ pub fn generate_simple_filler_goal_activities( ) -> Vec { let mut activities = goals .iter() - .flat_map(|goal| { - Activity::get_filler_activities_from_simple_goal( - goal, - calendar, - goal.get_parent_goal(goals), - ) - }) + .flat_map(|goal| Activity::get_filler_activities_from_simple_goal(goal, calendar)) .collect::>(); for activity in &mut activities { if let Some(goal) = goals.iter().find(|g| g.id == activity.goal_id) { From bdd3c1603a27ff454dda369188260fde01a524fa Mon Sep 17 00:00:00 2001 From: Tijl Leenders Date: Sat, 23 Mar 2024 07:28:34 +0100 Subject: [PATCH 15/29] fix input --- tests/jsons/stable/filler-goal/input.json | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/jsons/stable/filler-goal/input.json b/tests/jsons/stable/filler-goal/input.json index 5ef06346..d63c5131 100644 --- a/tests/jsons/stable/filler-goal/input.json +++ b/tests/jsons/stable/filler-goal/input.json @@ -16,12 +16,16 @@ { "id": "2", "title": "Buy stuff", - "minDuration": 1 + "minDuration": 1, + "start": "2022-01-01T10:00:00", + "deadline": "2022-01-01T18:00:00" }, { "id": "3", "title": "Invite friends", - "minDuration": 1 + "minDuration": 1, + "start": "2022-01-01T10:00:00", + "deadline": "2022-01-01T18:00:00" } ] } \ No newline at end of file From 096a85120555d342f54ccc17ac7f90de216bd457 Mon Sep 17 00:00:00 2001 From: Tijl Leenders Date: Sat, 23 Mar 2024 07:41:23 +0100 Subject: [PATCH 16/29] gen_activities and generate_activities identical result --- src/lib.rs | 2 +- src/services/activity_generator.rs | 44 +++++++++++++++++++++--------- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a02df4b6..b0d5a1f8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -94,7 +94,7 @@ pub fn run_scheduler( calendar.add_budgets_from(goals); - let mut activities = activity_generator::generate_activities(&calendar, goals); + let mut activities = activity_generator::gen_activities(&calendar, goals); activities = activity_placer::place(&mut calendar, activities) .expect("should get activities back from placer"); diff --git a/src/services/activity_generator.rs b/src/services/activity_generator.rs index b089dd28..ae06eb92 100644 --- a/src/services/activity_generator.rs +++ b/src/services/activity_generator.rs @@ -112,19 +112,37 @@ pub fn generate_top_up_week_budget_activities( pub(crate) fn gen_activities(calendar: &Calendar, goals: &[Goal]) -> Vec { let mut activities: Vec = vec![]; - // for goal in goals { - // if goal.children.is_none() { - // if goal.budget_config.is_some() { - // activities.append(&mut Activity::get_activities_from_budget_goal( - // goal, calendar, - // )); - // } else { - // activities.append(&mut Activity::get_activities_from_simple_goal( - // goal, calendar, - // )); - // } - // } - // } + for goal in goals { + if goal.children.is_none() { + if goal.budget_config.is_some() { + activities.append(&mut Activity::get_activities_from_budget_goal( + goal, calendar, + )); + } else { + activities.append(&mut Activity::get_activities_from_simple_goal( + goal, calendar, + )); + } + } else if goal.budget_config.is_none() { + let mut temp_activities = + Activity::get_filler_activities_from_simple_goal(goal, calendar); + for activity in &mut temp_activities { + if let Some(goal) = goals.iter().find(|g| g.id == activity.goal_id) { + let children: Vec<&Goal> = goals + .iter() + .filter(|child| goal.children.clone().unwrap().contains(&child.id)) + .collect(); + for c in children { + activity.min_block_size -= c.min_duration.unwrap(); + activity.max_block_size -= c.min_duration.unwrap(); + activity.total_duration -= c.min_duration.unwrap(); + activity.duration_left -= c.min_duration.unwrap(); + } + } + } + activities.append(&mut temp_activities); + } + } activities } From 8c2b926c90a71a16f20c1ce8131d509eadfddafa Mon Sep 17 00:00:00 2001 From: Tijl Leenders Date: Sat, 23 Mar 2024 08:06:47 +0100 Subject: [PATCH 17/29] remove unnecessary option handling --- src/lib.rs | 3 +- src/services/activity_placer.rs | 133 ++++++++++++++++---------------- 2 files changed, 68 insertions(+), 68 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index b0d5a1f8..ad653a1f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -96,8 +96,7 @@ pub fn run_scheduler( let mut activities = activity_generator::gen_activities(&calendar, goals); - activities = activity_placer::place(&mut calendar, activities) - .expect("should get activities back from placer"); + activities = activity_placer::place(&mut calendar, activities); calendar.log_impossible_min_day_budgets(); diff --git a/src/services/activity_placer.rs b/src/services/activity_placer.rs index c98c1320..e609fdcd 100644 --- a/src/services/activity_placer.rs +++ b/src/services/activity_placer.rs @@ -5,81 +5,82 @@ use crate::models::{ calendar::{Calendar, Hour, ImpossibleActivity}, }; -pub fn place(calendar: &mut Calendar, mut activities: Vec) -> Option> { +pub fn place(calendar: &mut Calendar, mut activities: Vec) -> Vec { loop { for activity in activities.iter_mut() { activity.update_overlay_with(&calendar.budgets); } - let act_index_to_schedule = find_act_index_to_schedule(&activities); - if act_index_to_schedule.is_none() { - println!("Tried to schedule activity index None"); - break; - } - if activities[act_index_to_schedule?].goal_id.len() > 5 { - println!( - "Next to schedule: {:?} {:?}", - &activities[act_index_to_schedule?].title, - &activities[act_index_to_schedule?].goal_id[0..5] - ); - } else { - println!( - "Next to schedule: {:?} {:?}", - &activities[act_index_to_schedule?].title, - &activities[act_index_to_schedule?].goal_id - ); - } - let best_hour_index_and_size: Option<(usize, usize)> = - activities[act_index_to_schedule?].get_best_scheduling_index_and_length(); - let best_hour_index: usize; - let best_size: usize; - if best_hour_index_and_size.is_some() { - best_hour_index = best_hour_index_and_size?.0; - best_size = best_hour_index_and_size?.1; - println!( - "Best index:{:?} and size {:?}", - &best_hour_index, &best_size - ); - } else { - activities[act_index_to_schedule?].release_claims(); - if activities[act_index_to_schedule?].activity_type == ActivityType::BudgetMinDay { - activities[act_index_to_schedule?].status = Status::Processed; - continue; + if let Some(act_index_to_schedule) = find_act_index_to_schedule(&activities) { + if activities[act_index_to_schedule].goal_id.len() > 5 { + println!( + "Next to schedule: {:?} {:?}", + &activities[act_index_to_schedule].title, + &activities[act_index_to_schedule].goal_id[0..5] + ); } else { - activities[act_index_to_schedule?].status = Status::Impossible; + println!( + "Next to schedule: {:?} {:?}", + &activities[act_index_to_schedule].title, + &activities[act_index_to_schedule].goal_id + ); + } + let best_hour_index_and_size: Option<(usize, usize)> = + activities[act_index_to_schedule].get_best_scheduling_index_and_length(); + let best_hour_index: usize; + let best_size: usize; + if let Some(best_hour_index_and_size) = best_hour_index_and_size { + best_hour_index = best_hour_index_and_size.0; + best_size = best_hour_index_and_size.1; + println!( + "Best index:{:?} and size {:?}", + &best_hour_index, &best_size + ); + } else { + activities[act_index_to_schedule].release_claims(); + if activities[act_index_to_schedule].activity_type == ActivityType::BudgetMinDay { + activities[act_index_to_schedule].status = Status::Processed; + continue; + } else { + activities[act_index_to_schedule].status = Status::Impossible; + } + let impossible_activity = ImpossibleActivity { + id: activities[act_index_to_schedule].goal_id.clone(), + hours_missing: activities[act_index_to_schedule].duration_left, + period_start_date_time: calendar.start_date_time, + period_end_date_time: calendar.end_date_time, + }; + calendar.impossible_activities.push(impossible_activity); + continue; } - let impossible_activity = ImpossibleActivity { - id: activities[act_index_to_schedule?].goal_id.clone(), - hours_missing: activities[act_index_to_schedule?].duration_left, - period_start_date_time: calendar.start_date_time, - period_end_date_time: calendar.end_date_time, - }; - calendar.impossible_activities.push(impossible_activity); - continue; - } - println!("reserving {:?} hours...", best_size); - for duration_offset in 0..best_size { - Rc::make_mut(&mut calendar.hours[best_hour_index + duration_offset]); - calendar.hours[best_hour_index + duration_offset] = Rc::new(Hour::Occupied { - activity_index: act_index_to_schedule?, - activity_title: activities[act_index_to_schedule?].title.clone(), - activity_goalid: activities[act_index_to_schedule?].goal_id.clone(), - }); - //TODO: activity doesn't need to know about time_budets => remove completely - calendar.update_budgets_for( - &activities[act_index_to_schedule?].goal_id.clone(), - best_hour_index + duration_offset, - ); - activities[act_index_to_schedule?].duration_left -= 1; - } - if activities[act_index_to_schedule?].duration_left == 0 { - activities[act_index_to_schedule?].status = Status::Scheduled; - (activities[act_index_to_schedule?]).release_claims(); - } - dbg!(&calendar); + println!("reserving {:?} hours...", best_size); + for duration_offset in 0..best_size { + Rc::make_mut(&mut calendar.hours[best_hour_index + duration_offset]); + calendar.hours[best_hour_index + duration_offset] = Rc::new(Hour::Occupied { + activity_index: act_index_to_schedule, + activity_title: activities[act_index_to_schedule].title.clone(), + activity_goalid: activities[act_index_to_schedule].goal_id.clone(), + }); + //TODO: activity doesn't need to know about time_budets => remove completely + calendar.update_budgets_for( + &activities[act_index_to_schedule].goal_id.clone(), + best_hour_index + duration_offset, + ); + activities[act_index_to_schedule].duration_left -= 1; + } + if activities[act_index_to_schedule].duration_left == 0 { + activities[act_index_to_schedule].status = Status::Scheduled; + (activities[act_index_to_schedule]).release_claims(); + } + + dbg!(&calendar); + } else { + println!("Tried to schedule activity index None"); + break; + } } dbg!(&calendar); - Some(activities) + activities } fn find_act_index_to_schedule(activities: &[Activity]) -> Option { From 88b474489b14e3f1f2f6a32be51f3d2377886187 Mon Sep 17 00:00:00 2001 From: Tijl Leenders Date: Sat, 23 Mar 2024 08:16:03 +0100 Subject: [PATCH 18/29] no need to look for goal --- src/services/activity_generator.rs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/services/activity_generator.rs b/src/services/activity_generator.rs index ae06eb92..dc87dd25 100644 --- a/src/services/activity_generator.rs +++ b/src/services/activity_generator.rs @@ -127,17 +127,15 @@ pub(crate) fn gen_activities(calendar: &Calendar, goals: &[Goal]) -> Vec = goals - .iter() - .filter(|child| goal.children.clone().unwrap().contains(&child.id)) - .collect(); - for c in children { - activity.min_block_size -= c.min_duration.unwrap(); - activity.max_block_size -= c.min_duration.unwrap(); - activity.total_duration -= c.min_duration.unwrap(); - activity.duration_left -= c.min_duration.unwrap(); - } + let children: Vec<&Goal> = goals + .iter() + .filter(|child| goal.children.clone().unwrap().contains(&child.id)) + .collect(); + for c in children { + activity.min_block_size -= c.min_duration.unwrap(); + activity.max_block_size -= c.min_duration.unwrap(); + activity.total_duration -= c.min_duration.unwrap(); + activity.duration_left -= c.min_duration.unwrap(); } } activities.append(&mut temp_activities); From 0483b4885e110175a3a894ba6efbcb524a1e6f7f Mon Sep 17 00:00:00 2001 From: Tijl Leenders Date: Sat, 23 Mar 2024 08:19:13 +0100 Subject: [PATCH 19/29] imrpove naming --- src/lib.rs | 8 ++++---- src/services/activity_generator.rs | 7 ++----- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index ad653a1f..6de851e6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -94,14 +94,14 @@ pub fn run_scheduler( calendar.add_budgets_from(goals); - let mut activities = activity_generator::gen_activities(&calendar, goals); + let mut base_activities = activity_generator::get_base_activities(&calendar, goals); - activities = activity_placer::place(&mut calendar, activities); + base_activities = activity_placer::place(&mut calendar, base_activities); calendar.log_impossible_min_day_budgets(); let get_to_week_min_budget_activities = - activity_generator::generate_get_to_week_min_budget_activities(&calendar, goals); + 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 @@ -112,7 +112,7 @@ pub fn run_scheduler( activity_placer::place(&mut calendar, top_up_week_budget_activities); //TODO: Test that day stays below min or max when week max being reachd - calendar.log_impossible_simple_activities(activities); + calendar.log_impossible_simple_activities(base_activities); calendar.print() } diff --git a/src/services/activity_generator.rs b/src/services/activity_generator.rs index dc87dd25..65c8e405 100644 --- a/src/services/activity_generator.rs +++ b/src/services/activity_generator.rs @@ -40,10 +40,7 @@ pub fn generate_budget_goal_activities(calendar: &Calendar, goals: &[Goal]) -> V .collect::>() } -pub fn generate_get_to_week_min_budget_activities( - calendar: &Calendar, - goals: &[Goal], -) -> Vec { +pub fn get_budget_min_week_activities(calendar: &Calendar, goals: &[Goal]) -> Vec { let mut get_to_week_min_budget_activities = vec![]; for budget in &calendar.budgets { let mut is_min_week_reached = true; @@ -110,7 +107,7 @@ pub fn generate_top_up_week_budget_activities( top_up_activities } -pub(crate) fn gen_activities(calendar: &Calendar, goals: &[Goal]) -> Vec { +pub(crate) fn get_base_activities(calendar: &Calendar, goals: &[Goal]) -> Vec { let mut activities: Vec = vec![]; for goal in goals { if goal.children.is_none() { From dee6eec74cd416f0e285da79e4d3aae14f9e490f Mon Sep 17 00:00:00 2001 From: Tijl Leenders Date: Sat, 23 Mar 2024 08:26:08 +0100 Subject: [PATCH 20/29] better names --- src/models/activity.rs | 15 +++------------ src/services/activity_generator.rs | 17 ++++++----------- 2 files changed, 9 insertions(+), 23 deletions(-) diff --git a/src/models/activity.rs b/src/models/activity.rs index 22fdbab0..f8327f40 100644 --- a/src/models/activity.rs +++ b/src/models/activity.rs @@ -180,10 +180,7 @@ 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, - ) -> Vec { + pub(crate) fn get_simple_activities(goal: &Goal, calendar: &Calendar) -> Vec { if goal.children.is_some() || goal.filters.as_ref().is_some() || calendar.is_budget(goal.id.clone()) @@ -232,10 +229,7 @@ impl Activity { activities } - pub(crate) fn get_activities_from_budget_goal( - goal: &Goal, - calendar: &Calendar, - ) -> Vec { + pub(crate) fn get_budget_min_day_activities(goal: &Goal, calendar: &Calendar) -> Vec { if goal.filters.as_ref().is_none() { return vec![]; } @@ -483,10 +477,7 @@ impl Activity { self.calendar_overlay = empty_overlay; } - pub(crate) fn get_filler_activities_from_simple_goal( - goal: &Goal, - calendar: &Calendar, - ) -> Vec { + pub(crate) fn get_simple_filler_activities(goal: &Goal, calendar: &Calendar) -> Vec { if goal.children.is_none() || goal.filters.as_ref().is_some() { return vec![]; } diff --git a/src/services/activity_generator.rs b/src/services/activity_generator.rs index 65c8e405..1b0fa21a 100644 --- a/src/services/activity_generator.rs +++ b/src/services/activity_generator.rs @@ -4,7 +4,7 @@ use chrono::Datelike; pub fn generate_simple_goal_activities(calendar: &Calendar, goals: &[Goal]) -> Vec { goals .iter() - .flat_map(|goal| Activity::get_activities_from_simple_goal(goal, calendar)) + .flat_map(|goal| Activity::get_simple_activities(goal, calendar)) .collect::>() } @@ -14,7 +14,7 @@ pub fn generate_simple_filler_goal_activities( ) -> Vec { let mut activities = goals .iter() - .flat_map(|goal| Activity::get_filler_activities_from_simple_goal(goal, calendar)) + .flat_map(|goal| Activity::get_simple_filler_activities(goal, calendar)) .collect::>(); for activity in &mut activities { if let Some(goal) = goals.iter().find(|g| g.id == activity.goal_id) { @@ -36,7 +36,7 @@ pub fn generate_simple_filler_goal_activities( pub fn generate_budget_goal_activities(calendar: &Calendar, goals: &[Goal]) -> Vec { goals .iter() - .flat_map(|goal| Activity::get_activities_from_budget_goal(goal, calendar)) + .flat_map(|goal| Activity::get_budget_min_day_activities(goal, calendar)) .collect::>() } @@ -112,17 +112,12 @@ pub(crate) fn get_base_activities(calendar: &Calendar, goals: &[Goal]) -> Vec = goals .iter() From ab595bf331c4e9770cfe19773462309c772d13a8 Mon Sep 17 00:00:00 2001 From: Tijl Leenders Date: Sat, 23 Mar 2024 08:28:17 +0100 Subject: [PATCH 21/29] better names --- src/lib.rs | 4 ++-- src/models/calendar.rs | 2 +- src/services/activity_generator.rs | 5 +---- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 6de851e6..1c0d3af1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -108,11 +108,11 @@ pub fn run_scheduler( 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 - calendar.log_impossible_simple_activities(base_activities); + calendar.log_impossible_base_activities(base_activities); calendar.print() } diff --git a/src/models/calendar.rs b/src/models/calendar.rs index 0174f811..c2e25384 100644 --- a/src/models/calendar.rs +++ b/src/models/calendar.rs @@ -304,7 +304,7 @@ impl Calendar { self.impossible_activities.extend(impossible_activities); } - pub fn log_impossible_simple_activities(&mut self, activities: Vec) { + pub fn log_impossible_base_activities(&mut self, activities: Vec) { for activity in activities { if activity.status == super::activity::Status::Impossible && activity.deadline.year() != 1970 diff --git a/src/services/activity_generator.rs b/src/services/activity_generator.rs index 1b0fa21a..adb1a175 100644 --- a/src/services/activity_generator.rs +++ b/src/services/activity_generator.rs @@ -82,10 +82,7 @@ pub fn get_budget_min_week_activities(calendar: &Calendar, goals: &[Goal]) -> Ve get_to_week_min_budget_activities } -pub fn generate_top_up_week_budget_activities( - calendar: &Calendar, - goals: &[Goal], -) -> Vec { +pub fn get_budget_top_up_week_activities(calendar: &Calendar, goals: &[Goal]) -> Vec { let mut top_up_activities = vec![]; for budget in &calendar.budgets { if let Some(goal_to_use) = goals.iter().find(|g| g.id.eq(&budget.originating_goal_id)) { From 877e3e54b5917017e2b03f22c48d6d7f46cad176 Mon Sep 17 00:00:00 2001 From: Tijl Leenders Date: Sat, 23 Mar 2024 08:44:10 +0100 Subject: [PATCH 22/29] remove refactored function --- src/models/activity.rs | 1 + src/services/activity_generator.rs | 31 ------------------------------ 2 files changed, 1 insertion(+), 31 deletions(-) diff --git a/src/models/activity.rs b/src/models/activity.rs index f8327f40..c96157e0 100644 --- a/src/models/activity.rs +++ b/src/models/activity.rs @@ -468,6 +468,7 @@ impl Activity { self.status = Status::Impossible; } } + pub(crate) fn release_claims(&mut self) { let mut empty_overlay: Vec>> = Vec::with_capacity(self.calendar_overlay.capacity()); diff --git a/src/services/activity_generator.rs b/src/services/activity_generator.rs index adb1a175..aa831af3 100644 --- a/src/services/activity_generator.rs +++ b/src/services/activity_generator.rs @@ -1,5 +1,4 @@ use crate::models::{activity::Activity, budget::TimeBudgetType, calendar::Calendar, goal::Goal}; -use chrono::Datelike; pub fn generate_simple_goal_activities(calendar: &Calendar, goals: &[Goal]) -> Vec { goals @@ -132,33 +131,3 @@ pub(crate) fn get_base_activities(calendar: &Calendar, goals: &[Goal]) -> Vec Vec { - //generate and place simple goal activities - let mut simple_goal_activities = generate_simple_goal_activities(calendar, goals); - dbg!(&simple_goal_activities); - - let mut simple_goal_activities_without_deadline: Vec = vec![]; - for activity in simple_goal_activities.iter() { - if activity.deadline.year() == 1970 { - simple_goal_activities_without_deadline.push(activity.clone()); - } - } - simple_goal_activities.retain(|a| a.deadline.year() != 1970); - - let simple_filler_activities = generate_simple_filler_goal_activities(calendar, goals); - dbg!(&simple_filler_activities); - - //generate and place budget goal activities - let budget_goal_activities: Vec = generate_budget_goal_activities(calendar, goals); - dbg!(&budget_goal_activities); - dbg!(&calendar); - - [ - simple_goal_activities, - simple_filler_activities, - budget_goal_activities, - simple_goal_activities_without_deadline, - ] - .concat() -} From 2c6ca0562be6a43b9ed21d9c87eef87f605302d9 Mon Sep 17 00:00:00 2001 From: Tijl Leenders Date: Sat, 23 Mar 2024 08:49:32 +0100 Subject: [PATCH 23/29] include BudgetMinDay in base_activities --- src/services/activity_generator.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/services/activity_generator.rs b/src/services/activity_generator.rs index aa831af3..e37e9479 100644 --- a/src/services/activity_generator.rs +++ b/src/services/activity_generator.rs @@ -127,6 +127,8 @@ pub(crate) fn get_base_activities(calendar: &Calendar, goals: &[Goal]) -> Vec Date: Sat, 23 Mar 2024 09:10:19 +0100 Subject: [PATCH 24/29] clear up if/else mess --- src/services/activity_generator.rs | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/services/activity_generator.rs b/src/services/activity_generator.rs index e37e9479..904ec786 100644 --- a/src/services/activity_generator.rs +++ b/src/services/activity_generator.rs @@ -106,13 +106,24 @@ pub fn get_budget_top_up_week_activities(calendar: &Calendar, goals: &[Goal]) -> pub(crate) fn get_base_activities(calendar: &Calendar, goals: &[Goal]) -> Vec { let mut activities: Vec = vec![]; for goal in goals { - if goal.children.is_none() { - if goal.budget_config.is_some() { - activities.append(&mut Activity::get_budget_min_day_activities(goal, calendar)); - } else { - activities.append(&mut Activity::get_simple_activities(goal, calendar)); - } - } else if goal.budget_config.is_none() { + //budget leaf + if goal.budget_config.is_some() && goal.children.is_none() { + activities.append(&mut Activity::get_budget_min_day_activities(goal, calendar)); + } + + //budget node => minDay + //TODO: or filler budget if children also budget?? + if goal.budget_config.is_some() && goal.children.is_some() { + activities.append(&mut Activity::get_budget_min_day_activities(goal, calendar)); + } + + //simple leaf + if goal.budget_config.is_none() && goal.children.is_none() { + activities.append(&mut Activity::get_simple_activities(goal, calendar)); + } + + //simple node => simple filler + if goal.budget_config.is_none() && goal.children.is_some() { let mut temp_activities = Activity::get_simple_filler_activities(goal, calendar); for activity in &mut temp_activities { let children: Vec<&Goal> = goals @@ -127,8 +138,6 @@ pub(crate) fn get_base_activities(calendar: &Calendar, goals: &[Goal]) -> Vec Date: Sat, 23 Mar 2024 09:22:05 +0100 Subject: [PATCH 25/29] remove unused time budgets --- src/models/activity.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/models/activity.rs b/src/models/activity.rs index c96157e0..efaa813f 100644 --- a/src/models/activity.rs +++ b/src/models/activity.rs @@ -21,7 +21,6 @@ pub struct Activity { pub min_block_size: usize, pub max_block_size: usize, pub calendar_overlay: Vec>>, - pub time_budgets: Vec, pub total_duration: usize, pub duration_left: usize, pub status: Status, @@ -216,7 +215,6 @@ 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, @@ -279,7 +277,6 @@ impl Activity { 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, @@ -322,7 +319,6 @@ 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, @@ -362,7 +358,6 @@ 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, @@ -510,7 +505,6 @@ 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, From f133b25191f9a884071bd54b894968bfeeb99cce Mon Sep 17 00:00:00 2001 From: Tijl Leenders Date: Sat, 23 Mar 2024 09:31:24 +0100 Subject: [PATCH 26/29] add todo --- src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 1c0d3af1..3a6f51e2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -112,6 +112,8 @@ pub fn run_scheduler( 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 + calendar.log_impossible_base_activities(base_activities); calendar.print() From 014218413e4299978a7d2d5093272e7e59dd628f Mon Sep 17 00:00:00 2001 From: Tijl Leenders Date: Sat, 23 Mar 2024 09:33:32 +0100 Subject: [PATCH 27/29] remove unnecessary check / fixes test --- src/models/activity.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/models/activity.rs b/src/models/activity.rs index efaa813f..5e6e2bd7 100644 --- a/src/models/activity.rs +++ b/src/models/activity.rs @@ -180,13 +180,6 @@ impl Activity { } pub(crate) fn get_simple_activities(goal: &Goal, calendar: &Calendar) -> Vec { - if goal.children.is_some() - || goal.filters.as_ref().is_some() - || calendar.is_budget(goal.id.clone()) - { - return vec![]; - } - let (adjusted_goal_start, adjusted_goal_deadline) = goal.get_adj_start_deadline(calendar); let mut activities: Vec = Vec::with_capacity(1); From 413994b66e3587658cca975c40b75f0e9aa9b258 Mon Sep 17 00:00:00 2001 From: Tijl Leenders Date: Sat, 23 Mar 2024 09:36:52 +0100 Subject: [PATCH 28/29] done todo --- src/services/activity_placer.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/services/activity_placer.rs b/src/services/activity_placer.rs index e609fdcd..2efa6606 100644 --- a/src/services/activity_placer.rs +++ b/src/services/activity_placer.rs @@ -61,7 +61,6 @@ pub fn place(calendar: &mut Calendar, mut activities: Vec) -> Vec remove completely calendar.update_budgets_for( &activities[act_index_to_schedule].goal_id.clone(), best_hour_index + duration_offset, From 52d34f35440b28ae50dd9fca0521bca181c0637a Mon Sep 17 00:00:00 2001 From: Tijl Leenders Date: Sat, 23 Mar 2024 09:46:42 +0100 Subject: [PATCH 29/29] add todo --- src/lib.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 3a6f51e2..a6f71dc7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -112,7 +112,11 @@ pub fn run_scheduler( 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 + //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);