const LB_TO_KG = 0.45359237; // exact, international avoirdupois pound const IN_TO_CM = 2.54; // exact, international inch function toKg(value, unit) { if (unit === "kg") return value; if (unit === "lb") return value * LB_TO_KG; throw new Error("weight_unit must be kg or lb"); } function toCm(value, unit) { if (unit === "cm") return value; if (unit === "in") return value * IN_TO_CM; throw new Error("height_unit must be cm or in"); } function categoryFor(bmi) { if (bmi < 18.5) return "Underweight"; if (bmi < 25) return "Normal weight"; if (bmi < 30) return "Overweight"; return "Obese"; } module.exports = { slug: "bmi-and-category", title: "BMI and WHO weight category", deck_category: "health", description: "Computes body mass index from weight and height and reports the WHO adult weight category.", inputs: [ { name: "weight", type: "number", unit: "kg or lb", required: true, description: "Body weight", min: 0 }, { name: "weight_unit", type: "string", required: true, description: "Unit of the weight value", enum: ["kg", "lb"] }, { name: "height", type: "number", unit: "cm or in", required: true, description: "Height", min: 0 }, { name: "height_unit", type: "string", required: true, description: "Unit of the height value", enum: ["cm", "in"] } ], outputs: [ { name: "bmi", unit: "kg/m^2", description: "Body mass index" }, { name: "category", unit: null, description: "WHO adult weight category" } ], steps: [ "Convert weight to kilograms: kg = lb * 0.45359237 if given in pounds.", "Convert height to meters: first cm = in * 2.54 if given in inches, then m = cm / 100.", "bmi = weight_kg / (height_m ^ 2), rounded to 1 decimal.", "Category from the WHO adult thresholds: underweight below 18.5, normal weight 18.5 to below 25, overweight 25 to below 30, obese 30 and above." ], constants: [ { name: "lb_to_kg", value: 0.45359237, unit: "kg per lb", source: 0 }, { name: "in_to_cm", value: 2.54, unit: "cm per in", source: 0 }, { name: "underweight_upper", value: 18.5, unit: "kg/m^2", source: 1 }, { name: "normal_upper", value: 25, unit: "kg/m^2", source: 1 }, { name: "overweight_upper", value: 30, unit: "kg/m^2", source: 1 } ], sources: [ { kind: "edition_page", value: "International Yard and Pound Agreement, 1959", title: "Exact pound and inch conversion factors", publisher: "NIST Handbook 44, Appendix C", retrieved_utc: "2026-09-30T19:00:00Z", note: "Defines 1 lb = 0.45359237 kg and 1 in = 2.54 cm exactly." }, { kind: "url", value: "https://www.who.int/europe/news-room/fact-sheets/item/a-healthy-lifestyle---who-recommendations", title: "Body mass index - BMI", publisher: "World Health Organization", retrieved_utc: "2026-09-30T19:00:00Z", note: "WHO adult BMI classification thresholds (underweight/normal/overweight/obese)." } ], disclaimer: "General formula only. Not medical advice. Dosing decisions belong to a licensed clinician and the product's label.", questionText(inputs) { return `What is the BMI and WHO category for a person weighing ${inputs.weight} ${inputs.weight_unit} at a height of ${inputs.height} ${inputs.height_unit}?`; }, run(inputs) { const { weight, weight_unit, height, height_unit } = inputs; if (typeof weight !== "number" || weight <= 0) throw new Error("weight must be a positive number"); if (typeof height !== "number" || height <= 0) throw new Error("height must be a positive number"); const weightKg = toKg(weight, weight_unit); const heightCm = toCm(height, height_unit); const heightM = heightCm / 100; const bmiRaw = weightKg / (heightM * heightM); const bmi = Math.round(bmiRaw * 10) / 10; const category = categoryFor(bmi); return { answer: `BMI ${bmi.toFixed(1)} (${category})`, values: { bmi, category } }; }, examples: [ { name: "worked example", inputs: { weight: 70, weight_unit: "kg", height: 175, height_unit: "cm" }, expected: { answer: "BMI 22.9 (Normal weight)" }, check: "70 / (1.75^2) = 70 / 3.0625 = 22.857..., rounds to 22.9, which is within WHO 18.5-24.9 normal range." }, { name: "test vector: imperial units, obese range", inputs: { weight: 220, weight_unit: "lb", height: 66, height_unit: "in" }, expected: { answer: "BMI 35.5 (Obese)" }, check: "220 lb * 0.45359237 = 99.7903 kg; 66 in * 2.54 = 167.64 cm = 1.6764 m; 99.7903 / 1.6764^2 = 99.7903 / 2.81032 = 35.5074, rounds to 35.5, which is >= 30 (Obese)." } ] };