feat: circ_summary with best-of-each strategy and age annotations
- 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:
parent
d06d3d84de
commit
159fcab17a
|
|
@ -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:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user