2026-10-28 22:55:07 +01:00
|
|
|
|
# ZenXercise
|
|
|
|
|
|
|
|
|
|
|
|
An offline Android app for stretching and working out, split into two fully separate Modes. The user
|
|
|
|
|
|
builds their own Plans from a large built-in Exercise Library and performs them in a guided Player.
|
|
|
|
|
|
|
|
|
|
|
|
## Modes
|
|
|
|
|
|
|
|
|
|
|
|
**Mode**:
|
|
|
|
|
|
One of the two top-level app states, **Stretching** or **Workout**. Switching Mode changes the whole
|
|
|
|
|
|
app: design, Exercise Library, Plans and History. The last-used Mode is remembered.
|
|
|
|
|
|
_Avoid_: Tab, section, category
|
|
|
|
|
|
|
|
|
|
|
|
**Stretching Mode**:
|
|
|
|
|
|
The calm Mode: light design, sage/teal, rounded shapes, slow transitions.
|
|
|
|
|
|
|
|
|
|
|
|
**Workout Mode**:
|
|
|
|
|
|
The energetic Mode: dark design, orange/red on near-black, bold type, snappy transitions.
|
|
|
|
|
|
|
|
|
|
|
|
## Exercises
|
|
|
|
|
|
|
|
|
|
|
|
**Exercise**:
|
|
|
|
|
|
A single movement from the Exercise Library, with name, Instructions, primary and secondary muscles,
|
|
|
|
|
|
equipment, level and a start and end image. Belongs to exactly one Mode. Users cannot create their own.
|
|
|
|
|
|
_Avoid_: Move, drill, activity
|
|
|
|
|
|
|
|
|
|
|
|
**Exercise Library**:
|
|
|
|
|
|
The read-only catalogue of Exercises bundled with the app, sourced from free-exercise-db (876
|
|
|
|
|
|
Exercises). Category `stretching` belongs to Stretching Mode (123); every other category to Workout
|
|
|
|
|
|
Mode (753). Browsed with text search and filters for muscle, equipment and level.
|
|
|
|
|
|
_Avoid_: Catalogue, database
|
|
|
|
|
|
|
|
|
|
|
|
**Flip Animation**:
|
|
|
|
|
|
Alternating an Exercise's start and end image about once a second, the v1 stand-in for real animation.
|
|
|
|
|
|
|
|
|
|
|
|
## Plans
|
|
|
|
|
|
|
|
|
|
|
|
**Plan**:
|
|
|
|
|
|
A user-created, ordered list of Steps (and Supersets) belonging to one Mode. The app ships no Plans.
|
|
|
|
|
|
_Avoid_: Routine, program, workout
|
|
|
|
|
|
|
|
|
|
|
|
**Step**:
|
|
|
|
|
|
One Exercise inside a Plan, with Mode-specific parameters:
|
|
|
|
|
|
- *Workout Step*: number of sets; reps **or** duration; optional target weight (kg).
|
|
|
|
|
|
- *Stretching Step*: hold duration; both-sides flag (left, then right); rounds.
|
|
|
|
|
|
_Avoid_: Item, entry
|
|
|
|
|
|
|
|
|
|
|
|
**Superset**:
|
2026-10-28 22:55:34 +01:00
|
|
|
|
Two or more adjacent Workout Steps grouped so they are performed alternately (A1 → B1 → A2 → B2 …).
|
|
|
|
|
|
It has one set count; each Step keeps its own reps or duration and weight. Rest between its Exercises
|
|
|
|
|
|
within a round is optional; the Rest Screen always follows the end of a round.
|
2026-10-28 22:55:07 +01:00
|
|
|
|
_Avoid_: Circuit, combo
|
|
|
|
|
|
|
2026-10-28 22:55:34 +01:00
|
|
|
|
**Rest Screen**:
|
|
|
|
|
|
In Workout Mode, the screen after "Set done": a count-up timer ("Resting 1:12") and a "Start next set"
|
|
|
|
|
|
button. Nothing counts down. Timed sets start only when the user taps Start.
|
|
|
|
|
|
|
|
|
|
|
|
**Transition**:
|
2026-10-29 00:20:16 +01:00
|
|
|
|
In Stretching Mode, a short card before the first hold ("Get ready") and between rounds, sides
|
|
|
|
|
|
("Switch sides") and Exercises, after which the next hold starts automatically. Its length is the
|
|
|
|
|
|
Plan's "pause between holds", 5 s by default; 0 s means no Transitions.
|
2026-10-28 22:55:34 +01:00
|
|
|
|
|
2026-10-28 22:55:07 +01:00
|
|
|
|
## Sessions
|
|
|
|
|
|
|
|
|
|
|
|
**Session**:
|
|
|
|
|
|
One run-through of a Plan in the Player. It stores a snapshot of the Plan, so later edits to the Plan
|
2026-10-29 00:20:16 +01:00
|
|
|
|
never change it. A Session is **complete** (reached the end) or **incomplete** (ended early). A Session
|
|
|
|
|
|
in which no hold or set was actually done is not saved at all.
|
2026-10-28 22:55:07 +01:00
|
|
|
|
_Avoid_: Workout, run
|
|
|
|
|
|
|
|
|
|
|
|
**Player**:
|
|
|
|
|
|
The guided, one-Exercise-at-a-time screen used to perform a Session. It shows a large countdown ring,
|
|
|
|
|
|
pulses the Mode's accent colour in the last three seconds, shows full-screen "next" cards, advances
|
2026-10-28 22:55:34 +01:00
|
|
|
|
automatically when a timer ends and keeps the screen awake. A single soft chime (singing bowl in
|
|
|
|
|
|
Stretching, muted "tok" in Workout) plays only when a timer ends or something new starts; it mixes
|
|
|
|
|
|
with the user's music and can be muted. No ticking, no vibration.
|
2026-10-28 22:55:07 +01:00
|
|
|
|
|
|
|
|
|
|
**Set Log**:
|
|
|
|
|
|
The reps and weight actually done for one Workout set, prefilled from the Step's targets and confirmed
|
|
|
|
|
|
with "Set done".
|
|
|
|
|
|
|
|
|
|
|
|
**History**:
|
|
|
|
|
|
The per-Mode list of Sessions with date, Plan, duration and Set Logs.
|
|
|
|
|
|
|
|
|
|
|
|
**Streak**:
|
2026-10-28 22:55:34 +01:00
|
|
|
|
A single, subtle, Duolingo-style daily streak shared by both Modes: consecutive days with at least one
|
2026-10-28 23:00:49 +01:00
|
|
|
|
complete Session in either Mode, however short. Incomplete Sessions do not count. Shown as a small 🔥
|
|
|
|
|
|
and count in the top bar (grey until today is done); tapping it opens current/longest Streak and a
|
|
|
|
|
|
month calendar. Protected by Streak Freezes and the Grace Hour.
|
|
|
|
|
|
|
|
|
|
|
|
**Streak Day**:
|
|
|
|
|
|
The day a complete Session counts for. Normally its calendar day, except during the Grace Hour.
|
|
|
|
|
|
|
|
|
|
|
|
**Grace Hour**:
|
|
|
|
|
|
00:00–01:00. A Session completed then counts for the previous day if that day has no complete Session
|
|
|
|
|
|
yet; otherwise it counts for the current day.
|
|
|
|
|
|
|
|
|
|
|
|
**Streak Freeze**:
|
2026-10-28 23:03:28 +01:00
|
|
|
|
A saved token that is used automatically to cover a missed day so the Streak survives. One is earned
|
|
|
|
|
|
per 7 consecutive Streak Days; at most 2 are held. A frozen day shows ❄️ in the calendar. Missing more
|
|
|
|
|
|
days than Freezes held resets the Streak to 0.
|
2026-10-28 23:00:49 +01:00
|
|
|
|
|
|
|
|
|
|
**Reminder**:
|
2026-10-29 00:34:49 +01:00
|
|
|
|
A local notification sent only if no complete Session exists for that day. Two by default (19:00 and
|
|
|
|
|
|
22:30); each can be switched on/off and moved in Settings. No more than two. Android may deliver one up
|
|
|
|
|
|
to about an hour late (see docs/adr/0006).
|