trainlog/docs/exercise_data_model.md

4.3 KiB

Exercise data model

Status

EXERCISE_DATA_MODEL_V1=FROZEN_FOR_IMPLEMENTATION
DATABASE_SCHEMA_V3=NEXT
TUI_PROFILE_AWARE_ENTRY=AFTER_SCHEMA_V3
ANDROID_PROFILE_AWARE_ENTRY=AFTER_TUI
TRAINLOG_FORMAT_V1=FROZEN
SESSION_EXCHANGE_V2=DESIGN_REQUIRED_LATER

Trainlog must not use one universal exercise form.

An exercise is defined by three independent pieces of metadata:

recording_mode = SETS | CONTINUOUS
tracking_mode  = REPS | DURATION
data_fields    = supplemental field bit mask

Initial valid combinations:

SETS + REPS
SETS + DURATION
CONTINUOUS + DURATION

CONTINUOUS + REPS is invalid in model v1.

Initial supplemental fields:

SPEED_KMH
DISTANCE_KM

Unknown field bits are invalid.

Examples:

Presse à cuisses
    SETS + REPS

Gainage
    SETS + DURATION

Marche
    CONTINUOUS + DURATION
    SPEED_KMH

Course
    CONTINUOUS + DURATION
    SPEED_KMH

Vélo
    CONTINUOUS + DURATION
    SPEED_KMH | DISTANCE_KM

Rameur
    CONTINUOUS + DURATION
    DISTANCE_KM

Load semantics remain separate and session-specific:

none
external
assistance

A continuous exercise does not ask for:

number of sets
repetitions
per-set rest

For example:

Marche

Durée      45 min
Vitesse    5.8 km/h

Creating/editing an exercise asks for:

Name
Organization: Sets | Continuous
Primary metric: Repetitions | Duration
Supplemental fields: Speed | Distance

Rules:

  • continuous forces duration in model v1;
  • sets accepts reps or duration;
  • UI fields are driven by metadata, never exercise-name heuristics;
  • changing catalog metadata affects future entry only.

Historical stability:

Every session exercise stores a snapshot of:

recording_mode
tracking_mode
data_fields

So changing Marche from an old set-based duration exercise to continuous duration + speed does not reinterpret old sessions.

SQLite schema v3 direction

Schema v3 adds to exercises:

recording_mode
data_fields

and snapshots the same values in session_exercises.

Migration v2 -> v3 is conservative:

all existing exercises         -> SETS
all existing session exercises -> SETS
data_fields                    -> 0

No migration guesses by exercise name.

Continuous actual activity data gets its own one-to-one record:

duration_seconds
speed_kmh       nullable
distance_km     nullable

Continuous activities have no performed_sets rows and no fake one-set representation.

Frozen JSON v1

Trainlog JSON session v1 remains frozen.

It represents the existing set-based exchange model.

Continuous data that cannot be represented in v1 must not be:

  • hidden in notes;
  • converted into a fake set;
  • silently discarded.

A future explicit session exchange v2 will carry profile-aware exercise data while v1 import remains supported.

Android/TUI parity

Both interfaces consume identical exercise metadata.

The future PC -> Android catalog snapshot must contain:

exercise_id
name
recording_mode
tracking_mode
data_fields

Implementation order

1. SQLite schema v3 + migration tests
2. C model/API additions
3. catalog create/edit support
4. TUI profile-aware session entry
5. manually convert Marche to CONTINUOUS + SPEED_KMH
6. profile-aware detail/history
7. Android uses the same model
8. design session exchange v2

Implemented checkpoint

The profile-aware exercise model is now implemented in the C model, SQLite persistence and TUI.

Current canonical rules:

recording_mode = SETS | CONTINUOUS
tracking_mode  = REPS | DURATION

known data_fields:
    SPEED_KMH
    DISTANCE_KM

Valid model-v1 combinations:

SETS + REPS
SETS + DURATION
CONTINUOUS + DURATION

Continuous exercise actual data is persisted as one continuous_activity record rather than a performed-set list.

A continuous activity never manufactures a one-set representation.

The TUI asks continuous duration in minutes, converts to seconds, and stores seconds internally.

Example:

Marche
    CONTINUOUS + DURATION + SPEED_KMH

TUI entry:
    Durée (minutes)
    Vitesse km/h

Historical session rows snapshot recording metadata and are not reinterpreted when catalog metadata later changes.