Flexibles KI Prompt System #48

Merged
Lars merged 56 commits from develop into main 2026-03-26 14:49:48 +01:00
Showing only changes of commit 0f2b85c6de - Show all commits

View File

@ -79,9 +79,19 @@ def get_nutrition_avg(profile_id: str, field: str, days: int = 30) -> str:
with get_db() as conn:
cur = get_cursor(conn)
cutoff = (datetime.now() - timedelta(days=days)).strftime('%Y-%m-%d')
# Map field names to actual column names
field_map = {
'protein': 'protein_g',
'fat': 'fat_g',
'carb': 'carbs_g',
'kcal': 'kcal'
}
db_field = field_map.get(field, field)
cur.execute(
f"""SELECT AVG({field}) as avg FROM nutrition_log
WHERE profile_id=%s AND date >= %s AND {field} IS NOT NULL""",
f"""SELECT AVG({db_field}) as avg FROM nutrition_log
WHERE profile_id=%s AND date >= %s AND {db_field} IS NOT NULL""",
(profile_id, cutoff)
)
row = cur.fetchone()
@ -93,6 +103,105 @@ def get_nutrition_avg(profile_id: str, field: str, days: int = 30) -> str:
return "nicht verfügbar"
def get_caliper_summary(profile_id: str) -> str:
"""Get latest caliper measurements summary."""
with get_db() as conn:
cur = get_cursor(conn)
cur.execute(
"""SELECT bf_jpl, bf_katch, date FROM caliper_log
WHERE profile_id=%s AND bf_jpl IS NOT NULL
ORDER BY date DESC LIMIT 1""",
(profile_id,)
)
row = r2d(cur.fetchone()) if cur.rowcount > 0 else None
if not row:
return "keine Caliper-Messungen"
return f"JPL: {row['bf_jpl']:.1f}% (Katch: {row['bf_katch']:.1f}% am {row['date']})"
def get_circ_summary(profile_id: str) -> str:
"""Get latest circumference measurements summary."""
with get_db() as conn:
cur = get_cursor(conn)
cur.execute(
"""SELECT brust, taille, huefte, 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:
return "keine Umfangsmessungen"
parts = []
if row.get('brust'): parts.append(f"Brust {row['brust']}cm")
if row.get('taille'): parts.append(f"Taille {row['taille']}cm")
if row.get('huefte'): parts.append(f"Hüfte {row['huefte']}cm")
return f"{', '.join(parts)} ({row['date']})" if parts else "keine Daten"
def get_goal_weight(profile_id: str) -> str:
"""Get goal weight from profile."""
profile = get_profile_data(profile_id)
goal = profile.get('goal_weight')
return f"{goal:.1f}" if goal else "nicht gesetzt"
def get_goal_bf_pct(profile_id: str) -> str:
"""Get goal body fat percentage from profile."""
profile = get_profile_data(profile_id)
goal = profile.get('goal_bf_pct')
return f"{goal:.1f}" if goal else "nicht gesetzt"
def get_nutrition_days(profile_id: str, days: int = 30) -> str:
"""Get number of days with nutrition data."""
with get_db() as conn:
cur = get_cursor(conn)
cutoff = (datetime.now() - timedelta(days=days)).strftime('%Y-%m-%d')
cur.execute(
"""SELECT COUNT(DISTINCT date) as days FROM nutrition_log
WHERE profile_id=%s AND date >= %s""",
(profile_id, cutoff)
)
row = cur.fetchone()
return str(row['days']) if row else "0"
def get_protein_ziel_low(profile_id: str) -> str:
"""Calculate lower protein target based on current weight (1.6g/kg)."""
with get_db() as conn:
cur = get_cursor(conn)
cur.execute(
"""SELECT weight FROM weight_log
WHERE profile_id=%s ORDER BY date DESC LIMIT 1""",
(profile_id,)
)
row = cur.fetchone()
if row:
return f"{int(row['weight'] * 1.6)}"
return "nicht verfügbar"
def get_protein_ziel_high(profile_id: str) -> str:
"""Calculate upper protein target based on current weight (2.2g/kg)."""
with get_db() as conn:
cur = get_cursor(conn)
cur.execute(
"""SELECT weight FROM weight_log
WHERE profile_id=%s ORDER BY date DESC LIMIT 1""",
(profile_id,)
)
row = cur.fetchone()
if row:
return f"{int(row['weight'] * 2.2)}"
return "nicht verfügbar"
def get_activity_summary(profile_id: str, days: int = 14) -> str:
"""Get activity summary for recent period."""
with get_db() as conn:
@ -194,12 +303,19 @@ PLACEHOLDER_MAP: Dict[str, Callable[[str], str]] = {
'{{weight_trend}}': get_weight_trend,
'{{kf_aktuell}}': get_latest_bf,
'{{bmi}}': lambda pid: calculate_bmi(pid),
'{{caliper_summary}}': get_caliper_summary,
'{{circ_summary}}': get_circ_summary,
'{{goal_weight}}': get_goal_weight,
'{{goal_bf_pct}}': get_goal_bf_pct,
# Ernährung
'{{kcal_avg}}': lambda pid: get_nutrition_avg(pid, 'kcal', 30),
'{{protein_avg}}': lambda pid: get_nutrition_avg(pid, 'protein', 30),
'{{carb_avg}}': lambda pid: get_nutrition_avg(pid, 'carb', 30),
'{{fat_avg}}': lambda pid: get_nutrition_avg(pid, 'fat', 30),
'{{nutrition_days}}': lambda pid: get_nutrition_days(pid, 30),
'{{protein_ziel_low}}': get_protein_ziel_low,
'{{protein_ziel_high}}': get_protein_ziel_high,
# Training
'{{activity_summary}}': get_activity_summary,