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.
This commit is contained in:
4aiman 2026-05-28 23:17:45 +03:00
commit 45341ddba4
2 changed files with 25 additions and 2 deletions

View file

@ -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 };

View file

@ -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