From ffb3cd5afa787946caa416ab1632d6c7e2bc41d4 Mon Sep 17 00:00:00 2001 From: Denis Defolie Date: Sun, 11 Oct 2026 18:18:40 +0200 Subject: [PATCH] Show "Exercise N/3" so repeated content doesn't look like a freeze Manual report: after "Bravo!", clicking Continue seemed to do nothing. An automated test proved the mission does advance (a new exercise instance loads, completed_count increments) -- but mission_02_pont_des_phrases has exactly one sentence_correction exercise in the data right now, so the "next" exercise is the identical sentence the child just solved. Nothing was broken; there was just no visible signal that progress happened. Added a persistent progress label at the top of exercise_host, updated on every exercise load. Doesn't address the underlying content-volume gap (still tracked in decisions.md point 14), but makes the repetition legible instead of indistinguishable from a stall. Rebuilt both exports. Co-Authored-By: Claude Sonnet 5 --- data/localization/fr.json | 1 + docs/specs/decisions.md | 8 +++++++ scenes/exercises/exercise_host.gd | 11 ++++++++++ scenes/exercises/exercise_host.tscn | 17 ++++++++++++++- .../test_exercise_host_sentence_correction.gd | 21 +++++++++++++++++++ 5 files changed, 57 insertions(+), 1 deletion(-) diff --git a/data/localization/fr.json b/data/localization/fr.json index 131225c..6efda91 100644 --- a/data/localization/fr.json +++ b/data/localization/fr.json @@ -30,6 +30,7 @@ "exercise_host.validate_button": "Valider", "exercise_host.continue_button": "Continuer", "exercise_host.finish_mission_button": "Terminer la mission", + "exercise_host.progress_label": "Exercice", "feedback_panel.correct_title": "Bravo !", "feedback_panel.incorrect_title": "Pas tout à fait", "feedback_panel.hint_label": "Indice :", diff --git a/docs/specs/decisions.md b/docs/specs/decisions.md index 35c76b4..bc2584b 100644 --- a/docs/specs/decisions.md +++ b/docs/specs/decisions.md @@ -146,3 +146,11 @@ Ajouts à l'arborescence proposée : **Correction** : la comparaison passe maintenant par `TextNormalizer.normalize(...).to_lower()` des deux côtés (même normalisation que pour les dictées), tout en gardant le texte brut saisi dans `found` pour l'affichage du retour. Un test automatisé avec la séquence exacte rapportée (toucher une fois, taper, valider) n'avait pas reproduit le bug — preuve que la logique fonctionnait pour une saisie identique au caractère près ; c'est la tolérance aux variations incidentes qui manquait, pas la logique d'association mot/correction elle-même. Trois tests couvrent maintenant la casse, les espaces superflus et les accents décomposés. **Leçon** : toute comparaison de texte saisi par l'enfant doit passer par `TextNormalizer`, pas par une égalité de chaîne brute — à vérifier si d'autres types d'exercices à saisie libre sont ajoutés plus tard. + +## 17. Bug signalé manuellement : « Bravo » sans suite visible + +**Symptôme** : après « Bravo ! » sur la mission « Le pont des phrases », cliquer sur « Continuer » semblait ne rien faire. + +**Diagnostic** : un test automatisé confirme que la mission avance bien (un nouvel exercice est réellement chargé, `completed_count` augmente). Le contenu pédagogique de cette mission ne contient qu'une seule correction de phrase (`ce1_accord_adjectif_correction_01`, voir le point 14 sur le volume de contenu encore minimal) : le deuxième exercice de la mission est donc **exactement la même phrase**, ce qui donne l'impression visuelle de n'avoir pas bougé alors que la mission en est à l'exercice 2 sur 3. + +**Correction** : ajout d'un repère visuel permanent (« Exercice N/3 ») en haut de `exercise_host`, mis à jour à chaque exercice chargé. Ne corrige pas le manque de contenu (qui reste à écrire), mais rend la répétition explicite plutôt que silencieuse. diff --git a/scenes/exercises/exercise_host.gd b/scenes/exercises/exercise_host.gd index b490599..0b5da0e 100644 --- a/scenes/exercises/exercise_host.gd +++ b/scenes/exercises/exercise_host.gd @@ -26,6 +26,7 @@ var _last_exercise_id := "" @onready var _exercise_container: Control = %ExerciseContainer @onready var _overlay_container: Control = %OverlayContainer +@onready var _progress_label: Label = %ProgressLabel ## Accesseurs reserves aux tests d'integration (scenes/exercises/ @@ -67,6 +68,7 @@ func _load_next_exercise() -> void: _mission, _last_exercise_id, _current_difficulty ) _attempt_number = 1 + _update_progress_label() if _current_exercise_scene != null: _current_exercise_scene.queue_free() @@ -78,6 +80,15 @@ func _load_next_exercise() -> void: _connect_answer_signal() +## Un contenu encore peu nombreux (voir docs/specs/decisions.md, point 14) +## peut faire redonner le meme exercice d'une mission a l'autre tentative : +## sans ce repere, ca ressemble a un blocage plutot qu'a une progression. +func _update_progress_label() -> void: + _progress_label.text = "%s %d/%d" % [ + UIText.get_text("exercise_host.progress_label"), _completed_count + 1, MISSION_LENGTH + ] + + func _connect_answer_signal() -> void: match _mission["exercise_type"]: "multiple_choice": diff --git a/scenes/exercises/exercise_host.tscn b/scenes/exercises/exercise_host.tscn index e00d84a..30b1943 100644 --- a/scenes/exercises/exercise_host.tscn +++ b/scenes/exercises/exercise_host.tscn @@ -11,12 +11,27 @@ grow_horizontal = 2 grow_vertical = 2 script = ExtResource("1") +[node name="HeaderBar" type="MarginContainer" parent="."] +layout_mode = 1 +anchor_right = 1.0 +offset_bottom = 40.0 +grow_horizontal = 2 +theme_override_constants/margin_left = 16 +theme_override_constants/margin_top = 8 +theme_override_constants/margin_right = 16 +theme_override_constants/margin_bottom = 8 + +[node name="ProgressLabel" type="Label" parent="HeaderBar"] +unique_name_in_owner = true +layout_mode = 2 +horizontal_alignment = 2 + [node name="ExerciseContainer" type="Control" parent="."] unique_name_in_owner = true layout_mode = 1 -anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 +offset_top = 40.0 grow_horizontal = 2 grow_vertical = 2 diff --git a/tests/exercises/test_exercise_host_sentence_correction.gd b/tests/exercises/test_exercise_host_sentence_correction.gd index ed72b57..f8007da 100644 --- a/tests/exercises/test_exercise_host_sentence_correction.gd +++ b/tests/exercises/test_exercise_host_sentence_correction.gd @@ -58,3 +58,24 @@ func test_correct_word_tap_and_retype_validates_through_exercise_host() -> void: var skill_state := ProgressManager.get_skill_state("accord_groupe_nominal") assert_eq(skill_state["recent_results"], [true]) + + # "Bravo pas de suite ici ?" : cliquer sur Continuer doit faire avancer + # la mission (deuxieme exercice charge), pas rester bloque sur le meme + # panneau. + var old_exercise_scene: Control = exercise_scene + feedback.get_node("%ContinueButton").pressed.emit() + await wait_process_frames(1) + + assert_eq(host.get_completed_count(), 1, "le premier exercice doit compter comme termine") + assert_eq(overlay.get_child_count(), 0, "le panneau de retour doit disparaitre") + + var new_exercise_scene: Control = host.get_node("%ExerciseContainer").get_child(0) + assert_ne( + new_exercise_scene, + old_exercise_scene, + "une nouvelle instance d'exercice doit remplacer la precedente", + ) + assert_eq(host.get_attempt_number(), 1, "le nouvel exercice repart a la premiere tentative") + + var progress_label: Label = host.get_node("%ProgressLabel") + assert_string_contains(progress_label.text, "2/3")