Skip to content

[Feature Request] Dumbbell inventory: progression and deload snap to the weights you own #376

Description

@torstenfeld

What problem does this solve?

I train at home with adjustable dumbbells (turn the handle to change the weight). They only come in these weights, in kg:

3, 6, 8, 9, 11, 13, 15, 17, 18, 19, 21, 24

The steps are irregular (3, 2, 1, 2, 2, 2, 2, 1, 1, 2, 3), so no per-exercise inc fits them. Fixed-weight dumbbell racks at home and in many small gyms have the same problem.

What happens today (v1.3.9):

  • Progression adds inc to an off-grid weight without snapping (addStep, Exercise increment step rounds #175). With inc: 2, 9 → 11 → … → 21 works, but the next step is 23 and I only have 24.
  • Deload candidates always come from multiples of inc (positiveGridAround in selectDeloadCandidate). With inc: 2 it suggests 10, 12, 14, 16, 20 or 22, none of which I own.
  • Below 9 kg (3 → 6 → 8 → 9) no step size works, which affects the light accessory lifts (lateral raises, curls, rear delts).
  • Tapping +/- from an even weight snaps to the even grid as well.

So almost every deload, and every lift at the edges of the range, needs a manual correction during the workout.

The plate inventory (lib/plates.js) already solves this for barbells, but it only changes the display, and loadKind is 'none' for dumbbells.

Proposed approach

A dumbbell inventory next to the plate inventory, stored per unit and stamped with _ts the same way S.plates is:

S.dumbbells = { kg: { weights: [3, 6, 8, 9, 11, 13, 15, 17, 18, 19, 21, 24], _ts } }

When a profile has one, exercises whose equipment is dumbbell (or that loadKind marks as such) use the list instead of the inc grid:

  • Progression "up": the next weight in the list above the current one, not current + inc.
  • Deload: selectDeloadCandidate takes its candidate weights from the list (the nearest ones around ideal) instead of positiveGridAround. The Epley scoring stays the same.
  • Stepper +/-: moves to the neighbouring weight in the list.
  • Edges: at the top of the list, progression keeps adding reps (or holds and says the heaviest dumbbell is reached) instead of suggesting a weight that doesn't exist.
  • Off-list current weight (history, import): treat it like an off-grid weight today. The next step is the nearest list weight in the direction of the change.

Without an inventory nothing changes: the inc grid stays the default, so existing profiles behave the same.

If it fits better into the v2 engine (#186), I'm happy to look at it there instead. A sorted list of loadable weights per equipment type might generalise better (it would also cover kettlebells and pin-loaded machines).

Dependencies

  • This doesn't require adding a new dependency

Activity

  1. giulioleuci commented on Oct 4, 2026

    @giulioleuci
    Contributor

    My engine implementation: #312. Feel free to build on it.

  2. torstenfeld commented on Oct 6, 2026

    @torstenfeld
    Author

    Thanks! I see #312 already has rounding.mode: 'allowed_values', which covers the snapping and the deload. What's left for this issue is a per-profile dumbbell inventory that fills allowedValues for every dumbbell exercise, so you don't enter the list once per exercise. I'll wait until #312 lands and then rework this on top of it.

  3. DuarteSantos8 commented on Oct 9, 2026

    @DuarteSantos8
    Owner

    Done in v1.4.0: Settings, Equipment, Dumbbells. Progression, deloads, warm-ups and the + and - buttons only land on dumbbells you own.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions