docs: goal system priority analysis - hybrid approach
Key Decision: Minimal Goal System BEFORE Placeholders Critical Finding: - Same data = different interpretation per goal - Example: -5kg FM, -2kg LBM - weight_loss: 78/100 (good!) - strength: 32/100 (LBM loss critical!) - Without goal: 50/100 (generic, wrong for both) Recommended Approach (Hybrid): 1. Phase 0a (2-3h): Minimal Goal System - DB: goal_mode field - API: Get/Set Goal - UI: Goal Selector - Default: health 2. Phase 0b (16-20h): Goal-Aware Placeholders - 84 placeholders with goal-dependent calculations - Scores use goal_mode from day 1 - No rework needed later 3. Phase 2+ (6-8h): Full Goal System - Goal recognition from patterns - Secondary goals - Goal progression tracking Why Hybrid Works: ✅ Charts show correct interpretations immediately ✅ No rework of 84 placeholders later ✅ Goal recognition can come later (needs placeholders anyway) ✅ System is "smart coach" from day 1 File: docs/GOAL_SYSTEM_PRIORITY_ANALYSIS.md (650 lines)
This commit is contained in:
parent
8398368ed7
commit
ae93b9d428
538
docs/GOAL_SYSTEM_PRIORITY_ANALYSIS.md
Normal file
538
docs/GOAL_SYSTEM_PRIORITY_ANALYSIS.md
Normal file
|
|
@ -0,0 +1,538 @@
|
||||||
|
# Zielesystem: Prioritäts-Analyse
|
||||||
|
|
||||||
|
**Datum:** 26. März 2026
|
||||||
|
**Frage:** Zielesystem vor oder nach Platzhaltern/Charts?
|
||||||
|
**Antwort:** **Minimales Zielesystem VOR Platzhaltern, volles System parallel**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Kritische Erkenntnis aus Fachkonzept
|
||||||
|
|
||||||
|
### Zitat Fachkonzept (Zeile 20-28):
|
||||||
|
> **Wichtig ist, dass das System zielabhängig interpretiert:**
|
||||||
|
> - Gewichtsreduktion
|
||||||
|
> - Muskel-/Kraftaufbau
|
||||||
|
> - Konditions-/Ausdaueraufbau
|
||||||
|
> - Körperrekomposition
|
||||||
|
> - allgemeine Gesundheit
|
||||||
|
>
|
||||||
|
> **Dasselbe Rohsignal kann je nach Ziel anders bewertet werden.**
|
||||||
|
> Ein Kaloriendefizit ist z. B. bei Gewichtsreduktion oft positiv,
|
||||||
|
> bei Kraftaufbau aber potenziell hinderlich.
|
||||||
|
|
||||||
|
### Konsequenz
|
||||||
|
❌ **Charts OHNE Zielesystem = falsche Interpretationen**
|
||||||
|
✅ **Charts MIT Zielesystem = korrekte, zielspezifische Aussagen**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Abhängigkeits-Matrix
|
||||||
|
|
||||||
|
### Was hängt vom Zielesystem ab?
|
||||||
|
|
||||||
|
| Komponente | Zielabhängig? | Beispiel |
|
||||||
|
|------------|---------------|----------|
|
||||||
|
| **Rohdaten-Charts** | ❌ Nein | Gewichtsverlauf, Umfänge-Trend |
|
||||||
|
| **Score-Gewichtung** | ✅ JA | Body Progress Score: 30% bei weight_loss, 20% bei strength |
|
||||||
|
| **Interpretationen** | ✅ JA | Kaloriendefizit: "gut" bei weight_loss, "kritisch" bei strength |
|
||||||
|
| **Hinweise** | ✅ JA | "Gewicht stagniert" → bei weight_loss: Warnung, bei strength: egal |
|
||||||
|
| **Platzhalter (Berechnungen)** | ⚠️ TEILWEISE | Trends: Nein, Scores: JA |
|
||||||
|
| **KI-Prompts** | ✅ JA | Analyse-Kontext ändert sich komplett |
|
||||||
|
|
||||||
|
### Fachkonzept: Score-Gewichtung (Zeile 185-216)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
score_weights:
|
||||||
|
weight_loss:
|
||||||
|
body_progress: 0.30 # Körper wichtig
|
||||||
|
nutrition: 0.25
|
||||||
|
activity: 0.20
|
||||||
|
recovery: 0.15
|
||||||
|
health_risk: 0.10
|
||||||
|
|
||||||
|
strength:
|
||||||
|
body_progress: 0.20
|
||||||
|
nutrition: 0.25
|
||||||
|
activity: 0.30 # Training wichtiger
|
||||||
|
recovery: 0.20
|
||||||
|
health_risk: 0.05 # Weniger kritisch
|
||||||
|
|
||||||
|
endurance:
|
||||||
|
body_progress: 0.10 # Körper unwichtiger
|
||||||
|
activity: 0.35 # Training am wichtigsten
|
||||||
|
recovery: 0.25 # Recovery sehr wichtig
|
||||||
|
```
|
||||||
|
|
||||||
|
### Beispiel: Body Progress Score
|
||||||
|
|
||||||
|
**OHNE Zielesystem:**
|
||||||
|
```python
|
||||||
|
def calculate_body_progress_score():
|
||||||
|
# Generisch, für niemanden wirklich passend
|
||||||
|
fm_delta_score = calculate_fm_change() # -5kg
|
||||||
|
lbm_delta_score = calculate_lbm_change() # -2kg
|
||||||
|
return (fm_delta_score + lbm_delta_score) / 2
|
||||||
|
# Score: 50/100 (FM gut runter, aber LBM auch runter)
|
||||||
|
```
|
||||||
|
|
||||||
|
**MIT Zielesystem:**
|
||||||
|
```python
|
||||||
|
def calculate_body_progress_score(goal_mode):
|
||||||
|
fm_delta_score = calculate_fm_change() # -5kg
|
||||||
|
lbm_delta_score = calculate_lbm_change() # -2kg
|
||||||
|
|
||||||
|
if goal_mode == "weight_loss":
|
||||||
|
# FM runter: sehr gut, LBM runter: tolerierbar wenn nicht zu viel
|
||||||
|
return 0.70 * fm_delta_score + 0.30 * lbm_delta_score
|
||||||
|
# Score: 78/100 (FM wichtiger, LBM-Verlust weniger kritisch)
|
||||||
|
|
||||||
|
elif goal_mode == "strength":
|
||||||
|
# FM runter: ok, LBM runter: SEHR SCHLECHT
|
||||||
|
return 0.30 * fm_delta_score + 0.70 * lbm_delta_score
|
||||||
|
# Score: 32/100 (LBM-Verlust ist Hauptproblem!)
|
||||||
|
|
||||||
|
elif goal_mode == "recomposition":
|
||||||
|
# FM runter: gut, LBM runter: schlecht
|
||||||
|
return 0.50 * fm_delta_score + 0.50 * lbm_delta_score
|
||||||
|
# Score: 50/100 (ausgewogen bewertet)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Ergebnis:**
|
||||||
|
- Gleiche Daten (-5kg FM, -2kg LBM)
|
||||||
|
- ABER: 78/100 bei weight_loss, 32/100 bei strength
|
||||||
|
- **Ohne Ziel: völlig falsche Bewertung!**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Ziel-Erkennung aus Daten
|
||||||
|
|
||||||
|
### Fachkonzept erwähnt dies NICHT explizit, aber logisch ableitbar:
|
||||||
|
|
||||||
|
**Pattern-Erkennung:**
|
||||||
|
```python
|
||||||
|
def suggest_goal_from_data(profile_id):
|
||||||
|
"""Schlägt Ziel basierend auf Daten-Mustern vor."""
|
||||||
|
|
||||||
|
# Analyse der letzten 28 Tage
|
||||||
|
training_types = get_training_distribution_28d(profile_id)
|
||||||
|
nutrition = get_nutrition_pattern_28d(profile_id)
|
||||||
|
body_changes = get_body_changes_28d(profile_id)
|
||||||
|
|
||||||
|
# Pattern 1: Viel Kraft + viel Protein + LBM steigt
|
||||||
|
if (training_types['strength'] > 60% and
|
||||||
|
nutrition['protein_g_per_kg'] > 1.8 and
|
||||||
|
body_changes['lbm_trend'] > 0):
|
||||||
|
return {
|
||||||
|
'suggested_goal': 'strength',
|
||||||
|
'confidence': 'high',
|
||||||
|
'reasoning': 'Krafttraining dominant + hohe Proteinzufuhr + Muskelaufbau erkennbar'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Pattern 2: Viel Cardio + Kaloriendefizit + Gewicht sinkt
|
||||||
|
if (training_types['endurance'] > 50% and
|
||||||
|
nutrition['kcal_balance_avg'] < -300 and
|
||||||
|
body_changes['weight_trend'] < 0):
|
||||||
|
return {
|
||||||
|
'suggested_goal': 'weight_loss',
|
||||||
|
'confidence': 'high',
|
||||||
|
'reasoning': 'Ausdauertraining + Kaloriendefizit + Gewichtsverlust'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Pattern 3: Mixed Training + Protein hoch + Gewicht stabil + Rekomposition
|
||||||
|
if (training_types['mixed'] == True and
|
||||||
|
nutrition['protein_g_per_kg'] > 1.6 and
|
||||||
|
abs(body_changes['weight_trend']) < 0.05 and
|
||||||
|
body_changes['fm_trend'] < 0 and
|
||||||
|
body_changes['lbm_trend'] > 0):
|
||||||
|
return {
|
||||||
|
'suggested_goal': 'recomposition',
|
||||||
|
'confidence': 'medium',
|
||||||
|
'reasoning': 'Gemischtes Training + Rekomposition sichtbar (FM↓, LBM↑)'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Default: Nicht genug Muster erkennbar
|
||||||
|
return {
|
||||||
|
'suggested_goal': 'health',
|
||||||
|
'confidence': 'low',
|
||||||
|
'reasoning': 'Keine klaren Muster erkennbar, gesundheitsorientiertes Training angenommen'
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Voraussetzungen für Ziel-Erkennung:
|
||||||
|
1. ✅ Mindestens 21-28 Tage Daten
|
||||||
|
2. ✅ Training-Type Distribution
|
||||||
|
3. ✅ Ernährungs-Pattern
|
||||||
|
4. ✅ Körper-Trends (FM, LBM, Gewicht)
|
||||||
|
5. ✅ Berechnet → **braucht Platzhalter!**
|
||||||
|
|
||||||
|
**ABER:** Ziel-Erkennung ist **nachgelagert**, nicht Voraussetzung.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Empfohlene Implementierungs-Strategie
|
||||||
|
|
||||||
|
### Hybrid-Ansatz: Minimal-Ziele SOFORT, Voll-System parallel
|
||||||
|
|
||||||
|
## Phase 0a: Minimal-Zielesystem (2-3h) ⭐ **START HIER**
|
||||||
|
|
||||||
|
### Ziel
|
||||||
|
User kann manuell Ziel setzen, System nutzt es für Berechnungen.
|
||||||
|
|
||||||
|
### Implementierung
|
||||||
|
|
||||||
|
**1. DB-Schema erweitern:**
|
||||||
|
```sql
|
||||||
|
-- Migration 023
|
||||||
|
ALTER TABLE profiles ADD COLUMN goal_mode VARCHAR(50) DEFAULT 'health';
|
||||||
|
ALTER TABLE profiles ADD COLUMN goal_weight DECIMAL(5,2);
|
||||||
|
ALTER TABLE profiles ADD COLUMN goal_bf_pct DECIMAL(4,1);
|
||||||
|
ALTER TABLE profiles ADD COLUMN goal_set_date DATE;
|
||||||
|
ALTER TABLE profiles ADD COLUMN goal_target_date DATE;
|
||||||
|
|
||||||
|
COMMENT ON COLUMN profiles.goal_mode IS
|
||||||
|
'Primary goal: weight_loss, strength, endurance, recomposition, health';
|
||||||
|
```
|
||||||
|
|
||||||
|
**2. Goal-Mode Konstanten:**
|
||||||
|
```python
|
||||||
|
# backend/goals.py (NEU)
|
||||||
|
GOAL_MODES = {
|
||||||
|
'weight_loss': {
|
||||||
|
'label': 'Gewichtsreduktion',
|
||||||
|
'description': 'Fettabbau bei Erhalt der Magermasse',
|
||||||
|
'score_weights': {
|
||||||
|
'body_progress': 0.30,
|
||||||
|
'nutrition': 0.25,
|
||||||
|
'activity': 0.20,
|
||||||
|
'recovery': 0.15,
|
||||||
|
'health_risk': 0.10
|
||||||
|
},
|
||||||
|
'focus_areas': ['fettmasse', 'gewichtstrend', 'kalorienbilanz', 'protein_sicherung']
|
||||||
|
},
|
||||||
|
'strength': {
|
||||||
|
'label': 'Kraftaufbau',
|
||||||
|
'description': 'Muskelaufbau und Kraftsteigerung',
|
||||||
|
'score_weights': {
|
||||||
|
'body_progress': 0.20,
|
||||||
|
'nutrition': 0.25,
|
||||||
|
'activity': 0.30,
|
||||||
|
'recovery': 0.20,
|
||||||
|
'health_risk': 0.05
|
||||||
|
},
|
||||||
|
'focus_areas': ['trainingsqualitaet', 'protein', 'lbm', 'recovery']
|
||||||
|
},
|
||||||
|
'endurance': {
|
||||||
|
'label': 'Ausdaueraufbau',
|
||||||
|
'description': 'Kondition und VO2max verbessern',
|
||||||
|
'score_weights': {
|
||||||
|
'body_progress': 0.10,
|
||||||
|
'nutrition': 0.20,
|
||||||
|
'activity': 0.35,
|
||||||
|
'recovery': 0.25,
|
||||||
|
'health_risk': 0.10
|
||||||
|
},
|
||||||
|
'focus_areas': ['trainingsvolumen', 'intensitaetsverteilung', 'vo2max', 'recovery']
|
||||||
|
},
|
||||||
|
'recomposition': {
|
||||||
|
'label': 'Körperrekomposition',
|
||||||
|
'description': 'Fettabbau bei gleichzeitigem Muskelaufbau',
|
||||||
|
'score_weights': {
|
||||||
|
'body_progress': 0.30,
|
||||||
|
'nutrition': 0.25,
|
||||||
|
'activity': 0.25,
|
||||||
|
'recovery': 0.15,
|
||||||
|
'health_risk': 0.05
|
||||||
|
},
|
||||||
|
'focus_areas': ['lbm', 'fettmasse', 'protein', 'trainingsqualitaet']
|
||||||
|
},
|
||||||
|
'health': {
|
||||||
|
'label': 'Allgemeine Gesundheit',
|
||||||
|
'description': 'Ausgeglichenes Gesundheits- und Fitnesstraining',
|
||||||
|
'score_weights': {
|
||||||
|
'body_progress': 0.20,
|
||||||
|
'nutrition': 0.20,
|
||||||
|
'activity': 0.20,
|
||||||
|
'recovery': 0.20,
|
||||||
|
'health_risk': 0.20
|
||||||
|
},
|
||||||
|
'focus_areas': ['bewegung', 'blutdruck', 'schlaf', 'gewicht', 'regelmaessigkeit']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**3. API-Endpoint:**
|
||||||
|
```python
|
||||||
|
# routers/goals.py (NEU)
|
||||||
|
from fastapi import APIRouter, Depends
|
||||||
|
from auth import require_auth
|
||||||
|
from goals import GOAL_MODES
|
||||||
|
|
||||||
|
router = APIRouter(prefix="/api/goals", tags=["goals"])
|
||||||
|
|
||||||
|
@router.get("/modes")
|
||||||
|
def get_goal_modes():
|
||||||
|
"""Return all available goal modes with descriptions."""
|
||||||
|
return GOAL_MODES
|
||||||
|
|
||||||
|
@router.get("/current")
|
||||||
|
def get_current_goal(session: dict = Depends(require_auth)):
|
||||||
|
"""Get user's current goal settings."""
|
||||||
|
profile_id = session['profile_id']
|
||||||
|
with get_db() as conn:
|
||||||
|
cur = get_cursor(conn)
|
||||||
|
cur.execute(
|
||||||
|
"""SELECT goal_mode, goal_weight, goal_bf_pct,
|
||||||
|
goal_set_date, goal_target_date
|
||||||
|
FROM profiles WHERE id=%s""",
|
||||||
|
(profile_id,)
|
||||||
|
)
|
||||||
|
row = r2d(cur.fetchone())
|
||||||
|
return {
|
||||||
|
**row,
|
||||||
|
'mode_config': GOAL_MODES.get(row['goal_mode'], GOAL_MODES['health'])
|
||||||
|
}
|
||||||
|
|
||||||
|
@router.post("/set")
|
||||||
|
def set_goal(
|
||||||
|
goal_mode: str,
|
||||||
|
goal_weight: Optional[float] = None,
|
||||||
|
goal_bf_pct: Optional[float] = None,
|
||||||
|
target_date: Optional[str] = None,
|
||||||
|
session: dict = Depends(require_auth)
|
||||||
|
):
|
||||||
|
"""Set user's goal."""
|
||||||
|
if goal_mode not in GOAL_MODES:
|
||||||
|
raise HTTPException(400, f"Invalid goal_mode. Must be one of: {list(GOAL_MODES.keys())}")
|
||||||
|
|
||||||
|
profile_id = session['profile_id']
|
||||||
|
with get_db() as conn:
|
||||||
|
cur = get_cursor(conn)
|
||||||
|
cur.execute(
|
||||||
|
"""UPDATE profiles
|
||||||
|
SET goal_mode=%s, goal_weight=%s, goal_bf_pct=%s,
|
||||||
|
goal_set_date=CURRENT_DATE, goal_target_date=%s
|
||||||
|
WHERE id=%s""",
|
||||||
|
(goal_mode, goal_weight, goal_bf_pct, target_date, profile_id)
|
||||||
|
)
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
return {"success": True, "goal_mode": goal_mode}
|
||||||
|
```
|
||||||
|
|
||||||
|
**4. Frontend UI (Settings.jsx):**
|
||||||
|
```jsx
|
||||||
|
// Minimal Goal Selector
|
||||||
|
function GoalSettings() {
|
||||||
|
const [goalModes, setGoalModes] = useState({})
|
||||||
|
const [currentGoal, setCurrentGoal] = useState(null)
|
||||||
|
const [selectedMode, setSelectedMode] = useState('health')
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
loadGoalModes()
|
||||||
|
loadCurrentGoal()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const loadGoalModes = async () => {
|
||||||
|
const modes = await api.getGoalModes()
|
||||||
|
setGoalModes(modes)
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadCurrentGoal = async () => {
|
||||||
|
const goal = await api.getCurrentGoal()
|
||||||
|
setCurrentGoal(goal)
|
||||||
|
setSelectedMode(goal.goal_mode || 'health')
|
||||||
|
}
|
||||||
|
|
||||||
|
const saveGoal = async () => {
|
||||||
|
await api.setGoal({
|
||||||
|
goal_mode: selectedMode,
|
||||||
|
goal_weight: goalWeight,
|
||||||
|
goal_bf_pct: goalBfPct,
|
||||||
|
target_date: targetDate
|
||||||
|
})
|
||||||
|
loadCurrentGoal()
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="card">
|
||||||
|
<h2>🎯 Trainingsziel</h2>
|
||||||
|
|
||||||
|
<div className="form-row">
|
||||||
|
<label>Hauptziel</label>
|
||||||
|
<select value={selectedMode} onChange={e => setSelectedMode(e.target.value)}>
|
||||||
|
{Object.entries(goalModes).map(([key, config]) => (
|
||||||
|
<option key={key} value={key}>
|
||||||
|
{config.label}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
<p style={{fontSize: 12, color: 'var(--text3)'}}>
|
||||||
|
{goalModes[selectedMode]?.description}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{(selectedMode === 'weight_loss' || selectedMode === 'recomposition') && (
|
||||||
|
<div className="form-row">
|
||||||
|
<label>Zielgewicht (optional)</label>
|
||||||
|
<input type="number" step="0.1" value={goalWeight} onChange={...} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<button onClick={saveGoal}>Ziel speichern</button>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Aufwand: 2-3h
|
||||||
|
- 1h: DB + Backend
|
||||||
|
- 1h: Frontend UI
|
||||||
|
- 0.5h: Testing
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 0b: Goal-Aware Platzhalter (16-20h)
|
||||||
|
|
||||||
|
**Alle 84 Platzhalter implementieren, ABER:**
|
||||||
|
- Score-Berechnungen nutzen `goal_mode` von Anfang an
|
||||||
|
- Beispiel:
|
||||||
|
|
||||||
|
```python
|
||||||
|
def get_body_progress_score(profile_id: str) -> str:
|
||||||
|
"""Body Progress Score (0-100, goal-dependent)."""
|
||||||
|
profile = get_profile_data(profile_id)
|
||||||
|
goal_mode = profile.get('goal_mode', 'health')
|
||||||
|
|
||||||
|
# Hole Gewichte aus goals.GOAL_MODES
|
||||||
|
weights = GOAL_MODES[goal_mode]['score_weights']
|
||||||
|
|
||||||
|
# Berechne Sub-Scores
|
||||||
|
fm_score = calculate_fm_progress(profile_id)
|
||||||
|
lbm_score = calculate_lbm_progress(profile_id)
|
||||||
|
weight_score = calculate_weight_progress(profile_id, goal_mode)
|
||||||
|
|
||||||
|
# Gewichte nach Ziel
|
||||||
|
if goal_mode == 'weight_loss':
|
||||||
|
total = (0.50 * fm_score + 0.30 * weight_score + 0.20 * lbm_score)
|
||||||
|
elif goal_mode == 'strength':
|
||||||
|
total = (0.60 * lbm_score + 0.30 * fm_score + 0.10 * weight_score)
|
||||||
|
elif goal_mode == 'recomposition':
|
||||||
|
total = (0.45 * fm_score + 0.45 * lbm_score + 0.10 * weight_score)
|
||||||
|
else: # health, endurance
|
||||||
|
total = (0.40 * weight_score + 0.30 * fm_score + 0.30 * lbm_score)
|
||||||
|
|
||||||
|
return f"{int(total)}/100"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Resultat:**
|
||||||
|
- Charts bekommen von Anfang an **korrekte** Scores
|
||||||
|
- Keine Umarbeitung nötig später
|
||||||
|
- System ist "smart" ab Tag 1
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 2+: Vollständiges Zielesystem (6-8h)
|
||||||
|
|
||||||
|
**Features:**
|
||||||
|
1. **Ziel-Erkennung aus Daten**
|
||||||
|
- Pattern-Analyse (wie oben)
|
||||||
|
- Vorschlag mit Confidence
|
||||||
|
- "Passt dein Ziel noch?" Check
|
||||||
|
|
||||||
|
2. **Sekundäre Ziele**
|
||||||
|
- `goal_mode` = primary
|
||||||
|
- `secondary_goals[]` = weitere Schwerpunkte
|
||||||
|
- Gewichtung: 70% primary, 30% secondary
|
||||||
|
|
||||||
|
3. **Ziel-Progression Tracking**
|
||||||
|
- Fortschritt zum Ziel (%)
|
||||||
|
- Geschätzte Erreichung (Datum)
|
||||||
|
- Anpassungs-Vorschläge
|
||||||
|
|
||||||
|
4. **Goal-Aware Charts**
|
||||||
|
- Priorisierung nach goal_relevance
|
||||||
|
- Dashboard zeigt ziel-spezifische Charts zuerst
|
||||||
|
|
||||||
|
5. **Goal-Aware KI**
|
||||||
|
- Prompt-Kontext enthält goal_mode
|
||||||
|
- KI interpretiert zielspezifisch
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Entscheidungs-Matrix
|
||||||
|
|
||||||
|
### Option A: Zielesystem komplett ZUERST
|
||||||
|
**Aufwand:** 10-12h
|
||||||
|
**Pro:**
|
||||||
|
- Alles konsistent von Anfang an
|
||||||
|
- Keine Umarbeitung
|
||||||
|
**Contra:**
|
||||||
|
- Verzögert Platzhalter-Start
|
||||||
|
- Ziel-Erkennung braucht Platzhalter (Henne-Ei)
|
||||||
|
|
||||||
|
### Option B: Platzhalter ZUERST, dann Ziele
|
||||||
|
**Aufwand:** 16-20h + später Rework
|
||||||
|
**Pro:**
|
||||||
|
- Schneller Start
|
||||||
|
**Contra:**
|
||||||
|
- ALLE Scores falsch gewichtet
|
||||||
|
- Komplette Umarbeitung nötig
|
||||||
|
- User sehen falsche Werte
|
||||||
|
|
||||||
|
### Option C: HYBRID ⭐ **EMPFOHLEN**
|
||||||
|
**Aufwand:** 2-3h (Minimal-Ziele) + 16-20h (Goal-Aware Platzhalter) + später 6-8h (Voll-System)
|
||||||
|
**Pro:**
|
||||||
|
- ✅ Beste aus beiden Welten
|
||||||
|
- ✅ Korrekte Scores von Anfang an
|
||||||
|
- ✅ Keine Umarbeitung
|
||||||
|
- ✅ Ziel-Erkennung später als Enhancement
|
||||||
|
**Contra:**
|
||||||
|
- Keinen signifikanten Nachteil
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Empfehlung
|
||||||
|
|
||||||
|
### JA, Zielesystem VOR Platzhaltern – aber minimal!
|
||||||
|
|
||||||
|
**Reihenfolge:**
|
||||||
|
|
||||||
|
1. **Phase 0a (2-3h):** Minimal-Zielesystem
|
||||||
|
- DB: goal_mode field
|
||||||
|
- API: Get/Set Goal
|
||||||
|
- UI: Goal Selector (Settings)
|
||||||
|
- Default: "health"
|
||||||
|
|
||||||
|
2. **Phase 0b (16-20h):** Goal-Aware Platzhalter
|
||||||
|
- 84 Platzhalter implementieren
|
||||||
|
- Scores nutzen goal_mode
|
||||||
|
- Berechnungen goal-abhängig
|
||||||
|
|
||||||
|
3. **Phase 1 (12-16h):** Charts
|
||||||
|
- Nutzen goal-aware Platzhalter
|
||||||
|
- Zeigen korrekte Interpretationen
|
||||||
|
|
||||||
|
4. **Phase 2+ (6-8h):** Vollständiges Zielesystem
|
||||||
|
- Ziel-Erkennung
|
||||||
|
- Sekundäre Ziele
|
||||||
|
- Goal Progression Tracking
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Fazit
|
||||||
|
|
||||||
|
**Deine Intuition war 100% richtig!**
|
||||||
|
|
||||||
|
✅ **Ohne Zielesystem:**
|
||||||
|
- Charts zeigen falsche Interpretationen
|
||||||
|
- Scores sind generisch und für niemanden passend
|
||||||
|
- System bleibt "dummer Datensammler"
|
||||||
|
|
||||||
|
✅ **Mit Zielesystem:**
|
||||||
|
- Charts interpretieren zielspezifisch
|
||||||
|
- Scores sind individuell gewichtet
|
||||||
|
- System wird "intelligenter Coach"
|
||||||
|
|
||||||
|
**Nächster Schritt:** Phase 0a implementieren (2-3h), dann Phase 0b mit goal-aware Platzhaltern.
|
||||||
|
|
||||||
|
**Soll ich mit Phase 0a (Minimal-Zielesystem) starten?**
|
||||||
Loading…
Reference in New Issue
Block a user