feat: add metabolic age derived value#1417
Open
DanyPM wants to merge 1 commit into
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Add Metabolic Age derived value
Summary
Adds Metabolic Age as a new derived measurement value, computed automatically for every measurement that carries a body-composition signal (body-fat % or lean body mass). It follows the existing derived-value pattern (
isDerivedrow, recomputed on every insert/update) alongside BMI, BMR, TDEE, etc.Scientific basis
Metabolic age answers: at what age would a population-average metabolism match this person's actual metabolism? We derive it by inverting the age term of an established BMR equation:
BMR = 370 + 21.6 × FFM(kg). This uses fat-free mass, so it reflects the individual's real body composition (muscle mass), not just body size. FFM is taken from a measured LBM value, or computed asweight × (1 − bodyFat%/100).BMR = 10w + 6.25h − 5·age + s, with sex constants = +5(male) /−161(female). This is the population-normative curve at the user's own weight, height and sex, and it is linear in age.A higher actual BMR (more lean mass) yields a younger metabolic age, and vice-versa — the expected physiological direction. The result is clamped to a plausible 15–99 range.
Both formulas are peer-reviewed and already used elsewhere in openScale (Mifflin-St Jeor for BMR; Katch-McArdle in
StandardImpedanceLib).Why a body-composition signal is required
If the "actual" BMR were itself the anthropometric Mifflin-St Jeor value, inverting the curve would trivially return the chronological age. The metric is only meaningful when the actual BMR is derived from fat-free mass. Metabolic age is therefore computed only when the measurement has body-fat % or LBM; plain manual weigh-ins are skipped (and any stale value is removed).
Changes
MeasurementTypeKey.METABOLIC_AGEand unitUnitType.YEARS(displayed as"N years", whole numbers); dedicated hourglass icon.DerivedValuesCalculator.processMetabolicAgeCalculation(...)plus fat-free-mass derivation (LBM preferred, else weight + body-fat, with unit normalisation) in the recalculation pass.version 16withMIGRATION_15_16seeding the new derived type; exported schema16.json.YEARS → "a".Tests
DerivedValuesCalculatorFormulasTest— formula correctness (male/female constants, monotonicity: higher FFM → younger age, clamping, null-guards).DerivedValuesCalculatorIntegrationTest— end-to-end against a real Room DB: value is persisted from weight + body-fat and removed when the body-composition source disappears.MigrationTest— full migration chain (incl. 15→16) produces the new type.