From 1ad530127e6217df9597dd5614e863862a7cea01 Mon Sep 17 00:00:00 2001 From: Knyffen Date: Fri, 31 Jan 2025 18:58:22 +0100 Subject: [PATCH] Initial adjustment for calories burned based on weight --- server/src/main.rs | 4 ++- server/src/math/calculations.rs | 46 +++++++++++++++++++++++++++++---- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/server/src/main.rs b/server/src/main.rs index d39f1dc..55e16b3 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -131,11 +131,13 @@ async fn svg_calorie_intake( let nutrition_val_promise = Nutrition::get_nutrition_hashmap(state.sql_pool.clone()); let purchases_val_promise = Purchase::get_purchase_rows(state.sql_pool.clone()); + let weight_val_promise = Weight::get_weight_rows(state.sql_pool.clone()); let nutrition_val = nutrition_val_promise.await?; let purchases_val = purchases_val_promise.await?; + let weight_val = weight_val_promise.await?; - let plotfun = math::plot_calories_per_day(nutrition_val, purchases_val); + let plotfun = math::plot_calories_per_day(nutrition_val, purchases_val, weight_val); Ok(plotting::SVGPlotter::plot(640, 480, plotfun)) } diff --git a/server/src/math/calculations.rs b/server/src/math/calculations.rs index 6c6d181..5cc9047 100644 --- a/server/src/math/calculations.rs +++ b/server/src/math/calculations.rs @@ -13,6 +13,8 @@ use time::*; const MEALS_PER_DAY: f32 = 2.3; const SMOOTHING_DAYS: usize = 21; const CALORIES_BURNED_PER_DAY: f32 = 2270.; +const CALORIES_BURNED_PER_DAY_BASE_WEIGHT: f32 = 83.; +const CALORIES_BURNED_LESS_PER_DAY_PER_KG: f32 = 12.5; fn time_date_to_chrono_naive_date(d: Date) -> chrono::NaiveDate { chrono::NaiveDate::from_ymd_opt(d.year(), d.month() as u32, d.day() as u32).unwrap() @@ -82,6 +84,7 @@ fn calculate_calories_per_day( pub fn plot_calories_per_day( nutrition_map: HashMap, purchases: Vec, + weight: Vec, ) -> plotting::SVGPlotFun { let (mindate, calorie_days) = calculate_calories_per_day(nutrition_map, purchases); @@ -99,6 +102,28 @@ pub fn plot_calories_per_day( .reduce(|a, b| a.max(b)) .unwrap(); + let weight_dates: Vec = weight + .iter() + .map(|w| (w.datetime.date() - mindate).whole_days() as f32) + .collect(); + let weight_values: Vec = weight.iter().map(|w| w.weight).collect(); + let weight_days = interp_slice( + &weight_dates, + &weight_values, + &(0..calorie_days.len()) + .map(|x| x as f32) + .collect::>(), + &InterpMode::FirstLast, + ); + let calories_burned_per_day_days: Vec = weight_days + .iter() + .map(|weight| { + CALORIES_BURNED_PER_DAY + + CALORIES_BURNED_LESS_PER_DAY_PER_KG + * (weight - CALORIES_BURNED_PER_DAY_BASE_WEIGHT) + }) + .collect(); + let plotfun = Box::new(move |root: plotting::SVGPlotRoot| { root.fill(&WHITE).unwrap(); let mut chart = ChartBuilder::on(&root) @@ -128,10 +153,17 @@ pub fn plot_calories_per_day( chart .draw_series(LineSeries::new( - vec![ - (mindate_chrono, CALORIES_BURNED_PER_DAY), - (maxdate_chrono, CALORIES_BURNED_PER_DAY), - ], + calories_burned_per_day_days + .iter() + .enumerate() + .map(|(i, cal)| { + ( + mindate_chrono + .checked_add_days(chrono::Days::new(i.try_into().unwrap())) + .unwrap(), + *cal, + ) + }), BLACK.stroke_width(2), )) .unwrap() @@ -206,7 +238,11 @@ pub fn plot_weight_loss( .iter() .enumerate() .scan(0., |deficit, (i, &calories)| { - *deficit += calories - CALORIES_BURNED_PER_DAY - running_days[i]; + *deficit += calories + - (CALORIES_BURNED_PER_DAY + + CALORIES_BURNED_LESS_PER_DAY_PER_KG + * (weight_days[i] - CALORIES_BURNED_PER_DAY_BASE_WEIGHT)) + - running_days[i]; Some(*deficit) }) .collect();