from datetime import date, timedelta from models import db, Meal, WaterLog, WeightLog, DailySummary, UserGoal def calculate_bmr(weight_kg, height_cm, age, gender): """ Calculate Basal Metabolic Rate using Mifflin-St Jeor Equation """ if gender.lower() == 'male': bmr = (10 * weight_kg) + (6.25 * height_cm) - (5 * age) + 5 else: # female bmr = (10 * weight_kg) + (6.25 * height_cm) - (5 * age) - 161 return round(bmr) def calculate_tdee(bmr, activity_level): """ Calculate Total Daily Energy Expenditure """ multipliers = { 'sedentary': 1.2, 'light': 1.375, 'moderate': 1.55, 'active': 1.725, 'very_active': 1.9 } multiplier = multipliers.get(activity_level, 1.55) return round(bmr * multiplier) def calculate_macro_targets(weight_kg, goal_type='recomp'): """ Calculate macro targets based on body weight and goal """ if goal_type == 'muscle_gain': protein = weight_kg * 2.4 # High protein for muscle building carbs = weight_kg * 3.5 # Higher carbs for energy fat = weight_kg * 1.0 # Moderate fat elif goal_type == 'weight_loss': protein = weight_kg * 2.2 # High protein to preserve muscle carbs = weight_kg * 2.0 # Lower carbs for deficit fat = weight_kg * 0.8 # Lower fat else: # recomp (body recomposition) protein = weight_kg * 2.2 # High protein carbs = weight_kg * 2.5 # Moderate carbs fat = weight_kg * 0.9 # Moderate fat return { 'protein_g': round(protein), 'carbs_g': round(carbs), 'fat_g': round(fat) } def calculate_daily_totals(user_id, target_date=None): """ Calculate total nutrition consumed for a given date """ if target_date is None: target_date = date.today() # Get all meals for the date meals = Meal.query.filter_by(user_id=user_id, date=target_date).all() totals = { 'calories': 0, 'protein': 0, 'carbs': 0, 'fat': 0, 'meals': [] } for meal in meals: meal_totals = meal.calculate_totals() totals['calories'] += meal_totals['calories'] totals['protein'] += meal_totals['protein'] totals['carbs'] += meal_totals['carbs'] totals['fat'] += meal_totals['fat'] totals['meals'].append({ 'id': meal.id, 'type': meal.meal_type, 'time': meal.time.strftime('%H:%M') if meal.time else None, 'totals': meal_totals, 'foods': [ { 'name': mf.food.name, 'quantity': mf.quantity, 'calories': mf.calories_consumed } for mf in meal.foods ] }) return totals def calculate_water_total(user_id, target_date=None): """ Calculate total water intake for a given date """ if target_date is None: target_date = date.today() water_logs = WaterLog.query.filter_by(user_id=user_id, date=target_date).all() total = sum(log.amount_ml for log in water_logs) return { 'total_ml': total, 'logs': [ { 'id': log.id, 'amount_ml': log.amount_ml, 'time': log.time.strftime('%H:%M') if log.time else None } for log in water_logs ] } def get_weight_trend(user_id, days=7): """ Get weight trend for the past N days """ end_date = date.today() start_date = end_date - timedelta(days=days-1) weight_logs = WeightLog.query.filter( WeightLog.user_id == user_id, WeightLog.date >= start_date, WeightLog.date <= end_date ).order_by(WeightLog.date).all() return [ { 'date': log.date.strftime('%Y-%m-%d'), 'weight_kg': log.weight_kg } for log in weight_logs ] def get_calorie_trend(user_id, days=7): """ Get calorie intake trend for the past N days """ end_date = date.today() start_date = end_date - timedelta(days=days-1) trend = [] current_date = start_date while current_date <= end_date: totals = calculate_daily_totals(user_id, current_date) trend.append({ 'date': current_date.strftime('%Y-%m-%d'), 'calories': round(totals['calories']), 'protein': round(totals['protein']), 'carbs': round(totals['carbs']), 'fat': round(totals['fat']) }) current_date += timedelta(days=1) return trend def update_daily_summary(user_id, target_date=None): """ Update or create daily summary for a user """ if target_date is None: target_date = date.today() # Calculate totals nutrition = calculate_daily_totals(user_id, target_date) water = calculate_water_total(user_id, target_date) # Get weight for the day weight_log = WeightLog.query.filter_by(user_id=user_id, date=target_date).first() weight = weight_log.weight_kg if weight_log else None # Get user's calorie target from models import User user = User.query.get(user_id) target_calories = user.target_daily_calories if user else 2000 # Find or create summary summary = DailySummary.query.filter_by(user_id=user_id, date=target_date).first() if not summary: summary = DailySummary(user_id=user_id, date=target_date) db.session.add(summary) # Update values summary.total_calories = nutrition['calories'] summary.total_protein_g = nutrition['protein'] summary.total_carbs_g = nutrition['carbs'] summary.total_fat_g = nutrition['fat'] summary.total_water_ml = water['total_ml'] summary.calories_remaining = target_calories - nutrition['calories'] summary.weight_kg = weight try: db.session.commit() return summary except Exception as e: db.session.rollback() print(f"Error updating daily summary: {e}") return None def get_macro_percentages(protein_g, carbs_g, fat_g): """ Calculate macro distribution as percentages """ protein_cal = protein_g * 4 carbs_cal = carbs_g * 4 fat_cal = fat_g * 9 total_cal = protein_cal + carbs_cal + fat_cal if total_cal == 0: return {'protein': 0, 'carbs': 0, 'fat': 0} return { 'protein': round((protein_cal / total_cal) * 100), 'carbs': round((carbs_cal / total_cal) * 100), 'fat': round((fat_cal / total_cal) * 100) } def suggest_foods_for_macros(remaining_protein, remaining_carbs, remaining_fat): """ Suggest Filipino foods based on remaining macros Returns category suggestions """ suggestions = [] # High protein needed if remaining_protein > 30: suggestions.append({ 'category': 'High Protein Ulam', 'examples': ['Grilled Tilapia', 'Chicken Tinola', 'Grilled Chicken'] }) # High carbs needed if remaining_carbs > 40: suggestions.append({ 'category': 'Carbs', 'examples': ['White Rice', 'Pandesal', 'Sweet Potato'] }) # High fat needed if remaining_fat > 20: suggestions.append({ 'category': 'Healthy Fats', 'examples': ['Sisig', 'Lechon Kawali', 'Bicol Express'] }) # Balanced meal needed if remaining_protein > 20 and remaining_carbs > 30: suggestions.append({ 'category': 'Balanced Meals', 'examples': ['Tapsilog', 'Chicken Adobo with Rice', 'Sinigang'] }) return suggestions