docs(ideai): mémoire, sprint et tickets du chantier exercices à étapes
Ajoute les notes mémoire d'architecture et UX pour les exercices à étapes, un nouveau sprint, clôture le ticket #56 et reflète les tickets #46/#53, ajoute le cadrage des tickets #57 à #63. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -14,3 +14,5 @@
|
||||
- [gametime-ux-series-counter](gametime-ux-series-counter.md) — memory note gametime-ux-series-counter
|
||||
- [gametime-ux-exercise-media-viewer](gametime-ux-exercise-media-viewer.md) — memory note gametime-ux-exercise-media-viewer
|
||||
- [gametime-server-architecture-sync-sharing](gametime-server-architecture-sync-sharing.md) — memory note gametime-server-architecture-sync-sharing
|
||||
- [gametime-ux-exercise-steps](gametime-ux-exercise-steps.md) — memory note gametime-ux-exercise-steps
|
||||
- [gametime-architecture-exercise-steps](gametime-architecture-exercise-steps.md) — memory note gametime-architecture-exercise-steps
|
||||
|
||||
167
.ideai/memory/gametime-architecture-exercise-steps.md
Normal file
167
.ideai/memory/gametime-architecture-exercise-steps.md
Normal file
@ -0,0 +1,167 @@
|
||||
---
|
||||
name: gametime-architecture-exercise-steps
|
||||
description: memory note gametime-architecture-exercise-steps
|
||||
metadata:
|
||||
type: project
|
||||
---
|
||||
# GameTime — Architecture exercices à plusieurs étapes
|
||||
|
||||
Décision d'architecture pour le ticket #54, basée sur la mémoire UX `gametime-ux-exercise-steps` et les patterns existants : snapshots, `ActiveSetResult` distinct des résultats détaillés, timers persistés via tables dédiées (`ActiveRestState`, `ActiveScoreStopwatchState`).
|
||||
|
||||
## Principe métier
|
||||
|
||||
Les étapes sont un rythme interne d'un exercice, pas une nouvelle mesure de série. Elles coexistent avec les mesures existantes `Temps`, `Répétitions`, `Score`.
|
||||
|
||||
- Si `Répétitions` est active sur la série, un passage complet de la séquence d'étapes = une répétition/passsage réalisé.
|
||||
- Si `Temps` est actif sur la série, il reste une durée/fenêtre globale de série, indépendante des timers d'étapes.
|
||||
- Le score de série reste porté par `ActiveSetResult` / `WorkoutHistorySetResult`.
|
||||
- Les résultats d'étapes restent dans des entités dédiées et ne se mélangent jamais avec les résultats de série.
|
||||
|
||||
## Domaine exercice
|
||||
|
||||
Ajouter :
|
||||
|
||||
```dart
|
||||
enum ExerciseStepType { time, reps }
|
||||
|
||||
final class ExerciseStep {
|
||||
final String id;
|
||||
final int position;
|
||||
final String name;
|
||||
final ExerciseStepType type;
|
||||
final int defaultTargetValue;
|
||||
final bool hasScore;
|
||||
final ScoreInputMode scoreInputMode;
|
||||
final String? scoreLabel;
|
||||
final String? scoreUnit;
|
||||
final double? defaultTargetScore;
|
||||
final int? defaultTargetScoreTimeMs;
|
||||
}
|
||||
```
|
||||
|
||||
Ajouter `List<ExerciseStep> steps` sur `Exercise`.
|
||||
|
||||
Invariants :
|
||||
- `steps.length <= 8`.
|
||||
- positions uniques, contiguës et `>= 0` dans l'ordre affiché.
|
||||
- `name` non vide.
|
||||
- `defaultTargetValue > 0` ; unité métier : secondes si `type=time`, répétitions si `type=reps`.
|
||||
- si `hasScore=false`, aucune valeur/label de score d'étape ne doit être significative.
|
||||
- si `hasScore=true` et `scoreInputMode=manual`, `scoreLabel` et `scoreUnit` obligatoires ; `defaultTargetScore` nullable mais si renseigné `>= 0`.
|
||||
- si `hasScore=true` et `scoreInputMode=stopwatch`, `defaultTargetScoreTimeMs` nullable mais si renseigné `> 0`; pas d'unité libre.
|
||||
- score manuel et score chrono d'étape sont exclusifs.
|
||||
- `type=time` + score chrono d'étape est autorisé mais doit rester un avertissement UX non bloquant.
|
||||
|
||||
## Snapshot pattern
|
||||
|
||||
Les étapes doivent suivre le même pattern que les autres propriétés d'exercice :
|
||||
|
||||
`Exercise.steps` -> snapshot dans `ProgramExercise` -> inclus dans `ProgramExercise.toSnapshotJson()` -> inclus dans `WorkoutTemplateProgram.programSnapshotJson` -> résolu dans `ActiveWorkoutSession.resolvedTemplateSnapshotJson` -> copié dans l'historique.
|
||||
|
||||
Recommandation Drift :
|
||||
- source normalisée : table `exercise_steps` liée à `exercises`.
|
||||
- snapshot programme : colonne `exercise_steps_snapshot_json` sur `program_exercises` plutôt qu'une table normalisée de snapshots pour le MVP.
|
||||
- historique : les snapshots utiles sont copiés dans `WorkoutHistoryStepResult`, et le snapshot global reste dans `historySnapshotJson`.
|
||||
|
||||
Les modifications ultérieures d'un Exercise ne modifient pas les ProgramExercise existants.
|
||||
|
||||
## Modèle d'exécution
|
||||
|
||||
Ne pas étendre `ActiveSetResult` pour porter les détails d'étapes. `ActiveSetResult` reste le résultat global de série.
|
||||
|
||||
Ajouter une table/entité dédiée pour la progression courante : `ActiveExerciseStepProgressState`.
|
||||
|
||||
Champs recommandés :
|
||||
- champs sync communs.
|
||||
- `activeWorkoutSessionId`.
|
||||
- `programIndex`, `exerciseIndex`, `setIndex`.
|
||||
- `currentPassageIndex` : `>= 0`.
|
||||
- `currentStepIndex` : `>= 0`.
|
||||
- `currentStepSnapshotId`.
|
||||
- `status` : `notStarted | waitingManual | runningTimer | pausedTimer | stoppedTimer | sequenceComplete`.
|
||||
- `startedAt?` : horodatage du run timer courant.
|
||||
- `accumulatedMs` : `>= 0`, temps déjà accumulé pour l'étape timer courante.
|
||||
- `lastTransitionAt`.
|
||||
|
||||
Contraintes :
|
||||
- unique `(active_workout_session_id, program_index, exercise_index, set_index)`.
|
||||
- pas de compteur uniquement mémoire ; tout timer d'étape actif est reconstituable depuis `startedAt + accumulatedMs`.
|
||||
- pause séance : un `runningTimer` devient `pausedTimer` en figeant `accumulatedMs`.
|
||||
- kill app : à la reprise, recalculer depuis les horodatages et avancer automatiquement les étapes chronométrées écoulées jusqu'à la première étape manuelle ou fin de séquence.
|
||||
|
||||
Ajouter une table/entité de résultats actifs : `ActiveExerciseStepResult`.
|
||||
|
||||
Champs recommandés :
|
||||
- champs sync communs.
|
||||
- `activeWorkoutSessionId`.
|
||||
- `programSnapshotId`, `exerciseSnapshotId`.
|
||||
- `programIndex`, `exerciseIndex`, `setIndex`.
|
||||
- `passageIndex`, `stepIndex`, `stepSnapshotId`.
|
||||
- snapshots : `stepNameSnapshot`, `stepTypeSnapshot`, `targetValueSnapshot`, `hasScoreSnapshot`, `scoreInputModeSnapshot`, `scoreLabelSnapshot?`, `scoreUnitSnapshot?`, `targetScoreSnapshot?`, `targetScoreTimeMsSnapshot?`.
|
||||
- `status` : `completed | skipped`.
|
||||
- `startedAt?`, `completedAt?`.
|
||||
- `actualTimeMs?` pour étape `time`.
|
||||
- `actualReps?` pour étape `reps` si correction future ; MVP peut enregistrer la cible quand validée ou laisser null avec statut completed selon choix UI, mais l'historique doit rester lisible.
|
||||
- `actualScore?` pour score manuel d'étape.
|
||||
- `actualScoreTimeMs?` pour score chrono d'étape.
|
||||
- `note?` optionnel.
|
||||
|
||||
Contraintes :
|
||||
- unique `(active_workout_session_id, program_index, exercise_index, set_index, passage_index, step_index)`.
|
||||
- `skipped` implique toutes les valeurs `actual*` nulles.
|
||||
- `actualTimeMs` seulement pour `stepType=time`.
|
||||
- `actualReps` seulement pour `stepType=reps`.
|
||||
- `actualScore` seulement si `hasScoreSnapshot=true` et `scoreInputModeSnapshot=manual`.
|
||||
- `actualScoreTimeMs` seulement si `hasScoreSnapshot=true` et `scoreInputModeSnapshot=stopwatch`.
|
||||
- score manuel et score chrono jamais remplis simultanément.
|
||||
|
||||
## Historique
|
||||
|
||||
Ajouter `WorkoutHistoryStepResult`, distinct de `WorkoutHistorySetResult`.
|
||||
|
||||
Champs analogues à `ActiveExerciseStepResult`, avec `workoutHistoryId` au lieu de `activeWorkoutSessionId` et snapshots complets pour affichage autonome.
|
||||
|
||||
À la clôture d'une séance :
|
||||
- créer `WorkoutHistory` et `WorkoutHistorySetResult` comme aujourd'hui pour les résultats globaux de série.
|
||||
- copier tous les `ActiveExerciseStepResult` de la session vers `WorkoutHistoryStepResult`.
|
||||
- ne jamais recalculer `WorkoutHistorySetResult.actualReps` depuis les step results sans décision explicite du use case ; les passages réalisés peuvent alimenter l'UI, mais le résultat de série reste sa propre source.
|
||||
|
||||
## Drift / migration
|
||||
|
||||
Le schéma actuel est `schemaVersion = 7`. Le ticket #54 doit passer à `schemaVersion = 8`.
|
||||
|
||||
Ajouts recommandés :
|
||||
- table `exercise_steps`.
|
||||
- colonne `exercise_steps_snapshot_json` sur `program_exercises`.
|
||||
- table `active_exercise_step_progress_states`.
|
||||
- table `active_exercise_step_results`.
|
||||
- table `workout_history_step_results`.
|
||||
- index de session sur les tables actives.
|
||||
- index history sur `workout_history_step_results(workout_history_id)`.
|
||||
- contraintes CHECK pour types, statuts, valeurs positives/non négatives.
|
||||
|
||||
## Audio / bips
|
||||
|
||||
Choix recommandé : introduire un port applicatif/presentation `ExerciseStepAudioCuePlayer` ou équivalent, avec méthodes métier `playShortCountdownBeep()` et `playLongCompletionBeep()`.
|
||||
|
||||
Adapter Flutter recommandé : `audioplayers` avec deux assets très courts bundlés (`short_beep`, `long_beep`), préchargés et joués en mode faible latence si possible.
|
||||
|
||||
Raison : solution mature et multiplateforme iOS/Android, fiable pour distinguer bip court et bip long. `SystemSound` est plus simple mais ne garantit pas un bip long distinct ni un contrôle suffisant. Une génération synthétique pure éviterait les assets mais augmente la complexité native/test.
|
||||
|
||||
Invariants de test :
|
||||
- les widgets/use cases dépendent du port, jamais directement du lecteur audio réel.
|
||||
- tests unitaires/widget avec fake player uniquement.
|
||||
- l'absence/échec audio ne doit pas bloquer la progression d'étape.
|
||||
|
||||
## Tickets créés
|
||||
|
||||
- #56 `[DevBackend] Modèle domain + Drift pour exercices à étapes`.
|
||||
- #58 `[DevBackend] Exécution persistante des étapes et résultats par passage`, dépend de #56.
|
||||
- #59 `[DevFrontend] Éditeur d'exercice avec séquence d'étapes`, dépend de #56.
|
||||
- #60 `[DevFrontend] Exécution de séance avec module séquence et bips`, dépend de #58 et #59.
|
||||
- #61 `[DevFrontend] Plan de séance et historique avec résultats d'étapes`, dépend de #58.
|
||||
- #62 `[QA] Validation exercices à étapes, persistance et historique`, dépend de #60 et #61.
|
||||
|
||||
Ordre recommandé : #56 -> #58 -> #59 -> #60 et #61 -> #62.
|
||||
|
||||
Note orchestration : le sprint dédié `Exercice editor enhancement` existe avec id `1bb8bdf2-9c35-4f53-9a31-1390a47bec63`, mais l'outil de création de ticket exposé à Architect ne permet pas de renseigner `sprintId`. Les tickets ont donc été créés liés à #54 et devront être rattachés au sprint par l'orchestrateur si nécessaire.
|
||||
437
.ideai/memory/gametime-ux-exercise-steps.md
Normal file
437
.ideai/memory/gametime-ux-exercise-steps.md
Normal file
@ -0,0 +1,437 @@
|
||||
---
|
||||
name: gametime-ux-exercise-steps
|
||||
description: memory note gametime-ux-exercise-steps
|
||||
metadata:
|
||||
type: project
|
||||
---
|
||||
# GameTime — Exercice à plusieurs étapes (ticket #54, UX 2026-07-19)
|
||||
|
||||
Conception UX pour ajouter des **séquences d'étapes** aux exercices, sans remplacer les mesures existantes `Temps / Répétitions / Score` au niveau de la série.
|
||||
|
||||
## Décision structurante
|
||||
|
||||
Les étapes sont un **rythme interne de l'exercice**, pas un nouveau mode exclusif d'exécution.
|
||||
|
||||
- Un exercice peut conserver toutes ses mesures de série existantes : `Temps`, `Répétitions`, `Score`.
|
||||
- La séquence d'étapes s'ajoute par-dessus ces mesures.
|
||||
- Si la mesure `Répétitions` est active au niveau de la série, elle représente le nombre de **passages complets dans la séquence**.
|
||||
- Si la mesure `Temps` est active au niveau de la série, elle représente une fenêtre globale ou une durée cible de série, indépendante des chronos d'étapes.
|
||||
- Le score de série reste disponible tel que déjà conçu, y compris score libre ou score chrono.
|
||||
|
||||
Exemple validé par le besoin utilisateur : une série peut demander de répéter 10 fois la séquence `dribble gauche -> dribble droite`, ou d'enchaîner cette séquence pendant 10 minutes, ou les deux.
|
||||
|
||||
## A. Création / édition d'exercice
|
||||
|
||||
Surface concernée : `ExerciseFormScreen`, section existante `Mesures disponibles`.
|
||||
|
||||
Ajouter une nouvelle section après les mesures disponibles et leurs valeurs par défaut :
|
||||
|
||||
```text
|
||||
Séquence d'étapes
|
||||
[ ] Rythmer cet exercice avec des étapes
|
||||
```
|
||||
|
||||
Texte d'aide quand désactivé :
|
||||
|
||||
```text
|
||||
Ajoute des étapes si l'exercice doit suivre un ordre précis pendant chaque série.
|
||||
```
|
||||
|
||||
Quand activé :
|
||||
|
||||
```text
|
||||
Séquence d'étapes
|
||||
Chaque passage suit ces étapes dans l'ordre. Si la série suit des répétitions, une répétition correspond à un passage complet.
|
||||
|
||||
[Ajouter une étape]
|
||||
```
|
||||
|
||||
### Limite d'étapes
|
||||
|
||||
Recommandation UX MVP : limite dure à **8 étapes** par exercice.
|
||||
|
||||
Raison : 5-6 étapes restent lisibles pendant l'effort ; 8 couvre les exercices complexes sans rendre la progression mobile trop dense. Si l'utilisateur atteint la limite :
|
||||
|
||||
```text
|
||||
Limite atteinte
|
||||
Un exercice peut contenir jusqu'à 8 étapes.
|
||||
```
|
||||
|
||||
### Liste des étapes dans le formulaire
|
||||
|
||||
Chaque étape est une carte compacte réordonnable, style Court Blazer : surface plate, rayon 6 px, bordure, liseré supérieur crimson si ouverte/active.
|
||||
|
||||
Carte repliée :
|
||||
|
||||
```text
|
||||
[drag] 1. Dribble main droite [modifier]
|
||||
Temps · 10 s [menu]
|
||||
```
|
||||
|
||||
ou :
|
||||
|
||||
```text
|
||||
[drag] 3. Pompes [modifier]
|
||||
Répétitions · 10 [menu]
|
||||
```
|
||||
|
||||
Actions accessibles :
|
||||
|
||||
- poignée drag-and-drop pour réordonner ;
|
||||
- menu `...` avec `Monter`, `Descendre`, `Dupliquer`, `Supprimer` ;
|
||||
- bouton/icône `Modifier l'étape` ouvrant le détail.
|
||||
|
||||
Ne pas dépendre uniquement du drag-and-drop : `Monter` / `Descendre` doivent exister pour l'accessibilité tactile.
|
||||
|
||||
### Détail d'étape
|
||||
|
||||
Ouvrir un écran ou une bottom sheet haute `Modifier l'étape`. Recommandation : **écran dédié** si le formulaire principal est déjà long ; bottom sheet acceptable seulement si elle reste plein écran.
|
||||
|
||||
Champs :
|
||||
|
||||
```text
|
||||
Nom de l'étape
|
||||
[ Dribble main droite ]
|
||||
```
|
||||
|
||||
Validation :
|
||||
|
||||
```text
|
||||
Le nom de l'étape est obligatoire.
|
||||
```
|
||||
|
||||
Type d'étape, exclusif :
|
||||
|
||||
```text
|
||||
Type d'étape
|
||||
(•) Temps
|
||||
( ) Répétitions
|
||||
```
|
||||
|
||||
Si `Temps` :
|
||||
|
||||
```text
|
||||
Durée par défaut (s)
|
||||
[ 10 ]
|
||||
```
|
||||
|
||||
Validation :
|
||||
|
||||
```text
|
||||
Saisis une durée supérieure à 0.
|
||||
```
|
||||
|
||||
Si `Répétitions` :
|
||||
|
||||
```text
|
||||
Répétitions par défaut
|
||||
[ 10 ]
|
||||
```
|
||||
|
||||
Validation :
|
||||
|
||||
```text
|
||||
Saisis un nombre de répétitions supérieur à 0.
|
||||
```
|
||||
|
||||
### Score d'étape
|
||||
|
||||
Chaque étape peut avoir un score optionnel.
|
||||
|
||||
```text
|
||||
Score d'étape
|
||||
[ ] Ajouter un score pour cette étape
|
||||
```
|
||||
|
||||
Si activé :
|
||||
|
||||
```text
|
||||
Mode de score
|
||||
(•) Saisie libre
|
||||
( ) Chrono intégré
|
||||
```
|
||||
|
||||
Score libre :
|
||||
|
||||
```text
|
||||
Score à saisir
|
||||
[ Réussites ]
|
||||
|
||||
Unité
|
||||
[ paniers ]
|
||||
|
||||
Score par défaut
|
||||
[ 5 ]
|
||||
```
|
||||
|
||||
Validation :
|
||||
|
||||
- `Le libellé du score est obligatoire.`
|
||||
- `L'unité du score est obligatoire.`
|
||||
- `Saisis un score supérieur ou égal à 0.`
|
||||
|
||||
Score chrono :
|
||||
|
||||
```text
|
||||
Objectif de chrono par défaut (optionnel)
|
||||
[ 00:12 ]
|
||||
```
|
||||
|
||||
Validation seulement si rempli :
|
||||
|
||||
```text
|
||||
Saisis un objectif supérieur à 0.
|
||||
```
|
||||
|
||||
Recommandation UX : autoriser le score chrono surtout sur les étapes à répétitions. Sur une étape de type `Temps`, si l'utilisateur choisit aussi `Score chrono`, afficher un avertissement non bloquant :
|
||||
|
||||
```text
|
||||
Cette étape utilise déjà un compte à rebours. Le score chrono ajoute un second temps mesuré ; garde-le seulement si tu veux enregistrer une performance distincte.
|
||||
```
|
||||
|
||||
### États et validations du formulaire exercice
|
||||
|
||||
- Si `Rythmer cet exercice avec des étapes` est activé, il faut au moins une étape.
|
||||
- Message : `Ajoute au moins une étape ou désactive la séquence.`
|
||||
- Chaque étape doit avoir un nom, un type, et une cible par défaut strictement positive pour son type.
|
||||
- Supprimer une étape demande confirmation seulement si elle contient déjà des champs remplis ou un score configuré.
|
||||
- Pour un exercice déjà utilisé dans des programmes, conserver l'avertissement existant : les programmes existants restent inchangés. Les étapes doivent être snapshotées comme le reste de l'exercice.
|
||||
|
||||
## B. Exécution pendant une séance
|
||||
|
||||
Surface concernée : écran d'exécution déjà structuré avec : header discret, bloc `SÉRIE X/Y`, nom d'exercice, bouton médias, inputs de mesures, actions de série.
|
||||
|
||||
### Placement du module séquence
|
||||
|
||||
Si l'exercice a des étapes, ajouter un module `Séquence` entre le nom de l'exercice et les inputs de mesures de série.
|
||||
|
||||
Structure générale :
|
||||
|
||||
```text
|
||||
00:12
|
||||
Programme 1/2 · Exercice 3/8
|
||||
|
||||
SÉRIE
|
||||
2 / 4
|
||||
|
||||
Dribble combo [Voir médias]
|
||||
|
||||
SÉQUENCE
|
||||
Passage 1 / 10
|
||||
[1] [2] [3] [4]
|
||||
|
||||
ÉTAPE 1 / 4
|
||||
Dribble main droite
|
||||
10 s
|
||||
|
||||
00:10
|
||||
[Démarrer la séquence]
|
||||
|
||||
Résultat de la série
|
||||
Passages réalisés : 0 / 10
|
||||
Score : --
|
||||
|
||||
[Terminer la série]
|
||||
[Passer la série]
|
||||
```
|
||||
|
||||
Si la série n'a pas la mesure `Répétitions` active :
|
||||
|
||||
```text
|
||||
Passage en cours
|
||||
```
|
||||
|
||||
Si la série a `Répétitions` active :
|
||||
|
||||
```text
|
||||
Passage 1 / 10
|
||||
```
|
||||
|
||||
Le mot `Passage` est utilisé dans l'UI pour éviter de confondre les répétitions de série avec les répétitions internes d'une étape.
|
||||
|
||||
### Progression des étapes
|
||||
|
||||
Afficher une progression compacte compatible 5-6 étapes et jusqu'à 8 :
|
||||
|
||||
- chips carrées ou petits segments `1 2 3 4` ;
|
||||
- étape courante : fond primaire or, texte fond ;
|
||||
- étapes terminées : succès ou contour primaire ;
|
||||
- étapes passées : contour/texte secondaire ;
|
||||
- étapes à venir : surface neutre.
|
||||
|
||||
Pour plus de 6 étapes, la rangée peut défiler horizontalement, mais le label `ÉTAPE X / Y` reste toujours visible.
|
||||
|
||||
### Étape chronométrée
|
||||
|
||||
État initial si c'est la première étape active de la série :
|
||||
|
||||
```text
|
||||
ÉTAPE 1 / 4
|
||||
Dribble main droite
|
||||
Objectif : 10 s
|
||||
|
||||
00:10
|
||||
[Démarrer la séquence]
|
||||
[Passer l'étape]
|
||||
```
|
||||
|
||||
Après démarrage :
|
||||
|
||||
```text
|
||||
00:07
|
||||
[Passer l'étape]
|
||||
```
|
||||
|
||||
Style :
|
||||
|
||||
- compte à rebours en Anton, 56-64 px, couleur primaire or ;
|
||||
- label et nom en Archivo ;
|
||||
- liseré crimson 2 px sur le panneau ;
|
||||
- dans les 3 dernières secondes, flash discret du liseré ou du fond du compteur en crimson, sans nuire à la lisibilité.
|
||||
|
||||
Son :
|
||||
|
||||
- à `3`, `2`, `1` : bip court à chaque seconde ;
|
||||
- à `0` : bip long ;
|
||||
- à `0`, passage automatique à l'étape suivante.
|
||||
|
||||
Enchaînement :
|
||||
|
||||
- Si l'étape suivante est aussi chronométrée, son compte à rebours démarre immédiatement, sans pause ni bouton intermédiaire.
|
||||
- Si l'étape suivante est à répétitions, l'écran affiche l'étape suivante et attend l'action utilisateur `Étape suivante`.
|
||||
- Si c'est la dernière étape et qu'un nouveau passage doit commencer, le premier chrono du passage suivant démarre immédiatement si la première étape est chronométrée.
|
||||
|
||||
### Étape à répétitions
|
||||
|
||||
Affichage :
|
||||
|
||||
```text
|
||||
ÉTAPE 3 / 4
|
||||
Pompes
|
||||
|
||||
10
|
||||
RÉPÉTITIONS
|
||||
|
||||
[Étape suivante]
|
||||
[Passer l'étape]
|
||||
```
|
||||
|
||||
- Le nombre cible utilise Anton, couleur primaire or.
|
||||
- `Étape suivante` valide l'étape et avance.
|
||||
- Il n'y a pas de compteur manuel des répétitions internes au MVP : l'utilisateur confirme quand l'étape est faite.
|
||||
|
||||
### Score d'étape pendant l'exécution
|
||||
|
||||
Si l'étape a un score libre : afficher un champ compact sous le bloc principal de l'étape :
|
||||
|
||||
```text
|
||||
Score de l'étape (paniers)
|
||||
[ ]
|
||||
```
|
||||
|
||||
Si l'étape est chronométrée, le score libre ne bloque jamais l'enchaînement automatique. Si l'utilisateur ne l'a pas renseigné, il pourra le corriger via le plan de séance / détail de série.
|
||||
|
||||
Si l'étape a un score chrono et que l'étape est à répétitions : afficher un petit module `Chrono score d'étape` avec `Démarrer / Arrêter / Réinitialiser`, même logique que le score chrono de série.
|
||||
|
||||
Recommandation UX pour éviter la surcharge : ne pas afficher de second gros compteur si l'étape elle-même est déjà chronométrée. Dans ce cas, si le score chrono est configuré, afficher l'avertissement en configuration et, en exécution, garder le compteur d'étape prioritaire.
|
||||
|
||||
### Passage d'une répétition/passage à l'autre
|
||||
|
||||
Quand la dernière étape d'un passage est validée ou terminée :
|
||||
|
||||
- incrémenter `Passages réalisés` de 1 ;
|
||||
- si la série a une cible de répétitions et que la cible n'est pas atteinte, commencer le passage suivant ;
|
||||
- si le prochain passage commence par une étape chronométrée, démarrer immédiatement le chrono ;
|
||||
- si le prochain passage commence par une étape à répétitions, afficher l'étape et attendre `Étape suivante`.
|
||||
|
||||
Quand la cible de passages est atteinte :
|
||||
|
||||
```text
|
||||
Séquence terminée
|
||||
10 / 10 passages réalisés
|
||||
```
|
||||
|
||||
Le bouton principal devient ou reste :
|
||||
|
||||
```text
|
||||
Terminer la série
|
||||
```
|
||||
|
||||
La fin de séquence ne doit pas forcément clôturer la série automatiquement, car la série peut aussi avoir un score global, un chrono score global ou une correction à faire. L'utilisateur garde le contrôle via `Terminer la série`.
|
||||
|
||||
Si la série a `Temps` mais pas `Répétitions`, la séquence boucle tant que l'utilisateur ne termine pas la série. Le temps de série reste indépendant ; à expiration, afficher un feedback `Temps de série terminé`, mais ne pas interrompre brutalement une étape en cours.
|
||||
|
||||
### Articulation avec les mesures de série existantes
|
||||
|
||||
Quand un exercice a des étapes, renommer visuellement la mesure `Répétitions` de série en contexte :
|
||||
|
||||
```text
|
||||
Passages réalisés
|
||||
0 / 10
|
||||
```
|
||||
|
||||
Ce compteur est alimenté automatiquement par les passages terminés, avec action secondaire `Corriger` si l'utilisateur doit ajuster.
|
||||
|
||||
Les autres mesures de série restent dans un bloc `Résultat de la série`, sous le module séquence :
|
||||
|
||||
- `Temps de série` si actif ;
|
||||
- `Passages réalisés` si répétitions actif ;
|
||||
- `Score de série` ou `Chrono score` si actif.
|
||||
|
||||
Ce bloc peut être compact par défaut pour ne pas écraser la séquence, mais les champs nécessaires doivent rester accessibles sans changer d'écran.
|
||||
|
||||
### Skip / passer
|
||||
|
||||
Renommer le bouton de série existant en contexte :
|
||||
|
||||
```text
|
||||
Passer la série
|
||||
```
|
||||
|
||||
Dans le module séquence :
|
||||
|
||||
```text
|
||||
Passer l'étape
|
||||
```
|
||||
|
||||
Menu secondaire recommandé :
|
||||
|
||||
```text
|
||||
Passer ce passage
|
||||
```
|
||||
|
||||
Comportements :
|
||||
|
||||
- `Passer l'étape` marque l'étape comme passée et avance à la suivante. Si un chrono d'étape tourne, confirmation : `Le chrono de cette étape sera arrêté.`
|
||||
- `Passer ce passage` marque les étapes restantes du passage comme passées, ne compte pas ce passage dans `Passages réalisés`, puis démarre le passage suivant si la série doit continuer.
|
||||
- `Passer la série` conserve le comportement existant : la série est passée sans résultat de série. Si une étape est en cours, demander confirmation : `La séquence en cours sera arrêtée.`
|
||||
|
||||
### Pause, reprise, fermeture d'app
|
||||
|
||||
- Pause de séance met aussi en pause le chrono d'étape et les éventuels chronos score d'étape.
|
||||
- À la reprise, afficher l'étape courante avec son temps restant exact.
|
||||
- Si l'app est tuée pendant une étape chronométrée, la reprise doit restaurer le passage, l'étape et le temps restant. UX attend la même robustesse que `ActiveRestState`.
|
||||
- Si un chrono arrive à zéro pendant que l'app est en arrière-plan, à la réouverture afficher l'état recalculé : étape suivante ou passage suivant selon le temps écoulé. Si plusieurs étapes chronométrées se sont enchaînées, l'app peut avancer jusqu'à la première étape à répétitions ou jusqu'à la fin calculée du passage.
|
||||
|
||||
### Plan de séance / édition ponctuelle
|
||||
|
||||
Dans le `Plan de séance`, une série avec étapes garde son état global `À faire / En cours / Terminée / Passée`, mais le détail de série doit pouvoir afficher les étapes enregistrées :
|
||||
|
||||
```text
|
||||
Série 2 / 4
|
||||
Passages réalisés : 7 / 10
|
||||
|
||||
Passage 1
|
||||
Étape 1 · Terminée · 10 s
|
||||
Étape 2 · Terminée · 10 reps
|
||||
Étape 3 · Passée
|
||||
```
|
||||
|
||||
Édition ponctuelle d'une série passée/terminée : ne rejoue pas la séquence en mode interactif. Elle permet de corriger les résultats enregistrés : passages réalisés, score de série, scores d'étapes. La position courante de séance ne bouge pas.
|
||||
|
||||
## Exigences remontées à Architect
|
||||
|
||||
- Les étapes doivent être snapshotées avec l'exercice dans les programmes/séances/historiques.
|
||||
- Chaque étape : position, nom, type `time` ou `reps`, cible par défaut > 0, score optionnel avec mode et valeurs par défaut selon les règles existantes.
|
||||
- L'état d'exécution doit suivre : passage courant, étape courante, états des étapes du passage, temps restant/accumulé des chronos d'étapes, scores d'étapes, et robustesse après pause/kill app.
|
||||
- Les résultats historiques doivent pouvoir stocker les résultats d'étapes par série et par passage, sans remplacer les résultats de série existants.
|
||||
Reference in New Issue
Block a user