Skip to content

feat: add computed therapy score to session detail#105

Open
kilo-WATT wants to merge 3 commits into
joshuamyers-dev:mainfrom
kilo-WATT:feat/therapy-score
Open

feat: add computed therapy score to session detail#105
kilo-WATT wants to merge 3 commits into
joshuamyers-dev:mainfrom
kilo-WATT:feat/therapy-score

Conversation

@kilo-WATT
Copy link
Copy Markdown
Contributor

Summary

Adds a computed therapy score to the session detail response and displays it on the session detail page.

The score is calculated at request time from existing session fields. No therapy-score data is persisted.

image

Changes

  • Added therapy_score to the session detail API response.
  • Added score_vs_30d_avg to compare the current night against the user’s prior 30-day average.
  • Added backend therapy score models.
  • Added a pure scoring helper in api/therapy_score.py.
  • Wired therapy score assembly into api/routers/sessions.py.
  • Added frontend API types.
  • Added a therapy score card to SessionDetail.tsx.
  • Added score total, grade, component bars, callout, low-confidence display, and info tooltip.
  • Added backend tests for scoring behavior and session detail response coverage.

Scoring Logic

The score is a computed 0–100 integer with an A–F grade.

Default component weights:

  • AHI: 40
  • Leak: 25
  • Duration: 20
  • SpO2: 15

Unavailable components are excluded and their weight is redistributed across available components.

ResMed leak scoring uses the 24 L/min large-leak threshold. Sessions that are not parser-validated still receive a score but are marked as low confidence.

30-Day Comparison

score_vs_30d_avg is computed from existing rows in the sessions table.

The calculation:

  • Is scoped to the same user.
  • Uses prior 30-day nightly scores.
  • Groups by folder_date to avoid double-counting multi-block nights.
  • Does not store historical scores.

Files Changed

api/models.py
api/routers/sessions.py
api/therapy_score.py
frontend/src/api/client.ts
frontend/src/pages/SessionDetail.tsx
tests/test_sessions.py
tests/test_therapy_score.py

@kilo-WATT
Copy link
Copy Markdown
Contributor Author

Added a follow-up commit to make manufacturer handling safer.

The score is no longer ResMed-only and no longer assumes missing manufacturer data means ResMed. AHI, duration, and SpO2 still score normally for unknown/non-ResMed manufacturers, while leak scoring is only applied when the manufacturer is explicitly ResMed. For unknown or unconfirmed manufacturers, the leak component is marked unavailable and its weight is redistributed.

Validation:

  • uv run pytest tests/test_therapy_score.py — 11 passed
  • uv run pytest — 48 passed, 69 skipped
  • npm run build — passed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant