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
JavaScript
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
};
};