2025-05-30 20:35:55 +00:00

132 lines
4.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
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),
}
}