Platzhaltersystem für Ernährung, Körper und Aktivity #60

Merged
Lars merged 1 commits from develop into main 2026-04-03 09:28:14 +02:00

View File

@ -1350,54 +1350,58 @@ def get_placeholder_catalog(profile_id: str) -> Dict[str, List[Dict[str, str]]]:
""" """
Get grouped placeholder catalog with descriptions and example values. Get grouped placeholder catalog with descriptions and example values.
Uses the Placeholder Registry as single source of truth.
Falls back to hardcoded legacy placeholders for non-registry items.
Args: Args:
profile_id: User profile ID profile_id: User profile ID
Returns: Returns:
Dict mapping category to list of {key, description, example} Dict mapping category to list of {key, description, example}
""" """
# Placeholder definitions with descriptions from placeholder_registry import get_registry
placeholders = {
catalog = {}
# Get all registered placeholders from Registry
registry = get_registry()
all_registered = registry.get_all()
# Group registry placeholders by category
for key, metadata in all_registered.items():
category = metadata.category
if category not in catalog:
catalog[category] = []
# Try to resolve value
try:
if metadata._resolver_func:
example = metadata._resolver_func(profile_id)
else:
# Fallback to PLACEHOLDER_MAP
placeholder = f'{{{{{key}}}}}'
resolver = PLACEHOLDER_MAP.get(placeholder)
if resolver:
example = resolver(profile_id)
else:
example = '[Nicht implementiert]'
except Exception as e:
example = '[Nicht verfügbar]'
catalog[category].append({
'key': key,
'description': metadata.description,
'example': str(example)
})
# Legacy placeholders (not in registry yet)
legacy_placeholders = {
'Profil': [ 'Profil': [
('name', 'Name des Nutzers'), ('name', 'Name des Nutzers'),
('age', 'Alter in Jahren'), ('age', 'Alter in Jahren'),
('height', 'Körpergröße in cm'), ('height', 'Körpergröße in cm'),
('geschlecht', 'Geschlecht'), ('geschlecht', 'Geschlecht'),
], ],
'Körper': [
('weight_aktuell', 'Aktuelles Gewicht in kg'),
('weight_trend', 'Gewichtstrend (7d/30d)'),
('kf_aktuell', 'Aktueller Körperfettanteil in %'),
('bmi', 'Body Mass Index'),
('weight_7d_median', 'Gewicht 7d Median (kg)'),
('weight_28d_slope', 'Gewichtstrend 28d (kg/Tag)'),
('fm_28d_change', 'Fettmasse Änderung 28d (kg)'),
('lbm_28d_change', 'Magermasse Änderung 28d (kg)'),
('waist_28d_delta', 'Taillenumfang Änderung 28d (cm)'),
('waist_hip_ratio', 'Taille/Hüfte-Verhältnis'),
('recomposition_quadrant', 'Rekomposition-Status'),
],
'Ernährung': [
('kcal_avg', 'Durchschn. Kalorien (30d)'),
('protein_avg', 'Durchschn. Protein in g (30d)'),
('carb_avg', 'Durchschn. Kohlenhydrate in g (30d)'),
('fat_avg', 'Durchschn. Fett in g (30d)'),
('energy_balance_7d', 'Energiebilanz 7d (kcal/Tag)'),
('protein_g_per_kg', 'Protein g/kg Körpergewicht'),
('protein_adequacy_28d', 'Protein Adequacy Score (0-100)'),
('macro_consistency_score', 'Makro-Konsistenz Score (0-100)'),
],
'Training': [
('activity_summary', 'Aktivitäts-Zusammenfassung (7d)'),
('trainingstyp_verteilung', 'Verteilung nach Trainingstypen'),
('training_minutes_week', 'Trainingsminuten pro Woche'),
('training_frequency_7d', 'Trainingshäufigkeit 7d'),
('quality_sessions_pct', 'Qualitätssessions (%)'),
('ability_balance_strength', 'Ability Balance - Kraft (0-100)'),
('ability_balance_endurance', 'Ability Balance - Ausdauer (0-100)'),
('proxy_internal_load_7d', 'Proxy Load 7d'),
('rest_day_compliance', 'Ruhetags-Compliance (%)'),
],
'Schlaf & Erholung': [ 'Schlaf & Erholung': [
('sleep_avg_duration', 'Durchschn. Schlafdauer (7d)'), ('sleep_avg_duration', 'Durchschn. Schlafdauer (7d)'),
('sleep_avg_quality', 'Durchschn. Schlafqualität (7d)'), ('sleep_avg_quality', 'Durchschn. Schlafqualität (7d)'),
@ -1440,13 +1444,17 @@ def get_placeholder_catalog(profile_id: str) -> Dict[str, List[Dict[str, str]]]:
], ],
} }
catalog = {} # Add legacy placeholders (skip if already in registry)
for category, items in legacy_placeholders.items():
if category not in catalog:
catalog[category] = []
for category, items in placeholders.items():
catalog[category] = []
for key, description in items: for key, description in items:
# Skip if already added from registry
if any(p['key'] == key for p in catalog[category]):
continue
placeholder = f'{{{{{key}}}}}' placeholder = f'{{{{{key}}}}}'
# Get example value if resolver exists
resolver = PLACEHOLDER_MAP.get(placeholder) resolver = PLACEHOLDER_MAP.get(placeholder)
if resolver: if resolver:
try: try: