feat: circ_summary with best-of-each strategy and age annotations
All checks were successful
Deploy Development / deploy (push) Successful in 42s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 14s

- Each circumference point shows most recent value (even from different dates)
- Age annotations: heute, gestern, vor X Tagen/Wochen/Monaten
- Gives AI better context about measurement freshness
- Example: 'Brust 105cm (heute), Nacken 38cm (vor 2 Wochen)'
This commit is contained in:
Lars 2026-03-26 13:09:38 +01:00
parent d06d3d84de
commit 159fcab17a

View File

@ -123,33 +123,62 @@ def get_caliper_summary(profile_id: str) -> str:
def get_circ_summary(profile_id: str) -> str: def get_circ_summary(profile_id: str) -> str:
"""Get latest circumference measurements summary.""" """Get latest circumference measurements summary with age annotations.
For each measurement point, fetches the most recent value (even if from different dates).
Annotates each value with measurement age for AI context.
"""
with get_db() as conn: with get_db() as conn:
cur = get_cursor(conn) cur = get_cursor(conn)
cur.execute(
"""SELECT c_neck, c_chest, c_waist, c_belly, c_hip, c_thigh, c_calf, c_arm, date
FROM circumference_log
WHERE profile_id=%s
ORDER BY date DESC LIMIT 1""",
(profile_id,)
)
row = r2d(cur.fetchone()) if cur.rowcount > 0 else None
if not row: # Define all circumference points with their labels
return "keine Umfangsmessungen" fields = [
('c_neck', 'Nacken'),
('c_chest', 'Brust'),
('c_waist', 'Taille'),
('c_belly', 'Bauch'),
('c_hip', 'Hüfte'),
('c_thigh', 'Oberschenkel'),
('c_calf', 'Wade'),
('c_arm', 'Arm')
]
# Check all 8 circumference points
parts = [] parts = []
if row.get('c_neck'): parts.append(f"Nacken {row['c_neck']:.1f}cm") today = datetime.now().date()
if row.get('c_chest'): parts.append(f"Brust {row['c_chest']:.1f}cm")
if row.get('c_waist'): parts.append(f"Taille {row['c_waist']:.1f}cm")
if row.get('c_belly'): parts.append(f"Bauch {row['c_belly']:.1f}cm")
if row.get('c_hip'): parts.append(f"Hüfte {row['c_hip']:.1f}cm")
if row.get('c_thigh'): parts.append(f"Oberschenkel {row['c_thigh']:.1f}cm")
if row.get('c_calf'): parts.append(f"Wade {row['c_calf']:.1f}cm")
if row.get('c_arm'): parts.append(f"Arm {row['c_arm']:.1f}cm")
return f"{', '.join(parts)} ({row['date']})" if parts else "keine Daten" # Get latest value for each field individually
for field_name, label in fields:
cur.execute(
f"""SELECT {field_name}, date,
CURRENT_DATE - date AS age_days
FROM circumference_log
WHERE profile_id=%s AND {field_name} IS NOT NULL
ORDER BY date DESC LIMIT 1""",
(profile_id,)
)
row = r2d(cur.fetchone()) if cur.rowcount > 0 else None
if row:
value = row[field_name]
age_days = row['age_days']
# Format age annotation
if age_days == 0:
age_str = "heute"
elif age_days == 1:
age_str = "gestern"
elif age_days <= 7:
age_str = f"vor {age_days} Tagen"
elif age_days <= 30:
weeks = age_days // 7
age_str = f"vor {weeks} Woche{'n' if weeks > 1 else ''}"
else:
months = age_days // 30
age_str = f"vor {months} Monat{'en' if months > 1 else ''}"
parts.append(f"{label} {value:.1f}cm ({age_str})")
return ', '.join(parts) if parts else "keine Umfangsmessungen"
def get_goal_weight(profile_id: str) -> str: def get_goal_weight(profile_id: str) -> str: