Migrated from GitLab issue #76, opened by Giulio Leuci (@leuci.giulio on GitLab) on 2026-09-09. openGym moved back to GitHub on 2026-09-11; the GitLab thread is closed and points here.
Labels: enhancement, training-engine, algorithm
1. Current Statea
In frontend/src/lib/onerm.js, openGym currently implements only three 1RM equations: Epley, Brzycki, and Lombardi.
- Epley is hardcoded as the default formula.
- Sets above
REP_CAP = 12 are rejected.
- Each formula has recognized structural biases: Epley progressively overestimates 1RM at moderate-to-high repetitions (> 6 reps), Brzycki diverges sharply near 10–12 reps, and Lombardi is overly conservative at low repetitions.
2. Motivation
Estimated 1RM is a critical metric in openGym: it directly powers percentage-based load resolution (%1RM), the in-session load calculator, and PR tracking. Relying on a single equation introduces systemic distortion. A multi-formula composite average weighted by empirical reliability and penalized for high reps creates a stable, smooth, and robust estimate across all rep ranges up to 15 reps.
3. Feature to Implement
- Extend Formula Suite:
- Add 4 peer-reviewed submaximal equations: O'Conner, Mayhew, Wathan, and Lander.
- Reliability-Weighted Average (
weightedEstimate):
- At r = 1: Return the exact lifted weight (1RM = w).
- For r > 1: Compute estimates across all 7 equations. Weight each formula by its empirical reliability factor a_i and apply a logarithmic rep penalty factor w_i = \frac{1}{\log_{10}(r) + 0.1} \cdot a_i.
- Set the default formula in openGym to
'weighted'.
- Extend the safe calculation cap to
WEIGHTED_REP_CAP = 15.
- Preserve Legacy Signatures:
- Preserve exact backwards compatibility for explicit calls (e.g.
estimate1RM(w, r, 'epley')).
4. Technical Design & Code Changes
// In frontend/src/lib/onerm.js
export const FORMULAS = {
epley: (w, r) => w * (1 + r / 30),
brzycki: (w, r) => w * 36 / (37 - r),
lombardi: (w, r) => w * Math.pow(r, 0.1),
oconner: (w, r) => w * (1 + r / 40),
mayhew: (w, r) => (w * 100) / (52.2 + 41.9 * Math.exp(-0.055 * r)),
wathan: (w, r) => (w * 100) / (48.8 + 53.8 * Math.exp(-0.075 * r)),
lander: (w, r) => (w * 100) / (101.3 - 2.67123 * r)
}
const RELIABILITY = {
epley: 1.0, brzycki: 1.1, lombardi: 0.95,
oconner: 0.9, mayhew: 1.05, wathan: 0.9, lander: 0.85
}
export const DEFAULT_FORMULA = 'weighted'
export const WEIGHTED_REP_CAP = 15
export function weightedEstimate(w, r) {
const reps = Math.round(Number(r))
const weight = Number(w)
if (!weight || weight <= 0 || !reps || reps <= 0) return null
if (reps === 1) return weight
if (reps > WEIGHTED_REP_CAP) return null
const repPenalty = 1 / (Math.abs(Math.log10(reps)) + 0.1)
let sum = 0, sumW = 0
for (const [name, fn] of Object.entries(FORMULAS)) {
const est = fn(weight, reps)
if (!Number.isFinite(est) || est <= 0) continue
const coeff = repPenalty * (RELIABILITY[name] || 1)
sum += coeff * est
sumW += coeff
}
return sumW > 0 ? Math.round((sum / sumW) * 10) / 10 : null
}
export function estimate1RM(w, r, formula = DEFAULT_FORMULA) {
if (formula === 'weighted') return weightedEstimate(w, r)
const fn = FORMULAS[formula] || FORMULAS.epley
return fn(w, r)
}
Giulio Leuci (@leuci.giulio on GitLab) commented on 2026-09-09:
I've partially implemented this feature in my fork available in https://github.com/giulioleuci/simple-opengym-range using Claude Code and Codex. This fork, however, is simplified because I've eliminated the entire AI infrastructure, for example.
Labels:
enhancement,training-engine,algorithm1. Current Statea
In
frontend/src/lib/onerm.js, openGym currently implements only three 1RM equations: Epley, Brzycki, and Lombardi.REP_CAP = 12are rejected.2. Motivation
Estimated 1RM is a critical metric in openGym: it directly powers percentage-based load resolution (%1RM), the in-session load calculator, and PR tracking. Relying on a single equation introduces systemic distortion. A multi-formula composite average weighted by empirical reliability and penalized for high reps creates a stable, smooth, and robust estimate across all rep ranges up to 15 reps.
3. Feature to Implement
weightedEstimate):'weighted'.WEIGHTED_REP_CAP = 15.estimate1RM(w, r, 'epley')).4. Technical Design & Code Changes
Giulio Leuci (
@leuci.giulioon GitLab) commented on 2026-09-09:I've partially implemented this feature in my fork available in https://github.com/giulioleuci/simple-opengym-range using Claude Code and Codex. This fork, however, is simplified because I've eliminated the entire AI infrastructure, for example.