diff --git a/backend/calculations/activity_metrics.py b/backend/calculations/activity_metrics.py index c11eabe..f767da4 100644 --- a/backend/calculations/activity_metrics.py +++ b/backend/calculations/activity_metrics.py @@ -341,59 +341,72 @@ def calculate_activity_score(profile_id: str, focus_weights: Optional[Dict] = No from calculations.scores import get_user_focus_weights focus_weights = get_user_focus_weights(profile_id) - # Activity-related focus areas - activity_focus = { - 'kraftaufbau': focus_weights.get('kraftaufbau', 0), - 'cardio': focus_weights.get('cardio', 0), - 'bewegungsumfang': focus_weights.get('bewegungsumfang', 0), - 'trainingsqualität': focus_weights.get('trainingsqualität', 0), - 'ability_balance': focus_weights.get('ability_balance', 0), - } + # Activity-related focus areas (English keys from DB) + # Strength training + strength = focus_weights.get('strength', 0) + strength_endurance = focus_weights.get('strength_endurance', 0) + power = focus_weights.get('power', 0) + total_strength = strength + strength_endurance + power - total_activity_weight = sum(activity_focus.values()) + # Endurance training + aerobic = focus_weights.get('aerobic_endurance', 0) + anaerobic = focus_weights.get('anaerobic_endurance', 0) + cardiovascular = focus_weights.get('cardiovascular_health', 0) + total_cardio = aerobic + anaerobic + cardiovascular + + # Mobility/Coordination + flexibility = focus_weights.get('flexibility', 0) + mobility = focus_weights.get('mobility', 0) + balance = focus_weights.get('balance', 0) + reaction = focus_weights.get('reaction', 0) + rhythm = focus_weights.get('rhythm', 0) + coordination = focus_weights.get('coordination', 0) + total_ability = flexibility + mobility + balance + reaction + rhythm + coordination + + total_activity_weight = total_strength + total_cardio + total_ability if total_activity_weight == 0: return None # No activity goals components = [] - # 1. Weekly minutes (if bewegungsumfang goal) - if activity_focus['bewegungsumfang'] > 0: - minutes = calculate_training_minutes_week(profile_id) - if minutes is not None: - # WHO: 150-300 min/week - if 150 <= minutes <= 300: - minutes_score = 100 - elif minutes < 150: - minutes_score = max(40, (minutes / 150) * 100) - else: - minutes_score = max(80, 100 - ((minutes - 300) / 10)) + # 1. Weekly minutes (general activity volume) + minutes = calculate_training_minutes_week(profile_id) + if minutes is not None: + # WHO: 150-300 min/week + if 150 <= minutes <= 300: + minutes_score = 100 + elif minutes < 150: + minutes_score = max(40, (minutes / 150) * 100) + else: + minutes_score = max(80, 100 - ((minutes - 300) / 10)) - components.append(('minutes', minutes_score, activity_focus['bewegungsumfang'])) + # Volume relevant for all activity types (20% base weight) + components.append(('minutes', minutes_score, total_activity_weight * 0.2)) - # 2. Quality sessions (if trainingsqualität goal) - if activity_focus['trainingsqualität'] > 0: - quality_pct = calculate_quality_sessions_pct(profile_id) - if quality_pct is not None: - components.append(('quality', quality_pct, activity_focus['trainingsqualität'])) + # 2. Quality sessions (always relevant) + quality_pct = calculate_quality_sessions_pct(profile_id) + if quality_pct is not None: + # Quality gets 10% base weight + components.append(('quality', quality_pct, total_activity_weight * 0.1)) - # 3. Strength presence (if kraftaufbau goal) - if activity_focus['kraftaufbau'] > 0: + # 3. Strength presence (if strength focus active) + if total_strength > 0: strength_score = _score_strength_presence(profile_id) if strength_score is not None: - components.append(('strength', strength_score, activity_focus['kraftaufbau'])) + components.append(('strength', strength_score, total_strength)) - # 4. Cardio presence (if cardio goal) - if activity_focus['cardio'] > 0: + # 4. Cardio presence (if cardio focus active) + if total_cardio > 0: cardio_score = _score_cardio_presence(profile_id) if cardio_score is not None: - components.append(('cardio', cardio_score, activity_focus['cardio'])) + components.append(('cardio', cardio_score, total_cardio)) - # 5. Ability balance (if ability_balance goal) - if activity_focus['ability_balance'] > 0: + # 5. Ability balance (if mobility/coordination focus active) + if total_ability > 0: balance_score = _score_ability_balance(profile_id) if balance_score is not None: - components.append(('balance', balance_score, activity_focus['ability_balance'])) + components.append(('balance', balance_score, total_ability)) if not components: return None diff --git a/backend/calculations/body_metrics.py b/backend/calculations/body_metrics.py index 1558d1d..837ab62 100644 --- a/backend/calculations/body_metrics.py +++ b/backend/calculations/body_metrics.py @@ -339,12 +339,12 @@ def calculate_body_progress_score(profile_id: str, focus_weights: Optional[Dict] from calculations.scores import get_user_focus_weights focus_weights = get_user_focus_weights(profile_id) - # Get all body-related focus area weights - body_weight = focus_weights.get('körpergewicht', 0) - body_fat_weight = focus_weights.get('körperfett', 0) - muscle_weight = focus_weights.get('muskelmasse', 0) + # Get all body-related focus area weights (English keys from DB) + weight_loss = focus_weights.get('weight_loss', 0) + muscle_gain = focus_weights.get('muscle_gain', 0) + body_recomp = focus_weights.get('body_recomposition', 0) - total_body_weight = body_weight + body_fat_weight + muscle_weight + total_body_weight = weight_loss + muscle_gain + body_recomp if total_body_weight == 0: return None # No body-related goals @@ -352,23 +352,23 @@ def calculate_body_progress_score(profile_id: str, focus_weights: Optional[Dict] # Calculate component scores (0-100) components = [] - # Weight trend component (if weight goal active) - if body_weight > 0: + # Weight trend component (if weight loss goal active) + if weight_loss > 0: weight_score = _score_weight_trend(profile_id) if weight_score is not None: - components.append(('weight', weight_score, body_weight)) + components.append(('weight', weight_score, weight_loss)) - # Body composition component (if BF% or LBM goal active) - if body_fat_weight > 0 or muscle_weight > 0: + # Body composition component (if muscle gain or recomp goal active) + if muscle_gain > 0 or body_recomp > 0: comp_score = _score_body_composition(profile_id) if comp_score is not None: - components.append(('composition', comp_score, body_fat_weight + muscle_weight)) + components.append(('composition', comp_score, muscle_gain + body_recomp)) # Waist circumference component (proxy for health) waist_score = _score_waist_trend(profile_id) if waist_score is not None: - # Waist gets 20% base weight + bonus from BF% goals - waist_weight = 20 + (body_fat_weight * 0.3) + # Waist gets 20% base weight + bonus from weight loss goals + waist_weight = 20 + (weight_loss * 0.3) components.append(('waist', waist_score, waist_weight)) if not components: diff --git a/backend/calculations/nutrition_metrics.py b/backend/calculations/nutrition_metrics.py index c106c77..9406e0a 100644 --- a/backend/calculations/nutrition_metrics.py +++ b/backend/calculations/nutrition_metrics.py @@ -341,45 +341,44 @@ def calculate_nutrition_score(profile_id: str, focus_weights: Optional[Dict] = N from calculations.scores import get_user_focus_weights focus_weights = get_user_focus_weights(profile_id) - # Nutrition-related focus areas - nutrition_focus = { - 'ernährung_basis': focus_weights.get('ernährung_basis', 0), - 'ernährung_makros': focus_weights.get('ernährung_makros', 0), - 'proteinzufuhr': focus_weights.get('proteinzufuhr', 0), - 'kalorienbilanz': focus_weights.get('kalorienbilanz', 0), - } + # Nutrition-related focus areas (English keys from DB) + protein_intake = focus_weights.get('protein_intake', 0) + calorie_balance = focus_weights.get('calorie_balance', 0) + macro_consistency = focus_weights.get('macro_consistency', 0) + meal_timing = focus_weights.get('meal_timing', 0) + hydration = focus_weights.get('hydration', 0) - total_nutrition_weight = sum(nutrition_focus.values()) + total_nutrition_weight = protein_intake + calorie_balance + macro_consistency + meal_timing + hydration if total_nutrition_weight == 0: return None # No nutrition goals components = [] - # 1. Calorie target adherence (if kalorienbilanz goal active) - if nutrition_focus['kalorienbilanz'] > 0: + # 1. Calorie target adherence (if calorie_balance goal active) + if calorie_balance > 0: calorie_score = _score_calorie_adherence(profile_id) if calorie_score is not None: - components.append(('calories', calorie_score, nutrition_focus['kalorienbilanz'])) + components.append(('calories', calorie_score, calorie_balance)) - # 2. Protein target adherence (always important if any nutrition goal) - protein_score = calculate_protein_adequacy_28d(profile_id) - if protein_score is not None: - # Higher weight if protein-specific goal - protein_weight = nutrition_focus['proteinzufuhr'] or (total_nutrition_weight * 0.3) - components.append(('protein', protein_score, protein_weight)) + # 2. Protein target adherence (if protein_intake goal active) + if protein_intake > 0: + protein_score = calculate_protein_adequacy_28d(profile_id) + if protein_score is not None: + components.append(('protein', protein_score, protein_intake)) - # 3. Intake consistency (always relevant) - consistency_score = calculate_macro_consistency_score(profile_id) - if consistency_score is not None: - consistency_weight = total_nutrition_weight * 0.2 - components.append(('consistency', consistency_score, consistency_weight)) + # 3. Intake consistency (if macro_consistency goal active) + if macro_consistency > 0: + consistency_score = calculate_macro_consistency_score(profile_id) + if consistency_score is not None: + components.append(('consistency', consistency_score, macro_consistency)) - # 4. Macro balance (if makros goal active) - if nutrition_focus['ernährung_makros'] > 0: + # 4. Macro balance (always relevant if any nutrition goal) + if total_nutrition_weight > 0: macro_score = _score_macro_balance(profile_id) if macro_score is not None: - components.append(('macros', macro_score, nutrition_focus['ernährung_makros'])) + # Use 20% of total weight for macro balance + components.append(('macros', macro_score, total_nutrition_weight * 0.2)) if not components: return None