Quêtes : bulle "❓ Question" à choix multiples, à côté de "+ Réplique"
Nouveau type de ligne dans un dialogue de quête (voir
db/quests/sanitize_quest_dialogues.py) : une bulle JAUNE, dans la même
chaîne verticale que les répliques (même alignement, reliée par un
trait) — header : nombre de choix (2 à 8) + récompense (score, montant
en points) ; body : la question, ses choix et un bouton radio pour
désigner la bonne réponse. Aucune limite au nombre de questions par
colonne, comme pour une réplique.
Les lignes de dialogue portent maintenant explicitement
{"type": "dialogue", ...} (au lieu d'un objet sans type) pour
distinguer les deux formes — migration de forme, tests mis à jour.
Portée de ce commit : l'ÉDITEUR (créer/modifier une question). Le jeu
lui-même (afficher la question au joueur, vérifier la réponse,
attribuer la récompense) reste à construire — le widget "💬 Boîte de
dialogue" ne sait aujourd'hui afficher qu'une réplique.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
f2ed602459
commit
e972acf9e6
+32
-6
@@ -86,19 +86,45 @@ def test_sanitize_quest_dialogues_keeps_only_valid_lines_per_status():
|
||||
}
|
||||
cleaned = db.sanitize_quest_dialogues(raw)
|
||||
assert cleaned == {
|
||||
"nouvelle": [{"speaker": "Le Sorcier", "text": "Bonjour !"}],
|
||||
"nouvelle": [{"type": "dialogue", "speaker": "Le Sorcier", "text": "Bonjour !"}],
|
||||
"en_cours": [],
|
||||
"terminee": [],
|
||||
}
|
||||
|
||||
|
||||
def test_sanitize_quest_dialogues_accepts_a_valid_question_and_rejects_malformed_ones():
|
||||
""""❓ Question" (voir static/js/quests/quest-editor.js) : une bulle
|
||||
jaune avec plusieurs choix, une seule bonne réponse, une récompense —
|
||||
même chaîne qu'une réplique de dialogue, un autre "type" de ligne."""
|
||||
raw = {
|
||||
"nouvelle": [
|
||||
{"type": "question", "text": "2+2 ?", "choices": ["3", "4", "5"], "correct_index": 1, "reward_type": "score", "reward_amount": 2},
|
||||
{"type": "question", "text": "Une seule option", "choices": ["seule"], "correct_index": 0}, # < 2 choix -> rejetée
|
||||
{"type": "question", "text": "index hors bornes", "choices": ["a", "b"], "correct_index": 5}, # rejetée
|
||||
{"type": "question", "text": " ", "choices": ["a", "b"], "correct_index": 0}, # texte vide -> rejetée
|
||||
{"type": "question", "text": "type de récompense inconnu", "choices": ["a", "b"], "correct_index": 0, "reward_type": "vie"},
|
||||
],
|
||||
"en_cours": [], "terminee": [],
|
||||
}
|
||||
cleaned = db.sanitize_quest_dialogues(raw)
|
||||
assert cleaned["nouvelle"] == [
|
||||
{"type": "question", "text": "2+2 ?", "choices": ["3", "4", "5"], "correct_index": 1, "reward_type": "score", "reward_amount": 2},
|
||||
# reward_type invalide -> repli sur le premier type connu ("score"), jamais rejetée pour ça seul
|
||||
{"type": "question", "text": "type de récompense inconnu", "choices": ["a", "b"], "correct_index": 0, "reward_type": "score", "reward_amount": 0},
|
||||
]
|
||||
|
||||
|
||||
def test_set_quest_dialogues_persists_all_three_columns(tmp_game_slug_cleanup):
|
||||
slug = _make_game(tmp_game_slug_cleanup)
|
||||
quest = db.create_quest(slug, "Trouver la clé")
|
||||
dialogues = {
|
||||
"nouvelle": [{"speaker": "pnj", "text": "Peux-tu m'aider ?"}, {"speaker": "joueur", "text": "Bien sûr !"}],
|
||||
"en_cours": [{"speaker": "pnj", "text": "Alors, cette clé ?"}],
|
||||
"terminee": [{"speaker": "pnj", "text": "Merci beaucoup !"}],
|
||||
"nouvelle": [
|
||||
{"type": "dialogue", "speaker": "pnj", "text": "Peux-tu m'aider ?"},
|
||||
{"type": "dialogue", "speaker": "joueur", "text": "Bien sûr !"},
|
||||
{"type": "question", "text": "2+2 ?", "choices": ["3", "4"], "correct_index": 1, "reward_type": "score", "reward_amount": 2},
|
||||
],
|
||||
"en_cours": [{"type": "dialogue", "speaker": "pnj", "text": "Alors, cette clé ?"}],
|
||||
"terminee": [{"type": "dialogue", "speaker": "pnj", "text": "Merci beaucoup !"}],
|
||||
}
|
||||
db.set_quest_dialogues(slug, quest["id"], dialogues)
|
||||
reloaded = db.get_quest(slug, quest["id"])
|
||||
@@ -159,8 +185,8 @@ def test_quest_dialogues_route_sanitizes_and_persists(client, tmp_game_slug_clea
|
||||
data='{"dialogues": {"nouvelle": [{"speaker": "pnj", "text": "Salut !"}], "en_cours": [], "terminee": []}}',
|
||||
content_type="application/json",
|
||||
)
|
||||
assert resp.get_json()["dialogues"]["nouvelle"] == [{"speaker": "pnj", "text": "Salut !"}]
|
||||
assert db.get_quest(slug, quest["id"])["dialogues"]["nouvelle"] == [{"speaker": "pnj", "text": "Salut !"}]
|
||||
assert resp.get_json()["dialogues"]["nouvelle"] == [{"type": "dialogue", "speaker": "pnj", "text": "Salut !"}]
|
||||
assert db.get_quest(slug, quest["id"])["dialogues"]["nouvelle"] == [{"type": "dialogue", "speaker": "pnj", "text": "Salut !"}]
|
||||
|
||||
|
||||
def test_quest_dialogues_route_404s_for_missing_quest(client, game):
|
||||
|
||||
Reference in New Issue
Block a user