UNPKG

masterclass-mcp

Version:

Un serveur MCP pour le calcul nutritionnel et la génération de plans alimentaires

262 lines (261 loc) 11.6 kB
import { activityMultipliers } from "../type.js"; /** * Formule allométrique pour calculer le BMR des hommes * Basée sur une formule empirique allométrique */ const calculAllometricMan = (weight, height, age) => 1.083 * Math.pow(weight, 0.48) * Math.pow(height / 100, 0.5) * Math.pow(age, -0.13) * (1000 / 4.1855); /** * Formule allométrique pour calculer le BMR des femmes * Basée sur une formule empirique allométrique */ const calculAllometricWoman = (weight, height, age) => 0.963 * Math.pow(weight, 0.48) * Math.pow(height / 100, 0.5) * Math.pow(age, -0.13) * (1000 / 4.1855); /** * Formule de Mifflin-St Jeor pour calculer le BMR des hommes * Considérée comme plus précise pour les adultes modernes */ const calculMifflinMan = (weight, height, age) => (10 * weight) + (6.25 * height) - (5 * age) + 5; /** * Formule de Mifflin-St Jeor pour calculer le BMR des femmes * Considérée comme plus précise pour les adultes modernes */ const calculMifflinWoman = (weight, height, age) => (10 * weight) + (6.25 * height) - (5 * age) - 161; /** * Formule de Katch-McArdle pour calculer le BMR * Utilise la masse maigre (LBM) pour plus de précision * Cette formule est indépendante du sexe */ const calculKatchMcArdle = (weight, bodyFatPercentage) => { // Calcul de la masse maigre (Lean Body Mass) const lbm = weight * (1 - (bodyFatPercentage / 100)); // Formule de Katch-McArdle return 370 + (21.6 * lbm); }; /** * Calcule le métabolisme basal en fonction de la formule choisie * @param gender Genre ("male" ou "female") * @param age Âge en années * @param weight Poids en kg * @param height Taille en cm * @param formula Formule à utiliser ("mifflin", "allometric" ou "katchMcArdle") * @param bodyFatPercentage Pourcentage de graisse corporelle (requis pour Katch-McArdle) * @returns Métabolisme basal en calories */ export const calculMetabolism = (gender, age, weight, height, formula = "mifflin", bodyFatPercentage) => { switch (formula) { case "mifflin": return gender === "female" ? calculMifflinWoman(weight, height, age) : calculMifflinMan(weight, height, age); case "allometric": return gender === "female" ? calculAllometricWoman(weight, height, age) : calculAllometricMan(weight, height, age); case "katchMcArdle": if (bodyFatPercentage === undefined) { throw new Error("Le pourcentage de graisse corporelle est requis pour la formule de Katch-McArdle"); } return calculKatchMcArdle(weight, bodyFatPercentage); default: return gender === "female" ? calculMifflinWoman(weight, height, age) : calculMifflinMan(weight, height, age); } }; /** * Calcule la répartition des macronutriments en fonction de l'objectif et de la stratégie choisie * @param goal Objectif (perte de poids, prise de muscle, maintien) * @param calories Calories totales * @param strategy Stratégie de répartition des macros * @param weight Poids en kg (utilisé pour les stratégies basées sur le poids) * @param customRatios Ratios personnalisés (optionnel) * @returns Répartition des macronutriments en grammes */ export const calculRepartition = (goal, calories, strategy = "standard", weight, customRatios) => { // Ajustement des calories en fonction de l'objectif let caloriesTotal; switch (goal) { case "weightLoss": caloriesTotal = Math.round(calories * 0.9); // Réduction de 10% des calories break; case "muscleGain": caloriesTotal = Math.round(calories * 1.12); // Augmentation de 12% des calories break; case "maintenance": caloriesTotal = Math.round(calories); break; default: caloriesTotal = Math.round(calories); } // Valeurs par défaut pour les ratios let proteinRatio; let fatRatio; let carbohydrateRatio; let protein; let fat; let carbohydrate; // Application de la stratégie de répartition des macros switch (strategy) { case "standard": // Stratégie standard basée sur l'objectif switch (goal) { case "weightLoss": proteinRatio = 0.25; fatRatio = 0.25; carbohydrateRatio = 0.5; break; case "muscleGain": proteinRatio = 0.3; fatRatio = 0.25; carbohydrateRatio = 0.45; break; case "maintenance": proteinRatio = 0.3; fatRatio = 0.3; carbohydrateRatio = 0.4; break; default: proteinRatio = 0.3; fatRatio = 0.3; carbohydrateRatio = 0.4; } // Calcul des macronutriments en grammes protein = Math.round((caloriesTotal * proteinRatio) / 4); fat = Math.round((caloriesTotal * fatRatio) / 9); carbohydrate = Math.round((caloriesTotal * carbohydrateRatio) / 4); break; case "proteinFirst": // Stratégie qui priorise les protéines en fonction du poids if (!weight) { throw new Error("Le poids est requis pour la stratégie 'proteinFirst'"); } // Calcul des protéines en fonction du poids (2g/kg pour prise de muscle, 1.8g/kg pour maintien, 2.2g/kg pour perte) let proteinPerKg; switch (goal) { case "weightLoss": proteinPerKg = 2.2; break; case "muscleGain": proteinPerKg = 2.0; break; default: proteinPerKg = 1.8; } // Calcul des protéines en grammes protein = Math.round(weight * proteinPerKg); // Calcul des calories restantes après allocation des protéines const remainingCalories = caloriesTotal - (protein * 4); // Répartition des calories restantes entre lipides et glucides if (goal === "weightLoss") { // Pour la perte de poids, favoriser les lipides pour la satiété fatRatio = 0.6; // 60% des calories restantes carbohydrateRatio = 0.4; // 40% des calories restantes } else { // Pour la prise de muscle ou le maintien, favoriser les glucides pour l'énergie fatRatio = 0.35; // 35% des calories restantes carbohydrateRatio = 0.65; // 65% des calories restantes } // Calcul des lipides et glucides en grammes fat = Math.round((remainingCalories * fatRatio) / 9); carbohydrate = Math.round((remainingCalories * carbohydrateRatio) / 4); break; case "keto": // Stratégie cétogène (très faible en glucides, riche en lipides) proteinRatio = 0.25; // 25% des calories totales fatRatio = 0.7; // 70% des calories totales carbohydrateRatio = 0.05; // 5% des calories totales // Calcul des macronutriments en grammes protein = Math.round((caloriesTotal * proteinRatio) / 4); fat = Math.round((caloriesTotal * fatRatio) / 9); carbohydrate = Math.round((caloriesTotal * carbohydrateRatio) / 4); break; case "lowFat": // Stratégie faible en lipides, riche en glucides proteinRatio = 0.3; // 30% des calories totales fatRatio = 0.15; // 15% des calories totales carbohydrateRatio = 0.55; // 55% des calories totales // Calcul des macronutriments en grammes protein = Math.round((caloriesTotal * proteinRatio) / 4); fat = Math.round((caloriesTotal * fatRatio) / 9); carbohydrate = Math.round((caloriesTotal * carbohydrateRatio) / 4); break; case "custom": // Stratégie personnalisée avec des ratios fournis par l'utilisateur if (!customRatios) { throw new Error("Les ratios personnalisés sont requis pour la stratégie 'custom'"); } // Utilisation des ratios personnalisés ou des valeurs par défaut proteinRatio = customRatios.protein ?? 0.3; fatRatio = customRatios.fat ?? 0.3; carbohydrateRatio = customRatios.carbs ?? 0.4; // Vérification que la somme des ratios est égale à 1 const totalRatio = proteinRatio + fatRatio + carbohydrateRatio; if (Math.abs(totalRatio - 1) > 0.01) { // Tolérance de 1% throw new Error(`La somme des ratios doit être égale à 1, actuellement: ${totalRatio}`); } // Calcul des macronutriments en grammes protein = Math.round((caloriesTotal * proteinRatio) / 4); fat = Math.round((caloriesTotal * fatRatio) / 9); carbohydrate = Math.round((caloriesTotal * carbohydrateRatio) / 4); break; default: // Stratégie par défaut (même que standard) proteinRatio = 0.3; fatRatio = 0.3; carbohydrateRatio = 0.4; // Calcul des macronutriments en grammes protein = Math.round((caloriesTotal * proteinRatio) / 4); fat = Math.round((caloriesTotal * fatRatio) / 9); carbohydrate = Math.round((caloriesTotal * carbohydrateRatio) / 4); } // Création de l'objet de répartition const repartition = { calories: caloriesTotal, protein, fat, carbohydrates: carbohydrate }; return repartition; }; /** * Calcule la répartition nutritionnelle complète en fonction du profil de l'utilisateur * @param profile Profil complet de l'utilisateur * @returns Répartition nutritionnelle complète en grammes */ export const calculNutrition = (profile) => { // Récupération des options de calcul nutritionnel const options = profile.nutritionOptions || {}; // Calcul du métabolisme basal avec la formule choisie const basalMetabolism = calculMetabolism(profile.gender, profile.age, profile.weight, profile.height, options.bmrFormula, options.bodyFatPercentage); // Application du niveau d'activité const activityMultiplier = typeof profile.activityLevel === 'number' ? profile.activityLevel : activityMultipliers[profile.activityLevel]; const caloriesTotal = basalMetabolism * activityMultiplier; // Calcul de la répartition en fonction de l'objectif et de la stratégie choisie return calculRepartition(profile.objective, caloriesTotal, options.macroStrategy, profile.weight, { protein: options.customProteinRatio, fat: options.customFatRatio, carbs: options.customCarbRatio }); }; /** * Fonction d'aide pour créer un profil avec des options de calcul nutritionnel * @param baseProfile Profil de base * @param nutritionOptions Options de calcul nutritionnel * @returns Profil complet avec options nutritionnelles */ export const createProfileWithOptions = (baseProfile, nutritionOptions) => { return { ...baseProfile, nutritionOptions }; };