fix: Phase 0b - fix remaining calculation bugs from log analysis
Bugs fixed based on actual error logs:
1. TypeError: progress_pct None handling - changed .get('progress_pct', 0) to (goal.get('progress_pct') or 0)
2. UUID Error: focus_area_id query - changed WHERE focus_area_id = %s to WHERE key = %s
3. NameError: calculate_recovery_score_v2 - added missing import in calculate_category_progress
4. UndefinedColumn: c_thigh_r - removed left/right separation, only c_thigh exists
5. UndefinedColumn: resting_heart_rate - fixed remaining AVG(resting_heart_rate) to AVG(resting_hr)
6. KeyError: total_sleep_min - changed dict access to duration_minutes
Changes:
- scores.py: Fixed progress_pct None handling, focus_area key query, added recovery import
- body_metrics.py: Fixed thigh_28d_delta to use single c_thigh column
- recovery_metrics.py: Fixed resting_hr SELECT queries, fixed sleep_debt dict access
All errors from logs should now be resolved.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
dd3a4111fc
commit
02394ea19c
|
|
@ -224,14 +224,13 @@ def calculate_arm_28d_delta(profile_id: str) -> Optional[float]:
|
||||||
|
|
||||||
|
|
||||||
def calculate_thigh_28d_delta(profile_id: str) -> Optional[float]:
|
def calculate_thigh_28d_delta(profile_id: str) -> Optional[float]:
|
||||||
"""Calculate 28-day thigh circumference change (cm, average of L/R)"""
|
"""Calculate 28-day thigh circumference change (cm)"""
|
||||||
left = _calculate_circumference_delta(profile_id, 'c_thigh', 28)
|
delta = _calculate_circumference_delta(profile_id, 'c_thigh', 28)
|
||||||
right = _calculate_circumference_delta(profile_id, 'c_thigh_r', 28)
|
|
||||||
|
|
||||||
if left is None or right is None:
|
if delta is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return round((left + right) / 2, 1)
|
return round(delta, 1)
|
||||||
|
|
||||||
|
|
||||||
def _calculate_circumference_delta(profile_id: str, column: str, days: int) -> Optional[float]:
|
def _calculate_circumference_delta(profile_id: str, column: str, days: int) -> Optional[float]:
|
||||||
|
|
|
||||||
|
|
@ -161,7 +161,7 @@ def _score_rhr_vs_baseline(profile_id: str) -> Optional[int]:
|
||||||
|
|
||||||
# Get baseline (28d average, excluding last 3 days)
|
# Get baseline (28d average, excluding last 3 days)
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
SELECT AVG(resting_heart_rate) as baseline_rhr
|
SELECT AVG(resting_hr) as baseline_rhr
|
||||||
FROM vitals_baseline
|
FROM vitals_baseline
|
||||||
WHERE profile_id = %s
|
WHERE profile_id = %s
|
||||||
AND resting_hr IS NOT NULL
|
AND resting_hr IS NOT NULL
|
||||||
|
|
@ -351,7 +351,7 @@ def calculate_rhr_vs_baseline_pct(profile_id: str) -> Optional[float]:
|
||||||
|
|
||||||
# Baseline
|
# Baseline
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
SELECT AVG(resting_heart_rate) as baseline_rhr
|
SELECT AVG(resting_hr) as baseline_rhr
|
||||||
FROM vitals_baseline
|
FROM vitals_baseline
|
||||||
WHERE profile_id = %s
|
WHERE profile_id = %s
|
||||||
AND resting_hr IS NOT NULL
|
AND resting_hr IS NOT NULL
|
||||||
|
|
@ -407,7 +407,7 @@ def calculate_sleep_debt_hours(profile_id: str) -> Optional[float]:
|
||||||
ORDER BY date DESC
|
ORDER BY date DESC
|
||||||
""", (profile_id,))
|
""", (profile_id,))
|
||||||
|
|
||||||
sleep_data = [row['total_sleep_min'] for row in cur.fetchall()]
|
sleep_data = [row['duration_minutes'] for row in cur.fetchall()]
|
||||||
|
|
||||||
if len(sleep_data) < 10: # Need at least 10 days
|
if len(sleep_data) < 10: # Need at least 10 days
|
||||||
return None
|
return None
|
||||||
|
|
|
||||||
|
|
@ -404,7 +404,7 @@ def get_top_priority_goal(profile_id: str) -> Optional[Dict]:
|
||||||
|
|
||||||
for goal in goals:
|
for goal in goals:
|
||||||
# Progress gap (0-100, higher = further from target)
|
# Progress gap (0-100, higher = further from target)
|
||||||
goal['progress_gap'] = 100 - goal.get('progress_pct', 0)
|
goal['progress_gap'] = 100 - (goal.get('progress_pct') or 0)
|
||||||
|
|
||||||
# Get focus areas for this goal
|
# Get focus areas for this goal
|
||||||
with get_db() as conn:
|
with get_db() as conn:
|
||||||
|
|
@ -480,7 +480,7 @@ def calculate_focus_area_progress(profile_id: str, focus_area_id: str) -> Option
|
||||||
JOIN goal_focus_contributions gfc ON g.id = gfc.goal_id
|
JOIN goal_focus_contributions gfc ON g.id = gfc.goal_id
|
||||||
WHERE g.profile_id = %s
|
WHERE g.profile_id = %s
|
||||||
AND gfc.focus_area_id = (
|
AND gfc.focus_area_id = (
|
||||||
SELECT id FROM focus_area_definitions WHERE focus_area_id = %s
|
SELECT id FROM focus_area_definitions WHERE key = %s
|
||||||
)
|
)
|
||||||
AND g.status = 'active'
|
AND g.status = 'active'
|
||||||
""", (profile_id, focus_area_id))
|
""", (profile_id, focus_area_id))
|
||||||
|
|
@ -533,6 +533,7 @@ def calculate_category_progress(profile_id: str, category: str) -> Optional[int]
|
||||||
from calculations.activity_metrics import calculate_activity_score
|
from calculations.activity_metrics import calculate_activity_score
|
||||||
return calculate_activity_score(profile_id)
|
return calculate_activity_score(profile_id)
|
||||||
elif score_func_name == 'recovery_score':
|
elif score_func_name == 'recovery_score':
|
||||||
|
from calculations.recovery_metrics import calculate_recovery_score_v2
|
||||||
return calculate_recovery_score_v2(profile_id)
|
return calculate_recovery_score_v2(profile_id)
|
||||||
elif score_func_name == 'data_quality_score':
|
elif score_func_name == 'data_quality_score':
|
||||||
return calculate_data_quality_score(profile_id)
|
return calculate_data_quality_score(profile_id)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user