Pacotes incorporados e simulações

Visão geral

O bloco Código incorporado pode mostrar uma pasta que carrega: um index.html com os seus recursos, a correr dentro da lição. Por predefinição, esse pacote é uma caixa fechada. Se levar também um pequeno manifesto e falar com a lição através de algumas mensagens, pode:

  • avisar a lição de que o formando terminou (para que a lição o espere);
  • indicar a sua altura, para que a moldura se ajuste ao conteúdo;
  • entregar o seu progresso, para que o formando o encontre onde o deixou;
  • enviar uma nota e cada decisão, o que o torna uma simulação que conta na classificação, em SCORM e em xAPI;
  • expor variáveis que o conteúdo condicional pode ler.

Esta página destina-se a quem constrói o pacote. Pode ser seguida sem ler qualquer código do Creator. Para o lado do autor (o painel do bloco, a nota e os avisos), consulte Bricks de Conteúdo.

Tudo é opcional. Um pacote sem manifesto funciona na mesma: é mostrado, conta como concluído ao ser visto e nunca trava o formando.

Como o pacote é executado

O pacote corre numa moldura isolada: pode executar scripts, mas não tem acesso à aplicação (nem cookies, nem armazenamento da aplicação, nem origem partilhada). A lição só escuta as mensagens que vêm da moldura desse mesmo bloco, pelo que nada mais na página se pode fazer passar pelo seu pacote. Uma mensagem inválida é ignorada em silêncio.

Um código incorporado que aponta para um URL externo em vez de uma pasta carregada não tem pacote: as suas mensagens são sempre ignoradas e nunca declara nada.

O manifesto: slxd-embed.json

Coloque um ficheiro chamado slxd-embed.json na raiz da pasta, junto a index.html:

{
  "protocol": "slxd-embed",
  "version": 1,
  "capabilities": ["complete", "resize", "state", "result", "interaction"],
  "variables": { "trust": "number", "reused": "boolean" }
}
CampoSignificado
protocolSempre "slxd-embed".
versionSempre 1; é a única versão compreendida.
capabilitiesO que o pacote vai enviar. Cada comportamento só funciona se a sua capacidade estiver declarada. O que for desconhecido é ignorado. Até 32 entradas.
variablesOpcional. As variáveis de state.vars que o pacote envia, com o seu tipo (number ou boolean). Até 64. O conteúdo condicional só pode nomear estas.

Sem o ficheiro, com JSON inválido, com outra versão ou com mais de 16 KB, o pacote simplesmente não declara nada.

O manifesto é lido quando carrega a pasta no bloco. Carregue slxd-embed.json juntamente com o resto da pasta. Se alterar o manifesto, volte a carregar a pasta: um pacote carregado antes mantém o que declarava então.

CapacidadeO que permite
completeO pacote pode dizer «terminei». Necessária para que o bloqueio do bloco espere pelo pacote.
resizeO pacote pode definir a altura da sua moldura.
stateA lição guarda o progresso do pacote e devolve-o quando o formando volta.
resultO pacote pode enviar uma nota.
interactionO pacote pode enviar cada decisão (interações SCORM e xAPI).

Nomes de variável reservados

grade, score, maxScore, ending e kind leem sempre o último result do pacote (ver abaixo), pelo que não podem ser também variáveis do seu estado. Um pacote cujo variables declare algum deles não é aceite ao carregá-lo: o editor mostra o erro e a pasta não é usada até mudar esses nomes. Dentro de state.vars, uma chave com nome reservado é simplesmente ignorada.

Os nomes de variável começam por uma letra ou _, continuam com letras, algarismos ou _ e têm no máximo 64 carateres. Uma entrada com outro nome ou tipo é ignorada sem rejeitar o resto.

Mensagens

Cada mensagem é um objeto simples enviado com postMessage, com o mesmo envelope:

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

A origem de destino é "*" porque a moldura não pode conhecer a origem da lição; nestas mensagens não viaja nada sensível.

Do pacote para a lição

typeCamposRequerO que o Creator faz
ready——Envie-o assim que o pacote tiver carregado. Se o pacote declarar state, a lição responde com restore.
complete—completeMarca o bloco como concluído e levanta o seu bloqueio. Numa simulação, também a encerra (ver abaixo).
resizeheight: número ≥ 0, em píxeis CSSresizeA moldura assume essa altura, limitada entre 100 e 4000 px e arredondada por excesso. Até à primeira mensagem, vale a altura configurada no bloco.
statestate: objeto JSON; done: booleanostateGuarda state tal como veio. done: true indica que é um final: encerra a simulação e conclui o bloco. Envie-o após cada decisão e ao chegar a um final.
resultscore, maxScore, grade, ending, kindresultSó atualiza a nota. Pode chegar parcial e prevalece o último. Não conclui o bloco nem encerra a simulação.
interactionattempt, n, response, description, result, weightinginteractionRegista uma decisão. Envie-o após cada decisão.

Uma mensagem que não se ajuste a estas formas é ignorada por inteiro, sem qualquer aviso. Verifique cada campo:

  • state.state: um objeto JSON simples (não uma lista nem um valor solto) com no máximo 1024 carateres depois de serializado. state.done é obrigatório. O Creator trata o estado como opaco, exceto um membro opcional, vars: um objeto de números e valores verdadeiro/falso que o conteúdo condicional lê.
  • result.score: qualquer número finito (pode ser negativo). maxScore: número finito ≥ 0. grade: um número de 0 a 100 que o seu pacote calcula; é o único valor que conta para a classificação. ending: um identificador. kind: good, mixed ou bad.
  • interaction.attempt e n (o número da decisão dentro da tentativa): inteiros de 1 a 9999. response: o identificador da opção escolhida. description: texto de no máximo 250 carateres, obrigatório (uma cadeia vazia serve). result: correct, incorrect ou neutral. weighting: um número maior que 0 (envie 1 se a decisão valia 0).
  • Identificadores (ending, response): minúsculas, algarismos e _, começando por uma letra, até 64 carateres.

Da lição para o pacote

typeCamposQuando
restorestate: o último estado guardado, ou nullEm resposta a ready, se o pacote declarar state. É null se não havia nada guardado.
reset—Quando o exame abre uma nova tentativa. Recomece do zero: o estado e a nota guardados já foram apagados.

Um pacote mínimo

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

Terminar: result antes de complete

Uma simulação é encerrada por complete ou por um state com done: true. Um result nunca a encerra. A nota que conta é a do último result recebido antes do encerramento; depois de encerrada, os resultados posteriores são ignorados. Se o pacote encerrar sem ter enviado nenhum result, a simulação vale 0.

A ordem correta num final é, portanto:

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

Um state sem done depois de um final é um jogo novo: a nota anterior é esquecida.

Um pacote que vá ser marcado como Avaliável tem, por isso, de declarar complete ou state; de outro modo, a sua nota nunca poderia ser encerrada.

O que o Creator faz com cada coisa

Bloqueio do avanço. O bloco de código incorporado não trava o formando por predefinição. Se o autor ativar o bloqueio (no bloco ou nas definições do tema para o código incorporado), só funciona com um pacote que declare complete: o formando não pode continuar até chegar a mensagem, sem tempo limite nem botão para desbloquear. state e result não o levantam. Um pacote sem complete, e qualquer URL externo, contam como concluídos ao serem vistos. O editor avisa quando o bloqueio está ativado mas o pacote não o pode cumprir.

Altura. A moldura segue o último resize (entre 100 e 4000 px). Até ao primeiro, usa a altura configurada no bloco.

Estado ao voltar. O estado da simulação é guardado sob o seu identificador de simulação, por conteúdo. Quando o pacote carrega e diz ready, recebe restore com o último estado. Numa exportação SCORM, o estado sobrevive entre sessões (viaja nos dados de suspensão do LMS); na pré-visualização, nas ligações partilhadas e na revisão, dura a sessão. Se o estado não couber no espaço do LMS, o Creator corta o indispensável por uma ordem fixa: primeiro as simulações que nem contam nem são lidas pelo conteúdo condicional, depois o estado das restantes, mantendo o mais possível as suas variáveis e notas.

Nota. Para que a simulação conte, o autor dá ao bloco um identificador de simulação (único no conteúdo), marca-o como Avaliável e atribui-lhe um peso; o pacote tem de declarar result, além de complete ou state. Dentro de um exame, a simulação conta junto das perguntas: cada simulação vale o seu peso vezes grade / 100, e o exame só fecha quando todas as simulações que contam estão encerradas. Num conteúdo sem exames, a nota do conteúdo é a média ponderada das suas simulações avaliáveis quando todas terminaram, com o limiar de aprovação do conteúdo (mostrado na página de exportar). As simulações avaliáveis que acompanham exames classificáveis não contam; o editor avisa.

Interações em SCORM. Numa exportação SCORM, cada interaction torna-se uma entrada de cmi.interactions do tipo choice, com o id <identificador de simulação>-<tentativa>-<n>, a opção escolhida, o resultado (correct, wrong/incorrect ou neutral) e a ponderação; o SCORM 2004 guarda também a descrição. Na pré-visualização não há LMS, pelo que nada é registado.

xAPI. Onde o xAPI está ativo, cada interaction é comunicada como «respondeu» sobre uma atividade de decisão (com a descrição, a opção escolhida e success para correct e incorrect; neutral não o leva) e, quando a simulação é encerrada, uma única declaração de «pontuou» transporta a nota que conta, com o final e o tipo como extensões. Um result parcial não emite nada. Começar um jogo novo permite emitir de novo a declaração. O autor pode desativar o xAPI no bloco.

Limites num relance

O quêLimite
slxd-embed.json16 KB, só versão 1
Capacidadesaté 32 entradas
Variáveisaté 64, number ou boolean
stateobjeto JSON, ≤ 1024 carateres
Altura da moldura100–4000 px
Descrição de uma decisão≤ 250 carateres
attempt, ninteiros 1–9999
Identificadores[a-z][a-z0-9_]*, ≤ 64 carateres
Progresso guardado (SCORM)orçamento partilhado de 4096 carateres para todo o conteúdo

Próximos passos

Pacotes incorporados e simulações