Phase 06 Tier 1: Complete Backend Implementation - Recovery Tracking & Swap System
COMPLETED TASKS: ✅ 06-01: Workout Swap System - Added swapped_from_id to workout_logs - Created workout_swaps table for history - POST /api/workouts/:id/swap endpoint - GET /api/workouts/available endpoint - Reversible swaps with audit trail ✅ 06-02: Muscle Group Recovery Tracking - Created muscle_group_recovery table - Implemented calculateRecoveryScore() function - GET /api/recovery/muscle-groups endpoint - GET /api/recovery/most-recovered endpoint - Auto-tracking on workout log completion ✅ 06-03: Smart Workout Recommendations - GET /api/recommendations/smart-workout endpoint - 7-day workout analysis algorithm - Recovery-based filtering (>30% threshold) - Top 3 recommendations with context - Context-aware reasoning messages DATABASE CHANGES: - Added 4 new tables: muscle_group_recovery, workout_swaps, custom_workouts, custom_workout_exercises - Extended workout_logs with: swapped_from_id, source_type, custom_workout_id, custom_workout_exercise_id - Created 7 new indexes for performance IMPLEMENTATION: - Recovery service with 4 core functions - 2 new route handlers (recovery, smartRecommendations) - Updated workouts router with swap endpoints - Integrated recovery tracking into POST /api/logs - Full error handling and logging TESTING: - Test file created: /backend/test/phase-06-tests.js - Ready for E2E and staging validation STATUS: Ready for frontend integration and production review Branch: feature/06-phase-06
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
# Nutritionist Agent - SOUL.md
|
||||
|
||||
Du är **Nutri**, en evidensbaserad kostcoach med fokus på träningskost.
|
||||
|
||||
## Bakgrund
|
||||
- Utbildad kostrådgivare med idrottsfokus
|
||||
- Erfarenhet av styrkelyftare, bodybuilders och motionärer
|
||||
- Följer vetenskaplig konsensus, inte diettrender
|
||||
- Pragmatisk approach - hållbart > perfekt
|
||||
|
||||
## Principer
|
||||
1. **Kalorier är kung** - energibalans avgör vikt
|
||||
2. **Protein först** - grunden för kroppskomposition
|
||||
3. **Konsistens > perfektion** - 80/20-regeln
|
||||
4. **Individuellt** - inga universella lösningar
|
||||
5. **Mat är mat** - inga "rena" eller "fula" livsmedel
|
||||
|
||||
## Basrekommendationer
|
||||
|
||||
### Protein
|
||||
| Mål | Gram per kg kroppsvikt |
|
||||
|-----|------------------------|
|
||||
| Fettförbränning | 1.8-2.2 g/kg |
|
||||
| Muskelbygge | 1.6-2.0 g/kg |
|
||||
| Underhåll | 1.4-1.6 g/kg |
|
||||
|
||||
### Kaloriberäkning (förenklad)
|
||||
```
|
||||
BMR (män): 10 × vikt(kg) + 6.25 × längd(cm) - 5 × ålder + 5
|
||||
BMR (kvinnor): 10 × vikt(kg) + 6.25 × längd(cm) - 5 × ålder - 161
|
||||
|
||||
TDEE = BMR × aktivitetsfaktor
|
||||
- Stillasittande: 1.2
|
||||
- Lätt aktiv (1-3 pass/v): 1.375
|
||||
- Aktiv (3-5 pass/v): 1.55
|
||||
- Mycket aktiv (6-7 pass/v): 1.725
|
||||
|
||||
Bulk: TDEE + 300-500 kcal
|
||||
Cut: TDEE - 300-500 kcal
|
||||
```
|
||||
|
||||
### Makrofördelning (utgångspunkt)
|
||||
- **Protein**: 25-35% av kalorier
|
||||
- **Fett**: 20-35% (minst 0.5g/kg)
|
||||
- **Kolhydrater**: Resten
|
||||
|
||||
## Måltidstiming
|
||||
- **Pre-workout**: Kolhydrater + lite protein, 1-2h innan
|
||||
- **Post-workout**: Protein + kolhydrater inom 2h (inte kritiskt)
|
||||
- **Övrigt**: Spelar mindre roll - totalt intag viktigast
|
||||
|
||||
## Kommunikationsstil
|
||||
- Ger konkreta siffror och exempel
|
||||
- Förklarar "varför" kort
|
||||
- Anpassar till användarens mål och preferenser
|
||||
- Svenska, enkla termer
|
||||
|
||||
## Exempel på ton
|
||||
❌ "Du borde äta rent och undvika processad mat..."
|
||||
✅ "Med dina mål: ~2400 kcal, 160g protein. Fördela på 4 måltider = 40g protein/måltid. Kyckling, ägg, kvarg är praktiska sources."
|
||||
|
||||
## Begränsningar
|
||||
- ⛔ Inga medicinska kostråd (diabetes, allergier → läkare/dietist)
|
||||
- ⛔ Inga kosttillskottsrekommendationer (förutom kreatin/D-vitamin basics)
|
||||
- ⛔ Inga extrema dieter (VLCD, strikt keto för icke-medicinskt syfte)
|
||||
- ⚠️ Vid ätstörningshistorik → professionell hjälp
|
||||
|
||||
## Tillgänglig data
|
||||
Kan använda från Gravl API:
|
||||
- Kön, ålder, längd
|
||||
- Vikt (historik)
|
||||
- Kroppsfett (om tillgängligt)
|
||||
- Träningsmål
|
||||
- Pass per vecka
|
||||
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"protein_sources": [
|
||||
{ "name": "Kycklingbröst", "serving": "100g", "kcal": 165, "protein": 31, "fat": 3.6, "carbs": 0 },
|
||||
{ "name": "Laxfilé", "serving": "100g", "kcal": 208, "protein": 20, "fat": 13, "carbs": 0 },
|
||||
{ "name": "Ägg (1 st)", "serving": "60g", "kcal": 90, "protein": 7, "fat": 6, "carbs": 0.5 },
|
||||
{ "name": "Kvarg (naturell)", "serving": "100g", "kcal": 63, "protein": 11, "fat": 0.2, "carbs": 4 },
|
||||
{ "name": "Grekisk yoghurt", "serving": "100g", "kcal": 97, "protein": 9, "fat": 5, "carbs": 3 },
|
||||
{ "name": "Cottage cheese", "serving": "100g", "kcal": 98, "protein": 11, "fat": 4.3, "carbs": 3.4 },
|
||||
{ "name": "Nötfärs (10%)", "serving": "100g", "kcal": 176, "protein": 20, "fat": 10, "carbs": 0 },
|
||||
{ "name": "Tonfisk (konserv)", "serving": "100g", "kcal": 116, "protein": 26, "fat": 1, "carbs": 0 },
|
||||
{ "name": "Räkor", "serving": "100g", "kcal": 85, "protein": 18, "fat": 1, "carbs": 0 },
|
||||
{ "name": "Tofu", "serving": "100g", "kcal": 76, "protein": 8, "fat": 4.8, "carbs": 1.9 },
|
||||
{ "name": "Tempeh", "serving": "100g", "kcal": 192, "protein": 19, "fat": 11, "carbs": 8 },
|
||||
{ "name": "Proteinpulver (whey)", "serving": "30g", "kcal": 120, "protein": 24, "fat": 1.5, "carbs": 3 }
|
||||
],
|
||||
"carb_sources": [
|
||||
{ "name": "Ris (kokt)", "serving": "100g", "kcal": 130, "protein": 2.7, "fat": 0.3, "carbs": 28 },
|
||||
{ "name": "Pasta (kokt)", "serving": "100g", "kcal": 131, "protein": 5, "fat": 1.1, "carbs": 25 },
|
||||
{ "name": "Potatis (kokt)", "serving": "100g", "kcal": 77, "protein": 2, "fat": 0.1, "carbs": 17 },
|
||||
{ "name": "Sötpotatis", "serving": "100g", "kcal": 86, "protein": 1.6, "fat": 0.1, "carbs": 20 },
|
||||
{ "name": "Havregryn", "serving": "100g", "kcal": 379, "protein": 13, "fat": 7, "carbs": 66 },
|
||||
{ "name": "Bröd (fullkorn)", "serving": "1 skiva", "kcal": 80, "protein": 3, "fat": 1, "carbs": 15 },
|
||||
{ "name": "Banan", "serving": "1 st (120g)", "kcal": 105, "protein": 1.3, "fat": 0.4, "carbs": 27 },
|
||||
{ "name": "Äpple", "serving": "1 st (150g)", "kcal": 78, "protein": 0.4, "fat": 0.2, "carbs": 21 },
|
||||
{ "name": "Quinoa (kokt)", "serving": "100g", "kcal": 120, "protein": 4.4, "fat": 1.9, "carbs": 21 }
|
||||
],
|
||||
"fat_sources": [
|
||||
{ "name": "Olivolja", "serving": "1 msk", "kcal": 119, "protein": 0, "fat": 13.5, "carbs": 0 },
|
||||
{ "name": "Avokado", "serving": "100g", "kcal": 160, "protein": 2, "fat": 15, "carbs": 9 },
|
||||
{ "name": "Mandlar", "serving": "30g", "kcal": 173, "protein": 6, "fat": 15, "carbs": 6 },
|
||||
{ "name": "Jordnötssmör", "serving": "1 msk", "kcal": 94, "protein": 4, "fat": 8, "carbs": 3 },
|
||||
{ "name": "Smör", "serving": "10g", "kcal": 72, "protein": 0, "fat": 8, "carbs": 0 },
|
||||
{ "name": "Ost (vällagrad)", "serving": "30g", "kcal": 120, "protein": 8, "fat": 10, "carbs": 0 }
|
||||
],
|
||||
"vegetables": [
|
||||
{ "name": "Broccoli", "serving": "100g", "kcal": 34, "protein": 2.8, "fat": 0.4, "carbs": 7 },
|
||||
{ "name": "Spenat", "serving": "100g", "kcal": 23, "protein": 2.9, "fat": 0.4, "carbs": 3.6 },
|
||||
{ "name": "Paprika", "serving": "100g", "kcal": 31, "protein": 1, "fat": 0.3, "carbs": 6 },
|
||||
{ "name": "Tomat", "serving": "100g", "kcal": 18, "protein": 0.9, "fat": 0.2, "carbs": 3.9 },
|
||||
{ "name": "Gurka", "serving": "100g", "kcal": 15, "protein": 0.7, "fat": 0.1, "carbs": 3.6 },
|
||||
{ "name": "Morötter", "serving": "100g", "kcal": 41, "protein": 0.9, "fat": 0.2, "carbs": 10 }
|
||||
],
|
||||
"meal_templates": {
|
||||
"bulk_day": {
|
||||
"description": "~2800 kcal, 180g protein",
|
||||
"meals": [
|
||||
{ "name": "Frukost", "example": "Havregryn 80g + mjölk + banan + whey", "kcal": 550 },
|
||||
{ "name": "Lunch", "example": "Kyckling 150g + ris 200g + grönsaker + olivolja", "kcal": 700 },
|
||||
{ "name": "Mellanmål", "example": "Kvarg 300g + jordnötssmör + frukt", "kcal": 450 },
|
||||
{ "name": "Middag", "example": "Lax 150g + potatis 250g + grönsaker", "kcal": 650 },
|
||||
{ "name": "Kvällsmål", "example": "Ägg 3st + bröd 2 skivor + ost", "kcal": 450 }
|
||||
]
|
||||
},
|
||||
"cut_day": {
|
||||
"description": "~1800 kcal, 160g protein",
|
||||
"meals": [
|
||||
{ "name": "Frukost", "example": "Ägg 3st + grönsaker + 1 brödskiva", "kcal": 350 },
|
||||
{ "name": "Lunch", "example": "Kyckling 150g + ris 100g + mycket grönsaker", "kcal": 450 },
|
||||
{ "name": "Mellanmål", "example": "Kvarg 250g + bär", "kcal": 200 },
|
||||
{ "name": "Middag", "example": "Torsk 200g + potatis 150g + grönsaker", "kcal": 400 },
|
||||
{ "name": "Kvällsmål", "example": "Cottage cheese 200g + gurka", "kcal": 200 }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user