Insluitpakketten en simulaties

Overzicht

Het blok Ingesloten code kan een map tonen die je uploadt: een index.html met bijbehorende bestanden, die binnen de les draait. Standaard is dat pakket een gesloten doos. Levert het ook een klein manifest mee en praat het via een paar berichten met de les, dan kan het:

  • de les laten weten dat de cursist klaar is (zodat de les erop wacht);
  • zijn hoogte doorgeven, zodat het kader zich aan de inhoud aanpast;
  • zijn voortgang doorgeven, zodat de cursist verdergaat waar hij gebleven was;
  • een cijfer en elke beslissing melden, waardoor het een simulatie wordt die meetelt in de beoordeling, in SCORM en in xAPI;
  • variabelen beschikbaar stellen die voorwaardelijke inhoud kan lezen.

Deze pagina is voor wie het pakket bouwt. Je kunt haar volgen zonder de code van Creator te lezen. Voor de kant van de auteur (het paneel van het blok, het cijfer en de waarschuwingen), zie Content-bricks.

Alles is optioneel. Een pakket zonder manifest werkt gewoon: het wordt getoond, telt als voltooid zodra het in beeld is en houdt de cursist nooit tegen.

Hoe het pakket draait

Het pakket draait in een afgeschermd kader: scripts zijn toegestaan, maar het heeft geen toegang tot de applicatie (geen cookies, geen opslag van de applicatie, geen gedeelde oorsprong). De les luistert alleen naar berichten uit het kader van dat blok zelf; niets anders op de pagina kan zich dus als jouw pakket voordoen. Een ongeldig bericht wordt stilzwijgend genegeerd.

Een ingesloten code die naar een externe URL verwijst in plaats van naar een geüploade map, heeft geen pakket: de berichten worden altijd genegeerd en er wordt nooit iets gedeclareerd.

Het manifest: slxd-embed.json

Zet een bestand met de naam slxd-embed.json in de hoofdmap van de map, naast index.html:

{
  "protocol": "slxd-embed",
  "version": 1,
  "capabilities": ["complete", "resize", "state", "result", "interaction"],
  "variables": { "trust": "number", "reused": "boolean" }
}
VeldBetekenis
protocolAltijd "slxd-embed".
versionAltijd 1; dat is de enige versie die wordt begrepen.
capabilitiesWat het pakket gaat versturen. Elk gedrag werkt alleen als de bijbehorende mogelijkheid is gedeclareerd. Onbekende waarden worden genegeerd. Maximaal 32 items.
variablesOptioneel. De variabelen van state.vars die het pakket verstuurt, met hun type (number of boolean). Maximaal 64. Voorwaardelijke inhoud kan alleen deze noemen.

Zonder het bestand, met ongeldige JSON, een andere versie of meer dan 16 KB declareert het pakket gewoon niets.

Het manifest wordt gelezen wanneer je de map in het blok uploadt. Upload slxd-embed.json samen met de rest van de map. Wijzig je het manifest, upload dan de map opnieuw: een eerder geüpload pakket houdt wat het toen declareerde.

MogelijkheidWat het mogelijk maakt
completeHet pakket kan zeggen „ik ben klaar”. Nodig om de blokkering van het blok op het pakket te laten wachten.
resizeHet pakket kan de hoogte van zijn kader instellen.
stateDe les bewaart de voortgang van het pakket en geeft die terug wanneer de cursist terugkomt.
resultHet pakket kan een cijfer versturen.
interactionHet pakket kan elke beslissing melden (SCORM-interacties en xAPI).

Gereserveerde variabelenamen

grade, score, maxScore, ending en kind lezen altijd het laatste result van het pakket (zie hieronder) en kunnen dus niet ook variabelen van je status zijn. Een pakket waarvan variables er een declareert, wordt bij het uploaden geweigerd: de editor toont de fout en de map wordt niet gebruikt totdat je de namen wijzigt. In state.vars wordt een sleutel met een gereserveerde naam gewoon genegeerd.

Variabelenamen beginnen met een letter of _, vervolgen met letters, cijfers of _ en zijn hoogstens 64 tekens lang. Een item met een andere naam of een ander type wordt genegeerd zonder de rest te weigeren.

Berichten

Elk bericht is een eenvoudig object dat met postMessage wordt verstuurd, met dezelfde envelop:

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

De doeloorsprong is "*", omdat het kader de oorsprong van de les niet kan kennen; er reist niets gevoeligs in deze berichten.

Van pakket naar les

typeVeldenVereistWat Creator doet
ready——Verstuur het zodra het pakket is geladen. Declareert het pakket state, dan antwoordt de les met restore.
complete—completeMarkeert het blok als voltooid en heft de blokkering op. In een simulatie sluit het die bovendien af (zie hieronder).
resizeheight: getal ≥ 0, in CSS-pixelsresizeHet kader neemt die hoogte aan, begrensd tot 100–4000 px en naar boven afgerond. Tot het eerste bericht geldt de in het blok ingestelde hoogte.
statestate: JSON-object; done: booleanstateBewaart state ongewijzigd. done: true betekent dat het een einde is: het sluit de simulatie af en voltooit het blok. Verstuur het na elke beslissing en bij het bereiken van een einde.
resultscore, maxScore, grade, ending, kindresultWerkt alleen het cijfer bij. Het kan onvolledig binnenkomen en het laatste telt. Het voltooit het blok niet en sluit de simulatie niet af.
interactionattempt, n, response, description, result, weightinginteractionRegistreert één beslissing. Verstuur het na elke beslissing.

Een bericht dat niet in deze vormen past, wordt volledig genegeerd, zonder waarschuwing. Controleer elk veld:

  • state.state: een eenvoudig JSON-object (geen lijst of losse waarde) van hoogstens 1024 tekens na serialisatie. state.done is verplicht. Creator behandelt de status als ondoorzichtig, op één optioneel onderdeel na, vars: een object met getallen en waar/onwaar-waarden dat voorwaardelijke inhoud leest.
  • result.score: elk eindig getal (mag negatief zijn). maxScore: eindig getal ≥ 0. grade: een getal van 0 tot 100 dat jouw pakket berekent; alleen dat telt voor de beoordeling. ending: een ID. kind: good, mixed of bad.
  • interaction.attempt en n (het nummer van de beslissing binnen de poging): gehele getallen van 1 tot 9999. response: het ID van de gekozen optie. description: tekst van hoogstens 250 tekens, verplicht (een lege tekst volstaat). result: correct, incorrect of neutral. weighting: een getal groter dan 0 (verstuur 1 als de beslissing 0 waard was).
  • ID's (ending, response): kleine letters, cijfers en _, beginnend met een letter, tot 64 tekens.

Van les naar pakket

typeVeldenWanneer
restorestate: de laatst bewaarde status, of nullAls antwoord op ready, als het pakket state declareert. Is null als er niets bewaard was.
reset—Wanneer het examen een nieuwe poging opent. Begin opnieuw: bewaarde status en cijfer zijn al gewist.

Een minimaal pakket

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 });

Afronden: result vóór complete

Een simulatie wordt afgesloten door complete of door een state met done: true. Een result sluit haar nooit af. Het cijfer dat telt is dat van het laatste result dat vóór het afsluiten binnenkwam; na het afsluiten worden latere resultaten genegeerd. Sluit het pakket af zonder ooit een result te hebben verstuurd, dan is de simulatie 0 waard.

De juiste volgorde bij een einde is dus:

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

Een state zonder done na een einde is een nieuw spel: het vorige cijfer wordt vergeten.

Een pakket dat als Beoordeeld wordt gemarkeerd, moet dus complete of state declareren; anders zou zijn cijfer nooit kunnen worden afgesloten.

Wat Creator met elk onderdeel doet

Blokkering van de voortgang. Het blok Ingesloten code houdt de cursist standaard niet tegen. Zet de auteur de blokkering aan (in het blok of in de thema-instellingen voor ingesloten code), dan werkt die alleen bij een pakket dat complete declareert: de cursist kan pas verder als het bericht binnenkomt, zonder time-out en zonder ontgrendelknop. state en result heffen haar niet op. Een pakket zonder complete en elke externe URL tellen als voltooid zodra ze in beeld zijn. De editor waarschuwt wanneer de blokkering aanstaat maar het pakket haar niet kan nakomen.

Hoogte. Het kader volgt de laatste resize (tussen 100 en 4000 px). Tot de eerste gebruikt het de in het blok ingestelde hoogte.

Status bij terugkeer. De status van de simulatie wordt bewaard onder haar simulatie-ID, per inhoud. Wanneer het pakket laadt en ready zegt, krijgt het restore met de laatste status. In een SCORM-export overleeft de status tussen sessies (ze reist mee in de suspend-gegevens van de LMS); in het voorbeeld, bij deellinks en in de review geldt ze voor de sessie. Past de status niet in de ruimte van de LMS, dan snoeit Creator het hoogstnodige in een vaste volgorde: eerst simulaties die niet meetellen en die voorwaardelijke inhoud niet leest, dan de status van de overige, waarbij hun variabelen en cijfers zo lang mogelijk behouden blijven.

Cijfer. Om de simulatie te laten meetellen geeft de auteur het blok een simulatie-ID (uniek in de inhoud), markeert het als Beoordeeld en geeft het een gewicht; het pakket moet result declareren, plus complete of state. In een examen telt de simulatie mee naast de vragen: elke simulatie is haar gewicht maal grade / 100 waard, en het examen sluit pas af als alle meetellende simulaties zijn afgesloten. In een inhoud zonder examens is het cijfer van de inhoud het gewogen gemiddelde van de beoordeelde simulaties zodra ze allemaal klaar zijn, gemeten tegen de slaaggrens van de inhoud (getoond op de exportpagina). Beoordeelde simulaties naast beoordeelde examens tellen niet mee; de editor waarschuwt.

Interacties in SCORM. In een SCORM-export wordt elke interaction een item van cmi.interactions van het type choice, met het ID <simulatie-ID>-<poging>-<n>, de gekozen optie, het resultaat (correct, wrong/incorrect of neutral) en de weging; SCORM 2004 bewaart bovendien de beschrijving. In het voorbeeld is er geen LMS, dus wordt er niets geregistreerd.

xAPI. Waar xAPI actief is, wordt elke interaction gemeld als „beantwoord” op een beslissingsactiviteit (met de beschrijving, de gekozen optie en success voor correct en incorrect; neutral heeft die niet), en bij het afsluiten van de simulatie draagt één enkele „scored”-statement het cijfer dat telt, met het einde en het soort als extensies. Een onvolledig result verstuurt niets. Een nieuw spel staat de statement opnieuw toe. De auteur kan xAPI voor het blok uitzetten.

Grenzen in één oogopslag

WatGrens
slxd-embed.json16 KB, alleen versie 1
Mogelijkhedentot 32 items
Variabelentot 64, number of boolean
stateJSON-object, ≤ 1024 tekens
Kaderhoogte100–4000 px
Beschrijving van een beslissing≤ 250 tekens
attempt, ngehele getallen 1–9999
ID's[a-z][a-z0-9_]*, ≤ 64 tekens
Bewaarde voortgang (SCORM)gedeeld budget van 4096 tekens voor de hele inhoud

Volgende stappen

Insluitpakketten en simulaties