diff --git a/docs/GOAL_SYSTEM_REDESIGN_v2.md b/docs/GOAL_SYSTEM_REDESIGN_v2.md new file mode 100644 index 0000000..be6aab1 --- /dev/null +++ b/docs/GOAL_SYSTEM_REDESIGN_v2.md @@ -0,0 +1,729 @@ +# Goal System Redesign v2.0 + +**Datum:** 26. MΓ€rz 2026 +**Status:** πŸ“‹ KONZEPTION +**Anlass:** Fundamentale Design-Probleme in Phase 0a identifiziert + +--- + +## 1. Probleme der aktuellen Implementierung (Phase 0a) + +### 1.1 PrimΓ€rziel zu simplistisch +**Problem:** +- Nur EIN PrimΓ€rziel erlaubt +- BinΓ€res System (primΓ€r/nicht-primΓ€r) +- Toggle funktioniert nicht richtig beim Update + +**RealitΓ€t:** +- User hat MEHRERE Ziele gleichzeitig mit unterschiedlichen PrioritΓ€ten +- Beispiel: 30% Abnehmen, 25% Kraft, 25% Ausdauer, 20% Beweglichkeit + +**LΓΆsung:** +β†’ **Gewichtungssystem** (0-100%, Summe = 100%) + +--- + +### 1.2 Ein Goal Mode zu simpel +**Problem:** +- User muss sich fΓΌr EINEN Modus entscheiden (weight_loss ODER strength) +- In RealitΓ€t: Kombinierte Ziele (Abnehmen + Kraft + Ausdauer gleichzeitig) + +**RealitΓ€t (User-Zitat):** +> "Ich versuche nach einer Operation Kraft und Ausdauer aufzubauen, gleichzeitig Abzunehmen und meine Beweglichkeit und Koordination wieder zu steigern." + +**LΓΆsung:** +β†’ **Multi-Mode mit Gewichtung** statt Single-Mode + +--- + +### 1.3 Fehlende Current Values +**Problem:** +- `lean_mass` current value = "-" (nicht implementiert) +- `strength`, `flexibility` haben keine Datenquellen +- VO2Max wirft Internal Server Error + +**LΓΆsung:** +β†’ Alle Goal-Typen mit korrekten Datenquellen verbinden + +--- + +### 1.4 Abstrakte Zieltypen +**Problem:** +- "Kraft" - was bedeutet das? BankdrΓΌcken? Kniebeuge? Gesamt? +- "Beweglichkeit" - welcher Test? Sit-and-Reach? HΓΌftbeugung? +- Zu unspezifisch fΓΌr konkrete Messung + +**LΓΆsung:** +β†’ **Konkrete, messbare Zieltypen** mit standardisierten Tests + +--- + +### 1.5 Blutdruck als einzelner Wert +**Problem:** +- BP braucht ZWEI Werte (systolisch/diastolisch) +- Aktuelles Schema: nur ein `target_value` + +**LΓΆsung:** +β†’ **Compound Goals** (Ziele mit mehreren Werten) + +--- + +### 1.6 Keine Guidance fΓΌr User +**Problem:** +- User muss konkrete Zahlen eingeben ohne Kontext +- Was ist ein guter VO2Max Wert? Was ist realistisch? + +**LΓΆsung:** +β†’ **Richtwerte, Normen, Beispiele** in UI + +--- + +## 2. Redesign-Konzept v2.0 + +### 2.1 Kern-Prinzipien + +**Prinzip 1: Gewichtung statt Priorisierung** +- Alle Ziele haben eine Gewichtung (0-100%) +- Summe aller Gewichtungen = 100% +- KI berΓΌcksichtigt Gewichtung in Analysen + +**Prinzip 2: Multi-dimensional statt Singular** +- Kein einzelner "Goal Mode" +- Stattdessen: Gewichtete Kombination von Fokus-Bereichen +- RealitΓ€tsnah: User hat mehrere Ziele gleichzeitig + +**Prinzip 3: Konkret statt Abstrakt** +- Jedes Ziel hat klare Messbarkeit +- Standardisierte Tests wo mΓΆglich +- Datenquellen eindeutig definiert + +**Prinzip 4: Guidance statt Ratlosigkeit** +- Richtwerte fΓΌr jedes Ziel +- Alters-/Geschlechts-spezifische Normen +- Beispiele und ErklΓ€rungen + +--- + +## 3. Neues Datenmodell + +### 3.1 Fokus-Bereiche (statt Goal Modes) + +**Tabelle: `focus_areas` (NEU)** +```sql +CREATE TABLE focus_areas ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + profile_id UUID NOT NULL REFERENCES profiles(id) ON DELETE CASCADE, + + -- Gewichtete Fokus-Bereiche + weight_loss_pct INT DEFAULT 0, -- 0-100% + muscle_gain_pct INT DEFAULT 0, -- 0-100% + endurance_pct INT DEFAULT 0, -- 0-100% + strength_pct INT DEFAULT 0, -- 0-100% + flexibility_pct INT DEFAULT 0, -- 0-100% + health_pct INT DEFAULT 0, -- 0-100% (Erhaltung, kein spezifisches Ziel) + + -- Constraint: Summe muss 100 sein + CONSTRAINT sum_equals_100 CHECK ( + weight_loss_pct + muscle_gain_pct + endurance_pct + + strength_pct + flexibility_pct + health_pct = 100 + ), + + active BOOLEAN DEFAULT true, + created_at TIMESTAMP DEFAULT NOW(), + updated_at TIMESTAMP DEFAULT NOW(), + + -- Nur ein aktiver Fokus-Mix pro User + UNIQUE(profile_id, active) WHERE active = true +); + +COMMENT ON TABLE focus_areas IS + 'Weighted focus distribution - replaces single goal_mode. + Example: 30% weight loss + 25% strength + 25% endurance + 20% flexibility = 100%'; +``` + +**Beispiel-Daten:** +```json +// User nach Operation (wie im Feedback beschrieben): +{ + "weight_loss_pct": 30, + "muscle_gain_pct": 20, + "endurance_pct": 25, + "strength_pct": 15, + "flexibility_pct": 10, + "health_pct": 0 +} + +// User reiner Kraftfokus: +{ + "weight_loss_pct": 0, + "muscle_gain_pct": 50, + "strength_pct": 40, + "endurance_pct": 10, + "flexibility_pct": 0, + "health_pct": 0 +} + +// User Gewichtsverlust primΓ€r: +{ + "weight_loss_pct": 60, + "muscle_gain_pct": 0, + "endurance_pct": 20, + "strength_pct": 10, + "flexibility_pct": 5, + "health_pct": 5 +} +``` + +--- + +### 3.2 Überarbeitete Goal-Typen + +**Tabelle: `goals` (ÜBERARBEITET)** + +**A) Simple Goals (ein Wert):** +```sql +goal_type: +- 'weight' β†’ kg (aus weight_log) +- 'body_fat_pct' β†’ % (aus caliper_log) +- 'lean_mass' β†’ kg (berechnet: weight - (weight * bf_pct)) +- 'vo2max' β†’ ml/kg/min (aus vitals_baseline) +- 'rhr' β†’ bpm (aus vitals_baseline) +- 'hrv' β†’ ms (aus vitals_baseline) +``` + +**B) Test-based Goals (standardisierte Tests):** +```sql +goal_type: +- 'cooper_test' β†’ Meter (12min Lauf) +- 'pushups_max' β†’ Anzahl +- 'plank_max' β†’ Sekunden +- 'sit_reach' β†’ cm (Beweglichkeit) +- 'squat_1rm' β†’ kg (Kraft UnterkΓΆrper) +- 'bench_1rm' β†’ kg (Kraft OberkΓΆrper) +- 'deadlift_1rm' β†’ kg (Kraft RΓΌcken) +``` + +**C) Compound Goals (mehrere Werte):** +```sql +goal_type: +- 'blood_pressure' β†’ systolic/diastolic (mmHg) + β†’ Braucht: target_value_secondary +``` + +**Schema-Erweiterung:** +```sql +ALTER TABLE goals ADD COLUMN goal_weight INT DEFAULT 100; + -- Gewichtung dieses Ziels (0-100%) + -- Summe aller goal_weight fΓΌr einen User sollte ~100% sein + +ALTER TABLE goals ADD COLUMN target_value_secondary DECIMAL(10,2); + -- FΓΌr Compound Goals (z.B. BP diastolisch) + +ALTER TABLE goals ADD COLUMN current_value_secondary DECIMAL(10,2); + -- Aktueller Wert fΓΌr sekundΓ€ren Target + +ALTER TABLE goals DROP COLUMN is_primary; + -- Nicht mehr nΓΆtig (wird durch goal_weight ersetzt) + +COMMENT ON COLUMN goals.goal_weight IS + 'Weight/priority of this goal (0-100%). + Higher weight = more important in AI scoring. + Sum of all goal_weight should be ~100% per user.'; +``` + +--- + +### 3.3 Datenquellen-Mapping + +**Korrekte Current-Value Extraktion:** + +```python +# backend/routers/goals.py - _get_current_value_for_goal_type() + +GOAL_TYPE_SOURCES = { + # Simple values from existing tables + 'weight': { + 'table': 'weight_log', + 'column': 'weight', + 'order': 'date DESC' + }, + 'body_fat_pct': { + 'table': 'caliper_log', + 'column': 'body_fat_pct', + 'order': 'date DESC' + }, + 'lean_mass': { + 'calculation': 'weight - (weight * body_fat_pct / 100)', + 'requires': ['weight_log', 'caliper_log'] + }, + 'vo2max': { + 'table': 'vitals_baseline', + 'column': 'vo2_max', + 'order': 'date DESC' + }, + 'rhr': { + 'table': 'vitals_baseline', + 'column': 'resting_hr', + 'order': 'date DESC' + }, + 'hrv': { + 'table': 'vitals_baseline', + 'column': 'hrv', + 'order': 'date DESC' + }, + + # Test-based values from fitness_tests + 'cooper_test': { + 'table': 'fitness_tests', + 'filter': "test_type = 'cooper_12min'", + 'column': 'result_value', + 'order': 'test_date DESC' + }, + 'pushups_max': { + 'table': 'fitness_tests', + 'filter': "test_type = 'pushups_max'", + 'column': 'result_value', + 'order': 'test_date DESC' + }, + # ... weitere Tests + + # Compound goals + 'blood_pressure': { + 'table': 'blood_pressure_log', + 'columns': ['systolic', 'diastolic'], # Beide Werte + 'order': 'measured_at DESC' + } +} +``` + +--- + +## 4. UI/UX Redesign + +### 4.1 Fokus-Bereiche Konfigurator + +**Statt 5 einzelne Cards β†’ Slider-Interface:** + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ 🎯 Mein Trainings-Fokus β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ Verschiebe die Regler um deine PrioritΓ€ten zu β”‚ +β”‚ setzen. Die Summe muss 100% ergeben. β”‚ +β”‚ β”‚ +β”‚ πŸ“‰ Gewichtsverlust [====] 30% β”‚ +β”‚ Schwerpunkt auf Kaloriendefizit & Fettabbau β”‚ +β”‚ β”‚ +β”‚ πŸ’ͺ Muskelaufbau [===] 20% β”‚ +β”‚ Magermasse steigern, KΓΆrperkomposition β”‚ +β”‚ β”‚ +β”‚ πŸƒ Ausdauer [====] 25% β”‚ +β”‚ VO2Max, aerobe KapazitΓ€t, Pace β”‚ +β”‚ β”‚ +β”‚ πŸ‹οΈ Maximalkraft [==] 15% β”‚ +β”‚ 1RM Steigerung, progressive Belastung β”‚ +β”‚ β”‚ +β”‚ 🀸 Beweglichkeit [=] 10% β”‚ +β”‚ MobilitΓ€t, FlexibilitΓ€t, Koordination β”‚ +β”‚ β”‚ +β”‚ ❀️ Allgemeine Gesundheit [ ] 0% β”‚ +β”‚ Erhaltung, prΓ€ventiv β”‚ +β”‚ β”‚ +β”‚ ────────────────────────────────────────────────── β”‚ +β”‚ Gesamt: 100% βœ“ β”‚ +β”‚ β”‚ +β”‚ [Speichern] [ZurΓΌcksetzen] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +**Technisch:** +- HTML Range Slider (0-100) +- Live-Update der Summe +- Validierung: Summe muss 100% sein +- Auto-Adjust: Wenn User einen Slider erhΓΆht, andere proportional reduzieren + +--- + +### 4.2 Ziele mit Gewichtung + +**Goal-List mit Gewichtungs-Indikator:** + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ 🎯 Konkrete Ziele β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ βš–οΈ Zielgewicht: 82 kg [30%]β”‚ β”‚ +β”‚ β”‚ Start: 95 kg β†’ Aktuell: 89 kg β†’ Ziel: 82 kg β”‚ β”‚ +β”‚ β”‚ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 65% β”‚ β”‚ +β”‚ β”‚ βœ“ Voraussichtlich: 15.05.2026 (on track) β”‚ β”‚ +β”‚ β”‚ [✏️] [πŸ—‘οΈ] β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ πŸ’ͺ Magermasse: 72 kg [20%]β”‚ β”‚ +β”‚ β”‚ Start: 68 kg β†’ Aktuell: 70.5 kg β†’ Ziel: 72 kgβ”‚ β”‚ +β”‚ β”‚ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 63% β”‚ β”‚ +β”‚ β”‚ ⚠ Prognose: 20.06.2026 (5 Tage spΓ€ter) β”‚ β”‚ +β”‚ β”‚ [✏️] [πŸ—‘οΈ] β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ [+ Neues Ziel] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +Summe Gewichtungen: 50% (noch 50% verfΓΌgbar) +``` + +**Γ„nderungen:** +- Gewichtung in `[30%]` Badge angezeigt +- Summe unten angezeigt +- Warnung wenn Summe > 100% + +--- + +### 4.3 Ziel-Editor mit Guidance + +**Beispiel: VO2Max Ziel erstellen:** + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Neues Ziel erstellen β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ Zieltyp β”‚ +β”‚ [VO2 Max β–Ό] β”‚ +β”‚ β”‚ +β”‚ ℹ️ VO2 Max (ml/kg/min) - Maximale Sauerstoffauf- β”‚ +β”‚ nahme. Misst die aerobe LeistungsfΓ€higkeit. β”‚ +β”‚ β”‚ +β”‚ πŸ“Š Richtwerte (MΓ€nner, 35 Jahre): β”‚ +β”‚ Sehr gut: > 48 ml/kg/min β”‚ +β”‚ Gut: 44-48 ml/kg/min β”‚ +β”‚ Durchschn.: 40-44 ml/kg/min β”‚ +β”‚ Unterdurch.: 35-40 ml/kg/min β”‚ +β”‚ β”‚ +β”‚ 🎯 Zielwert β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ [ 46 ] β”‚ ml/kg/minβ”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ Dein aktueller Wert: 42 ml/kg/min (Durchschnitt) β”‚ +β”‚ β†’ Ziel liegt in "Gut"-Bereich βœ“ β”‚ +β”‚ β”‚ +β”‚ πŸ“… Zieldatum (optional) β”‚ +β”‚ [2026-06-30] β”‚ +β”‚ β”‚ +β”‚ βš–οΈ Gewichtung β”‚ +β”‚ [==== ] 25% β”‚ +β”‚ Wie wichtig ist dir dieses Ziel? β”‚ +β”‚ β”‚ +β”‚ πŸ’‘ Name (optional) β”‚ +β”‚ [Ausdauer fΓΌr Bergwandern ] β”‚ +β”‚ β”‚ +β”‚ [Ziel erstellen] [Abbrechen] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +**Features:** +- Info-Box mit ErklΓ€rung +- Alters-/geschlechtsspezifische Richtwerte +- Live-Feedback zum eingegebenen Wert +- Aktueller Wert automatisch geladen +- Gewichtungs-Slider mit Live-Preview + +--- + +### 4.4 Compound Goals (Blutdruck) + +**Spezial-UI fΓΌr Blutdruck:** + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Zieltyp: Blutdruck β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ 🎯 Zielwerte β”‚ +β”‚ β”‚ +β”‚ Systolisch (oberer Wert) β”‚ +β”‚ [ 120 ] mmHg β”‚ +β”‚ β”‚ +β”‚ Diastolisch (unterer Wert) β”‚ +β”‚ [ 80 ] mmHg β”‚ +β”‚ β”‚ +β”‚ ℹ️ WHO/ISH Klassifikation: β”‚ +β”‚ Optimal: < 120/80 mmHg β”‚ +β”‚ Normal: 120-129 / 80-84 mmHg β”‚ +β”‚ Hoch-norm.: 130-139 / 85-89 mmHg β”‚ +β”‚ Hypertonie: β‰₯ 140/90 mmHg β”‚ +β”‚ β”‚ +β”‚ Dein aktueller Wert: 135/88 mmHg (Hoch-normal) β”‚ +β”‚ Dein Ziel: 120/80 mmHg (Optimal) βœ“ β”‚ +β”‚ β”‚ +β”‚ [Ziel erstellen] [Abbrechen] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +--- + +## 5. Scoring-System mit Gewichtung + +### 5.1 Score-Berechnung v2.0 + +**Aktuell (Phase 0a):** +```python +# Feste Gewichtung per goal_mode +SCORE_WEIGHTS = { + "strength": { + "body_progress": 0.35, + "nutrition": 0.30, + # ... + } +} +``` + +**Neu (v2.0):** +```python +def calculate_weighted_score(profile_id): + """ + Berechnet Score basierend auf: + 1. Focus Areas (Multi-dimensional statt single mode) + 2. Goal Weights (individuelle Ziel-Gewichtungen) + """ + + # 1. Hole Focus Areas + focus = get_focus_areas(profile_id) + # β†’ {weight_loss: 30%, muscle_gain: 20%, endurance: 25%, ...} + + # 2. Hole alle Ziele mit Gewichtung + goals = get_goals_with_weights(profile_id) + # β†’ [{type: 'weight', weight: 30%}, {type: 'lean_mass', weight: 20%}, ...] + + # 3. Berechne Basis-Scores + base_scores = { + 'body_composition': calculate_body_score(profile_id), + 'nutrition': calculate_nutrition_score(profile_id), + 'training': calculate_training_score(profile_id), + 'recovery': calculate_recovery_score(profile_id) + } + + # 4. Gewichte Scores nach Focus Areas + weighted_score = 0 + + # Weight Loss Focus β†’ Body Composition + Nutrition wichtiger + if focus['weight_loss_pct'] > 0: + weighted_score += ( + base_scores['body_composition'] * 0.4 + + base_scores['nutrition'] * 0.4 + + base_scores['training'] * 0.1 + + base_scores['recovery'] * 0.1 + ) * (focus['weight_loss_pct'] / 100) + + # Muscle Gain Focus β†’ Body + Nutrition + Training + if focus['muscle_gain_pct'] > 0: + weighted_score += ( + base_scores['body_composition'] * 0.35 + + base_scores['nutrition'] * 0.35 + + base_scores['training'] * 0.25 + + base_scores['recovery'] * 0.05 + ) * (focus['muscle_gain_pct'] / 100) + + # Endurance Focus β†’ Training + Recovery + if focus['endurance_pct'] > 0: + weighted_score += ( + base_scores['training'] * 0.50 + + base_scores['recovery'] * 0.30 + + base_scores['body_composition'] * 0.10 + + base_scores['nutrition'] * 0.10 + ) * (focus['endurance_pct'] / 100) + + # ... weitere Focus Areas + + return { + 'overall_score': round(weighted_score, 1), + 'base_scores': base_scores, + 'focus_weights': focus, + 'goal_weights': [g['weight'] for g in goals] + } +``` + +**Beispiel:** +```python +User: 30% Weight Loss + 25% Endurance + 20% Muscle Gain + 25% Strength + +Base Scores: +- Body Composition: 75/100 +- Nutrition: 80/100 +- Training: 70/100 +- Recovery: 65/100 + +Calculation: +Weight Loss (30%): + = (75*0.4 + 80*0.4 + 70*0.1 + 65*0.1) * 0.30 + = 69.5 * 0.30 = 20.85 + +Endurance (25%): + = (70*0.50 + 65*0.30 + 75*0.10 + 80*0.10) * 0.25 + = 69.0 * 0.25 = 17.25 + +Muscle Gain (20%): + = (75*0.35 + 80*0.35 + 70*0.25 + 65*0.05) * 0.20 + = 74.0 * 0.20 = 14.80 + +Strength (25%): + = (70*0.40 + 80*0.30 + 75*0.20 + 65*0.10) * 0.25 + = 72.5 * 0.25 = 18.13 + +Overall Score = 20.85 + 17.25 + 14.80 + 18.13 = 71.03/100 +``` + +--- + +## 6. Migration-Strategie + +### 6.1 Daten-Migration von Phase 0a + +**Bestehende Daten:** +- `profiles.goal_mode` (single mode) +- `goals` mit `is_primary` + +**Migrations-Logik:** +```sql +-- Migration 023: Goal System Redesign v2.0 + +-- 1. Erstelle focus_areas Tabelle +CREATE TABLE focus_areas (...); + +-- 2. Migriere bestehende goal_mode β†’ focus_areas +INSERT INTO focus_areas (profile_id, weight_loss_pct, muscle_gain_pct, ...) +SELECT + id, + CASE goal_mode + WHEN 'weight_loss' THEN 70 -- 70% Weight Loss + 15% Health + 15% Endurance + WHEN 'strength' THEN 0 + -- ... + END as weight_loss_pct, + CASE goal_mode + WHEN 'strength' THEN 60 + WHEN 'recomposition' THEN 30 + -- ... + END as muscle_gain_pct, + -- ... weitere +FROM profiles +WHERE goal_mode IS NOT NULL; + +-- 3. Erweitere goals Tabelle +ALTER TABLE goals ADD COLUMN goal_weight INT DEFAULT 100; +ALTER TABLE goals ADD COLUMN target_value_secondary DECIMAL(10,2); +ALTER TABLE goals ADD COLUMN current_value_secondary DECIMAL(10,2); + +-- 4. Migriere is_primary β†’ goal_weight +UPDATE goals SET goal_weight = 100 WHERE is_primary = true; +UPDATE goals SET goal_weight = 50 WHERE is_primary = false; + +-- 5. Cleanup (spΓ€ter) +-- ALTER TABLE profiles DROP COLUMN goal_mode; -- nach Verifikation +-- ALTER TABLE goals DROP COLUMN is_primary; -- nach Verifikation +``` + +--- + +## 7. Implementierungs-Phasen + +### Phase 1: Konzeption βœ… (DIESES DOKUMENT) +**Dauer:** - +**Ziel:** VollstΓ€ndiges Redesign-Konzept + +### Phase 2: Backend Redesign (6-8h) +- Migration 023 erstellen +- `focus_areas` Tabelle + CRUD +- `goals` erweitern (weight, secondary values) +- Datenquellen-Mapping korrigieren (lean_mass, VO2Max fix, etc.) +- Scoring-System v2.0 implementieren + +### Phase 3: Frontend Redesign (8-10h) +- Fokus-Bereiche Slider-UI +- Ziel-Editor mit Guidance (Richtwerte, Normen) +- Gewichtungs-System in Goal-Liste +- Compound Goals UI (Blutdruck zwei Werte) +- Neue Goal-Typen (Tests) integrieren + +### Phase 4: Testing & Refinement (2-3h) +- Migration testen (Phase 0a β†’ v2.0) +- Scoring-Logik verifizieren +- UI/UX Testing +- Edge Cases (Summe β‰  100%, keine Ziele, etc.) + +**Total: 16-21h** + +--- + +## 8. Offene Fragen / Entscheidungen + +### 8.1 Focus Areas vs Goals Weight +**Frage:** Brauchen wir BEIDE Gewichtungssysteme? +- Focus Areas (Weight Loss 30%, Strength 25%, ...) +- Goal Weights (Ziel "82kg" = 30%, Ziel "VO2Max 46" = 25%, ...) + +**Option A:** NUR Focus Areas +- Einfacher +- Weniger Redundanz +- Aber: Weniger granular + +**Option B:** BEIDE Systeme +- Focus Areas = Strategisch (Richtung) +- Goal Weights = Taktisch (konkrete PrioritΓ€ten) +- Komplexer, aber flexibler + +**Empfehlung:** Option B - beide Systeme ergΓ€nzen sich + +--- + +### 8.2 Konkrete vs Abstrakte Tests +**Frage:** Wie konkret sollen Strength-Goals sein? + +**Option A:** Sehr konkret +- `bench_press_1rm`, `squat_1rm`, `deadlift_1rm` +- Vorteil: PrΓ€zise, messbar +- Nachteil: Viele Goal-Typen + +**Option B:** Abstrakt mit Kontext +- `strength` mit Sub-Type (Bench/Squat/Deadlift) +- Vorteil: Flexibler +- Nachteil: Komplizierteres Schema + +**Empfehlung:** Option A - konkrete Typen, dafΓΌr klare Messbarkeit + +--- + +### 8.3 Auto-Update von Current Values +**Frage:** Wie oft sollen current_value aktualisiert werden? + +**Option A:** On-Demand (beim Laden der Goals-Seite) +- Vorteil: Keine Background-Jobs +- Nachteil: Kann verzΓΆgert sein + +**Option B:** Trigger-basiert (bei neuem Messwert) +- Vorteil: Immer aktuell +- Nachteil: Mehr KomplexitΓ€t + +**Empfehlung:** Option A fΓΌr MVP, Option B spΓ€ter + +--- + +## 9. NΓ€chste Schritte + +### User-Feedback einholen: +1. βœ… LΓΆst das Redesign alle genannten Probleme? +2. βœ… Ist die Fokus-Bereiche UI verstΓ€ndlich? +3. βœ… Sind die konkreten Goal-Typen sinnvoll? +4. βœ… Brauchen wir beide Gewichtungssysteme? +5. βœ… Fehlt noch etwas? + +### Nach Freigabe: +1. Migration 023 schreiben +2. Backend implementieren +3. Frontend implementieren +4. Testing + +--- + +**Erstellt:** 26. MΓ€rz 2026 +**Status:** πŸ“‹ WARTET AUF FEEDBACK +**NΓ€chster Schritt:** User-Review & Freigabe