Skip to content

1RM: seven-formula estimation suite with RIR handling, weighting, and accuracy index (#155) - #195

Open
giulioleuci wants to merge 2 commits into
DuarteSantos8:mainfrom
giulioleuci:feat/multi-formula-1rm-issue-155
Open

giulioleuci wants to merge 2 commits into
DuarteSantos8:mainfrom
giulioleuci:feat/multi-formula-1rm-issue-155

Conversation

@giulioleuci

Copy link
Copy Markdown
Contributor

Summary

Implements issue #155 (milestone v1.3.12): extends the estimated-1RM module with a seven-formula suite, RIR-aware estimation, a formula weight matrix, a confidence index — and routes the fatigue model through the same estimate.

What changed

frontend/src/lib/onerm.js

Formula suite. Keeps Epley, Brzycki and Lombardi; adds O'Connor, Mayhew, Wathan and Lander in a single FORMULAS map.

RIR handling. The estimate1RM(w, r, formula, rir) signature gains an optional rir parameter. Effective reps (reps + rir) are read against a Mike Tuchscherer / RTS %1RM map, and the RIR-based estimate weight / (%1RM / 100) participates in the weighted ensemble.

Weight matrix. The flat rep-based cutoff is replaced by a two-tier per-formula weighting: an absolute reliability factor a_i multiplied by a variable rep attenuation v_i(r) (weight_i = a_i * v_i(r)). E.g. Brzycki decays rapidly past 8 reps, Epley overestimates past 6, the RIR map loses accuracy past 10.

Weighted estimate. A new weighted formula blends all seven formulas (plus the RIR map when RIR is present), capped at the new WEIGHTED_REP_CAP = 15; individual formulas keep REP_CAP = 12. weightedEstimate() is exported unrounded for internal consumers.

Accuracy index. calculate1RMAccuracy(reps, rir, formula) returns a 0–1 confidence index combining:

  1. rep-count decay (highest at 1 rep, dropping toward WEIGHTED_REP_CAP),
  2. RIR subjectivity (~8% penalty, only when rir > 0 — RIR 0 is an objective to-failure set),
  3. inter-formula coefficient-of-variation spread (for the weighted formula).

Backward compatibility. Existing callers are unaffected; a single rep still returns the measurement unchanged, and r === 1, rir === 0 returns the load exactly.

frontend/src/lib/recovery.js

The fatigue model's session-local 1RM anchor now uses the onerm weighted mean instead of a hand-rolled Epley clamp (removed the duplicated formula and rep cap). The unrounded blend keeps kg↔lb equivalence and the causal-reference math exact. Sets beyond WEIGHTED_REP_CAP form no anchor and register as unweighted raw stimulus — honest rather than scaled by a fantasy 1RM.

Tests

frontend/src/lib/onerm.test.js gains coverage for the new formulas, the weighted estimate, RIR cases, and the accuracy index; recovery.test.js fixtures now derive from the weighted anchor instead of hardcoded Epley intensity. Full frontend suite: 1492 tests passing.

@giulioleuci

Copy link
Copy Markdown
Contributor Author

Implement #155

@DuarteSantos8

Copy link
Copy Markdown
Owner

Thanks for this! Since it touches the 1RM estimate that the fatigue model and progression read, I'll review it together with the new progression engine (#312, milestone v1.3.12) rather than on its own. It will need a rebase onto v1.3.9 (https://github.com/DuarteSantos8/openGym/releases/tag/v1.3.9).

giulioleuci and others added 2 commits October 4, 2026 12:36
…g, and accuracy index (DuarteSantos8#155)

Extend the 1RM module for issue DuarteSantos8#155 (milestone v1.3.12):

- Formula suite: keep Epley, Brzycki, Lombardi; add O'Connor, Mayhew, Wathan, Lander.
- RIR handling: optional rir param; effectiveReps = reps + rir against a Mike
  Tuchscherer (RTS) %1RM map; the estimate weight / (%1RM / 100) joins the weighted
  ensemble.
- Weight matrix: per-formula absolute reliability x variable rep attenuation,
  replacing the flat rep-based cutoff. Weighted ensemble capped at WEIGHTED_REP_CAP
  (15); single formulas keep REP_CAP (12).
- calculate1RMAccuracy(reps, rir, formula): 0-1 confidence index from rep decay,
  RIR subjectivity, and inter-formula spread.
- Backward compatible estimate1RM(w, r, formula, rir); 1 rep with RIR 0 returns the
  load exactly.

recovery.js: the fatigue model's session-local 1RM anchor now uses the onerm
weighted mean instead of a hand-rolled Epley clamp; sets beyond WEIGHTED_REP_CAP form
no anchor and count as unweighted raw stimulus.
- useStore.media: the sign-out purge keeps any file put at or after the sign-out's own start, so a
  file put in the same millisecond was kept for good and the wait for its removal could never end.
  Pause 5 ms after the put, as the sibling test does.
- CoachChat.demo-failure: the demo is imported on first use, a cold load is file I/O, and the test
  waited twenty microtasks for it. Load it before the click.
- server-password: only sign-ins already running when the password changes are the subject; one
  that starts after it is a wrong password, and five pause the account for a minute, so the final
  sign-in got 429 whenever the loop outlasted the change. Stop starting new ones once it is done.
- server-media: the server writes the log line before it replies, but the test reads the two on
  separate pipes. Wait for the line instead of reading it once.

Each was reproduced first (the media and password ones under CPU load) and fails without its fix.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4o3WJxPtaibivEfhLvwAR
@giulioleuci
giulioleuci force-pushed the feat/multi-formula-1rm-issue-155 branch from e669c89 to 1049b86 Compare October 4, 2026 10:54
@giulioleuci

Copy link
Copy Markdown
Contributor Author

Hi @DuarteSantos8 , I rebased my branch.

This branch has not been deployed

No deployments
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.

3 participants