""" Utility functions for calories calculation """ from datetime import date from enum import Enum from typing import Dict, Any class ActivityLevel(str, Enum): """Activity level for BMR calculations""" SEDENTARY = "sedentary" # Little or no exercise LIGHTLY_ACTIVE = "lightly_active" # Light exercise/sports 1-3 days/week MODERATELY_ACTIVE = "moderately_active" # Moderate exercise/sports 3-5 days/week VERY_ACTIVE = "very_active" # Hard exercise/sports 6-7 days/week EXTRA_ACTIVE = "extra_active" # Very hard exercise, physical job or training twice a day class WeightGoal(str, Enum): """Weight goals for calorie adjustments""" LOSE_FAST = "lose_fast" # Lose 1kg per week LOSE = "lose" # Lose 0.5kg per week MAINTAIN = "maintain" # Maintain current weight GAIN = "gain" # Gain 0.5kg per week GAIN_FAST = "gain_fast" # Gain 1kg per week def calculate_age(birth_date: date) -> int: """ Calculate age from birth date """ today = date.today() age = today.year - birth_date.year # Check if birthday has occurred this year if today.month < birth_date.month or (today.month == birth_date.month and today.day < birth_date.day): age -= 1 return age def calculate_bmr( weight_kg: float, height_cm: float, age: int, gender: str ) -> float: """ Calculate Basal Metabolic Rate (BMR) using the Mifflin-St Jeor Equation For men: BMR = (10 × weight in kg) + (6.25 × height in cm) - (5 × age in years) + 5 For women: BMR = (10 × weight in kg) + (6.25 × height in cm) - (5 × age in years) - 161 """ if gender.lower() in ("male", "m"): return (10 * weight_kg) + (6.25 * height_cm) - (5 * age) + 5 else: # female return (10 * weight_kg) + (6.25 * height_cm) - (5 * age) - 161 def calculate_tdee(bmr: float, activity_level: ActivityLevel) -> float: """ Calculate Total Daily Energy Expenditure (TDEE) based on BMR and activity level """ activity_multipliers = { ActivityLevel.SEDENTARY: 1.2, ActivityLevel.LIGHTLY_ACTIVE: 1.375, ActivityLevel.MODERATELY_ACTIVE: 1.55, ActivityLevel.VERY_ACTIVE: 1.725, ActivityLevel.EXTRA_ACTIVE: 1.9, } return bmr * activity_multipliers[activity_level] def adjust_calories_for_goal(tdee: float, goal: WeightGoal) -> float: """ Adjust TDEE based on weight goal 1kg of fat is approximately 7700 calories To lose/gain 1kg per week: 7700 / 7 = 1100 calories per day To lose/gain 0.5kg per week: 7700 / 14 = 550 calories per day """ goal_adjustments = { WeightGoal.LOSE_FAST: -1100, WeightGoal.LOSE: -550, WeightGoal.MAINTAIN: 0, WeightGoal.GAIN: 550, WeightGoal.GAIN_FAST: 1100, } return tdee + goal_adjustments[goal] def calculate_recommended_calories( weight_kg: float, height_cm: float, birth_date: date, gender: str, activity_level: ActivityLevel, goal: WeightGoal ) -> Dict[str, Any]: """ Calculate recommended daily calories based on personal data and goals """ age = calculate_age(birth_date) bmr = calculate_bmr(weight_kg, height_cm, age, gender) tdee = calculate_tdee(bmr, activity_level) adjusted_calories = adjust_calories_for_goal(tdee, goal) # Calculate macronutrient recommendations based on a balanced diet # Protein: 30%, Carbs: 40%, Fat: 30% calories_from_protein = adjusted_calories * 0.3 calories_from_carbs = adjusted_calories * 0.4 calories_from_fat = adjusted_calories * 0.3 # Convert calories to grams # Protein: 4 calories per gram # Carbs: 4 calories per gram # Fat: 9 calories per gram protein_g = calories_from_protein / 4 carbs_g = calories_from_carbs / 4 fat_g = calories_from_fat / 9 return { "bmr": round(bmr), "tdee": round(tdee), "recommended_calories": round(adjusted_calories), "macronutrients": { "protein_g": round(protein_g), "carbs_g": round(carbs_g), "fat_g": round(fat_g), } }