docs(ideai): mémoire chaînage de chronos, clôture ticket #75, cadrage #76-#79
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>
This commit is contained in:
@ -19,3 +19,5 @@
|
||||
- [gametime-online-layer-philosophy](gametime-online-layer-philosophy.md) — memory note gametime-online-layer-philosophy
|
||||
- [gametime-ux-online-client](gametime-ux-online-client.md) — memory note gametime-ux-online-client
|
||||
- [gametime-architecture-online-client](gametime-architecture-online-client.md) — memory note gametime-architecture-online-client
|
||||
- [gametime-ux-step-chaining-override](gametime-ux-step-chaining-override.md) — memory note gametime-ux-step-chaining-override
|
||||
- [gametime-architecture-step-chaining-override](gametime-architecture-step-chaining-override.md) — memory note gametime-architecture-step-chaining-override
|
||||
|
||||
153
.ideai/memory/gametime-architecture-step-chaining-override.md
Normal file
153
.ideai/memory/gametime-architecture-step-chaining-override.md
Normal file
@ -0,0 +1,153 @@
|
||||
---
|
||||
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.
|
||||
271
.ideai/memory/gametime-ux-step-chaining-override.md
Normal file
271
.ideai/memory/gametime-ux-step-chaining-override.md
Normal file
@ -0,0 +1,271 @@
|
||||
---
|
||||
name: gametime-ux-step-chaining-override
|
||||
description: memory note gametime-ux-step-chaining-override
|
||||
metadata:
|
||||
type: project
|
||||
---
|
||||
# GameTime — Enchaînement configurable des chronos d'étapes (ticket #73, UX 2026-07-20)
|
||||
|
||||
Conception UX pour rendre configurable le comportement d'enchaînement automatique entre deux étapes chronométrées consécutives dans un exercice à séquence.
|
||||
|
||||
Mémoire de référence : `gametime-ux-exercise-steps`.
|
||||
|
||||
## Décision structurante
|
||||
|
||||
Le comportement historiquement fixe devient un réglage hiérarchique :
|
||||
|
||||
```text
|
||||
séance-modèle > programme > exercice
|
||||
```
|
||||
|
||||
La valeur effective pendant l'exécution est la valeur la plus spécifique renseignée :
|
||||
|
||||
- override séance si présent ;
|
||||
- sinon override/config programme si présent ;
|
||||
- sinon valeur par défaut de l'exercice.
|
||||
|
||||
Valeur par défaut recommandée pour les exercices existants et nouveaux : **activé**, afin de préserver le comportement livré aux tickets #54/#60.
|
||||
|
||||
Libellé commun :
|
||||
|
||||
```text
|
||||
Enchaîner automatiquement les chronos consécutifs
|
||||
```
|
||||
|
||||
Aide commune :
|
||||
|
||||
```text
|
||||
Quand une étape Temps est suivie d'une autre étape Temps, le chrono suivant démarre dès que le précédent arrive à 0.
|
||||
```
|
||||
|
||||
Si désactivé, aide complémentaire :
|
||||
|
||||
```text
|
||||
L'app attendra ton démarrage avant de lancer le chrono suivant.
|
||||
```
|
||||
|
||||
## 1. Niveau Exercice
|
||||
|
||||
Surface : `ExerciseFormScreen`, section `Séquence d'étapes`.
|
||||
|
||||
Afficher le réglage uniquement si `Rythmer cet exercice avec des étapes` est activé.
|
||||
|
||||
Placement recommandé : juste sous le switch `Rythmer cet exercice avec des étapes`, avant la liste des étapes.
|
||||
|
||||
UI :
|
||||
|
||||
```text
|
||||
Séquence d'étapes
|
||||
[ON] Rythmer cet exercice avec des étapes
|
||||
|
||||
[ON] Enchaîner automatiquement les chronos consécutifs
|
||||
Quand une étape Temps est suivie d'une autre étape Temps, le chrono suivant démarre dès que le précédent arrive à 0.
|
||||
```
|
||||
|
||||
Si désactivé :
|
||||
|
||||
```text
|
||||
[OFF] Enchaîner automatiquement les chronos consécutifs
|
||||
L'app attendra ton démarrage avant de lancer le chrono suivant.
|
||||
```
|
||||
|
||||
Ne pas masquer le réglage s'il n'y a pas encore deux étapes Temps consécutives : l'utilisateur peut encore ajouter/réordonner des étapes. Le réglage est simplement sans effet tant qu'aucun enchaînement Temps -> Temps n'existe.
|
||||
|
||||
## 2. Niveau Programme
|
||||
|
||||
Surface : écran `Personnaliser l'exercice` dans un programme (`ProgramExerciseCustomizationScreen`).
|
||||
|
||||
Afficher une nouvelle section `Séquence` seulement si l'exercice possède des étapes.
|
||||
|
||||
Placement recommandé : après `Objectifs`, avant `Repos`, car le réglage concerne le déroulé interne de l'exercice, pas les mesures de série.
|
||||
|
||||
UI recommandée : switch + indication d'héritage.
|
||||
|
||||
État sans override programme :
|
||||
|
||||
```text
|
||||
Séquence
|
||||
[ON] Enchaîner automatiquement les chronos consécutifs
|
||||
Réglage de l'exercice
|
||||
```
|
||||
|
||||
Si l'utilisateur change le switch, cela crée une personnalisation programme :
|
||||
|
||||
```text
|
||||
Séquence
|
||||
[OFF] Enchaîner automatiquement les chronos consécutifs
|
||||
Personnalisé pour ce programme
|
||||
|
||||
[Revenir au réglage de l'exercice]
|
||||
```
|
||||
|
||||
Règle UX : il doit toujours être possible de supprimer l'override programme via `Revenir au réglage de l'exercice`. Sans ce retour, un simple switch force une valeur locale permanente et ne respecte pas le modèle hiérarchique.
|
||||
|
||||
Résumé compact de l'exercice dans le programme : ne pas ajouter ce détail dans la ligne compacte par défaut. Le réglage reste dans `Personnaliser` pour éviter de surcharger la liste.
|
||||
|
||||
## 3. Niveau Séance-modèle
|
||||
|
||||
Surface : détail d'un programme intégré dans une séance-modèle (`WorkoutTemplateProgramDetailScreen`), là où l'utilisateur surcharge déjà le nombre de séries et les cibles numériques.
|
||||
|
||||
Afficher la section `Séquence` dans chaque carte exercice seulement si l'exercice possède des étapes.
|
||||
|
||||
Placement recommandé : après les champs numériques de l'exercice, dans la même carte.
|
||||
|
||||
UI :
|
||||
|
||||
État sans override séance :
|
||||
|
||||
```text
|
||||
Séquence
|
||||
[ON] Enchaîner automatiquement les chronos consécutifs
|
||||
Réglage du programme
|
||||
```
|
||||
|
||||
État avec override séance :
|
||||
|
||||
```text
|
||||
Séquence
|
||||
[OFF] Enchaîner automatiquement les chronos consécutifs
|
||||
Personnalisé pour cette séance
|
||||
|
||||
[Revenir au réglage du programme]
|
||||
```
|
||||
|
||||
Règle UX : la séance doit pouvoir revenir au réglage du programme. C'est nécessaire pour conserver une vraie résolution `séance > programme > exercice`.
|
||||
|
||||
Point d'attention Architect : `WorkoutTemplateExerciseOverride` ne porte aujourd'hui que des overrides numériques. Il faudra un override booléen nullable, par exemple `autoStartNextTimedStepOverride`, pour représenter `non renseigné / activé / désactivé`.
|
||||
|
||||
## 4. Exécution quand le réglage est activé
|
||||
|
||||
Comportement inchangé :
|
||||
|
||||
- une étape Temps arrive à `0` ;
|
||||
- bip long ;
|
||||
- si l'étape suivante est aussi Temps, son chrono démarre immédiatement ;
|
||||
- pas de pause ni bouton intermédiaire.
|
||||
|
||||
C'est aussi le comportement à conserver pour les exercices existants après migration.
|
||||
|
||||
## 5. Exécution quand le réglage est désactivé
|
||||
|
||||
Cas ciblé : étape `Temps` suivie directement d'une autre étape `Temps`.
|
||||
|
||||
Quand le premier chrono arrive à `0` :
|
||||
|
||||
- bips des 3 dernières secondes inchangés ;
|
||||
- bip long à `0` inchangé ;
|
||||
- l'app passe à l'étape suivante ;
|
||||
- le chrono suivant **ne démarre pas** ;
|
||||
- l'écran attend une action explicite.
|
||||
|
||||
État visuel attendu dans le module `SÉQUENCE` :
|
||||
|
||||
```text
|
||||
ÉTAPE 2 / 4
|
||||
Dribble main gauche
|
||||
Objectif : 10 s
|
||||
|
||||
00:10
|
||||
Chrono suivant prêt
|
||||
|
||||
[Démarrer le chrono]
|
||||
[Passer l'étape]
|
||||
```
|
||||
|
||||
Différence de libellé :
|
||||
|
||||
- première étape chronométrée de la séquence : bouton `Démarrer la séquence` ;
|
||||
- étape chronométrée mise en attente après une autre étape Temps : bouton `Démarrer le chrono`.
|
||||
|
||||
Style Court Blazer :
|
||||
|
||||
- timer `00:10` en Anton, primaire or ;
|
||||
- label `Chrono suivant prêt` en Archivo, texte secondaire ;
|
||||
- optionnel : petit badge contour primaire `PRÊT` ;
|
||||
- panneau avec surface habituelle + liseré crimson 2 px ;
|
||||
- pas de rouge/alerte : c'est un état attendu, pas une erreur.
|
||||
|
||||
Si plusieurs étapes Temps se suivent et que le réglage est désactivé, l'app attend avant chaque nouveau chrono.
|
||||
|
||||
Si la dernière étape d'un passage est Temps et que le passage suivant commence aussi par Temps : appliquer la même règle. L'écran peut afficher :
|
||||
|
||||
```text
|
||||
Passage 2 / 10
|
||||
ÉTAPE 1 / 4
|
||||
Dribble main droite
|
||||
|
||||
Chrono suivant prêt
|
||||
[Démarrer le chrono]
|
||||
```
|
||||
|
||||
## 6. Interaction avec étapes à répétitions
|
||||
|
||||
Aucun changement.
|
||||
|
||||
- Temps -> Répétitions : le chrono finit, l'app affiche l'étape à répétitions et attend `Étape suivante` comme aujourd'hui.
|
||||
- Répétitions -> Temps : après `Étape suivante`, si l'étape suivante est Temps, le chrono peut démarrer immédiatement selon le comportement déjà existant pour démarrer une étape Temps après action utilisateur. Le nouveau réglage cible uniquement le cas Temps -> Temps automatique.
|
||||
|
||||
## 7. Pause, reprise, app fermée
|
||||
|
||||
Si le réglage est désactivé et que l'app est dans l'état `Chrono suivant prêt` :
|
||||
|
||||
- pause/reprise conserve cet état prêt ;
|
||||
- aucun temps ne s'écoule pour l'étape suivante ;
|
||||
- après kill/reprise, revenir au même état avec le bouton `Démarrer le chrono`.
|
||||
|
||||
Si l'app est en arrière-plan pendant un chrono et que celui-ci atteint `0` :
|
||||
|
||||
- si l'enchaînement est activé, l'app peut recalculer et avancer dans les chronos consécutifs comme prévu ;
|
||||
- si l'enchaînement est désactivé, l'app s'arrête au premier état `Chrono suivant prêt` et n'avance pas plus loin sans action utilisateur.
|
||||
|
||||
## 8. Libellés définitifs
|
||||
|
||||
Réglage :
|
||||
|
||||
```text
|
||||
Enchaîner automatiquement les chronos consécutifs
|
||||
```
|
||||
|
||||
Aide activée :
|
||||
|
||||
```text
|
||||
Le chrono suivant démarre dès que le précédent arrive à 0.
|
||||
```
|
||||
|
||||
Aide désactivée :
|
||||
|
||||
```text
|
||||
L'app attendra ton démarrage avant de lancer le chrono suivant.
|
||||
```
|
||||
|
||||
État d'exécution :
|
||||
|
||||
```text
|
||||
Chrono suivant prêt
|
||||
```
|
||||
|
||||
Bouton :
|
||||
|
||||
```text
|
||||
Démarrer le chrono
|
||||
```
|
||||
|
||||
Retour héritage programme :
|
||||
|
||||
```text
|
||||
Revenir au réglage de l'exercice
|
||||
```
|
||||
|
||||
Retour héritage séance :
|
||||
|
||||
```text
|
||||
Revenir au réglage du programme
|
||||
```
|
||||
|
||||
## 9. Découpage conseillé
|
||||
|
||||
1. `Domain · réglage auto-start chronos d'étapes` : valeur exercice + overrides programme/séance nullable.
|
||||
2. `ExerciseForm · switch valeur par défaut`.
|
||||
3. `ProgramExerciseCustomization · override avec retour au réglage exercice`.
|
||||
4. `WorkoutTemplateProgramDetail · override avec retour au réglage programme`.
|
||||
5. `WorkoutExecution · état Chrono suivant prêt + résolution effective`.
|
||||
Reference in New Issue
Block a user