mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-12 14:16:12 +00:00
fix(health-score): grade the blood-pressure pillar by clinical proximity
The BP pillar value equalled the binary all-time in-target rate: the share of paired readings where both systolic and diastolic sat at or below the age-band ceiling. A borderline stage-1 profile (diastolic a few mmHg over the ceiling on most readings) collapsed the pillar to the teens even though the reading is "a bit high", not catastrophic — and improvement never surfaced because the rate is all-time and binary. Replace the binary rate AS THE SCORE with a smooth clinical-proximity grade. A recency-weighted representative reading (45-day half-life) is mapped per axis onto a 0-100 curve anchored on the same age-band ceiling the rest of the app uses — optimal ≈ 100, at the ceiling ≈ 85, then piecewise-linear down through the over-target bands; hypotension is penalised symmetrically below the clinical floors. The pillar takes the worse of the two axes, so an elevated diastolic counts without binary-zeroing the result. A 134/87 profile against a 129/79 ceiling now reads in the mid-50s. The in-target rate stays available as a secondary "X% of readings in range" stat. The healthScore.components.bp shape is unchanged — only the value moves.
This commit is contained in:
1 parent
2851776af6
commit
60359dbcb7
8 files changed
+502
-5
No files matched your search
@@ -258,6 +258,11 @@ async function buildAnalyticsResponse(user: AuthedUser) {
|
||||
// pillar compares the same window on both ends (the tile headline keeps
|
||||
// its 30-day scope; the score reads all-time per its documented contract).
|
||||
let windowsPriorWeekAllTime: number | null = null;
|
||||
// v1.15.12 A1 — graded clinical-proximity BP score (recency-weighted
|
||||
// representative reading) for the Health-Score BP pillar value, plus
|
||||
// the prior-week run for the week-over-week delta.
|
||||
let bpGradedScore: number | null = null;
|
||||
let bpGradedScorePriorWeek: number | null = null;
|
||||
const bpTargets = getBpTargets(user.dateOfBirth);
|
||||
if (bpTargets) {
|
||||
const now = new Date();
|
||||
@@ -309,6 +314,8 @@ async function buildAnalyticsResponse(user: AuthedUser) {
|
||||
bpInTargetPctPriorMonth = windows.priorMonth?.pct ?? null;
|
||||
bpInTargetPctPriorYear = windows.priorYear?.pct ?? null;
|
||||
bpInTargetPctPriorWeek = windowsPriorWeek.last30Days?.pct ?? null;
|
||||
bpGradedScore = windows.gradedScore;
|
||||
bpGradedScorePriorWeek = windowsPriorWeek.gradedScore;
|
||||
// The Health-Score BP pillar reads the all-time window (see the
|
||||
// `bpInTargetPctForScore` derivation below). Capture the prior-week
|
||||
// run's all-time pct too so the week-over-week delta compares the
|
||||
@@ -395,6 +402,12 @@ async function buildAnalyticsResponse(user: AuthedUser) {
|
||||
// same all-time window as the current snapshot so the delta is
|
||||
// apples-to-apples.
|
||||
bpInTargetPctPriorWeek: bpInTargetPctPriorWeekForScore,
|
||||
// v1.15.12 A1 — graded clinical-proximity BP score drives the pillar
|
||||
// VALUE; the binary in-target rate above only gates presence and is
|
||||
// surfaced as a secondary stat. Closes the "borderline-stage-1 reads
|
||||
// 16/100" trust bug.
|
||||
bpGradedScore,
|
||||
bpGradedScorePriorWeek,
|
||||
heightCm: user.heightCm ?? null,
|
||||
now: new Date(),
|
||||
coverage,
|
||||
|
||||
Reference in new issue
Block a user