La consequence du Scenario remplace la situation, pas un feedback Quiz
Build and deploy / test-python (push) Failing after 1m2s
Build and deploy / test-js (push) Successful in 51s
Build and deploy / lint-python (push) Failing after 58s
Build and deploy / lint-js (push) Failing after 51s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped
Build and deploy / sonarqube (push) Failing after 1m1s
Build and deploy / test-python (push) Failing after 1m2s
Build and deploy / test-js (push) Successful in 51s
Build and deploy / lint-python (push) Failing after 58s
Build and deploy / lint-js (push) Failing after 51s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped
Build and deploy / sonarqube (push) Failing after 1m1s
Retour utilisateur : "ce n'est pas un quiz, la consequence s'affiche a la place de la situation precedente". L'ancien design affichait la situation ET les choix en permanence avec un encart de feedback separe en dessous (calque sur le Quiz). Desormais un seul bloc de texte (.docScenarioSituation) sert successivement a la situation PUIS, une fois un choix fait, a la consequence a sa place ; les boutons de choix disparaissent avec elle. Supprime l'element .docScenarioConsequence devenu inutile. Verifie via simulation DOM reelle (jsdom) : la consequence remplace bien le texte de la situation (jamais affichee a cote), les choix disparaissent, le retour a une situation neutre au scenario suivant/au redemarrage fonctionne. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
b2292de122
commit
c04a81cfec
@@ -467,10 +467,17 @@ def _render_scenario_player(config: dict[str, Any]) -> str:
|
|||||||
scénarios gardent l'ORDRE d'écriture du créateur (contrairement à
|
scénarios gardent l'ORDRE d'écriture du créateur (contrairement à
|
||||||
l'Association/Memory/Mots mêlés, jamais mélangés) : ce sont des mises
|
l'Association/Memory/Mots mêlés, jamais mélangés) : ce sont des mises
|
||||||
en situation séquentielles, pas des éléments à faire correspondre ou
|
en situation séquentielles, pas des éléments à faire correspondre ou
|
||||||
retrouver — un mélange n'aurait ici aucun sens pédagogique. Réutilise
|
retrouver — un mélange n'aurait ici aucun sens pédagogique. Un seul
|
||||||
les classes visuelles du Quiz (.docQuizOptions/.docQuizFeedback/
|
bloc de texte (.docScenarioSituation) sert successivement à afficher
|
||||||
.docQuizNextBar/.docQuizQuestionText) plutôt que de dupliquer ces
|
la situation PUIS, une fois un choix fait, la conséquence à sa place
|
||||||
règles, même esprit que .docAssocCard/.docMinigameRestartBar."""
|
(les boutons de choix disparaissent aussi) — volontairement PAS le
|
||||||
|
comportement du Quiz, où la question reste affichée à côté d'un
|
||||||
|
encart de feedback séparé (retour utilisateur du 20/09/2026 : "ce
|
||||||
|
n'est pas un quiz, la conséquence s'affiche à la place de la
|
||||||
|
situation précédente"). Réutilise les classes visuelles du Quiz
|
||||||
|
(.docQuizOptions/.docQuizFeedback/.docQuizNextBar/
|
||||||
|
.docQuizQuestionText) plutôt que de dupliquer ces règles, même esprit
|
||||||
|
que .docAssocCard/.docMinigameRestartBar."""
|
||||||
config_json = html_lib.escape(json.dumps({"scenarios": config["scenarios"]}), quote=True)
|
config_json = html_lib.escape(json.dumps({"scenarios": config["scenarios"]}), quote=True)
|
||||||
return (
|
return (
|
||||||
f'<div class="docScenarioPlayer" data-scenario-config="{config_json}">'
|
f'<div class="docScenarioPlayer" data-scenario-config="{config_json}">'
|
||||||
@@ -479,7 +486,6 @@ def _render_scenario_player(config: dict[str, Any]) -> str:
|
|||||||
f'<div class="docAssocMeta"><span class="docScenarioProg"></span></div>'
|
f'<div class="docAssocMeta"><span class="docScenarioProg"></span></div>'
|
||||||
f'<div class="docScenarioSituation docQuizQuestionText"></div>'
|
f'<div class="docScenarioSituation docQuizQuestionText"></div>'
|
||||||
f'<div class="docScenarioChoices docQuizOptions"></div>'
|
f'<div class="docScenarioChoices docQuizOptions"></div>'
|
||||||
f'<div class="docScenarioConsequence docQuizFeedback"></div>'
|
|
||||||
f'<div class="docQuizNextBar">'
|
f'<div class="docQuizNextBar">'
|
||||||
f'<button type="button" class="docQuizNextBtn docScenarioNextBtn">Scénario suivant</button>'
|
f'<button type="button" class="docQuizNextBtn docScenarioNextBtn">Scénario suivant</button>'
|
||||||
f"</div>"
|
f"</div>"
|
||||||
|
|||||||
@@ -102,14 +102,19 @@ regroupement à chaque appel.
|
|||||||
scénarios) — sanitizée (`sanitize_scenario_config`) avant lecture. Si
|
scénarios) — sanitizée (`sanitize_scenario_config`) avant lecture. Si
|
||||||
au moins un scénario existe, s'y ajoute (fonction privée
|
au moins un scénario existe, s'y ajoute (fonction privée
|
||||||
`_render_scenario_player`) la mise en situation RÉELLE et interactive :
|
`_render_scenario_player`) la mise en situation RÉELLE et interactive :
|
||||||
l'apprenant lit la situation, choisit une option, découvre la
|
l'apprenant lit la situation, choisit une option, puis la conséquence
|
||||||
conséquence de SON choix et si c'était le bon, puis passe au scénario
|
de SON choix REMPLACE l'affichage de la situation (les boutons de
|
||||||
suivant. Les scénarios gardent l'ORDRE d'écriture du créateur (jamais
|
choix disparaissent avec elle) avant de passer au scénario suivant —
|
||||||
mélangés, contrairement à Association/Memory/Mots mêlés — ce sont des
|
volontairement PAS le comportement du Quiz, où la question resterait
|
||||||
mises en situation séquentielles, pas des éléments à faire
|
affichée à côté d'un encart de feedback séparé (retour utilisateur du
|
||||||
correspondre/retrouver). Réutilise les classes visuelles du Quiz
|
20/09/2026 : "ce n'est pas un quiz, la conséquence s'affiche à la
|
||||||
(`.docQuizOptions`/`.docQuizFeedback`/`.docQuizNextBar`/
|
place de la situation précédente"). Les scénarios gardent l'ORDRE
|
||||||
`.docQuizQuestionText`) plutôt que de dupliquer ces règles. Embarqué en
|
d'écriture du créateur (jamais mélangés, contrairement à
|
||||||
|
Association/Memory/Mots mêlés — ce sont des mises en situation
|
||||||
|
séquentielles, pas des éléments à faire correspondre/retrouver).
|
||||||
|
Réutilise les classes visuelles du Quiz (`.docQuizOptions`/
|
||||||
|
`.docQuizFeedback`/`.docQuizNextBar`/`.docQuizQuestionText`) plutôt que
|
||||||
|
de dupliquer ces règles. Embarqué en
|
||||||
JSON dans un attribut `data-scenario-config`, échappé pour l'HTML —
|
JSON dans un attribut `data-scenario-config`, échappé pour l'HTML —
|
||||||
même principe que les autres mini-jeux, aucun aller-retour serveur
|
même principe que les autres mini-jeux, aucun aller-retour serveur
|
||||||
pendant qu'on joue. Comme l'Association/Memory/Mots mêlés (mais
|
pendant qu'on joue. Comme l'Association/Memory/Mots mêlés (mais
|
||||||
|
|||||||
@@ -1163,14 +1163,15 @@ function forgeDocRenderScenarioPlayerScenario(playerEl, state) {
|
|||||||
const item = state.scenarios[state.current];
|
const item = state.scenarios[state.current];
|
||||||
const situationEl = playerEl.querySelector('.docScenarioSituation');
|
const situationEl = playerEl.querySelector('.docScenarioSituation');
|
||||||
const choicesEl = playerEl.querySelector('.docScenarioChoices');
|
const choicesEl = playerEl.querySelector('.docScenarioChoices');
|
||||||
const consequenceEl = playerEl.querySelector('.docScenarioConsequence');
|
|
||||||
const progEl = playerEl.querySelector('.docScenarioProg');
|
const progEl = playerEl.querySelector('.docScenarioProg');
|
||||||
const nextBtn = playerEl.querySelector('.docScenarioNextBtn');
|
const nextBtn = playerEl.querySelector('.docScenarioNextBtn');
|
||||||
|
|
||||||
|
// Repart d'un bloc "situation" neutre (jamais un résidu des classes
|
||||||
|
// is-visible/is-ok/is-ko posées par une réponse précédente, voir
|
||||||
|
// forgeDocScenarioPlayerAnswer ci-dessous).
|
||||||
|
situationEl.className = 'docScenarioSituation docQuizQuestionText';
|
||||||
situationEl.textContent = item.situation;
|
situationEl.textContent = item.situation;
|
||||||
choicesEl.innerHTML = '';
|
choicesEl.innerHTML = '';
|
||||||
consequenceEl.className = 'docScenarioConsequence docQuizFeedback';
|
|
||||||
consequenceEl.textContent = '';
|
|
||||||
nextBtn.classList.remove('is-visible');
|
nextBtn.classList.remove('is-visible');
|
||||||
playerEl.querySelector('.docMinigameRestartBar').classList.remove('is-visible');
|
playerEl.querySelector('.docMinigameRestartBar').classList.remove('is-visible');
|
||||||
item.choices.forEach((choice, idx) => {
|
item.choices.forEach((choice, idx) => {
|
||||||
@@ -1180,30 +1181,31 @@ function forgeDocRenderScenarioPlayerScenario(playerEl, state) {
|
|||||||
btn.textContent = choice.text;
|
btn.textContent = choice.text;
|
||||||
btn.addEventListener('click', (e) => {
|
btn.addEventListener('click', (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
forgeDocScenarioPlayerAnswer(playerEl, state, idx, btn);
|
forgeDocScenarioPlayerAnswer(playerEl, state, idx);
|
||||||
});
|
});
|
||||||
choicesEl.appendChild(btn);
|
choicesEl.appendChild(btn);
|
||||||
});
|
});
|
||||||
progEl.textContent = `Scénario ${state.current + 1} sur ${state.scenarios.length}`;
|
progEl.textContent = `Scénario ${state.current + 1} sur ${state.scenarios.length}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function forgeDocScenarioPlayerAnswer(playerEl, state, idx, btn) {
|
function forgeDocScenarioPlayerAnswer(playerEl, state, idx) {
|
||||||
if (state.answered) return;
|
if (state.answered) return;
|
||||||
state.answered = true;
|
state.answered = true;
|
||||||
const item = state.scenarios[state.current];
|
const item = state.scenarios[state.current];
|
||||||
const buttons = playerEl.querySelectorAll('.docScenarioChoice');
|
const situationEl = playerEl.querySelector('.docScenarioSituation');
|
||||||
buttons.forEach((b) => { b.disabled = true; });
|
const choicesEl = playerEl.querySelector('.docScenarioChoices');
|
||||||
const consequenceEl = playerEl.querySelector('.docScenarioConsequence');
|
|
||||||
const isLast = state.current === state.scenarios.length - 1;
|
const isLast = state.current === state.scenarios.length - 1;
|
||||||
if (idx === item.correct_index) {
|
const isCorrect = idx === item.correct_index;
|
||||||
btn.classList.add('is-correct');
|
const consequenceText = item.choices[idx].consequence || 'Aucune conséquence renseignée pour ce choix.';
|
||||||
consequenceEl.classList.add('is-visible', 'is-ok');
|
|
||||||
} else {
|
// Ce n'est pas un Quiz : la conséquence REMPLACE la situation (le récit
|
||||||
btn.classList.add('is-wrong');
|
// avance), et les boutons de choix disparaissent avec elle — jamais un
|
||||||
buttons[item.correct_index].classList.add('is-correct');
|
// encart de feedback séparé pendant que la situation resterait affichée
|
||||||
consequenceEl.classList.add('is-visible', 'is-ko');
|
// (retour utilisateur du 20/09/2026).
|
||||||
}
|
situationEl.className = `docScenarioSituation docQuizFeedback is-visible ${isCorrect ? 'is-ok' : 'is-ko'}`;
|
||||||
consequenceEl.textContent = item.choices[idx].consequence || 'Aucune conséquence renseignée pour ce choix.';
|
situationEl.textContent = consequenceText;
|
||||||
|
choicesEl.innerHTML = '';
|
||||||
|
|
||||||
if (isLast) {
|
if (isLast) {
|
||||||
playerEl.querySelector('.docMinigameRestartBar').classList.add('is-visible');
|
playerEl.querySelector('.docMinigameRestartBar').classList.add('is-visible');
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user