Update Concepts et objets de MACAO: ajout exercices Flash-only authored by Eliott Sammier's avatar Eliott Sammier
Cette page décrit la structure de Macao-Legacy et l'emplacement des données de contenu. Cette page décrit la structure de Macao-Legacy et l'emplacement des données de contenu.
*À plusieurs reprises, on a besoin de décrire un motif de nommage : dans ces cas, le caractère `#` correspond à un chiffre, et `_` à n'importe quel caractère alphanumérique. Quand ces caractères sont répétés, ils décrivent par défaut un champ de longueur variable (exemple: `###` désigne de 1 à 3 chiffres)* *À plusieurs reprises, on a besoin de décrire un motif de nommage : dans ces cas, le caractère `#` correspond à un chiffre, et `_` à n'importe quel caractère alphanumérique. Quand ces caractères sont répétés, ils décrivent par défaut un champ de longueur variable (exemple: `###` désigne de 1 à 3 chiffres)*
--- ---
**Modules** : Macao est composé de 3 modules (Macao 1, 2 et 3). Macao 1 et 2 partagent la même base de code `macao_12`, Macao 3 a été développé plus tard et réside dans `macao_3`. **Modules** : Macao est composé de 3 modules (Macao 1, 2 et 3). Macao 1 et 2 partagent la même base de code `macao_12`, Macao 3 a été développé plus tard et réside dans `macao_3`.
[[_TOC_]] [[_TOC_]]
# Dans Macao 1 et 2 : # Dans Macao 1 et 2 :
![Macao_12_concepts_annotation](uploads/3d911416917cd59c2e27ae0ca0c80309/Screenshot_2024-08-15_17-17-18.png) ![Macao_12_concepts_annotation](uploads/3d911416917cd59c2e27ae0ca0c80309/Screenshot_2024-08-15_17-17-18.png)
![class_diagram.drawio.svg](uploads/a8e9b401c9a8d8b1927ee88b2b00f4b4/class_diagram.drawio.svg) ![class_diagram.drawio.svg](uploads/a8e9b401c9a8d8b1927ee88b2b00f4b4/class_diagram.drawio.svg)
--- ---
## Parties ## Parties
Un module contient une ou plusieurs parties _(ex: "Reconnaître les syllabes")_, qui elles-mêmes peuvent contenir d'autres (sous-)parties. Côté code, une partie a la même représentation qu'un module, c'est un élément sans contenu propre, décrit seulement dans le manifeste [`imsmanifest.xml`](https://gitlab.tetras-libre.fr/macao/macao-legacy/-/blob/main/Basilisk/MACAO/macao_12/imsmanifest.xml) Un module contient une ou plusieurs parties _(ex: "Reconnaître les syllabes")_, qui elles-mêmes peuvent contenir d'autres (sous-)parties. Côté code, une partie a la même représentation qu'un module, c'est un élément sans contenu propre, décrit seulement dans le manifeste [`imsmanifest.xml`](https://gitlab.tetras-libre.fr/macao/macao-legacy/-/blob/main/Basilisk/MACAO/macao_12/imsmanifest.xml)
<details> <details>
<summary>Exemple XML</summary> <summary>Exemple XML</summary>
```xml ```xml
<organization> <organization>
<!-- ... --> <!-- ... -->
<item identifier="MosMod10"> <!-- module "MosMod10" --> <item identifier="MosMod10"> <!-- module "MosMod10" -->
<title>MACAO 1 - S'entraîner à la reconnaissance</title> <!-- titre de MosMod10 --> <title>MACAO 1 - S'entraîner à la reconnaissance</title> <!-- titre de MosMod10 -->
<!-- Contenu de MosMod10 --> <!-- Contenu de MosMod10 -->
<item identifier="MosMod11"> <item identifier="MosMod11">
<title>Reconnaître les syllabes</title> <title>Reconnaître les syllabes</title>
<!-- Contenu de MosMod11 --> <!-- Contenu de MosMod11 -->
<item identifier="MosEtp129" identifierref="rsrcMosEtp129"> <item identifier="MosEtp129" identifierref="rsrcMosEtp129">
<!-- Sous-partie "MosEtp129", contenu défini dans MosEtp129.html --> <!-- Sous-partie "MosEtp129", contenu défini dans MosEtp129.html -->
<title>&gt; Reconnaître les syllabes en anglais oral</title> <title>&gt; Reconnaître les syllabes en anglais oral</title>
</item> </item>
</item> </item>
<item identifier="MosMod34"> <item identifier="MosMod34">
<title>Reconnaître les auxiliaires, les prépositions et les déterminants</title> <title>Reconnaître les auxiliaires, les prépositions et les déterminants</title>
<item identifier="MosEtp210" identifierref="rsrcMosEtp210"> <item identifier="MosEtp210" identifierref="rsrcMosEtp210">
<title>&gt; Reconnaître les auxiliaires</title> <title>&gt; Reconnaître les auxiliaires</title>
</item> </item>
<item identifier="MosEtp335" identifierref="rsrcMosEtp335"> <item identifier="MosEtp335" identifierref="rsrcMosEtp335">
<title>&gt; Reconnaître les prépositions</title> <title>&gt; Reconnaître les prépositions</title>
</item> </item>
<item identifier="MosEtp558" identifierref="rsrcMosEtp558"> <item identifier="MosEtp558" identifierref="rsrcMosEtp558">
<title>&gt; Reconnaître les déterminants</title> <title>&gt; Reconnaître les déterminants</title>
</item> </item>
</item> </item>
</item> </item>
<!-- ... --> <!-- ... -->
</organization> </organization>
``` ```
</details> </details>
**Données à extraire :** **Données à extraire :**
- [x] ID -\> attribut `identifier` - [x] ID -\> attribut `identifier`
- [x] Titre -\> élément `<title>` - [x] Titre -\> élément `<title>`
- [x] Descendants dans l'arbre -\> éléments `<item>` - [x] Descendants dans l'arbre -\> éléments `<item>`
--- ---
## Sous-parties ## Sous-parties
On appelle sous-parties les parties de dernier niveau, les "feuilles" de l'arborescence. Dans le panneau de gauche, ce sont les éléments non dépliables _(ex: "Reconnaître les syllabes en anglais oral")_. Une sous-partie contient plusieurs **activités**, dont la première est affichée quand on sélectionne la sous-partie. Une sous-partie est décrite dans un fichier `sco/MosEtp###`, qui déclare un objet `MosSCO` pour définir son contenu. On appelle sous-parties les parties de dernier niveau, les "feuilles" de l'arborescence. Dans le panneau de gauche, ce sont les éléments non dépliables _(ex: "Reconnaître les syllabes en anglais oral")_. Une sous-partie contient plusieurs **activités**, dont la première est affichée quand on sélectionne la sous-partie. Une sous-partie est décrite dans un fichier `sco/MosEtp###`, qui déclare un objet `MosSCO` pour définir son contenu.
```js ```js
oSco = new MosSCO("MosEtp129", "> Reconnaître les syllabes en anglais oral", "MACAO", "MACAO 1 - S'entraîner à la reconnaissance", "", "macao_fusion_ss_barre", "fr"); oSco = new MosSCO("MosEtp129", "> Reconnaître les syllabes en anglais oral", "MACAO", "MACAO 1 - S'entraîner à la reconnaissance", "", "macao_fusion_ss_barre", "fr");
``` ```
Peu d'infos utiles : nom du fichier, titre (déjà défini dans le `<title>`), titre du "stage" (constant), titre du module parent (déjà connu grâce au manifest), et quelques champs constants.\ Peu d'infos utiles : nom du fichier, titre (déjà défini dans le `<title>`), titre du "stage" (constant), titre du module parent (déjà connu grâce au manifest), et quelques champs constants.\
Ensuite quelques lignes inutiles, puis on passe à la déclaration des pages. Ensuite quelques lignes inutiles, puis on passe à la déclaration des pages.
```js ```js
oSco.tabPages[oSco.tabPages.length] = new PageContenu("Repérer les syllabes orales", "pg861", "exercice", ""); oSco.tabPages[oSco.tabPages.length] = new PageContenu("Repérer les syllabes orales", "pg861", "exercice", "");
oSco.tabPages[oSco.tabPages.length] = new PageContenu("Repérer les syllabes écrites", "pg60", "exercice", ""); oSco.tabPages[oSco.tabPages.length] = new PageContenu("Repérer les syllabes écrites", "pg60", "exercice", "");
oSco.tabPages[oSco.tabPages.length] = new PageContenu("Commentaire", "pg636", "cours", ""); oSco.tabPages[oSco.tabPages.length] = new PageContenu("Commentaire", "pg636", "cours", "");
// ^ titre ^ id ^ type // ^ titre ^ id ^ type
// [...] // [...]
``` ```
Le plus important est l'ID de la page `"pg###"`, et éventuellement le type (`"exercice"` ou `"cours"`), le titre de la page étant déclaré aussi dans la page elle-même. Le plus important est l'ID de la page `"pg###"`, et éventuellement le type (`"exercice"` ou `"cours"`), le titre de la page étant déclaré aussi dans la page elle-même.
**Données à extraire :** **Données à extraire :**
- Dans le manifest - Dans le manifest
- [x] ID -\> attribut `identifier` - [x] ID -\> attribut `identifier`
- [x] Titre -\> élément `<title>` - [x] Titre -\> élément `<title>`
- Dans le fichier `MosEtp###.html` - Dans le fichier `MosEtp###.html`
- [~] Titre -\> `<title>` - [~] Titre -\> `<title>`
- [x] Liste des pages (titre, ID) -\> arguments de `new PageContenu()` - [x] Liste des pages (titre, ID) -\> arguments de `new PageContenu()`
--- ---
## Activités, ou pages ## Activités, ou pages
Les "unités de navigation". La section centrale de Macao affiche toujours 1 activité, dont le nom est indiqué en haut à droite _(ex: "Repérer les syllabes orales")_. Une activité peut être un cours (sans saisie interactive) ou un des 4 types d'exercices (`QC, QM, TAT, GD` dans `MosMtr/scripts/contenu/ClasseExercice___.js` + `ClasseCours.js`). Elle est décrite dans un fichier `contenu/pages/pg###.html`, qui déclare un objet `Cours` ou `Exercice___` pour définir son contenu. Les "unités de navigation". La section centrale de Macao affiche toujours 1 activité, dont le nom est indiqué en haut à droite _(ex: "Repérer les syllabes orales")_. Une activité peut être un cours (sans saisie interactive) ou un des 4 types d'exercices (`QC, QM, TAT, GD` dans `MosMtr/scripts/contenu/ClasseExercice___.js` + `ClasseCours.js`). Elle est décrite dans un fichier `contenu/pages/pg###.html`, qui déclare un objet `Cours` ou `Exercice___` pour définir son contenu.
**Données à extraire (communes à toutes les activités) :** **Données à extraire (communes à toutes les activités) :**
- [x] Type d'activité -\> premier appel de constructeur `new ___()` - [x] Type d'activité -\> premier appel de constructeur `new ___()`
- [x] [Commentaires](#commentaires) -\> éléments `<div id="divCmt___">` dans `<div id="zoneInvisible">` - [x] [Commentaires](#commentaires) -\> éléments `<div id="divCmt___">` dans `<div id="zoneInvisible">`
- [ ] Dans les descriptions, commentaires, blocs HTML divers - [ ] Dans les descriptions, commentaires, blocs HTML divers
- [ ] [Images](#images) -\> éléments `<img id="MosImg###">` - [ ] [Images](#images) -\> éléments `<img id="MosImg###">`
- [ ] Objets Flash -\> appels de fonction `PF_clipAV(...)` - [ ] Objets Flash -\> appels de fonction `PF_clipAV(...)`
- [ ] Pages d'aide/docs -\> appels de fonction `SCO_ouvrirDoc(...)` - [ ] Pages d'aide/docs -\> appels de fonction `SCO_ouvrirDoc(...)`
### Cours ### Cours
Du texte, très souvent des audios, mais parfois aussi des objets Flash spécialisés (voir #11).\ Du texte, très souvent des audios, mais parfois aussi des objets Flash spécialisés (voir #11).\
**Quantité :** 59 **Quantité :** 59
<details> <details>
<summary>Exemples</summary> <summary>Exemples</summary>
**Exemple de cours simple** : `pg686.html`, mémento _"L'accentuation des auxiliaires"_\ **Exemple de cours simple** : `pg686.html`, mémento _"L'accentuation des auxiliaires"_\
![Screenshot_2024-05-15_15-58-10](uploads/6406297d502d9cd9e05360a6715f631a/Screenshot_2024-05-15_15-58-10.png)\ ![Screenshot_2024-05-15_15-58-10](uploads/6406297d502d9cd9e05360a6715f631a/Screenshot_2024-05-15_15-58-10.png)\
Exemple de "cours" avec un **exercice en Flash** : `pg455.html`, première page de _"\> Reconnaître les marques de l'accentuation"_\ Exemple de "cours" avec un **exercice en Flash** : `pg455.html`, première page de _"\> Reconnaître les marques de l'accentuation"_\
![Screenshot_2024-05-15_15-57-31](uploads/b967e6b37d1409105e910ea43c786ca3/Screenshot_2024-05-15_15-57-31.png) ![Screenshot_2024-05-15_15-57-31](uploads/b967e6b37d1409105e910ea43c786ca3/Screenshot_2024-05-15_15-57-31.png)
</details> </details>
**Données à extraire :** **Données à extraire :**
- [x] Contenu du cours (texte/HTML) -\> élément `<div id="STY_zoneCours">` - [x] Contenu du cours (texte/HTML) -\> élément `<div id="STY_zoneCours">`
### ExerciceQC ### ExerciceQC
_(Question Choix?)_\ _(Question Choix?)_\
Une question avec plusieurs réponses prédéfinies. Existe en variante QCU (une seule bonne réponse) et QCM (plusieurs bonnes réponses).\ Une question avec plusieurs réponses prédéfinies. Existe en variante QCU (une seule bonne réponse) et QCM (plusieurs bonnes réponses).\
**Quantité :** 39 QCU, 9 QCM **Quantité :** 39 QCU, 9 QCM
<details> <details>
<summary>Exemples</summary> <summary>Exemples</summary>
**Exemple QCU** : `pg381.html`, la première page de _"\> Reconnaître les auxiliaires"_\ **Exemple QCU** : `pg381.html`, la première page de _"\> Reconnaître les auxiliaires"_\
![Screenshot_2024-05-15_14-59-01](uploads/bb4795264824c0140f49bb7a2126d5d2/Screenshot_2024-05-15_14-59-01.png) ![Screenshot_2024-05-15_14-59-01](uploads/bb4795264824c0140f49bb7a2126d5d2/Screenshot_2024-05-15_14-59-01.png)
**Exemple QCM** : `pg8412.html`, page _"Vérifier la place de l'accent primaire (3)"_ dans la sous-partie _"\> Utiliser les marques de l'accentuation"_ **Exemple QCM** : `pg8412.html`, page _"Vérifier la place de l'accent primaire (3)"_ dans la sous-partie _"\> Utiliser les marques de l'accentuation"_
Il s'avère que les 9 exercices QCM sont tous dans la même sous-partie, et sont utilisés sémantiquement comme plusieurs QCU : ![Screenshot_2024-05-15_15-22-19](uploads/4be84e866d324dc5205bd1aa0fb808f3/Screenshot_2024-05-15_15-22-19.png)\ Il s'avère que les 9 exercices QCM sont tous dans la même sous-partie, et sont utilisés sémantiquement comme plusieurs QCU : ![Screenshot_2024-05-15_15-22-19](uploads/4be84e866d324dc5205bd1aa0fb808f3/Screenshot_2024-05-15_15-22-19.png)\
Dans cet exemple, on a 3 mots ayant chacun 3 réponses possibles dont 1 bonne, mais l'exercice est implémenté comme un QCM de 9 choix possibles ; on peut tout à fait cocher les 3 choix pour "narrator". C'est un exemple de cas particulier étrange qui devra être corrigé manuellement. Dans cet exemple, on a 3 mots ayant chacun 3 réponses possibles dont 1 bonne, mais l'exercice est implémenté comme un QCM de 9 choix possibles ; on peut tout à fait cocher les 3 choix pour "narrator". C'est un exemple de cas particulier étrange qui devra être corrigé manuellement.
</details> </details>
**Données à extraire :** **Données à extraire :**
- [x] Consigne -\> `<div id="STY_question">` - [x] Consigne -\> `<div id="STY_question">`
- [x] Choix de réponses - [x] Choix de réponses
- [x] Correction -\> dans la fonction `entrerDonnees()`, `exo.tabStylesR[nr] = CODE_V` ou `CODE_F` pour chaque valeur de `nr` - [x] Correction -\> dans la fonction `entrerDonnees()`, `exo.tabStylesR[nr] = CODE_V` ou `CODE_F` pour chaque valeur de `nr`
- [x] Commentaires de succès et d'échec -\> `divCmtSucces` et `divCmtSugg#` _(cf. commentaires d'activité)_ - [x] Commentaires de succès et d'échec -\> `divCmtSucces` et `divCmtSugg#` _(cf. commentaires d'activité)_
### ExerciceQM ### ExerciceQM
_(Question Multiple?)_\ _(Question Multiple?)_\
Comme ExerciceQC mais avec plusieurs questions, chacune ayant une seule bonne réponse.\ Comme ExerciceQC mais avec plusieurs questions, chacune ayant une seule bonne réponse.\
**Quantité :** 8 **Quantité :** 8
<details> <details>
<summary>Exemple</summary> <summary>Exemple</summary>
`pg262.html`, la toute première page de Macao 1\ `pg262.html`, la toute première page de Macao 1\
![Screenshot_2024-05-15_14-56-47](uploads/59667940add90fb4f94f55cdb370be6b/Screenshot_2024-05-15_14-56-47.png) ![Screenshot_2024-05-15_14-56-47](uploads/59667940add90fb4f94f55cdb370be6b/Screenshot_2024-05-15_14-56-47.png)
</details> </details>
**Données à extraire :** **Données à extraire :**
- [x] Consigne -\> `<div id="STY_question">` - [x] Consigne -\> `<div id="STY_question">`
- [ ] Choix de réponses -\> tableau dans `<div id="STY_texteQM">`, chaque ligne (`<tr>`) est une question, chaque cellule de colonne (`<td>`) est une case à cocher. Son `id` indique aussi ses coordonnées (ex: `id="lienRepImg13"` = ligne 1 choix 3) - [ ] Choix de réponses -\> tableau dans `<div id="STY_texteQM">`, chaque ligne (`<tr>`) est une question, chaque cellule de colonne (`<td>`) est une case à cocher. Son `id` indique aussi ses coordonnées (ex: `id="lienRepImg13"` = ligne 1 choix 3)
- [ ] Correction -\> dans la fonction `entrerDonnees()`, `exo.tabStylesR[nr] = '3'` indiquent le numéro du choix correct pour chaque numéro de ligne `nr` - [ ] Correction -\> dans la fonction `entrerDonnees()`, `exo.tabStylesR[nr] = '3'` indiquent le numéro du choix correct pour chaque numéro de ligne `nr`
- [x] Commentaires de succès et d'échec -\> `divCmtSucces` et `divCmtSugg#` _(cf. commentaires d'activité)_ - [x] Commentaires de succès et d'échec -\> `divCmtSucces` et `divCmtSugg#` _(cf. commentaires d'activité)_
### ExerciceTAT ### ExerciceTAT
Un texte à trous, avec pour chaque "trou" une liste déroulante de choix de mots.\ Un texte à trous, avec pour chaque "trou" une liste déroulante de choix de mots.\
**Quantité :** 12 **Quantité :** 12
<details> <details>
<summary>Exemple</summary> <summary>Exemple</summary>
`pg20.html`, page _"Ecoutez et complétez (2)"_ dans la sous-partie _"\> Reconnaître les déterminants"_\ `pg20.html`, page _"Ecoutez et complétez (2)"_ dans la sous-partie _"\> Reconnaître les déterminants"_\
![Screenshot_2024-05-15_15-40-29](uploads/23944659726f54961ea79cb4e87d2772/Screenshot_2024-05-15_15-40-29.png) ![Screenshot_2024-05-15_15-40-29](uploads/23944659726f54961ea79cb4e87d2772/Screenshot_2024-05-15_15-40-29.png)
</details> </details>
**Données à extraire :** **Données à extraire :**
- [x] Consigne -\> `<div id="STY_question">` - [x] Consigne -\> `<div id="STY_question">`
- [x] Texte avec position des "trous" -\> contenu dans `<div id="STY_texteTAT">`.\ - [x] Texte avec position des "trous" -\> contenu dans `<div id="STY_texteTAT">`.\
Chaque trou est un élément `<select class="STY_selectTAT" id="champTrou#">` et son numéro est indiqué dans l'`id`. Chaque trou est un élément `<select class="STY_selectTAT" id="champTrou#">` et son numéro est indiqué dans l'`id`.
- [x] Choix pour chaque trou et correction -\> appels `exo.ajouterReponse(index, correction, valeur)`.\ - [x] Choix pour chaque trou et correction -\> appels `exo.ajouterReponse(index, correction, valeur)`.\
Paramètre "correction" = `ng` pour faux, `nw` pour juste. Paramètre "correction" = `ng` pour faux, `nw` pour juste.
- [x] Commentaires de succès et d'échec -\> `divCmtSucces` et `divCmtSugg#` _(cf. commentaires d'activité)_ - [x] Commentaires de succès et d'échec -\> `divCmtSucces` et `divCmtSugg#` _(cf. commentaires d'activité)_
### ExerciceGD ### ExerciceGD
_(Glisser-Déposer ?)_\ _(Glisser-Déposer ?)_\
Le plus complexe, avec des objets à glisser et placer librement ou dans des cases.\ Le plus complexe, avec des objets à glisser et placer librement ou dans des cases.\
**Quantité :** 5 **Quantité :** 5
<details> <details>
<summary>Exemple</summary> <summary>Exemple</summary>
`pg545.html`, page _"Compléter une transcription (1)"_ dans _"\> Utiliser les symboles phonétiques"_\ `pg545.html`, page _"Compléter une transcription (1)"_ dans _"\> Utiliser les symboles phonétiques"_\
![Screenshot_2024-05-15_15-51-35](uploads/4c4963cf1ea6c82296d9f2022b9a712a/Screenshot_2024-05-15_15-51-35.png) ![Screenshot_2024-05-15_15-51-35](uploads/4c4963cf1ea6c82296d9f2022b9a712a/Screenshot_2024-05-15_15-51-35.png)
</details> </details>
**Données à extraire :** **Données à extraire :**
- [x] Consigne -\> `<div id="STY_question">` - [x] Consigne -\> `<div id="STY_question">`
- [ ] Éléments à déplacer -\> éléments `<div id="exoGDd#">` (le `d` est pour _déplaçable_, et est suivi de son numéro/ID) - [ ] Éléments à déplacer -\> éléments `<div id="exoGDd#">` (le `d` est pour _déplaçable_, et est suivi de son numéro/ID)
- [ ] Cibles de déplacement -\> éléments `<div id="exoGDc#">` (le `c` est pour _cible_, suivi aussi de son numéro/ID) - [ ] Cibles de déplacement -\> éléments `<div id="exoGDc#">` (le `c` est pour _cible_, suivi aussi de son numéro/ID)
- [ ] Correction -\> liste de `new PaireGD(deplacable, cible, correct, decalageX, decalageY)` indiquent pour chaque déplaçable sa cible associée et si il est juste (`ng` = faux, `nw` = juste). - [ ] Correction -\> liste de `new PaireGD(deplacable, cible, correct, decalageX, decalageY)` indiquent pour chaque déplaçable sa cible associée et si il est juste (`ng` = faux, `nw` = juste).
- [ ] Positions de tous les éléments -\> offsets CSS `absolute`, sûrement à refaire manuellement. - [ ] Positions de tous les éléments -\> offsets CSS `absolute`, sûrement à refaire manuellement.
- [x] Commentaires de succès et d'échec -\> `divCmtSucces` et `divCmtSugg#` _(cf. commentaires d'activité)_ - [x] Commentaires de succès et d'échec -\> `divCmtSucces` et `divCmtSugg#` _(cf. commentaires d'activité)_
### Inutilisés ### Inutilisés
ExerciceCURS, ExerciceEXP, ExerciceSEQ ExerciceCURS, ExerciceEXP, ExerciceSEQ
--- ---
## Pages d'aide ou "docs" ## Pages d'aide ou "docs"
Dans `contenu/pages/`, les fichiers `*.htm` et `pgd###.html` sont des pages d'aide. Au lieu d'être chargées dans la section centrale, elles peuvent être ouvertes dans une nouvelle fenêtre pop-up avec la fonction `SCO_ouvrirDoc()`, souvent appelée depuis un lien `<a>` dans les pages classiques. Dans `contenu/pages/`, les fichiers `*.htm` et `pgd###.html` sont des pages d'aide. Au lieu d'être chargées dans la section centrale, elles peuvent être ouvertes dans une nouvelle fenêtre pop-up avec la fonction `SCO_ouvrirDoc()`, souvent appelée depuis un lien `<a>` dans les pages classiques.
```html ```html
cliquez pour voir la définition d'un <a href="javascript:parent.SCO_ouvrirDoc('pgd171','PAGE')">phonème</a> cliquez pour voir la définition d'un <a href="javascript:parent.SCO_ouvrirDoc('pgd171','PAGE')">phonème</a>
``` ```
Ces pages peuvent inclure des objets Flash comme les autres, mais pas d'exercice. Ces pages peuvent inclure des objets Flash comme les autres, mais pas d'exercice.
## Contenus des pages ## Contenus des pages
### Commentaires ### Commentaires
Certains exercices ont des commentaires, des blocs HTML structurés chargés dans une `<div id="zoneInvisible">`, qui sont déplacés dans la `<div id="STY_zoneCommentaire">` à droite en réponse à certaines actions. Certains exercices ont des commentaires, des blocs HTML structurés chargés dans une `<div id="zoneInvisible">`, qui sont déplacés dans la `<div id="STY_zoneCommentaire">` à droite en réponse à certaines actions.
- Commentaire de succès : `<div id="divCmtSucces">` - Commentaire de succès : `<div id="divCmtSucces">`
- Commentaire d'échec : `<div id="divSugg#">`, numérotés à partir de 1 - Commentaire d'échec : `<div id="divSugg#">`, numérotés à partir de 1
- Autres commentaires : `<div id="divCmt#">`, numérotés à partir de 1, contiennent un petit texte d'aide. - Autres commentaires : `<div id="divCmt#">`, numérotés à partir de 1, contiennent un petit texte d'aide.
:warning: Les commentaires **peuvent contenir de la mise en forme et des objets Flash** (peut-être même des images ?) :warning: Les commentaires **peuvent contenir de la mise en forme et des objets Flash** (peut-être même des images ?)
### Images ### Images
Les images intégrées dans le contenu d'une page sont reconnaissables par un `id="MosImg###`, à la différence de celles utilisées pour l'UI (boutons). Leur chemin est toujours dans `contenu/media/`. Les images intégrées dans le contenu d'une page sont reconnaissables par un `id="MosImg###`, à la différence de celles utilisées pour l'UI (boutons). Leur chemin est toujours dans `contenu/media/`.
```html ```html
<img id="MosImg17" src="../media/phon_recognition_54_juste.png"> <img id="MosImg17" src="../media/phon_recognition_54_juste.png">
``` ```
### Objets Flash et audio ### Objets Flash et audio
TODO TODO
--- #### Exercices Flash
Les objets Flash sont parfois utilisés pour implémenter des exercices entiers, comme le choix de syllabes :
# Dans Macao 3
![image](uploads/3634072157524afcd20096953f0a3290/image.png){width=594 height=222}
## Modules / Parties ![image](uploads/8c50c72d0b240bfa8518dc9f346d5b71/image.png){width=594 height=477}
Idem que Macao12 avec `imsmanifest.xml`, mais le nommage devient `seq######` (Exemples : MACAO 2, "Reconnaître les marques de l'accentuation")
## Sous-parties Ceux-là sont très compliqués à extraire. Pour Macao-Hugo, on peut les réimplémenter sur-mesure ou bien en faire un nouveau type de widget SurveyJS.
Idem que Macao12, mais le nommage devient `act######`. De même, le fichier `sco/MosEtp###.html` devient `sco/act######.html`.\ ---
Des fichiers XML `sco/md_act######.xml` font leur apparition pour chaque sous-partie, mais contiennent des métadonnées pour SCORM qui ne nous intéressent pas.
# Dans Macao 3
À la fin du `imsmanifest.xml`, un tag `<resource ... identifier="rsrcact######" ...>` décrit les dépendances de la sous-partie, sous la forme d'une liste de fichiers : pages `pg###.html`, images, SWFs... Potentiellement utile, ou bien redondant si on les retrouve dans le contenu HTML des pages.
## Modules / Parties
Même format pour le contenu (JavaScript) de la sous-partie, avec `new MosSCO(...)` et presque le même pour les lignes `new PageContenu()`, qui ont ici 6 paramètres string au lieu de 4, le dernier indiquant le type d'activité (`"COURS"`, `"QC"`, `"TAT"`, etc...).
Idem que Macao12 avec `imsmanifest.xml`, mais le nommage devient `seq######`
## Activités
## Sous-parties
Mêmes types d'activités :
Idem que Macao12, mais le nommage devient `act######`. De même, le fichier `sco/MosEtp###.html` devient `sco/act######.html`.\
```sh Des fichiers XML `sco/md_act######.xml` font leur apparition pour chaque sous-partie, mais contiennent des métadonnées pour SCORM qui ne nous intéressent pas.
grep -rE --only-matching --no-filename 'new (Cours|Exercice).+;' macao_3/contenu/pages | sort | uniq
``` À la fin du `imsmanifest.xml`, un tag `<resource ... identifier="rsrcact######" ...>` décrit les dépendances de la sous-partie, sous la forme d'une liste de fichiers : pages `pg###.html`, images, SWFs... Potentiellement utile, ou bien redondant si on les retrouve dans le contenu HTML des pages.
``` Même format pour le contenu (JavaScript) de la sous-partie, avec `new MosSCO(...)` et presque le même pour les lignes `new PageContenu()`, qui ont ici 6 paramètres string au lieu de 4, le dernier indiquant le type d'activité (`"COURS"`, `"QC"`, `"TAT"`, etc...).
new Cours();
new ExerciceGD(); ## Activités
new ExerciceQC("QCM");
new ExerciceQC("QCU"); Mêmes types d'activités :
new ExerciceQM("QCU");
new ExerciceTAT(); ```sh
``` grep -rE --only-matching --no-filename 'new (Cours|Exercice).+;' macao_3/contenu/pages | sort | uniq
```
Cependant, Macao 3 (ou très probablement MOS Chorus) semble avoir essayé d'obfusquer les définitions des réponses dans le code, peut-être pour éviter qu'un étudiant puisse ouvrir les *devtools* et déduire facilement les réponses correctes. C'est toujours possible en lisant le code (puisque l'appli fonctionne toujours sans serveur), mais complexifié par l'utilisation de techniques... exotiques.
Les sections suivantes sur chaque type d'exercice détaillent ces changements. ```
new Cours();
### ExerciceQC new ExerciceGD();
new ExerciceQC("QCM");
L'initialisation des choix ne se base plus sur des indices, mais sur des ID. new ExerciceQC("QCU");
- Les éléments HTML des choix (ex: `<div class="STY_reponseQC" id="lienrep627" ...>`) portent chacun un ID de la forme `repX` (la partie `lien` est ignorée et `X` est un nombre). new ExerciceQM("QCU");
- À cet élément HTML correspond un objet JS déclaré comme new ExerciceTAT();
```js ```
var oItem = new ItemReponse('rep678');
``` Cependant, Macao 3 (ou très probablement MOS Chorus) semble avoir essayé d'obfusquer les définitions des réponses dans le code, peut-être pour éviter qu'un étudiant puisse ouvrir les *devtools* et déduire facilement les réponses correctes. C'est toujours possible en lisant le code (puisque l'appli fonctionne toujours sans serveur), mais complexifié par l'utilisation de techniques... exotiques.
où le paramètre du constructeur est décodé par une fonction `decodeX`, définie [ici](https://gitlab.tetras-libre.fr/macao/macao-legacy/blob/main/Basilisk/MACAO/macao_3/MosMtr/scripts/contenu/ClasseExerciceQC.js#L567), qui remplace les caractères `0 1 2 3 7 8 9` entre eux et conserve les autres. Le résultat est le vrai ID du choix correspondant. Les sections suivantes sur chaque type d'exercice détaillent ces changements.
- Cet objet JS est initialisé avec `oItem.init("42", "", "", "");`, où le premier paramètre indique la justesse du choix. Si le dernier caractère est `1`, c'est un choix juste, sinon faux.
- Chaque choix peut être associé à un commentaire de suggestion, de la façon suivante : ### ExerciceQC
```js
var idDet = 'divSugg3'; L'initialisation des choix ne se base plus sur des indices, mais sur des ID.
EXO_ajouterCommentaire(idDet, "", "", "", "", "", "", "rep627", "", "", "", "1", "1", "", "", "", "", ""); - Les éléments HTML des choix (ex: `<div class="STY_reponseQC" id="lienrep627" ...>`) portent chacun un ID de la forme `repX` (la partie `lien` est ignorée et `X` est un nombre).
``` - À cet élément HTML correspond un objet JS déclaré comme
Le premier paramètre est l'ID du commentaire, le huitième est l'ID du choix. ```js
var oItem = new ItemReponse('rep678');
À la vérification, si la réponse de l'utilisateur est incorrecte, l'application affiche le commentaire d'un des choix sélectionnés ; les commentaires des choix justes sont prioritaires, le reste de la sélection est arbitraire (ex: si 1 choix juste et 1 choix faux sont cochés, le commentaire du choix juste sera affiché). ```
où le paramètre du constructeur est décodé par une fonction `decodeX`, définie [ici](https://gitlab.tetras-libre.fr/macao/macao-legacy/blob/main/Basilisk/MACAO/macao_3/MosMtr/scripts/contenu/ClasseExerciceQC.js#L567), qui remplace les caractères `0 1 2 3 7 8 9` entre eux et conserve les autres. Le résultat est le vrai ID du choix correspondant.
### ExerciceQM - Cet objet JS est initialisé avec `oItem.init("42", "", "", "");`, où le premier paramètre indique la justesse du choix. Si le dernier caractère est `1`, c'est un choix juste, sinon faux.
- Chaque choix peut être associé à un commentaire de suggestion, de la façon suivante :
Question Multiple, plusieurs questions (une par ligne) avec les choix en titre de colonne. Il n'y a que 3 ExerciceQM dans Macao3 donc on peut aussi les extraire manuellement. ```js
var idDet = 'divSugg3';
Idem que pour QC, les indices sont remplacés par des ID obfusqués. EXO_ajouterCommentaire(idDet, "", "", "", "", "", "", "rep627", "", "", "", "1", "1", "", "", "", "", "");
```
- `oItem = new ItemReponse('rep###')` déclare une "question" qui correspond à une ligne du tableau `<tr id="trReprep###">` Le premier paramètre est l'ID du commentaire, le huitième est l'ID du choix.
:warning: L'ID est à décoder avec la fonction [`decodeX()`](https://gitlab.tetras-libre.fr/macao/macao-legacy/blob/main/Basilisk/MACAO/macao_3/MosMtr/scripts/contenu/ClasseExerciceQM.js#L452) (ex: `rep991` devient `rep228`)
- `oItem.init("rep###")` déclare la réponse correcte, qui correspond à une colonne `<td id="col###">` À la vérification, si la réponse de l'utilisateur est incorrecte, l'application affiche le commentaire d'un des choix sélectionnés ; les commentaires des choix justes sont prioritaires, le reste de la sélection est arbitraire (ex: si 1 choix juste et 1 choix faux sont cochés, le commentaire du choix juste sera affiché).
- :warning: L'ID est à décoder avec une *autre* fonction : [`decodeY()`](https://gitlab.tetras-libre.fr/macao/macao-legacy/blob/main/Basilisk/MACAO/macao_3/MosMtr/scripts/contenu/ClasseExerciceQM.js#L485)
### ExerciceTAT ### ExerciceTAT
Le texte à trous existe maintenant en variante "sélection" (menu déroulant) et "libre" (champ texte), tous les deux des `new ExerciceTAT()`. La différence semble se remarquer avec des lignes de la forme Le texte à trous existe maintenant en variante "sélection" (menu déroulant) et "libre" (champ texte), tous les deux des `new ExerciceTAT()`. La différence semble se remarquer avec des lignes de la forme
```js ```js
exo.tabSelects[exo.tabSelects.length] = '1'; exo.tabSelects[exo.tabSelects.length] = '1';
``` ```
qui définissent quels champs sont des sélecteurs (exemple: comparer `pg4487.html` et `pg1919.html`). qui définissent quels champs sont des sélecteurs (exemple: comparer `pg4487.html` et `pg1919.html`).
Autre changement, le format des réponses. Tous les libellés sont maintenant obfusqués : Autre changement, le format des réponses. Tous les libellés sont maintenant obfusqués :
```js ```js
exo.ajouterReponse('rep859', '1', '2', "D8ke8k VOX"); exo.ajouterReponse('rep859', '1', '2', "D8ke8k VOX");
exo.ajouterReponse('rep482', '1', '3', "D8ke8k qOX"); exo.ajouterReponse('rep482', '1', '3', "D8ke8k qOX");
exo.ajouterReponse('rep306', '2', '5', "D8ke8k VOX"); exo.ajouterReponse('rep306', '2', '5', "D8ke8k VOX");
exo.ajouterReponse('rep40', '2', '4', "D8ke8k qOX"); exo.ajouterReponse('rep40', '2', '4', "D8ke8k qOX");
``` ```
Heureusement la fonction de décodage `decodeX()` est statique (clé fixe, ne dépend pas d'autres attributs de l'activité) : [source](https://gitlab.tetras-libre.fr/macao/macao-legacy/blob/main/Basilisk/MACAO/macao_3/MosMtr/scripts/contenu/ClasseExerciceTAT.js#L774) Heureusement la fonction de décodage `decodeX()` est statique (clé fixe, ne dépend pas d'autres attributs de l'activité) : [source](https://gitlab.tetras-libre.fr/macao/macao-legacy/blob/main/Basilisk/MACAO/macao_3/MosMtr/scripts/contenu/ClasseExerciceTAT.js#L774)
Le 2e paramètre indique à quel champ appartient la réponse. Le troisième indique la correction, mais ce n'est plus simplement `"ng"` pour faux ou `nw` pour juste, mais une valeur numérique. La logique se passe dans la fonction `exo_ajouterReponse(...)` ([source](https://gitlab.tetras-libre.fr/macao/macao-legacy/blob/main/Basilisk/MACAO/macao_3/MosMtr/scripts/contenu/ClasseExerciceTAT.js#L75)) Le 2e paramètre indique à quel champ appartient la réponse. Le troisième indique la correction, mais ce n'est plus simplement `"ng"` pour faux ou `nw` pour juste, mais une valeur numérique. La logique se passe dans la fonction `exo_ajouterReponse(...)` ([source](https://gitlab.tetras-libre.fr/macao/macao-legacy/blob/main/Basilisk/MACAO/macao_3/MosMtr/scripts/contenu/ClasseExerciceTAT.js#L75))
```js ```js
function exo_ajouterReponse(lid, num, correction, txt) { function exo_ajouterReponse(lid, num, correction, txt) {
var res = decodeX(txt); // décodage du libellé var res = decodeX(txt); // décodage du libellé
// On a un "decalY" qui est la parité (modulo 2) du nombre de trous + le score total // On a un "decalY" qui est la parité (modulo 2) du nombre de trous + le score total
var decalY = (this.tabChamps.length + this.scoreTotal) % 2; var decalY = (this.tabChamps.length + this.scoreTotal) % 2;
// On calcule un "reste" à partir du numéro de question et de la valeur de "correction" // On calcule un "reste" à partir du numéro de question et de la valeur de "correction"
var reste = correction - num * 2 - 1; var reste = correction - num * 2 - 1;
// On décrémente le "reste" si decalY vaut 1 // On décrémente le "reste" si decalY vaut 1
// or decalY vaut 0 ou 1, donc ça revient à `reste = reste - decalY` // or decalY vaut 0 ou 1, donc ça revient à `reste = reste - decalY`
if (decalY == 1) { if (decalY == 1) {
reste--; reste--;
} }
// La réponse est correcte (CODE_V) si le reste vaut -1 // La réponse est correcte (CODE_V) si le reste vaut -1
if (reste == -1) { if (reste == -1) {
correction = CODE_V; correction = CODE_V;
} else { } else {
correction = CODE_F; correction = CODE_F;
} }
this.tabReponses[this.tabReponses.length] = new ChampTrou(lid, num, res, correction); this.tabReponses[this.tabReponses.length] = new ChampTrou(lid, num, res, correction);
} }
``` ```
La réponse ajoutée est correcte si le `reste` vaut -1. La réponse ajoutée est correcte si le `reste` vaut -1.
``` ```
reste == -1 reste == -1
correction - 2*num - decalY - 1 == -1 correction - 2*num - decalY - 1 == -1
correction - 2*num - decalY == 0 correction - 2*num - decalY == 0
correction == 2*num + decalY correction == 2*num + decalY
correction == 2*num + (nChamps + scoreTotal) % 2 correction == 2*num + (nChamps + scoreTotal) % 2
``` ```
On a donc besoin d'extraire en plus le nombre de champs et le `scoreTotal` pour déterminer si chaque réponse est vraie ou fausse. On a donc besoin d'extraire en plus le nombre de champs et le `scoreTotal` pour déterminer si chaque réponse est vraie ou fausse.
\ No newline at end of file
### ExerciceGD
Il n'y a qu'un seul ExerciceGD dans macao_3, plus simple à extraire manuellement.
\ No newline at end of file