import { getBfCategory, calcDerived } from './calc.js' export function getInterpretation(measurement, profile, prevMeasurement = null) { const results = [] const sex = profile?.sex || 'm' const height = profile?.height || 178 const age = profile?.dob ? Math.floor((Date.now() - new Date(profile.dob)) / (365.25 * 24 * 3600 * 1000)) : 30 const m = measurement // lean_mass and body_fat_pct come from caliper_log const derived = calcDerived(m, height) // ── Körperfett ───────────────────────────────────────────────────────────── if (m.body_fat_pct) { const cat = getBfCategory(m.body_fat_pct, sex) const ranges = sex === 'm' ? { essential: 6, athletic: 14, fit: 18, avg: 25 } : { essential: 14, athletic: 21, fit: 25, avg: 32 } let msg = '', detail = '' if (m.body_fat_pct <= ranges.essential) { msg = 'Sehr niedriger Körperfettanteil'; detail = 'Essenzielle Fettwerte – nur für Leistungssportler geeignet, auf Dauer nicht empfehlenswert.' } else if (m.body_fat_pct <= ranges.athletic) { msg = 'Athletischer Körperfettanteil'; detail = 'Ausgezeichnet. Typisch für aktive Sportler mit hohem Trainingsvolumen.' } else if (m.body_fat_pct <= ranges.fit) { msg = 'Guter Körperfettanteil'; detail = 'Sehr gute Fitness-Kategorie. Gesund und gut in Form.' } else if (m.body_fat_pct <= ranges.avg) { msg = 'Durchschnittlicher Körperfettanteil'; detail = 'Im normalen Bereich. Verbesserung durch Kombination aus Kraft- und Ausdauertraining möglich.' } else { msg = 'Erhöhter Körperfettanteil'; detail = 'Über dem empfohlenen Bereich. Ernährungsumstellung und regelmäßiges Training empfohlen.' } results.push({ category: 'Körperfett', icon: '🫧', status: m.body_fat_pct <= ranges.fit ? 'good' : m.body_fat_pct <= ranges.avg ? 'warn' : 'bad', title: msg, detail, value: `${m.body_fat_pct}%`, badge: cat?.label, color: cat?.color, }) } // ── Waist-Hip-Ratio ──────────────────────────────────────────────────────── if (derived.whr) { const limit = sex === 'm' ? 0.90 : 0.85 const limitHigh = sex === 'm' ? 1.0 : 0.95 let status, title, detail if (derived.whr < limit) { status = 'good'; title = 'Günstige Fettverteilung' detail = `Dein WHR von ${derived.whr} liegt unter dem Grenzwert (${limit}). Birnenförmige Fettverteilung – metabolisch günstig.` } else if (derived.whr < limitHigh) { status = 'warn'; title = 'Grenzwertiger WHR' detail = `Dein WHR von ${derived.whr} liegt leicht über dem Zielwert (${limit}). Apfelförmige Tendenz – Bauchfett reduzieren empfohlen.` } else { status = 'bad'; title = 'Erhöhtes Risiko durch Fettverteilung' detail = `WHR von ${derived.whr} deutlich über dem Grenzwert. Erhöhtes kardiovaskuläres Risiko durch viszerales Fett.` } results.push({ category: 'Fettverteilung', icon: '📐', status, title, detail, value: derived.whr.toString() }) } // ── Waist-to-Height ──────────────────────────────────────────────────────── if (derived.whtr) { let status, title, detail if (derived.whtr < 0.40) { status = 'warn'; title = 'Sehr schlanke Taille' detail = `WHtR ${derived.whtr} – möglicherweise zu wenig Körpermasse.` } else if (derived.whtr < 0.50) { status = 'good'; title = 'Optimale Taillen-Größen-Relation' detail = `WHtR ${derived.whtr} – im optimalen Bereich. Geringstes kardiovaskuläres Risiko.` } else if (derived.whtr < 0.60) { status = 'warn'; title = 'Leicht erhöhter WHtR' detail = `WHtR ${derived.whtr} – Ziel ist unter 0,50. Moderat erhöhtes Risiko.` } else { status = 'bad'; title = 'Stark erhöhter WHtR' detail = `WHtR ${derived.whtr} – deutlich erhöhtes Risiko. Taille sollte weniger als die Hälfte der Körpergröße betragen.` } results.push({ category: 'Taille/Größe', icon: '📏', status, title, detail, value: derived.whtr.toString() }) } // ── FFMI ─────────────────────────────────────────────────────────────────── if (derived.ffmi) { const naturalLimit = sex === 'm' ? 25 : 22 let status, title, detail if (derived.ffmi < (sex === 'm' ? 18 : 15)) { status = 'warn'; title = 'Unterdurchschnittliche Muskelmasse' detail = `FFMI ${derived.ffmi} – Krafttraining kann die Muskelmasse und den Grundumsatz deutlich verbessern.` } else if (derived.ffmi < (sex === 'm' ? 22 : 19)) { status = 'good'; title = 'Durchschnittliche Muskelmasse' detail = `FFMI ${derived.ffmi} – gute Basis. Mit regelmäßigem Krafttraining weiter ausbaubar.` } else if (derived.ffmi <= naturalLimit) { status = 'good'; title = 'Überdurchschnittliche Muskelmasse' detail = `FFMI ${derived.ffmi} – sehr gut. Oberes natürliches Spektrum für Kraftsportler.` } else { status = 'warn'; title = 'Außergewöhnlich hohe Muskelmasse' detail = `FFMI ${derived.ffmi} – oberhalb der natürlichen Grenze (~${naturalLimit}). Selten ohne unterstützende Mittel erreichbar.` } results.push({ category: 'Muskelmasse', icon: '💪', status, title, detail, value: derived.ffmi.toString() }) } // ── BMI (aus Gewicht + Größe) ────────────────────────────────────────────── if (m.weight && height) { const bmi = Math.round(m.weight / ((height / 100) ** 2) * 10) / 10 let status, title, detail if (bmi < 18.5) { status = 'warn'; title = 'Untergewicht (BMI)' detail = `BMI ${bmi} – unter 18,5. Auf ausreichende Kalorienzufuhr und Nährstoffversorgung achten.` } else if (bmi < 25) { status = 'good'; title = 'Normalgewicht (BMI)' detail = `BMI ${bmi} – im optimalen Bereich (18,5–24,9).` } else if (bmi < 30) { status = 'warn'; title = 'Übergewicht (BMI)' detail = `BMI ${bmi} – leichtes Übergewicht. BMI allein ist wenig aussagekräftig bei Muskelmasse – Körperfett-% beachten.` } else { status = 'bad'; title = 'Adipositas (BMI)' detail = `BMI ${bmi} – deutliches Übergewicht. Ärztliche Beratung empfohlen.` } results.push({ category: 'BMI', icon: '⚖️', status, title, detail, value: bmi.toString() }) } // ── Vergleich zur letzten Messung ────────────────────────────────────────── if (prevMeasurement) { const changes = [] const p = prevMeasurement const days = Math.round((new Date(m.date) - new Date(p.date)) / (1000 * 60 * 60 * 24)) if (m.body_fat_pct && p.body_fat_pct) { const diff = Math.round((m.body_fat_pct - p.body_fat_pct) * 10) / 10 if (Math.abs(diff) >= 0.3) changes.push({ label: 'Körperfett', diff, unit: '%', invert: true }) } if (m.weight && p.weight) { const diff = Math.round((m.weight - p.weight) * 10) / 10 if (Math.abs(diff) >= 0.2) changes.push({ label: 'Gewicht', diff, unit: 'kg', invert: true }) } if (m.lean_mass && p.lean_mass) { const diff = Math.round((m.lean_mass - p.lean_mass) * 10) / 10 if (Math.abs(diff) >= 0.2) changes.push({ label: 'Magermasse', diff, unit: 'kg', invert: false }) } if (m.c_waist && p.c_waist) { const diff = Math.round((m.c_waist - p.c_waist) * 10) / 10 if (Math.abs(diff) >= 0.5) changes.push({ label: 'Taille', diff, unit: 'cm', invert: true }) } if (m.c_belly && p.c_belly) { const diff = Math.round((m.c_belly - p.c_belly) * 10) / 10 if (Math.abs(diff) >= 0.5) changes.push({ label: 'Bauch', diff, unit: 'cm', invert: true }) } if (changes.length > 0) { const positiveChanges = changes.filter(c => c.invert ? c.diff < 0 : c.diff > 0) const negativeChanges = changes.filter(c => c.invert ? c.diff > 0 : c.diff < 0) const detail = changes.map(c => { const sign = c.diff > 0 ? '+' : '' const good = c.invert ? c.diff < 0 : c.diff > 0 return `${c.label}: ${sign}${c.diff} ${c.unit} ${good ? '✓' : '↑'}` }).join(' · ') results.push({ category: `Seit letzter Messung (${days} Tage)`, icon: '📊', status: positiveChanges.length >= negativeChanges.length ? 'good' : 'warn', title: positiveChanges.length > negativeChanges.length ? 'Positive Entwicklung seit letzter Messung' : negativeChanges.length > positiveChanges.length ? 'Verschlechterung seit letzter Messung' : 'Gemischte Entwicklung seit letzter Messung', detail, value: `${days}d`, }) } } return results } export function getStatusColor(status) { return status === 'good' ? '#1D9E75' : status === 'warn' ? '#EF9F27' : '#D85A30' } export function getStatusBg(status) { return status === 'good' ? '#E1F5EE' : status === 'warn' ? '#FAEEDA' : '#FCEBEB' }