document_engine/labels/quiz_config.py (nouveau) : modele de donnees complet, meme convention resolve_X/sanitize_X que game_engine/rendering/quiz_box_config.py cote jeu (aucun import croise) - DEFAULT_QUIZ_CONFIG, sanitize_quiz_config (valide/nettoie chaque question independamment, jamais ne leve, tronque a 2-4 choix, remet correct_index a 0 si hors bornes/non-entier, clampe points >= 0 et timer_seconds dans [5,300]), quiz_total_points. Cote serveur, routes/document/document_element_update.py revalide desormais un quiz avant persistance (seul kind qui en a besoin - les autres n'ont que des attributs scalaires sans structure a garantir) et renvoie les attributs REELLEMENT persistes dans sa reponse, pour que le client ne derive jamais de la verite serveur apres un nettoyage serveur (ex. choix en trop tronque). Cote editeur (static/document/js/document-editor.js), le panneau Proprietes d'un quiz est desormais reel : chronometre optionnel, couleur de theme, liste de questions repetable (ajout/suppression), chacune avec son texte, un nombre de choix ajustable (2-4, les inputs texte suivent), le choix correct via un radio par question, et les points gagnes. Le rendu canevas (render_document_element.py) affiche un resume reel (nombre de questions, total des points, minuteur) au lieu du placeholder generique. Tests : document_engine/labels/quiz_config.py couvert par 13 tests purs (tests/document/test_quiz_config.py, sans Flask - defauts, troncature, validation, cas limites dont bool comme correct_index) + 1 test de route verifiant la sanitization a l'ecriture et le rendu. SKIP=djlint : backlog H021 pre-existant, aucun template touche ici. ruff/mypy --strict/vulture/bandit/import-linter/eslint/stylelint tous verts ; 63 tests cibles (document + onboarding + auth) verifies fraichement + verification manuelle live via le serveur de dev (ajout, sanitization sur choix invalides/en trop, rendu du resume avec minuteur). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
3.7 KiB
document_engine/labels/
Catalogue statique des types d'éléments du support de formation : bibliothèque groupée par catégorie (panneau gauche de l'éditeur), libellés d'affichage, et attributs par défaut posés à la création de chaque type.
SHAPE_KINDS: tuple[str, ...]
("rectangle", "cercle", "triangle", "trait") — couche de formes libres,
toujours en position absolue (parent_id = NULL).
CONTENT_KINDS: tuple[str, ...]
("titre", "paragraphe", "image", "bouton") — éléments du flux, peuvent
être top-niveau ou enfants d'une rangée.
MINIGAME_KINDS: tuple[str, ...]
("quiz", "association", "memory", "mots", "scenario", "zones") — seul
"quiz" est implémenté (voir quiz_config.py ci-dessous) ; les 5 autres
gardent un panneau Propriétés minimal (emplacement réservé), formulaires
de contenu dédiés hors périmètre de cette passe.
ELEMENT_LIBRARY: dict[str, dict[str, Any]]
Bibliothèque affichée dans le panneau gauche, groupée par catégorie
(mise_en_page / contenu / minigames), chaque entrée portant un
label et sa liste de kinds. "row" n'y apparaît jamais — créé
implicitement par le moteur de layout, jamais choisi directement dans la
bibliothèque.
ELEMENT_KIND_LABELS: dict[str, str]
Libellé d'affichage pour chaque kind, y compris "row" (pour
l'affichage/debug hors bibliothèque).
element_default_attributes(kind: str) -> dict[str, Any]
Attributs posés à la création d'un élément de ce type (voir
document_engine/elements/add_document_element.py).
- Retour : un dict d'attributs par défaut, dépendant du
kind: formes (x/y/width/height/rotation/z_index/fill/stroke/stroke_width/label), texte (content/style+bold/italic/underline/align/color), image (src/alt), bouton (label/target), rangée (gap/align/justify), quiz (DEFAULT_QUIZ_CONFIG, voirquiz_config.py), autre mini-jeu (theme_color), ou{}pour unkindinconnu. - Exceptions : aucune.
quiz_config.py — modèle de données du mini-jeu Quiz
Seul mini-jeu réellement implémenté (les autres MINIGAME_KINDS restent
un emplacement réservé). Même convention resolve_X/sanitize_X que
game_engine/rendering/quiz_box_config.py côté jeu, mais sans aucun
import croisé (voir docs/plan/PLAN.md).
MIN_CHOICES, MAX_CHOICES, MIN_TIMER_SECONDS, MAX_TIMER_SECONDS, DEFAULT_TIMER_SECONDS: int
Bornes de validation (2/4 choix, 5/300 secondes, 30 par défaut).
DEFAULT_QUIZ_CONFIG: dict[str, Any]
{"theme_color": "#ff5f2e", "timer_enabled": False, "timer_seconds": 30, "questions": []}.
sanitize_quiz_config(raw_config: Any) -> dict[str, Any]
Valide/nettoie une config de quiz arbitraire (JSON venu du client) —
jamais lève, renvoie toujours un dict COMPLET fusionné sur
DEFAULT_QUIZ_CONFIG. Chaque question de raw_config["questions"] est
validée indépendamment (voir _sanitize_question, privée) : texte non
vide, au moins 2 choix non vides (tronqués à 4), correct_index remis à
0 s'il est absent/hors bornes/non-entier (un bool — qui est un int en
Python — est explicitement rejeté), points codé en entier ≥ 0. Une
question invalide est silencieusement supprimée de la liste (jamais une
levée qui ferait échouer tout le reste du quiz).
- Retour : dict complet (mêmes clés que
DEFAULT_QUIZ_CONFIG). - Exceptions : aucune.
quiz_total_points(config: dict[str, Any]) -> int
Somme du points de toutes les questions d'une config déjà sanitizée —
mirroir de db/dialogue_lines.py::sum_question_rewards côté jeu, utile
le jour où un export calculera un score maximum.
- Retour : entier ≥ 0.
- Exceptions : aucune.