diff --git a/db/__init__.py b/db/__init__.py index 83579465..884dd607 100644 --- a/db/__init__.py +++ b/db/__init__.py @@ -36,6 +36,10 @@ from .games.delete_game import delete_game from .games.move_game import move_game from .games.get_xapi_settings import get_xapi_settings from .games.set_xapi_settings import set_xapi_settings +from .games.get_success_threshold import get_success_threshold +from .games.set_success_threshold import set_success_threshold +from .games.get_scorm_version import get_scorm_version +from .games.set_scorm_version import set_scorm_version from .games.game_type_catalog import ( ONBOARDING_TYPES, DEFAULT_ONBOARDING_TYPE, get_onboarding_type, get_onboarding_type_raw, set_onboarding_type, diff --git a/db/games/get_scorm_version.py b/db/games/get_scorm_version.py new file mode 100644 index 00000000..fbe0b086 --- /dev/null +++ b/db/games/get_scorm_version.py @@ -0,0 +1,19 @@ +from ..connection import connect + +DEFAULT_SCORM_VERSION = "1.2" +VALID_SCORM_VERSIONS = ("1.2", "2004") + + +def get_scorm_version(slug): + """Version SCORM exportée pour ce jeu (voir publish/build_scorm_package.py, + publish/scorm_manifest.py) — '1.2' par défaut (compatibilité la plus + large) ou '2004' (3rd/4th edition, sépare completion_status/ + success_status : voir static/js/play/offline/scorm2004-api.js, corrige + la limite SCORM 1.2 où un statut unique doit coder à la fois + complétion ET réussite).""" + conn = connect(slug) + row = conn.execute("SELECT value FROM _meta WHERE key = 'scorm_version'").fetchone() + conn.close() + if row is None or row["value"] not in VALID_SCORM_VERSIONS: + return DEFAULT_SCORM_VERSION + return row["value"] diff --git a/db/games/get_success_threshold.py b/db/games/get_success_threshold.py new file mode 100644 index 00000000..8f5b5cbb --- /dev/null +++ b/db/games/get_success_threshold.py @@ -0,0 +1,19 @@ +from ..connection import connect + +DEFAULT_SUCCESS_THRESHOLD_PERCENT = 70 + + +def get_success_threshold(slug): + """Seuil de réussite (% de bonnes réponses au quiz) de CE jeu — stocké + dans _meta (clé 'success_threshold_percent'), même convention que + get_xapi_settings.py. Détermine le statut SCORM/xAPI de fin de partie + (reussi/echoue, voir static/js/play/dialogue-box-controller.js:: + forgeSyncAllQuestsCompletionToScorm) : 70% par défaut si jamais réglé.""" + conn = connect(slug) + row = conn.execute( + "SELECT value FROM _meta WHERE key = 'success_threshold_percent'" + ).fetchone() + conn.close() + if row is None or row["value"] in (None, ""): + return DEFAULT_SUCCESS_THRESHOLD_PERCENT + return int(row["value"]) diff --git a/db/games/set_scorm_version.py b/db/games/set_scorm_version.py new file mode 100644 index 00000000..21279a6d --- /dev/null +++ b/db/games/set_scorm_version.py @@ -0,0 +1,15 @@ +from ..connection import connect +from .get_scorm_version import VALID_SCORM_VERSIONS + + +def set_scorm_version(slug, version): + """Enregistre la version SCORM exportée — voir get_scorm_version.py.""" + if version not in VALID_SCORM_VERSIONS: + raise ValueError("version SCORM invalide : {!r}".format(version)) + conn = connect(slug) + conn.execute( + "INSERT OR REPLACE INTO _meta (key, value) VALUES ('scorm_version', ?)", + (version,), + ) + conn.commit() + conn.close() diff --git a/db/games/set_success_threshold.py b/db/games/set_success_threshold.py new file mode 100644 index 00000000..cb327628 --- /dev/null +++ b/db/games/set_success_threshold.py @@ -0,0 +1,14 @@ +from ..connection import connect + + +def set_success_threshold(slug, percent): + """Enregistre le seuil de réussite (0-100) — voir get_success_threshold.py.""" + percent = max(0, min(100, int(percent))) + conn = connect(slug) + conn.execute( + "INSERT OR REPLACE INTO _meta (key, value) VALUES ('success_threshold_percent', ?)", + (str(percent),), + ) + conn.commit() + conn.close() + return percent diff --git a/publish/accessibility_declaration.py b/publish/accessibility_declaration.py new file mode 100644 index 00000000..7ddd975e --- /dev/null +++ b/publish/accessibility_declaration.py @@ -0,0 +1,67 @@ +"""Déclaration d'accessibilité exportable (obligation légale RGAA pour +tout service numérique concerné, voir roadmap phase 1.2) — PAS un audit +certifié : un résumé honnête, généré à partir de ce que le moteur de jeu +implémente RÉELLEMENT aujourd'hui (voir static/js/play/triggers.js, +dialogue-box-controller.js, screens/scenes/render_scene_object.py), à +compléter/faire valider par le créateur du jeu avant publication.""" +from datetime import date + +_DECLARATION_TEMPLATE = """Déclaration d'accessibilité — {game_name} +Générée le {today} par Forge Engine + +Cette déclaration résume l'état d'accessibilité du jeu de formation +"{game_name}" au regard du RGAA (Référentiel Général d'Amélioration de +l'Accessibilité, version française de WCAG 2.1 niveau AA). Elle décrit ce +que le moteur Forge Engine implémente pour TOUT jeu exporté — elle ne +remplace pas un audit RGAA complet réalisé par un expert accessibilité, et +ne couvre pas le contenu propre à ce jeu (texte, images, choix de +couleurs) qui reste sous la responsabilité de son créateur. + +CRITÈRES PRIS EN CHARGE PAR LE MOTEUR +-------------------------------------- +- Navigation clavier : tout objet de scène réagissant "Au clic" ou "Au + survol" est focusable (Tab) et activable au clavier (Entrée/Espace), + en plus de la souris. Les boutons de dialogue/quiz sont de vrais +