Paquets intégrés et simulations

Vue d'ensemble

Le bloc Code intégré peut afficher un dossier que vous téléversez : un index.html avec ses ressources, exécuté dans la leçon. Par défaut, ce paquet est une boîte fermée. S'il fournit aussi un petit manifeste et dialogue avec la leçon par quelques messages, il peut :

  • indiquer à la leçon que l'apprenant a terminé (pour que la leçon l'attende) ;
  • communiquer sa hauteur, pour que le cadre s'ajuste à son contenu ;
  • transmettre sa progression, pour que l'apprenant retrouve l'activité là où il l'a laissée ;
  • envoyer une note et chaque décision, ce qui en fait une simulation comptant dans la note, en SCORM et en xAPI ;
  • exposer des variables que le contenu conditionnel peut lire.

Cette page s'adresse à la personne qui construit le paquet. On peut la suivre sans lire le code de Creator. Pour le côté auteur (le panneau du bloc, la note et les avertissements), voir Bricks de contenu.

Tout est facultatif. Un paquet sans manifeste fonctionne quand même : il s'affiche, est considéré comme terminé dès qu'il est vu et ne retient jamais l'apprenant.

Comment le paquet s'exécute

Le paquet tourne dans un cadre isolé : il peut exécuter des scripts, mais n'a aucun accès à l'application (ni cookies, ni stockage de l'application, ni origine partagée). La leçon n'écoute que les messages provenant du cadre de ce même bloc ; rien d'autre sur la page ne peut donc se faire passer pour votre paquet. Un message invalide est ignoré en silence.

Un code intégré qui pointe vers une URL externe au lieu d'un dossier téléversé n'a pas de paquet : ses messages sont toujours ignorés et il ne déclare jamais rien.

Le manifeste : slxd-embed.json

Placez un fichier nommé slxd-embed.json à la racine du dossier, à côté de index.html :

{
  "protocol": "slxd-embed",
  "version": 1,
  "capabilities": ["complete", "resize", "state", "result", "interaction"],
  "variables": { "trust": "number", "reused": "boolean" }
}
ChampSignification
protocolToujours "slxd-embed".
versionToujours 1 ; c'est la seule version comprise.
capabilitiesCe que le paquet enverra. Chaque comportement ne fonctionne que si sa capacité est déclarée. Ce qui est inconnu est ignoré. Jusqu'à 32 entrées.
variablesFacultatif. Les variables de state.vars que le paquet envoie, avec leur type (number ou boolean). Jusqu'à 64. Le contenu conditionnel ne peut nommer que celles-ci.

Sans le fichier, avec un JSON invalide, une autre version ou plus de 16 Ko, le paquet ne déclare simplement rien.

Le manifeste est lu lorsque vous téléversez le dossier dans le bloc. Téléversez slxd-embed.json avec le reste du dossier. Si vous modifiez le manifeste, téléversez de nouveau le dossier : un paquet téléversé auparavant conserve ce qu'il déclarait à ce moment-là.

CapacitéCe qu'elle permet
completeLe paquet peut dire « j'ai terminé ». Nécessaire pour que le blocage du bloc attende le paquet.
resizeLe paquet peut fixer la hauteur de son cadre.
stateLa leçon enregistre la progression du paquet et la lui rend au retour de l'apprenant.
resultLe paquet peut envoyer une note.
interactionLe paquet peut envoyer chaque décision (interactions SCORM et xAPI).

Noms de variables réservés

grade, score, maxScore, ending et kind lisent toujours le dernier result du paquet (voir plus bas) ; ils ne peuvent donc pas être aussi des variables de votre état. Un paquet dont variables déclare l'un d'eux est refusé au téléversement : l'éditeur affiche l'erreur et le dossier n'est pas utilisé tant que vous n'avez pas renommé ces variables. Dans state.vars, une clé portant un nom réservé est simplement ignorée.

Les noms de variables commencent par une lettre ou _, se poursuivent par des lettres, des chiffres ou _, et comptent au plus 64 caractères. Une entrée avec un autre nom ou un autre type est ignorée sans rejeter le reste.

Messages

Chaque message est un objet simple envoyé avec postMessage, avec la même enveloppe :

const send = (type, data = {}) =>
  window.parent.postMessage({ channel: "slxd-embed", version: 1, type, ...data }, "*");

L'origine cible est "*" car le cadre ne peut pas connaître l'origine de la leçon ; rien de sensible ne circule dans ces messages.

Du paquet vers la leçon

typeChampsRequiertCe que fait Creator
ready——À envoyer dès que le paquet est chargé. Si le paquet déclare state, la leçon répond par restore.
complete—completeMarque le bloc comme terminé et lève son blocage. Dans une simulation, il la clôt aussi (voir plus bas).
resizeheight : nombre ≥ 0, en pixels CSSresizeLe cadre prend cette hauteur, bornée entre 100 et 4000 px et arrondie à l'entier supérieur. Jusqu'au premier message, la hauteur configurée dans le bloc s'applique.
statestate : objet JSON ; done : booléenstateEnregistre state tel quel. done: true indique une fin : cela clôt la simulation et termine le bloc. À envoyer après chaque décision et en arrivant à une fin.
resultscore, maxScore, grade, ending, kindresultMet seulement la note à jour. Il peut arriver partiel et le dernier l'emporte. Il ne termine pas le bloc et ne clôt pas la simulation.
interactionattempt, n, response, description, result, weightinginteractionEnregistre une décision. À envoyer après chaque décision.

Un message qui ne correspond pas à ces formes est entièrement ignoré, sans avertissement. Vérifiez chaque champ :

  • state.state : un objet JSON simple (ni liste ni valeur isolée) d'au plus 1024 caractères une fois sérialisé. state.done est obligatoire. Creator traite l'état comme opaque, sauf un membre facultatif, vars : un objet de nombres et de valeurs vrai/faux que lit le contenu conditionnel.
  • result.score : tout nombre fini (il peut être négatif). maxScore : nombre fini ≥ 0. grade : un nombre de 0 à 100 que votre paquet calcule ; c'est la seule valeur qui compte pour la note. ending : un identifiant. kind : good, mixed ou bad.
  • interaction.attempt et n (le numéro de la décision dans la tentative) : entiers de 1 à 9999. response : l'identifiant de l'option choisie. description : texte d'au plus 250 caractères, obligatoire (une chaîne vide convient). result : correct, incorrect ou neutral. weighting : un nombre supérieur à 0 (envoyez 1 si la décision valait 0).
  • Identifiants (ending, response) : minuscules, chiffres et _, en commençant par une lettre, jusqu'à 64 caractères.

De la leçon vers le paquet

typeChampsQuand
restorestate : le dernier état enregistré, ou nullEn réponse à ready, si le paquet déclare state. Vaut null si rien n'était enregistré.
reset—Quand l'évaluation ouvre une nouvelle tentative. Repartez de zéro : l'état et la note enregistrés ont déjà été effacés.

Un paquet minimal

const send = (type, data = {}) =>
  window.parent.postMessage({ channel: "slxd-embed", version: 1, type, ...data }, "*");

let scene = "s1";
let vars = { trust: 0, reused: false };

window.addEventListener("message", (event) => {
  const msg = event.data;
  if (!msg || msg.channel !== "slxd-embed") return;
  if (msg.type === "restore" && msg.state) {
    scene = msg.state.scene;
    vars = msg.state.vars;
    render();
  }
  if (msg.type === "reset") {
    scene = "s1";
    vars = { trust: 0, reused: false };
    render();
  }
});

function choose(option) {
  vars.trust += option.points;
  scene = option.next;
  send("interaction", {
    attempt: 1,
    n: 1,
    response: option.id,
    description: option.label,
    result: option.points > 0 ? "correct" : "incorrect",
    weighting: Math.abs(option.points) || 1,
  });
  send("state", { state: { scene, vars }, done: false });
  render();
}

send("ready");
send("resize", { height: document.body.scrollHeight });

Terminer : result avant complete

Une simulation est clôturée par complete ou par un state avec done: true. Un result ne la clôt jamais. La note qui compte est celle du dernier result reçu avant la clôture ; une fois la simulation clôturée, les résultats suivants sont ignorés. Si le paquet se clôt sans avoir envoyé de result, la simulation vaut 0.

Le bon ordre à une fin est donc :

send("result", { score: 8, maxScore: 10, grade: 80, ending: "agreement", kind: "good" });
send("state", { state: { scene: "end", vars }, done: true }); // ou : send("complete")

Un state sans done après une fin est une nouvelle partie : la note précédente est oubliée.

Un paquet destiné à être marqué Noté doit donc déclarer complete ou state ; sinon sa note ne pourrait jamais être clôturée.

Ce que Creator fait de chaque élément

Blocage de la progression. Le bloc de code intégré ne retient pas l'apprenant par défaut. Si l'auteur active le blocage (dans le bloc ou dans les réglages du thème pour le code intégré), il ne fonctionne qu'avec un paquet qui déclare complete : l'apprenant ne peut pas continuer avant l'arrivée du message, sans délai d'attente ni bouton de déblocage. state et result ne le lèvent pas. Un paquet sans complete, et toute URL externe, sont considérés comme terminés dès qu'ils sont vus. L'éditeur avertit lorsque le blocage est activé mais que le paquet ne peut pas le respecter.

Hauteur. Le cadre suit le dernier resize (entre 100 et 4000 px). Jusqu'au premier, il utilise la hauteur configurée dans le bloc.

État au retour. L'état de la simulation est enregistré sous son identifiant de simulation, par contenu. Quand le paquet se charge et dit ready, il reçoit restore avec le dernier état. Dans une exportation SCORM, l'état survit d'une session à l'autre (il voyage dans les données de suspension du LMS) ; dans l'aperçu, les liens de partage et la relecture, il dure le temps de la session. Si l'état ne tient pas dans la place du LMS, Creator réduit le strict nécessaire dans un ordre fixe : d'abord les simulations qui ne comptent pas et que le contenu conditionnel ne lit pas, puis l'état des autres, en conservant le plus longtemps possible leurs variables et leurs notes.

Note. Pour que la simulation compte, l'auteur donne au bloc un identifiant de simulation (unique dans le contenu), la marque comme Notée et lui attribue un poids ; le paquet doit déclarer result, ainsi que complete ou state. Dans une évaluation, la simulation compte avec les questions : chaque simulation vaut son poids multiplié par grade / 100, et l'évaluation ne se termine pas avant que toutes les simulations comptabilisées soient clôturées. Dans un contenu sans évaluation, la note du contenu est la moyenne pondérée de ses simulations notées une fois toutes terminées, avec le seuil de réussite du contenu (affiché dans la page d'exportation). Les simulations notées accompagnant des évaluations notées ne comptent pas ; l'éditeur avertit.

Interactions en SCORM. Dans une exportation SCORM, chaque interaction devient une entrée de cmi.interactions de type choice, avec l'id <identifiant de simulation>-<tentative>-<n>, l'option choisie, le résultat (correct, wrong/incorrect ou neutral) et la pondération ; SCORM 2004 enregistre aussi la description. Dans l'aperçu, il n'y a pas de LMS : rien n'est enregistré.

xAPI. Là où xAPI est actif, chaque interaction est transmise comme « a répondu » sur une activité de décision (avec la description, l'option choisie et success pour correct et incorrect ; neutral n'en porte pas), et à la clôture de la simulation, une unique déclaration « a obtenu un score » porte la note qui compte, avec la fin et le type en extensions. Un result partiel n'émet rien. Commencer une nouvelle partie permet d'émettre de nouveau la déclaration. L'auteur peut désactiver xAPI pour le bloc.

Limites en un coup d'œil

QuoiLimite
slxd-embed.json16 Ko, version 1 uniquement
Capacitésjusqu'à 32 entrées
Variablesjusqu'à 64, number ou boolean
stateobjet JSON, ≤ 1024 caractères
Hauteur du cadre100–4000 px
Description d'une décision≤ 250 caractères
attempt, nentiers 1–9999
Identifiants[a-z][a-z0-9_]*, ≤ 64 caractères
Progression enregistrée (SCORM)budget partagé de 4096 caractères pour tout le contenu

Étapes suivantes

Paquets intégrés et simulations