Skip to Content
Interop EdTechPartie 5 — SCORM 2004 : séquencement5.2 — Arbre d'activités & objectifs

Chapitre 5.2 — L’arbre d’activités & les objectifs

⏱️ TL;DR — En SCORM 1.2, l’organization du manifeste n’est qu’un menu : une liste d’item que le LMS affiche et laisse cliquer. En SCORM 2004, ce même organization devient un arbre d’activités que le LMS pilote : chaque nœud est une activité, soit une feuille (un SCO lançable, rattaché à une resource), soit un regroupement (cluster, un nœud sans contenu qui organise ses enfants). On accroche à ces nœuds des <imsss:sequencing> qui portent des objectifs (<imsss:objectives>). Chaque activité a un objectif principal (primaryObjective) plus des objectifs secondaires ; un objectif peut être local (privé à l’activité) ou partagé entre activités via un objectif global, câblé par mapInfo. Cet arbre + ces objectifs sont le terrain de jeu des règles de séquencement (5.3) et du rollup (5.4).

🎯 Objectifs

  • Lire l’organization de 2004 comme un arbre d’activités, pas comme un menu.
  • Distinguer activité feuille (SCO) et activité de regroupement (cluster).
  • Comprendre les objectifs : primaryObjective, objectifs secondaires, objectiveID.
  • Câbler un objectif global partagé entre deux activités avec mapInfo.

Du menu à l’arbre : ce qui change

L’organization existe déjà en 1.2 : c’est le bloc du imsmanifest.xml qui liste les item, dont ceux qui pointent (identifierref) vers une resource de type SCO. Mais en 1.2, cette hiérarchie est décorative : elle sert à dessiner un sommaire. Le LMS n’en tire aucune logique.

En 2004, la même structure d’item devient un arbre d’activités que le moteur de séquencement du LMS exécute. Chaque item est une activité. On distingue deux natures :

  • Activité feuille : elle a un identifierref vers une resource scoType="sco". C’est du contenu lançable — un SCO qui dialogue avec l’API. C’est là que se posent completion_status, success_status, le score.
  • Activité de regroupement (cluster) : elle n’a pas de contenu propre (pas de identifierref, ou un enfant), elle organise ses activités enfants. Son état ne vient pas d’un SCO mais remonte de ses enfants (c’est le rollup, chapitre 5.4).

La racine et les deux « Module » sont des regroupements : aucun fichier HTML derrière eux. Les feuilles (Introduction, Chapitres, Évaluation) sont les seuls SCO réellement lancés. Le LMS parcourt cet arbre selon les règles de séquencement posées sur chaque nœud.

💡 Réflexe — Quand tu lis un manifeste 2004, repère d’abord qui a un identifierref : ces item-là sont tes SCO lançables (les feuilles). Les autres sont des regroupements dont l’état est calculé, jamais rapporté directement par du contenu. Confondre les deux, c’est chercher pendant des heures pourquoi « le Module 1 ne remonte pas de score » alors qu’un regroupement n’exécute aucun SCO.

Poser du séquencement sur un nœud

Le séquencement s’accroche à un item (ou à l’organization racine) via un élément <imsss:sequencing>. Voici le squelette d’un manifeste 2004, réduit à l’essentiel :

<manifest identifier="MANIFEST-1" xmlns="http://www.imsglobal.org/xsd/imscp_v1p1" xmlns:imsss="http://www.imsglobal.org/xsd/imsss" xmlns:adlcp="http://www.adlnet.org/xsd/adlcp_v1p3" xmlns:adlseq="http://www.adlnet.org/xsd/adlseq_v1p3" xmlns:adlnav="http://www.adlnet.org/xsd/adlnav_v1p3"> <organizations default="ORG-1"> <organization identifier="ORG-1"> <title>Cours Sécurité au travail</title> <item identifier="ITEM-INTRO" identifierref="RES-INTRO"> <title>Introduction</title> </item> <item identifier="ITEM-MOD1"> <!-- regroupement : pas de identifierref --> <title>Module 1</title> <item identifier="ITEM-CH1" identifierref="RES-CH1"> <title>Chapitre 1</title> </item> <item identifier="ITEM-CH2" identifierref="RES-CH2"> <title>Chapitre 2</title> </item> </item> <!-- Séquencement de la racine : on autorise le libre choix ET le flux --> <imsss:sequencing> <imsss:controlMode choice="true" flow="true"/> </imsss:sequencing> </organization> </organizations> <resources> <resource identifier="RES-INTRO" adlcp:scormType="sco" href="intro.html" type="webcontent"/> <resource identifier="RES-CH1" adlcp:scormType="sco" href="ch1.html" type="webcontent"/> <resource identifier="RES-CH2" adlcp:scormType="sco" href="ch2.html" type="webcontent"/> </resources> </manifest>

Retiens deux choses : les namespaces imsss, adlseq, adlnav déclarés sur <manifest> (sans eux, rien de tout ça n’existe), et le fait que <imsss:sequencing> se pose à n’importe quel niveau de l’arbre — racine, regroupement, feuille.

Les objectifs : la mémoire de chaque activité

Chaque activité peut porter des objectifs (<imsss:objectives>) : ce sont les variables sur lesquelles le séquencement raisonne. Un objectif a un objectiveID, un état de satisfaction (satisfait / non satisfait / inconnu) et une mesure (01, typiquement alimentée par cmi.score.scaled).

Chaque activité a exactement un objectif principal, le <imsss:primaryObjective> — c’est lui que le rollup utilise pour décider si l’activité est « satisfaite ». Elle peut avoir en plus des objectifs secondaires (<imsss:objective>).

<item identifier="ITEM-CH2" identifierref="RES-CH2"> <title>Chapitre 2</title> <imsss:sequencing> <imsss:objectives> <!-- Objectif principal : satisfait si la mesure atteint 0,8 --> <imsss:primaryObjective objectiveID="OBJ-CH2" satisfiedByMeasure="true" minNormalizedMeasure="0.8"/> </imsss:objectives> </imsss:sequencing> </item>

Ici, satisfiedByMeasure="true" dit au LMS : « ne te fie pas au success_status rapporté par le SCO, considère cet objectif satisfait dès que sa mesure (le score scalé) atteint minNormalizedMeasure, soit 0.8 ». C’est une des façons de brancher la note sur la logique de parcours.

⚠️ Piège — Croire qu’un objectif est partagé parce que deux activités lui donnent le même objectiveID. Faux : un objectiveID est local à son activité. Le Chapitre 2 et le Chapitre 3 peuvent tous deux avoir un objectif nommé OBJ, ce sont deux objectifs distincts qui s’ignorent. Pour qu’une info circule d’une activité à l’autre, il faut un objectif global et du mapInfo (voir ci-dessous).

Les objectifs globaux : faire circuler l’info entre activités

C’est le mécanisme le plus puissant — et le plus mal compris — de l’arbre. Un objectif global (dit shared global objective) vit au-dessus des activités : c’est une case mémoire partagée par tout le cours. Une activité y écrit son état ; une autre le lit. Le pont entre l’objectif local d’une activité et l’objectif global partagé, c’est <imsss:mapInfo>.

Exemple concret : le Chapitre 2 écrit son état de satisfaction dans un objectif global GLOBAL-CH2 ; le Chapitre 3 lit ce même global pour savoir si le 2 est réussi (on s’en servira pour le bloquer, en 5.3).

<!-- Chapitre 2 : ÉCRIT son statut dans l'objectif global partagé --> <item identifier="ITEM-CH2" identifierref="RES-CH2"> <title>Chapitre 2</title> <imsss:sequencing> <imsss:objectives> <imsss:primaryObjective objectiveID="OBJ-CH2" satisfiedByMeasure="true" minNormalizedMeasure="0.8"> <imsss:mapInfo targetObjectiveID="GLOBAL-CH2" writeSatisfiedStatus="true" writeNormalizedMeasure="true"/> </imsss:primaryObjective> </imsss:objectives> </imsss:sequencing> </item> <!-- Chapitre 3 : LIT ce même objectif global partagé --> <item identifier="ITEM-CH3" identifierref="RES-CH3"> <title>Chapitre 3</title> <imsss:sequencing> <imsss:objectives> <imsss:primaryObjective objectiveID="OBJ-CH3"/> <imsss:objective objectiveID="LU-CH2"> <imsss:mapInfo targetObjectiveID="GLOBAL-CH2" readSatisfiedStatus="true" readNormalizedMeasure="true"/> </imsss:objective> </imsss:objectives> </imsss:sequencing> </item>

Le targetObjectiveID identique (GLOBAL-CH2) des deux côtés est ce qui les relie. Le Chapitre 2 a writeSatisfiedStatus="true" (il publie) ; le Chapitre 3, via son objectif local LU-CH2, a readSatisfiedStatus="true" (il consomme). C’est le seul mécanisme normalisé pour qu’une donnée voyage entre activités du même cours.

💡 Réflexe — Modélise tes objectifs globaux comme des variables partagées : nomme-les explicitement (GLOBAL-CH2-REUSSI), et dessine qui écrit et qui lit avant d’écrire une seule ligne de XML. La moitié des bugs de séquencement 2004 sont des mapInfo où l’on a oublié le write d’un côté ou le read de l’autre — la donnée n’arrive jamais, et la règle qui en dépend ne se déclenche « mystérieusement » pas.

📚 La spec — L’arbre d’activités, les objectifs (primaryObjective, objective), l’objectif global partagé et le mapInfo relèvent du livre SN (Sequencing & Navigation) de SCORM 2004, lui-même bâti sur IMS Simple Sequencing (namespace imsss). Le SN n’existe que dans SCORM 2004 — jamais en 1.2. Pour la liste exacte des attributs de mapInfo et le comportement du modèle de suivi, réfère-toi au livre SN sur adlnet.gov .

🧭 Sur FormaCampus — Pour son cours « Sécurité au travail », FormaCampus veut imposer un vrai parcours : l’apprenant doit valider les fondamentaux avant d’accéder à l’évaluation. L’équipe modélise donc l’arbre : une racine, deux regroupements (« Fondamentaux », « Évaluation »), et un objectif global GLOBAL-FONDAMENTAUX que le regroupement « Fondamentaux » écrit et que « Évaluation » lit. Le squelette est propre sur le papier… mais l’équipe note déjà que ce câblage mapInfo est fragile et devra être testé LMS par LMS (on y revient en 5.5). Pour l’instant : l’arbre est posé, les objectifs globaux sont nommés.

✏️ Exercices

Exercice 1 — Feuille ou regroupement ? Dans le manifeste ci-dessous, dis pour chaque item s’il s’agit d’une activité feuille (SCO) ou d’un regroupement, et lesquels peuvent rapporter un score.

<item identifier="A"> <title>Bloc pratique</title> <item identifier="B" identifierref="RES-B"><title>Atelier 1</title></item> <item identifier="C" identifierref="RES-C"><title>Atelier 2</title></item> </item> <item identifier="D" identifierref="RES-D"><title>Bilan</title></item>

✅ Solution

  • A : regroupement (pas de identifierref, il contient B et C). Il ne lance aucun SCO ; son état remonte de B et C (rollup).
  • B, C : feuilles (SCO), elles ont un identifierref → contenu lançable qui peut rapporter complétion, réussite et score.
  • D : feuille (SCO) elle aussi.

Seuls B, C et D peuvent rapporter un score : ce sont les seuls SCO réellement exécutés. Attendre un score de A est une erreur — un regroupement ne dialogue pas avec l’API.

Exercice 2 — Câbler un objectif global. L’« Atelier 1 » doit publier sa réussite pour que le « Bilan » puisse la lire. Écris les deux blocs <imsss:objectives> (côté écriture, côté lecture) avec le bon targetObjectiveID.

✅ Solution

<!-- Atelier 1 : écrit --> <imsss:objectives> <imsss:primaryObjective objectiveID="OBJ-ATELIER1"> <imsss:mapInfo targetObjectiveID="GLOBAL-ATELIER1" writeSatisfiedStatus="true"/> </imsss:primaryObjective> </imsss:objectives> <!-- Bilan : lit --> <imsss:objectives> <imsss:primaryObjective objectiveID="OBJ-BILAN"/> <imsss:objective objectiveID="LU-ATELIER1"> <imsss:mapInfo targetObjectiveID="GLOBAL-ATELIER1" readSatisfiedStatus="true"/> </imsss:objective> </imsss:objectives>

Le lien tient au targetObjectiveID identique (GLOBAL-ATELIER1) : write d’un côté, read de l’autre. Sans cet identifiant commun, aucune donnée ne circule.

🧠 Quiz de révision

1. En quoi l’organization de 2004 diffère-t-il de celui de 1.2 ?

En 1.2, c’est un menu décoratif (un sommaire). En 2004, c’est un arbre d’activités que le moteur de séquencement du LMS exécute réellement, en appliquant les règles posées sur chaque nœud.

2. Quelle est la différence entre une activité feuille et une activité de regroupement ?

Une feuille a un identifierref vers une resource SCO : c’est du contenu lançable qui dialogue avec l’API. Un regroupement (cluster) n’a pas de contenu propre ; il organise ses enfants et son état remonte d’eux par rollup.

3. Combien d’objectifs principaux une activité possède-t-elle, et à quoi sert-il ?

Exactement un primaryObjective. C’est lui que le rollup utilise pour décider si l’activité est satisfaite. L’activité peut avoir en plus des objectifs secondaires (objective).

4. Deux activités avec le même objectiveID partagent-elles leur état ?

Non. Un objectiveID est local à son activité. Pour partager un état entre activités, il faut un objectif global relié par mapInfo (même targetObjectiveID), avec write d’un côté et read de l’autre.

5. À quoi sert satisfiedByMeasure="true" sur un objectif ?

Il fait dépendre la satisfaction de la mesure (le score scalé, 01) plutôt que du success_status rapporté : l’objectif est satisfait dès que la mesure atteint minNormalizedMeasure (par ex. 0.8).


Chapitre suivant : Les règles de séquencement — conditions, actions et contrôle de flux : comment bloquer, sauter ou forcer un ordre.

Last updated on