filename:
functions/awardCalculations.js
branch:
master
back to repo
export const calculateAwards = (metrics) => {
if (!metrics.length) return { streak: 0, totalDays: 0, perfectDays: 0, averageAccuracy: 0 };
// Filter out empty days before calculations
const daysWithData = metrics.filter(metric =>
metric.actual.calories > 0 || metric.actual.protein > 0
);
const sortedMetrics = [...daysWithData].sort((a, b) => new Date(b.date) - new Date(a.date));
const today = new Date();
today.setHours(0, 0, 0, 0);
let currentStreak = 0;
let previousDate = null;
// Calculate current streak starting from most recent day
for (const metric of sortedMetrics) {
const currentDate = new Date(metric.date);
currentDate.setHours(0, 0, 0, 0);
// Skip empty days
if (metric.actual.calories === 0) {
break;
}
// For first entry
if (!previousDate) {
// If first entry is not today or yesterday or two days ago, break
const daysDiff = Math.floor((today - currentDate) / (1000 * 60 * 60 * 24));
if (daysDiff > 2) break;
currentStreak = 1;
previousDate = currentDate;
continue;
}
// Check if dates are consecutive
const daysDiff = Math.floor((previousDate - currentDate) / (1000 * 60 * 60 * 24));
if (daysDiff !== 1) break;
currentStreak++;
previousDate = currentDate;
}
// Rest of award calculations
let stats = {
perfectDays: 0,
accuracySum: 0,
validDays: 0
};
// Calculate perfect days and accuracy
sortedMetrics.forEach(metric => {
stats.validDays++;
// Perfect days calculation (within 10% of goals)
const calorieAccuracy = metric.actual.calories / metric.goals.calories;
const proteinAccuracy = metric.actual.protein / metric.goals.protein;
const fatAccuracy = metric.actual.fat / metric.goals.fat;
const carbsAccuracy = metric.actual.carbs / metric.goals.carbs;
if (calorieAccuracy >= 0.9 && calorieAccuracy <= 1.1 &&
proteinAccuracy >= 0.9 && proteinAccuracy <= 1.1 &&
fatAccuracy >= 0.9 && fatAccuracy <= 1.1 &&
carbsAccuracy >= 0.9 && carbsAccuracy <= 1.1) {
stats.perfectDays++;
}
// Accuracy calculation
const dayProteinAccuracy = Math.min(metric.actual.protein / metric.goals.protein, 1) * 100;
const dayCalorieAccuracy = Math.min(metric.actual.calories / metric.goals.calories, 1) * 100;
const dayFatAccuracy = Math.min(metric.actual.fat / metric.goals.fat, 1) * 100;
const dayCarbsAccuracy = Math.min(metric.actual.carbs / metric.goals.carbs, 1) * 100;
stats.accuracySum += (dayProteinAccuracy + dayCalorieAccuracy + dayFatAccuracy + dayCarbsAccuracy) / 4;
});
return {
streak: currentStreak,
totalDays: daysWithData.length, // Only count days with actual data
perfectDays: stats.perfectDays,
averageAccuracy: stats.validDays > 0 ? Math.round(stats.accuracySum / stats.validDays) : 0
};
};