Ajoute un suivi xAPI optionnel (bolt-on) au paquet SCORM exporté
Build and deploy / test-python (push) Successful in 9m41s
Build and deploy / test-js (push) Successful in 51s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped

Greffe l'envoi de statements xAPI vers un LRS configurable par le
créateur du jeu, en parallèle du reporting SCORM existant : réglages
stockés en base (_meta), formulaire dans la modale d'export, injection
dans le paquet exporté. Relié aussi bien à l'action de flow "Modifier
un score/statut" qu'au parcours quête/quiz (qui alimentait déjà le
SCORM classique via un chemin séparé).

L'export ne se lance plus automatiquement à l'ouverture de la modale,
pour laisser le temps d'enregistrer les réglages xAPI avant de générer
le paquet.
This commit is contained in:
william
2026-09-05 10:00:57 +02:00
parent 7ebc9b143f
commit f7a50e5afe
13 changed files with 422 additions and 3 deletions
+26
View File
@@ -238,6 +238,26 @@ def build_scorm_zip(slug):
# seule personne à la fois sur son poste, comme /game/<slug>/play —
# jamais d'état "par joueur" à distinguer hors ligne.
payload = screens.full_game_payload(slug)
# xAPI (voir db/games/get_xapi_settings.py, routes/publish/
# xapi_settings.py) : bolt-on volontairement simple, JAMAIS le
# protocole cmi5 complet (pas de négociation de jeton au lancement) —
# les identifiants du LRS sont saisis une fois par le créateur du jeu
# et embarqués tels quels dans le paquet exporté, lu par
# static/js/play/offline/xapi-client.js. `endpoint` vide (réglage
# jamais renseigné) désactive entièrement xAPI pour ce jeu : le
# SCORM classique (scorm-api.js) continue de fonctionner à l'identique
# dans tous les cas.
xapi_settings = db.get_xapi_settings(slug)
xapi_config = None
if xapi_settings["endpoint"]:
xapi_config = {
"endpoint": xapi_settings["endpoint"],
"login": xapi_settings["login"],
"password": xapi_settings["password"],
"activity_id": f"urn:forge-engine:game:{slug}",
"activity_name": game["name"],
}
# gameData.icon_data_uris (voir forgeRenderIcone,
# static/js/play/offline/render-special-widgets.js) : ajouté au
# payload AVANT le rendu pour qu'il fasse partie du même payload_json
@@ -253,6 +273,12 @@ def build_scorm_zip(slug):
"play.html", game=game, screens_data=payload["screens"], payload_json=json.dumps(payload),
offline_mode=True, asset_url=lambda filename: "static/" + filename,
scorm_api_wrapper_url="static/js/play/offline/scorm-api.js",
# "</" -> "<\\/" : endpoint/login sont saisis librement par le
# créateur du jeu (voir routes/publish/xapi_settings.py) — sans
# cet échappement, une valeur contenant "</script>" refermerait
# prématurément la balise <script> de templates/play.html qui
# embarque ce JSON (json.dumps n'échappe jamais "<"/">"/"&").
xapi_config_json=json.dumps(xapi_config).replace("</", "<\\/"),
)
html = _relativize_absolute_urls(html, slug)
html = _inline_icon_urls(html, payload["icon_data_uris"])