← back to AbramsOS

lib/biometrics.js

63 lines

// biometrics.js — derived helpers for a person's biometric profile.
//
// Everything here is EXACT arithmetic (age, BMI) or a documented CDC threshold — no
// invented percentiles. For children we compute BMI and hand off to the CDC calculator
// for the age/sex percentile rather than fabricate one (that needs CDC LMS tables).

function ageYears(dob, asOf) {
  if (!dob) return null;
  const b = new Date(dob), now = asOf ? new Date(asOf) : new Date();
  if (isNaN(b.getTime())) return null;
  let a = now.getFullYear() - b.getFullYear();
  const m = now.getMonth() - b.getMonth();
  if (m < 0 || (m === 0 && now.getDate() < b.getDate())) a--;
  return a;
}

function ageMonths(dob, asOf) {
  if (!dob) return null;
  const b = new Date(dob), now = asOf ? new Date(asOf) : new Date();
  if (isNaN(b.getTime())) return null;
  return (now.getFullYear() - b.getFullYear()) * 12 + (now.getMonth() - b.getMonth());
}

// Imperial BMI = 703 × lb / in².
function bmi(heightIn, weightLb) {
  const h = Number(heightIn), w = Number(weightLb);
  if (!(h > 0) || !(w > 0)) return null;
  return Math.round((703 * w / (h * h)) * 10) / 10;
}

// Adult (20+) BMI category — CDC thresholds. For children this label does NOT apply
// (kids use age/sex percentiles), so we return null and the UI links to CDC.
function adultBmiCategory(bmiVal) {
  if (bmiVal == null) return null;
  if (bmiVal < 18.5) return 'underweight';
  if (bmiVal < 25) return 'healthy';
  if (bmiVal < 30) return 'overweight';
  return 'obese';
}

function isChild(dob) {
  const a = ageYears(dob);
  return a != null && a < 18;
}

// Build the derived view for one biometric row (+ its person).
function derive(b) {
  const age = ageYears(b.date_of_birth);
  const child = isChild(b.date_of_birth);
  const bmiVal = bmi(b.height_in, b.weight_lb);
  return {
    age,
    ageMonths: ageMonths(b.date_of_birth),
    isChild: child,
    bmi: bmiVal,
    bmiCategory: child ? null : adultBmiCategory(bmiVal),
    // For kids: authoritative CDC child BMI percentile calculator (we don't fake the number).
    cdcPercentileUrl: child ? 'https://www.cdc.gov/healthyweight/bmi/calculator.html' : null,
  };
}

module.exports = { ageYears, ageMonths, bmi, adultBmiCategory, isChild, derive };