Ajoute les notes mémoire d'architecture et UX pour l'auto-enchaînement des chronos d'étapes, clôture le ticket #75, reflète les tickets #63/#70, ajoute le cadrage des tickets #76 à #79. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
153 lines
7.2 KiB
Markdown
153 lines
7.2 KiB
Markdown
---
|
|
name: gametime-architecture-step-chaining-override
|
|
description: memory note gametime-architecture-step-chaining-override
|
|
metadata:
|
|
type: project
|
|
---
|
|
# GameTime — Architecture auto-enchaînement configurable des chronos d'étapes
|
|
|
|
Décision d'architecture pour le ticket #73, basée sur `gametime-ux-step-chaining-override` et `gametime-architecture-exercise-steps`.
|
|
|
|
## Décision métier
|
|
|
|
Ajouter un réglage booléen : `autoStartNextTimedStep`.
|
|
|
|
Libellé UX : `Enchaîner automatiquement les chronos consécutifs`.
|
|
|
|
Valeur par défaut : `true`, pour préserver le comportement livré par les tickets #54/#60.
|
|
|
|
Portée exacte : le réglage ne concerne que le cas `Étape Temps -> Étape Temps`. Il ne change pas :
|
|
- Temps -> Répétitions : attente manuelle comme aujourd'hui.
|
|
- Répétitions -> Temps : démarrage possible après action utilisateur comme aujourd'hui.
|
|
- Fin de série : la séquence ne termine toujours pas automatiquement la série.
|
|
|
|
## Stockage / modèle domain
|
|
|
|
### Exercise
|
|
|
|
Ajouter :
|
|
|
|
```dart
|
|
final bool autoStartNextTimedStep;
|
|
```
|
|
|
|
- non-null ;
|
|
- défaut `true` ;
|
|
- présent même si `steps` est vide, mais sans effet tant qu'il n'y a pas de séquence avec deux étapes Temps consécutives.
|
|
|
|
### ProgramExercise
|
|
|
|
Ajouter deux champs :
|
|
|
|
```dart
|
|
final bool autoStartNextTimedStepSnapshot;
|
|
final bool? autoStartNextTimedStepOverride;
|
|
```
|
|
|
|
Raison : `ProgramExercise` est à la fois snapshot d'exercice et configuration programme. Il faut pouvoir revenir au réglage exercice sans dépendre de l'Exercise vivant, puisque les programmes existants restent indépendants des modifications ultérieures de bibliothèque.
|
|
|
|
Résolution programme :
|
|
|
|
```dart
|
|
programEffective = autoStartNextTimedStepOverride ?? autoStartNextTimedStepSnapshot;
|
|
```
|
|
|
|
À propager impérativement dans :
|
|
- `ProgramExercise.snapshotFromExercise` ;
|
|
- `ProgramExercise.toSnapshotJson()` ;
|
|
- `ProgramExerciseConfig` ;
|
|
- `_ProgramExerciseDraft` ;
|
|
- mappers Drift ;
|
|
- copie/share/import payloads.
|
|
|
|
Point d'attention #72 : ne pas oublier la propagation UI draft/config comme cela est arrivé pour `exerciseStepsSnapshot`.
|
|
|
|
### WorkoutTemplateExerciseOverride
|
|
|
|
Ajouter :
|
|
|
|
```dart
|
|
final bool? autoStartNextTimedStepOverride;
|
|
```
|
|
|
|
Décision consciente : cela élargit légèrement la règle historique des overrides de séance-modèle. Jusqu'ici, l'override ne portait que des valeurs numériques de série. Ce booléen est accepté dans `WorkoutTemplateExerciseOverride` parce qu'il ne modifie ni la structure, ni les mesures actives, ni la liste/l'ordre des exercices/étapes. Il modifie uniquement un comportement d'exécution local et nullable, avec héritage explicite.
|
|
|
|
Résolution séance :
|
|
|
|
```dart
|
|
effective = templateOverride.autoStartNextTimedStepOverride
|
|
?? programExercise.autoStartNextTimedStepOverride
|
|
?? programExercise.autoStartNextTimedStepSnapshot;
|
|
```
|
|
|
|
Null signifie toujours héritage.
|
|
|
|
## Drift / migration
|
|
|
|
Le schéma actuel vérifié est `schemaVersion = 13`. Le ticket #73 doit passer à `schemaVersion = 14`.
|
|
|
|
Migration recommandée :
|
|
- `exercises.auto_start_next_timed_step BOOLEAN NOT NULL DEFAULT true`.
|
|
- `program_exercises.auto_start_next_timed_step_snapshot BOOLEAN NOT NULL DEFAULT true`.
|
|
- `program_exercises.auto_start_next_timed_step_override BOOLEAN NULL`.
|
|
- `workout_template_exercise_overrides.auto_start_next_timed_step_override BOOLEAN NULL`.
|
|
|
|
Les snapshots JSON anciens n'auront pas ces champs : les parseurs doivent traiter l'absence comme `true`.
|
|
|
|
## Résolution pendant l'exécution
|
|
|
|
La valeur effective doit être disponible dans le snapshot résolu de séance ou, a minima, dans `_StepSequenceContext`.
|
|
|
|
Approche recommandée :
|
|
- lors de `startFromTemplate`, inclure l'override séance dans `resolvedTemplateSnapshotJson` comme les autres overrides ;
|
|
- lors de `_findExerciseSnapshot` / `_stepContext`, calculer ou exposer `autoStartNextTimedStepEffective` ;
|
|
- `ActiveExerciseStepUseCases` ne doit pas relire les entités vivantes Exercise/Program/Template. Il travaille uniquement sur le snapshot de session, comme le reste de l'exécution.
|
|
|
|
Cela garantit que reprendre une séance en cours garde le comportement décidé au lancement, même si l'utilisateur modifie ensuite l'exercice ou le programme source.
|
|
|
|
## État `Chrono suivant prêt`
|
|
|
|
Ne pas ajouter de nouveau statut Drift/domain pour v1.
|
|
|
|
Réutiliser `ActiveExerciseStepProgressStatus.stoppedTimer` : il signifie déjà qu'une étape chronométrée courante est prête mais non lancée (`startedAt == null`, `accumulatedMs == 0`).
|
|
|
|
Ne pas utiliser `waitingManual`, réservé aux étapes de type `reps`.
|
|
|
|
Le libellé UX `Chrono suivant prêt` est dérivé côté présentation/use case view quand :
|
|
- `state.status == stoppedTimer` ;
|
|
- l'étape courante est `time` ;
|
|
- l'étape précédente effective était aussi `time` ;
|
|
- `autoStartNextTimedStepEffective == false` ;
|
|
- un résultat completed/skipped existe pour l'étape précédente ou on vient de la transition timer expirée.
|
|
|
|
Pour la première étape chronométrée de la séquence, l'UI garde `Démarrer la séquence`. Pour une étape chrono prête après une étape Temps avec auto-enchaînement désactivé, l'UI affiche `Chrono suivant prêt` + `Démarrer le chrono`.
|
|
|
|
## `_advanceState` et `_autoAdvanceElapsedTimers`
|
|
|
|
Comportement actuel : `_autoAdvanceElapsedTimers` consomme l'overflow d'un timer expiré et peut démarrer automatiquement les timers suivants.
|
|
|
|
Nouveau comportement :
|
|
- si `autoStartNextTimedStepEffective == true`, comportement inchangé ;
|
|
- si `false` et que l'étape expirée est suivie d'une étape `time`, enregistrer le résultat de l'étape expirée, avancer la position vers l'étape suivante, puis s'arrêter en `stoppedTimer` avec `startedAt = null`, `accumulatedMs = 0` ;
|
|
- dans ce cas, ne pas transférer `overflowMs` au chrono suivant ;
|
|
- après kill/reprise, `_autoAdvanceElapsedTimers` doit s'arrêter exactement au premier `Chrono suivant prêt` et ne jamais avancer plus loin sans action utilisateur ;
|
|
- si l'étape suivante est `reps`, comportement inchangé : `waitingManual` ;
|
|
- si la dernière étape d'un passage est `time` et que le passage suivant commence par `time`, appliquer la même règle.
|
|
|
|
## Invariants
|
|
|
|
- Le réglage ne change jamais les résultats déjà enregistrés.
|
|
- Le réglage ne crée pas une pause de séance : le temps total de séance continue selon les horodatages de session.
|
|
- L'état `Chrono suivant prêt` est persistant car représenté par la ligne `ActiveExerciseStepProgressState` en `stoppedTimer` sur la bonne étape/passage.
|
|
- Les anciens exercices/programmes/templates doivent migrer avec comportement effectif `true`.
|
|
- Les overrides restent nullable pour permettre les actions UX `Revenir au réglage de l'exercice` et `Revenir au réglage du programme`.
|
|
|
|
## Tickets créés
|
|
|
|
- #75 `[DevBackend] Modèle et migration pour auto-enchaînement des chronos d'étapes`.
|
|
- #76 `[DevBackend] Résolution effective et auto-advance des chronos d'étapes`, dépend de #75.
|
|
- #77 `[DevFrontend] Réglages auto-enchaînement exercice, programme et séance`, dépend de #75.
|
|
- #78 `[DevFrontend] État d'exécution Chrono suivant prêt`, dépend de #76 et #77.
|
|
- #79 `[QA] Validation auto-enchaînement configurable des chronos d'étapes`, dépend de #78.
|
|
|
|
Ordre recommandé : #75 -> #76 et #77 en parallèle -> #78 -> #79. |