From 45341ddba479905c0d5042645124e792ca7ea223 Mon Sep 17 00:00:00 2001 From: 4aiman Date: Thu, 28 May 2026 23:17:45 +0300 Subject: [PATCH] Real BMR from weight change history, not just formula Added BMR.estimateRealBmr(weights, foodTotals): - Uses actual weight delta + total food intake over 30 days - Formula: realExpenditure = (totalIntake + dWeight_kg * 7700) / days - 7700 kcal per kg of fat, negative dWeight = weight loss - Requires 3+ days of data and 2+ weight entries - Sanity check: rejects < 500 kcal/day as bad data - Overrides formula BMR when enough data available renderToday now queries recent weights + food and uses real BMR if calculated, falling back to Mifflin-St Jeor formula. --- frontend/js/bmr.js | 18 +++++++++++++++++- frontend/js/main.js | 9 ++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/frontend/js/bmr.js b/frontend/js/bmr.js index 43c6e9d..c7c8a78 100644 --- a/frontend/js/bmr.js +++ b/frontend/js/bmr.js @@ -11,4 +11,20 @@ function getAge(birthYear) { return new Date().getFullYear() - birthYear; } -window.BMR = { calculateBmr, getAge }; +// Estimate real daily expenditure from weight change + food intake. +// weights: [{date, weight_kg}], foodTotals: [{date, kcal}] +// Returns kcal/day or null if insufficient data. +// Formula: realExpenditure = (totalIntake + weightDelta_kg * 7700) / days +function estimateRealBmr(weights, foodTotals) { + if (!weights || weights.length < 2 || !foodTotals || foodTotals.length < 3) return null; + const firstW = weights[0]; + const lastW = weights[weights.length - 1]; + const days = Math.round((new Date(lastW.date) - new Date(firstW.date)) / 86400000); + if (days < 3) return null; + const dW = parseFloat(lastW.weight_kg) - parseFloat(firstW.weight_kg); // negative = lost weight + const totalIntake = foodTotals.reduce((s, d) => s + (d.kcal ?? 0), 0); + const realExpend = (totalIntake + dW * 7700) / days; + return realExpend > 500 ? Math.round(realExpend) : null; // sanity: < 500 kcal/day is wrong data +} + +window.BMR = { calculateBmr, getAge, estimateRealBmr }; diff --git a/frontend/js/main.js b/frontend/js/main.js index d358283..f616ff9 100644 --- a/frontend/js/main.js +++ b/frontend/js/main.js @@ -216,7 +216,14 @@ async function renderToday(container) { return; } - const bmr = calcBmr(weights); + let bmr = calcBmr(weights); + // Try to estimate real BMR from actual weight changes + food data (14 day window) + try { + const recentWeights = await DB.getRecentWeights(30); + const recentFood = await DB.getDailyFoodTotals(30); + const realBmr = BMR.estimateRealBmr(recentWeights, recentFood); + if (realBmr) bmr = realBmr; + } catch {} const intake = Math.round(foodTotals.kcal ?? 0); const actKcal = Math.round(actTotals.kcal ?? 0); // Show expenditure even without BMR if there are activities