From 3da0829b7216311a2c16acfc9850033d13ab3713 Mon Sep 17 00:00:00 2001 From: Alexander Senier Date: Thu, 21 Nov 2024 22:00:55 +0100 Subject: [PATCH] Use 7 day total for training/muscle set volume --- frontend/src/ui/common.rs | 7 ++- frontend/src/ui/data.rs | 93 ++++---------------------------- frontend/src/ui/page/muscles.rs | 41 +++++++------- frontend/src/ui/page/training.rs | 31 +++++------ 4 files changed, 52 insertions(+), 120 deletions(-) diff --git a/frontend/src/ui/common.rs b/frontend/src/ui/common.rs index 8c8e3ca..46982b7 100644 --- a/frontend/src/ui/common.rs +++ b/frontend/src/ui/common.rs @@ -39,6 +39,10 @@ pub fn plot_line_with_dots(color: usize) -> Vec { [PlotType::Line(color, 2), PlotType::Circle(color, 2)].to_vec() } +pub fn plot_line(color: usize) -> Vec { + [PlotType::Line(color, 2)].to_vec() +} + #[derive(Default)] pub struct PlotParams { pub y_min_opt: Option, @@ -1164,7 +1168,8 @@ pub fn centered_moving_grouping( .filter_map(|d| grouped.get(&d)) .copied() .collect::>(), - ).map(|result| (center, result)) + ) + .map(|result| (center, result)) }) .collect::>() } diff --git a/frontend/src/ui/data.rs b/frontend/src/ui/data.rs index dbf9a94..07ba902 100644 --- a/frontend/src/ui/data.rs +++ b/frontend/src/ui/data.rs @@ -69,8 +69,6 @@ pub fn init(url: Url, _orders: &mut impl Orders) -> Model { short_term_load: Vec::new(), long_term_load: Vec::new(), avg_rpe_per_week: Vec::new(), - total_set_volume_per_week: Vec::new(), - stimulus_for_each_muscle_per_week: BTreeMap::new(), }, settings, ongoing_training_session, @@ -275,8 +273,6 @@ pub struct TrainingStats { pub short_term_load: Vec<(NaiveDate, f32)>, pub long_term_load: Vec<(NaiveDate, f32)>, pub avg_rpe_per_week: Vec<(NaiveDate, f32)>, - pub total_set_volume_per_week: Vec<(NaiveDate, f32)>, - pub stimulus_for_each_muscle_per_week: BTreeMap>, } impl TrainingStats { @@ -297,7 +293,6 @@ impl TrainingStats { self.short_term_load.clear(); self.long_term_load.clear(); self.avg_rpe_per_week.clear(); - self.total_set_volume_per_week.clear(); } } @@ -875,21 +870,13 @@ pub fn calculate_cycle_stats(cycles: &[&Cycle]) -> CycleStats { } } -fn calculate_training_stats( - training_sessions: &[&TrainingSession], - exercises: &BTreeMap, -) -> TrainingStats { +fn calculate_training_stats(training_sessions: &[&TrainingSession]) -> TrainingStats { let short_term_load = calculate_weighted_sum_of_load(training_sessions, 7); let long_term_load = calculate_average_weighted_sum_of_load(&short_term_load, 28); TrainingStats { short_term_load, long_term_load, - total_set_volume_per_week: calculate_total_set_volume_per_week(training_sessions), avg_rpe_per_week: calculate_avg_rpe_per_week(training_sessions), - stimulus_for_each_muscle_per_week: calculate_stimulus_for_each_muscle_per_week( - training_sessions, - exercises, - ), } } @@ -951,21 +938,6 @@ fn calculate_average_weighted_sum_of_load( .collect::>() } -fn calculate_total_set_volume_per_week( - training_sessions: &[&TrainingSession], -) -> Vec<(NaiveDate, f32)> { - let mut result: BTreeMap = training_session_weeks(training_sessions); - - #[allow(clippy::cast_precision_loss)] - for t in training_sessions { - result - .entry(t.date.week(Weekday::Mon).last_day()) - .and_modify(|e| *e += t.set_volume() as f32); - } - - result.into_iter().collect() -} - fn calculate_avg_rpe_per_week(training_sessions: &[&TrainingSession]) -> Vec<(NaiveDate, f32)> { let mut result: BTreeMap> = training_session_weeks(training_sessions); @@ -993,39 +965,6 @@ fn calculate_avg_rpe_per_week(training_sessions: &[&TrainingSession]) -> Vec<(Na .collect() } -fn calculate_stimulus_for_each_muscle_per_week( - training_sessions: &[&TrainingSession], - exercises: &BTreeMap, -) -> BTreeMap> { - let mut result: BTreeMap> = BTreeMap::new(); - - for m in domain::Muscle::iter() { - result.insert( - domain::Muscle::id(*m), - training_session_weeks(training_sessions), - ); - } - - for t in training_sessions { - for (id, stimulus) in t.stimulus_per_muscle(exercises) { - if let Some(stimulus_per_week) = result.get_mut(&id) { - stimulus_per_week - .entry(t.date.week(Weekday::Mon).last_day()) - .and_modify(|s| *s += stimulus); - } else { - error!(format!( - "failed to access stimulus per week for muscle with id {id}" - )); - } - } - } - - result - .into_iter() - .map(|(id, stimulus_per_week)| (id, stimulus_per_week.into_iter().collect())) - .collect() -} - fn training_session_weeks( training_sessions: &[&TrainingSession], ) -> BTreeMap { @@ -1759,10 +1698,8 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders) { } Msg::ExerciseReplaced(Ok(exercise)) => { model.exercises.insert(exercise.id, exercise); - model.training_stats = calculate_training_stats( - &model.training_sessions.values().collect::>(), - &model.exercises, - ); + model.training_stats = + calculate_training_stats(&model.training_sessions.values().collect::>()); orders.notify(Event::ExerciseReplacedOk); } Msg::ExerciseReplaced(Err(message)) => { @@ -1917,10 +1854,8 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders) { let training_sessions = training_sessions.into_iter().map(|t| (t.id, t)).collect(); if model.training_sessions != training_sessions { model.training_sessions = training_sessions; - model.training_stats = calculate_training_stats( - &model.training_sessions.values().collect::>(), - &model.exercises, - ); + model.training_stats = + calculate_training_stats(&model.training_sessions.values().collect::>()); orders.notify(Event::DataChanged); } model.loading_training_sessions = false; @@ -1951,10 +1886,8 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders) { model .training_sessions .insert(training_session.id, training_session); - model.training_stats = calculate_training_stats( - &model.training_sessions.values().collect::>(), - &model.exercises, - ); + model.training_stats = + calculate_training_stats(&model.training_sessions.values().collect::>()); orders.notify(Event::TrainingSessionCreatedOk); } Msg::TrainingSessionCreated(Err(message)) => { @@ -1985,10 +1918,8 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders) { model .training_sessions .insert(training_session.id, training_session); - model.training_stats = calculate_training_stats( - &model.training_sessions.values().collect::>(), - &model.exercises, - ); + model.training_stats = + calculate_training_stats(&model.training_sessions.values().collect::>()); orders.notify(Event::TrainingSessionModifiedOk); } Msg::TrainingSessionModified(Err(message)) => { @@ -2011,10 +1942,8 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders) { } Msg::TrainingSessionDeleted(Ok(id)) => { model.training_sessions.remove(&id); - model.training_stats = calculate_training_stats( - &model.training_sessions.values().collect::>(), - &model.exercises, - ); + model.training_stats = + calculate_training_stats(&model.training_sessions.values().collect::>()); orders.notify(Event::TrainingSessionDeletedOk); } Msg::TrainingSessionDeleted(Err(message)) => { diff --git a/frontend/src/ui/page/muscles.rs b/frontend/src/ui/page/muscles.rs index b88feec..7260b84 100644 --- a/frontend/src/ui/page/muscles.rs +++ b/frontend/src/ui/page/muscles.rs @@ -69,24 +69,21 @@ pub fn view(model: &Model, data_model: &data::Model) -> Node { Msg::ChangeInterval ), domain::Muscle::iter().map(|m| { - let set_volume = data_model - .training_stats - .stimulus_for_each_muscle_per_week - .get(&domain::Muscle::id(*m)) - .map(|stimulus_per_muscle| { - stimulus_per_muscle - .iter() - .filter(|(date, _)| { - *date >= model.interval.first - && *date <= model.interval.last.week(Weekday::Mon).last_day() - }) - .map( - #[allow(clippy::cast_precision_loss)] - |(date, stimulus)| (*date, *stimulus as f32 / 100.0), - ) - .collect() - }) - .unwrap_or_default(); + #[allow(clippy::cast_precision_loss)] + let total_7day_set_volume = common::centered_moving_total( + &data_model + .training_sessions + .iter() + .filter_map(|(_, s)| { + s.stimulus_per_muscle(&data_model.exercises) + .get(&domain::Muscle::id(*m)) + .map(|stimulus| (s.date, *stimulus as f32 / 100.)) + }) + .collect::>(), + &model.interval, + 3, + ); + div![ common::view_title(&span![domain::Muscle::name(*m)], 1), div![ @@ -96,12 +93,12 @@ pub fn view(model: &Model, data_model: &data::Model) -> Node { domain::Muscle::description(*m) ], common::view_chart( - &[("Set volume (weekly total)", common::COLOR_SET_VOLUME)], + &[("Set volume (7 day total)", common::COLOR_SET_VOLUME)], common::plot_chart( &[common::PlotData { - values: set_volume, - plots: common::plot_line_with_dots(common::COLOR_SET_VOLUME), - params: common::PlotParams::primary_range(0., 10.), + values: total_7day_set_volume, + plots: common::plot_line(common::COLOR_SET_VOLUME), + params: common::PlotParams::default(), }], model.interval.first, model.interval.last, diff --git a/frontend/src/ui/page/training.rs b/frontend/src/ui/page/training.rs index 43b0806..9828508 100644 --- a/frontend/src/ui/page/training.rs +++ b/frontend/src/ui/page/training.rs @@ -232,16 +232,17 @@ pub fn view(model: &Model, data_model: &data::Model) -> Node { .filter(|(date, _)| *date >= model.interval.first && *date <= model.interval.last) .copied() .collect::>(); - let total_set_volume_per_week = data_model - .training_stats - .total_set_volume_per_week - .iter() - .filter(|(date, _)| { - *date >= model.interval.first - && *date <= model.interval.last.week(Weekday::Mon).last_day() - }) - .copied() - .collect::>(); + #[allow(clippy::cast_precision_loss)] + let total_7day_set_volume = common::centered_moving_total( + &data_model + .training_sessions + .values() + .map(|s| (s.date, s.set_volume() as f32)) + .collect::>(), + &model.interval, + 3, + ); + let avg_rpe_per_week = data_model .training_stats .avg_rpe_per_week @@ -325,7 +326,7 @@ pub fn view(model: &Model, data_model: &data::Model) -> Node { view_charts( short_term_load, long_term_load, - total_set_volume_per_week, + total_7day_set_volume, avg_rpe_per_week, &model.interval, data_model.theme(), @@ -506,7 +507,7 @@ fn view_training_sessions_dialog( pub fn view_charts( short_term_load: Vec<(NaiveDate, f32)>, long_term_load: Vec<(NaiveDate, f32)>, - total_set_volume_per_week: Vec<(NaiveDate, f32)>, + total_set_volume: Vec<(NaiveDate, f32)>, avg_rpe_per_week: Vec<(NaiveDate, f32)>, interval: &common::Interval, theme: &data::Theme, @@ -558,11 +559,11 @@ pub fn view_charts( false, ), common::view_chart( - &[("Set volume (weekly total)", common::COLOR_SET_VOLUME)], + &[("Set volume (7 day total)", common::COLOR_SET_VOLUME)], common::plot_chart( &[common::PlotData { - values: total_set_volume_per_week, - plots: common::plot_line_with_dots(common::COLOR_SET_VOLUME), + values: total_set_volume, + plots: [common::PlotType::Line(common::COLOR_SET_VOLUME, 2)].to_vec(), params: common::PlotParams::primary_range(0., 10.), }], interval.first,