Build and deploy / test-python (push) Successful in 11m5s
Build and deploy / test-js (push) Successful in 55s
Build and deploy / lint-python (push) Successful in 6m29s
Build and deploy / lint-js (push) Failing after 1m39s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped
Build and deploy / sonarqube (push) Failing after 5m18s
Bug reel constate le 21/09/2026 : un element Scenario cree avant la refonte en arbre de decision (ancien schema plat "situation"/"choices"/ "correct_index") faisait planter silencieusement le panneau Proprietes cote client des la selection - scenario.nodes etait inexistant sur l'ancienne forme, aucune erreur visible, juste "il ne se passe rien". Cause : document_edit.py et document_render.py renvoyaient les attributs BRUTS de la base au client, jamais revalides - contrairement a la route d'ecriture qui, elle, sanitize deja avant de persister. Ajoute document_engine.sanitize_element_attributes(kind, attributes), point d'entree unique de dispatch kind -> sanitize_X_config, utilise desormais a la fois en ecriture (document_element_update.py, qui reutilise ce nouveau dispatch au lieu de son if/elif duplique) ET en lecture (document_edit.py/document_render.py). Elimine toute la classe de bug "schema devenu obsolete apres une evolution du modele de donnees d'un mini-jeu, donnee jamais retouchee depuis" - present et futur, pas seulement pour Scenario. Migre les donnees reelles deja affectees (support de test, element 46) vers le nouveau schema en arbre, en preservant integralement le contenu deja redige par l'utilisateur (situation + 3 choix/consequences du scenario "chat sur la route"). Ajoute un test de non-regression qui ecrit delibirement l'ancien schema en base (en contournant le sanitize de la route d'ecriture, pour simuler une donnee reellement ancienne jamais nettoyee) puis verifie que /edit et /render renvoient une structure saine au client. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
114 lines
3.5 KiB
Python
114 lines
3.5 KiB
Python
"""
|
|
document_engine — support de formation : entité racine séparée du jeu 2D
|
|
(voir docs/plan/PLAN.md). Un support = un seul document, structuré en deux
|
|
couches sur le même canevas :
|
|
- le flux de contenu (titre/paragraphe/image/bouton/mini-jeux), organisé
|
|
en rangées ("row") par le moteur d'inférence de layout (voir
|
|
document_engine/rendering/render_document_element.py) ;
|
|
- la couche de formes libres (rectangle/cercle/triangle/trait), position-
|
|
nées en absolu (x/y/width/height/rotation/z_index).
|
|
|
|
Tout est stocké dans support.db (voir db/supports/) : une seule table,
|
|
_document_elements, portant les deux couches via parent_id (NULL = top-
|
|
niveau ou forme libre, sinon = enfant d'une rangée).
|
|
|
|
Aucun import croisé avec game_engine ou tout module lié au jeu 2D — voir
|
|
le contrat import-linter dans pyproject.toml (game_engine | document_engine
|
|
sont un même palier, mutuellement isolés).
|
|
|
|
Ce module se contente de ré-exporter l'intégralité de l'API publique du
|
|
paquet (pattern "un fichier = une fonction, un dossier = une responsabi-
|
|
lité", voir game_engine/__init__.py).
|
|
"""
|
|
|
|
from .elements.add_document_element import add_document_element
|
|
from .elements.delete_document_element import delete_document_element
|
|
from .elements.get_document_element import get_document_element
|
|
from .elements.list_document_elements import list_document_elements
|
|
from .elements.move_document_element import move_document_element
|
|
from .elements.update_document_element_attributes import update_document_element_attributes
|
|
from .labels.association_config import (
|
|
DEFAULT_ASSOCIATION_CONFIG,
|
|
MAX_PAIRS,
|
|
MIN_PAIRS,
|
|
sanitize_association_config,
|
|
)
|
|
from .labels.element_kind_labels import (
|
|
CONTENT_KINDS,
|
|
ELEMENT_KIND_LABELS,
|
|
ELEMENT_LIBRARY,
|
|
MINIGAME_KINDS,
|
|
SHAPE_KINDS,
|
|
element_default_attributes,
|
|
)
|
|
from .labels.memory_config import (
|
|
CARD_MODES,
|
|
DEFAULT_MEMORY_CONFIG,
|
|
MAX_CARDS,
|
|
MIN_CARDS,
|
|
sanitize_memory_config,
|
|
)
|
|
from .labels.mots_config import (
|
|
DEFAULT_MOTS_CONFIG,
|
|
MAX_WORDS,
|
|
MIN_WORDS,
|
|
sanitize_mots_config,
|
|
)
|
|
from .labels.quiz_config import (
|
|
DEFAULT_QUIZ_CONFIG,
|
|
MAX_CHOICES,
|
|
MAX_TIMER_SECONDS,
|
|
MIN_CHOICES,
|
|
MIN_TIMER_SECONDS,
|
|
quiz_total_points,
|
|
sanitize_quiz_config,
|
|
)
|
|
from .labels.sanitize_element_attributes import sanitize_element_attributes
|
|
from .labels.scenario_config import (
|
|
DEFAULT_SCENARIO_CONFIG,
|
|
MAX_SCENARIO_CHOICES,
|
|
sanitize_scenario_config,
|
|
)
|
|
from .rendering.render_document_element import render_document, render_document_element
|
|
|
|
__all__ = [
|
|
"CARD_MODES",
|
|
"CONTENT_KINDS",
|
|
"DEFAULT_ASSOCIATION_CONFIG",
|
|
"DEFAULT_MEMORY_CONFIG",
|
|
"DEFAULT_MOTS_CONFIG",
|
|
"DEFAULT_QUIZ_CONFIG",
|
|
"DEFAULT_SCENARIO_CONFIG",
|
|
"ELEMENT_KIND_LABELS",
|
|
"ELEMENT_LIBRARY",
|
|
"MAX_CARDS",
|
|
"MAX_CHOICES",
|
|
"MAX_PAIRS",
|
|
"MAX_SCENARIO_CHOICES",
|
|
"MAX_TIMER_SECONDS",
|
|
"MAX_WORDS",
|
|
"MIN_CARDS",
|
|
"MIN_CHOICES",
|
|
"MIN_PAIRS",
|
|
"MIN_TIMER_SECONDS",
|
|
"MIN_WORDS",
|
|
"MINIGAME_KINDS",
|
|
"SHAPE_KINDS",
|
|
"add_document_element",
|
|
"delete_document_element",
|
|
"element_default_attributes",
|
|
"get_document_element",
|
|
"list_document_elements",
|
|
"move_document_element",
|
|
"quiz_total_points",
|
|
"render_document",
|
|
"render_document_element",
|
|
"sanitize_association_config",
|
|
"sanitize_element_attributes",
|
|
"sanitize_memory_config",
|
|
"sanitize_mots_config",
|
|
"sanitize_quiz_config",
|
|
"sanitize_scenario_config",
|
|
"update_document_element_attributes",
|
|
]
|