JSON complet du syllabus + un gabarit d’énoncés xAPI (10 verbes usuels) et un wireframe Odoo
Parfait — voici exactement ce que vous avez demandé, en trois blocs prêts à l’emploi.
(Format FR, “lean”, copiable tel quel.)
1) Schéma JSON complet du syllabus
1.1 – JSON Schema (Draft 2020-12)
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://exemple.org/syllabus.schema.json", "title": "Syllabus", "type": "object", "properties": { "syllabus_id": { "type": "string" }, "title": { "type": "string" }, "version": { "type": "string" }, "language": { "type": "string", "enum": ["fr", "en"] }, "tracks": { "type": "array", "items": { "type": "object", "properties": { "track_id": { "type": "string" }, "title": { "type": "string" }, "subject": { "type": "string" }, "weight": { "type": "number" }, "modules": { "type": "array", "items": { "type": "object", "properties": { "module_id": { "type": "string" }, "title": { "type": "string" }, "prerequisites": { "type": "array", "items": { "type": "string" }, "default": [] }, "items": { "type": "array", "items": { "type": "object", "required": ["item_id","title","type"], "properties": { "item_id": { "type": "string" }, "title": { "type": "string" }, "type": { "type": "string", "enum": ["video","lecture","exercise","quiz","project","lab","notebook"] }, "weight": { "type": "number", "default": 1 }, "duration_minutes": { "type": "number" }, "khan_url": { "type": "string", "format": "uri" }, "notebooklm_id": { "type": "string" }, "resources": { "type": "array", "items": { "type": "object", "properties": { "title": { "type": "string" }, "url": { "type": "string", "format": "uri" }, "license": { "type": "string" } } } }, "objectives": { "type": "array", "items": { "type": "string" } }, "outcomes": { "type": "array", "items": { "type": "string" } }, "assessment": { "type": "object", "properties": { "passing_score": { "type": "number" }, "max_score": { "type": "number" }, "rubric_url": { "type": "string", "format": "uri" } } } } } } }, "required": ["module_id","title","items"] } } }, "required": ["track_id","title","modules"] } } }, "required": ["syllabus_id","title","version","language","tracks"] }
1.2 – Exemple minimal conforme
{ "syllabus_id": "SYL-2025-MATH", "title": "Math – Cycle fondamental", "version": "1.0.0", "language": "fr", "tracks": [ { "track_id": "T-MATH-A", "title": "Algèbre", "subject": "Math", "weight": 40, "modules": [ { "module_id": "M-ALG-01", "title": "Équations du 1er degré", "prerequisites": [], "items": [ { "item_id": "I-ALG-01-VID", "title": "Intro vidéo", "type": "video", "duration_minutes": 8, "khan_url": "https://www.khanacademy.org/...", "objectives": ["Comprendre la forme ax+b=c"], "outcomes": ["Résoudre des équations simples"] }, { "item_id": "I-ALG-01-QZ", "title": "Quiz de vérification", "type": "quiz", "weight": 2, "assessment": { "passing_score": 0.7, "max_score": 1 } }, { "item_id": "I-ALG-01-NB", "title": "Notebook d’étude", "type": "notebook", "notebooklm_id": "nlm_abc123" } ] } ] } ] }
2) Gabarit d’énoncés xAPI (10 verbes usuels)
Remplacez les accolades {{...}} par vos valeurs runtime.
Namespace verbes : utilisez ceux de l’ADL quand ils existent ; sinon, un URI stable à vous.
- initialized
{ "actor": {"mbox":"mailto:{{email}}"}, "verb": {"id":"http://adlnet.gov/expapi/verbs/initialized","display":{"fr":"a initialisé"}}, "object": {"id":"urn:item:{{item_id}}","definition":{"name":{"fr":"{{item_title}}"}}}, "context": {"contextActivities":{"parent":[{"id":"urn:module:{{module_id}}"}]}} }
- experienced (consulté)
{ "actor":{"mbox":"mailto:{{email}}"}, "verb":{"id":"http://adlnet.gov/expapi/verbs/experienced","display":{"fr":"a consulté"}}, "object":{"id":"urn:item:{{item_id}}"}, "result":{"duration":"PT{{minutes}}M"} }
- attempted
{ "actor":{"mbox":"mailto:{{email}}"}, "verb":{"id":"http://adlnet.gov/expapi/verbs/attempted","display":{"fr":"a tenté"}}, "object":{"id":"urn:item:{{item_id}}"} }
- answered
{ "actor":{"mbox":"mailto:{{email}}"}, "verb":{"id":"http://adlnet.gov/expapi/verbs/answered","display":{"fr":"a répondu"}}, "object":{"id":"urn:item:{{item_id}}#q{{question_id}}"}, "result":{"response":"{{raw_answer}}","success":{{true_false}}} }
- passed
{ "actor":{"mbox":"mailto:{{email}}"}, "verb":{"id":"http://adlnet.gov/expapi/verbs/passed","display":{"fr":"a réussi"}}, "object":{"id":"urn:item:{{item_id}}"}, "result":{"score":{"raw":{{raw}},"max":{{max}},"scaled":{{scaled}}},"success":true} }
- failed
{ "actor":{"mbox":"mailto:{{email}}"}, "verb":{"id":"http://adlnet.gov/expapi/verbs/failed","display":{"fr":"a échoué"}}, "object":{"id":"urn:item:{{item_id}}"}, "result":{"score":{"raw":{{raw}},"max":{{max}},"scaled":{{scaled}}},"success":false} }
- completed
{ "actor":{"mbox":"mailto:{{email}}"}, "verb":{"id":"http://adlnet.gov/expapi/verbs/completed","display":{"fr":"a terminé"}}, "object":{"id":"urn:item:{{item_id}}"}, "result":{"completion":true,"duration":"PT{{minutes}}M"} }
- progressed (avancement)
{ "actor":{"mbox":"mailto:{{email}}"}, "verb":{"id":"http://adlnet.gov/expapi/verbs/progressed","display":{"fr":"a progressé"}}, "object":{"id":"urn:module:{{module_id}}"}, "result":{"extensions":{"https://exemple.org/xapi/progress":{{percent_0_1}}}} }
- mastered (maîtrisé – verbe custom)
{ "actor":{"mbox":"mailto:{{email}}"}, "verb":{"id":"https://exemple.org/xapi/verbs/mastered","display":{"fr":"a maîtrisé"}}, "object":{"id":"urn:objective:{{objective_id}}","definition":{"name":{"fr":"{{objective_title}}"}}}, "result":{"success":true,"score":{"scaled":1}} }
- suspended / resumed (pause/reprise)
{ "actor":{"mbox":"mailto:{{email}}"}, "verb":{"id":"http://adlnet.gov/expapi/verbs/suspended","display":{"fr":"a mis en pause"}}, "object":{"id":"urn:item:{{item_id}}"}, "result":{"extensions":{"https://exemple.org/xapi/state":"bookmark-{{cursor}}"}} }
{ "actor":{"mbox":"mailto:{{email}}"}, "verb":{"id":"http://adlnet.gov/expapi/verbs/resumed","display":{"fr":"a repris"}}, "object":{"id":"urn:item:{{item_id}}"}, "context":{"extensions":{"https://exemple.org/xapi/state":"bookmark-{{cursor}}"}} }
3) Wireframe “lean” du dashboard dans Odoo
3.1 – Principe UX (1 écran, 2 niveaux)
- Header (élève) : Nom, Classe/Groupe, Score global (0–100), Temps cumulé (semaine), % progression (barre).
- Vue “Jour / Semaine / Mois” (3 boutons).
-
4 blocs (une ligne, responsive) :
- Projets / Quiz en cours (liste compacte : titre, deadline, statut, bouton “Reprendre”).
- Modules (progress bar par module + score).
- Activité (sparklines : minutes/jour, sessions réussies vs non réussies).
- Raccourcis (Khan / NotebookLM / Derniers fichiers).
3.2 – Champs (modèle minimal)
| Modèle | Champ | Type | Note |
|---|---|---|---|
| elearning.student.progress | student_id | many2one(res.partner) | Élève |
| period | selection(day/week/month) | Filtre | |
| score_scaled | float | 0→1 | |
| time_minutes | integer | Somme période | |
| success_rate | float | réussites / tentatives | |
| modules_progress_json | text | [{module_id, title, progress_0_1, score}] | |
| todos_json | text | [{item_id, title, deadline, status}] | |
| activity_series_json | text | séries pour graph |
3.3 – Vue Kanban/Tree (XML Odoo 17 — squelette lean)
<record id="view_student_dashboard_kanban" model="ir.ui.view"> <field name="name">elearning.student.progress.kanban</field> <field name="model">elearning.student.progress</field> <field name="arch" type="xml"> <kanban class="o_kanban_small_column"> <templates> <t t-name="kanban-box"> <div class="o_kanban_record"> <div class="o_kanban_header"> <field name="student_id"/> <div> <span>Score:</span> <t t-esc="Math.round(record.score_scaled.value*100)"/>% </div> <div>Temps: <t t-esc="record.time_minutes.value"/> min</div> </div> <div class="o_progress"> <div class="o_progressbar" t-att-style="'width:'+ (record.success_rate.value*100) + '%;'"/> </div> <div class="o_kanban_section"> <strong>À faire</strong> <t t-set="todos" t-value="JSON.parse(record.todos_json.value || '[]')"/> <ul> <t t-foreach="todos" t-as="t"> <li><t t-esc="t.title"/> — <t t-esc="t.status"/> — <t t-esc="t.deadline"/></li> </t> </ul> </div> <div class="o_kanban_section"> <strong>Modules</strong> <t t-set="mods" t-value="JSON.parse(record.modules_progress_json.value || '[]')"/> <ul> <t t-foreach="mods" t-as="m"> <li><t t-esc="m.title"/> — <t t-esc="Math.round(m.progress_0_1*100)"/>%</li> </t> </ul> </div> <div class="o_kanban_section"> <a type="action" name="%(action_open_khan)s">Khan</a> · <a type="action" name="%(action_open_notebooklm)s">NotebookLM</a> </div> </div> </t> </templates> </kanban> </field> </record>
3.4 – Indicateurs (KPI) Odoo à afficher
- KPI 1 : Score global (moyenne pondérée weight des items).
- KPI 2 : Temps cumulé (semaine en cours).
- KPI 3 : Taux de réussite (passed / attempted).
- KPI 4 : Modules terminés / totaux.
Petits plus utiles
- Mapping xAPI → Odoo : un cron récupère du LRS les statements (actor = email élève) et met à jour elearning.student.progress.
- Liens directs : stockez khan_url et notebooklm_id au niveau des items du syllabus et exposez-les dans les “Raccourcis”.
- Versioning : incrémentez syllabus.version et gardez l’historique (utile pour cohortes).
Parfait — voici exactement ce que vous avez demandé, en trois blocs prêts à l’emploi.
(Format FR, “lean”, copiable tel quel.)
1) Schéma JSON complet du syllabus
1.1 – JSON Schema (Draft 2020-12)
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://exemple.org/syllabus.schema.json", "title": "Syllabus", "type": "object", "properties": { "syllabus_id": { "type": "string" }, "title": { "type": "string" }, "version": { "type": "string" }, "language": { "type": "string", "enum": ["fr", "en"] }, "tracks": { "type": "array", "items": { "type": "object", "properties": { "track_id": { "type": "string" }, "title": { "type": "string" }, "subject": { "type": "string" }, "weight": { "type": "number" }, "modules": { "type": "array", "items": { "type": "object", "properties": { "module_id": { "type": "string" }, "title": { "type": "string" }, "prerequisites": { "type": "array", "items": { "type": "string" }, "default": [] }, "items": { "type": "array", "items": { "type": "object", "required": ["item_id","title","type"], "properties": { "item_id": { "type": "string" }, "title": { "type": "string" }, "type": { "type": "string", "enum": ["video","lecture","exercise","quiz","project","lab","notebook"] }, "weight": { "type": "number", "default": 1 }, "duration_minutes": { "type": "number" }, "khan_url": { "type": "string", "format": "uri" }, "notebooklm_id": { "type": "string" }, "resources": { "type": "array", "items": { "type": "object", "properties": { "title": { "type": "string" }, "url": { "type": "string", "format": "uri" }, "license": { "type": "string" } } } }, "objectives": { "type": "array", "items": { "type": "string" } }, "outcomes": { "type": "array", "items": { "type": "string" } }, "assessment": { "type": "object", "properties": { "passing_score": { "type": "number" }, "max_score": { "type": "number" }, "rubric_url": { "type": "string", "format": "uri" } } } } } } }, "required": ["module_id","title","items"] } } }, "required": ["track_id","title","modules"] } } }, "required": ["syllabus_id","title","version","language","tracks"] }
1.2 – Exemple minimal conforme
{ "syllabus_id": "SYL-2025-MATH", "title": "Math – Cycle fondamental", "version": "1.0.0", "language": "fr", "tracks": [ { "track_id": "T-MATH-A", "title": "Algèbre", "subject": "Math", "weight": 40, "modules": [ { "module_id": "M-ALG-01", "title": "Équations du 1er degré", "prerequisites": [], "items": [ { "item_id": "I-ALG-01-VID", "title": "Intro vidéo", "type": "video", "duration_minutes": 8, "khan_url": "https://www.khanacademy.org/...", "objectives": ["Comprendre la forme ax+b=c"], "outcomes": ["Résoudre des équations simples"] }, { "item_id": "I-ALG-01-QZ", "title": "Quiz de vérification", "type": "quiz", "weight": 2, "assessment": { "passing_score": 0.7, "max_score": 1 } }, { "item_id": "I-ALG-01-NB", "title": "Notebook d’étude", "type": "notebook", "notebooklm_id": "nlm_abc123" } ] } ] } ] }
2) Gabarit d’énoncés xAPI (10 verbes usuels)
Remplacez les accolades {{...}} par vos valeurs runtime.
Namespace verbes : utilisez ceux de l’ADL quand ils existent ; sinon, un URI stable à vous.
- initialized
{ "actor": {"mbox":"mailto:{{email}}"}, "verb": {"id":"http://adlnet.gov/expapi/verbs/initialized","display":{"fr":"a initialisé"}}, "object": {"id":"urn:item:{{item_id}}","definition":{"name":{"fr":"{{item_title}}"}}}, "context": {"contextActivities":{"parent":[{"id":"urn:module:{{module_id}}"}]}} }
- experienced (consulté)
{ "actor":{"mbox":"mailto:{{email}}"}, "verb":{"id":"http://adlnet.gov/expapi/verbs/experienced","display":{"fr":"a consulté"}}, "object":{"id":"urn:item:{{item_id}}"}, "result":{"duration":"PT{{minutes}}M"} }
- attempted
{ "actor":{"mbox":"mailto:{{email}}"}, "verb":{"id":"http://adlnet.gov/expapi/verbs/attempted","display":{"fr":"a tenté"}}, "object":{"id":"urn:item:{{item_id}}"} }
- answered
{ "actor":{"mbox":"mailto:{{email}}"}, "verb":{"id":"http://adlnet.gov/expapi/verbs/answered","display":{"fr":"a répondu"}}, "object":{"id":"urn:item:{{item_id}}#q{{question_id}}"}, "result":{"response":"{{raw_answer}}","success":{{true_false}}} }
- passed
{ "actor":{"mbox":"mailto:{{email}}"}, "verb":{"id":"http://adlnet.gov/expapi/verbs/passed","display":{"fr":"a réussi"}}, "object":{"id":"urn:item:{{item_id}}"}, "result":{"score":{"raw":{{raw}},"max":{{max}},"scaled":{{scaled}}},"success":true} }
- failed
{ "actor":{"mbox":"mailto:{{email}}"}, "verb":{"id":"http://adlnet.gov/expapi/verbs/failed","display":{"fr":"a échoué"}}, "object":{"id":"urn:item:{{item_id}}"}, "result":{"score":{"raw":{{raw}},"max":{{max}},"scaled":{{scaled}}},"success":false} }
- completed
{ "actor":{"mbox":"mailto:{{email}}"}, "verb":{"id":"http://adlnet.gov/expapi/verbs/completed","display":{"fr":"a terminé"}}, "object":{"id":"urn:item:{{item_id}}"}, "result":{"completion":true,"duration":"PT{{minutes}}M"} }
- progressed (avancement)
{ "actor":{"mbox":"mailto:{{email}}"}, "verb":{"id":"http://adlnet.gov/expapi/verbs/progressed","display":{"fr":"a progressé"}}, "object":{"id":"urn:module:{{module_id}}"}, "result":{"extensions":{"https://exemple.org/xapi/progress":{{percent_0_1}}}} }
- mastered (maîtrisé – verbe custom)
{ "actor":{"mbox":"mailto:{{email}}"}, "verb":{"id":"https://exemple.org/xapi/verbs/mastered","display":{"fr":"a maîtrisé"}}, "object":{"id":"urn:objective:{{objective_id}}","definition":{"name":{"fr":"{{objective_title}}"}}}, "result":{"success":true,"score":{"scaled":1}} }
- suspended / resumed (pause/reprise)
{ "actor":{"mbox":"mailto:{{email}}"}, "verb":{"id":"http://adlnet.gov/expapi/verbs/suspended","display":{"fr":"a mis en pause"}}, "object":{"id":"urn:item:{{item_id}}"}, "result":{"extensions":{"https://exemple.org/xapi/state":"bookmark-{{cursor}}"}} }
{ "actor":{"mbox":"mailto:{{email}}"}, "verb":{"id":"http://adlnet.gov/expapi/verbs/resumed","display":{"fr":"a repris"}}, "object":{"id":"urn:item:{{item_id}}"}, "context":{"extensions":{"https://exemple.org/xapi/state":"bookmark-{{cursor}}"}} }
3) Wireframe “lean” du dashboard dans Odoo
3.1 – Principe UX (1 écran, 2 niveaux)
- Header (élève) : Nom, Classe/Groupe, Score global (0–100), Temps cumulé (semaine), % progression (barre).
- Vue “Jour / Semaine / Mois” (3 boutons).
-
4 blocs (une ligne, responsive) :
- Projets / Quiz en cours (liste compacte : titre, deadline, statut, bouton “Reprendre”).
- Modules (progress bar par module + score).
- Activité (sparklines : minutes/jour, sessions réussies vs non réussies).
- Raccourcis (Khan / NotebookLM / Derniers fichiers).
3.2 – Champs (modèle minimal)
| Modèle | Champ | Type | Note |
|---|---|---|---|
| elearning.student.progress | student_id | many2one(res.partner) | Élève |
| period | selection(day/week/month) | Filtre | |
| score_scaled | float | 0→1 | |
| time_minutes | integer | Somme période | |
| success_rate | float | réussites / tentatives | |
| modules_progress_json | text | [{module_id, title, progress_0_1, score}] | |
| todos_json | text | [{item_id, title, deadline, status}] | |
| activity_series_json | text | séries pour graph |
3.3 – Vue Kanban/Tree (XML Odoo 17 — squelette lean)
<record id="view_student_dashboard_kanban" model="ir.ui.view"> <field name="name">elearning.student.progress.kanban</field> <field name="model">elearning.student.progress</field> <field name="arch" type="xml"> <kanban class="o_kanban_small_column"> <templates> <t t-name="kanban-box"> <div class="o_kanban_record"> <div class="o_kanban_header"> <field name="student_id"/> <div> <span>Score:</span> <t t-esc="Math.round(record.score_scaled.value*100)"/>% </div> <div>Temps: <t t-esc="record.time_minutes.value"/> min</div> </div> <div class="o_progress"> <div class="o_progressbar" t-att-style="'width:'+ (record.success_rate.value*100) + '%;'"/> </div> <div class="o_kanban_section"> <strong>À faire</strong> <t t-set="todos" t-value="JSON.parse(record.todos_json.value || '[]')"/> <ul> <t t-foreach="todos" t-as="t"> <li><t t-esc="t.title"/> — <t t-esc="t.status"/> — <t t-esc="t.deadline"/></li> </t> </ul> </div> <div class="o_kanban_section"> <strong>Modules</strong> <t t-set="mods" t-value="JSON.parse(record.modules_progress_json.value || '[]')"/> <ul> <t t-foreach="mods" t-as="m"> <li><t t-esc="m.title"/> — <t t-esc="Math.round(m.progress_0_1*100)"/>%</li> </t> </ul> </div> <div class="o_kanban_section"> <a type="action" name="%(action_open_khan)s">Khan</a> · <a type="action" name="%(action_open_notebooklm)s">NotebookLM</a> </div> </div> </t> </templates> </kanban> </field> </record>
3.4 – Indicateurs (KPI) Odoo à afficher
- KPI 1 : Score global (moyenne pondérée weight des items).
- KPI 2 : Temps cumulé (semaine en cours).
- KPI 3 : Taux de réussite (passed / attempted).
- KPI 4 : Modules terminés / totaux.
Petits plus utiles
- Mapping xAPI → Odoo : un cron récupère du LRS les statements (actor = email élève) et met à jour elearning.student.progress.
- Liens directs : stockez khan_url et notebooklm_id au niveau des items du syllabus et exposez-les dans les “Raccourcis”.
- Versioning : incrémentez syllabus.version et gardez l’historique (utile pour cohortes).
Souhaitez-vous que je vous génère les fichiers (JSON Schema + exemple + squelette XML) en téléchargement et, si besoin, un CSV Odoo minimal pour importer quelques modules/items de test ?
Vous avez dit :
oui
ChatGPT a dit :
Parfait — j’ai généré les 4 fichiers prêts à l’emploi :
- Télécharger syllabus.schema.json
- Télécharger syllabus.example.json
- Télécharger xapi.templates.json
- Télécharger odoo_dashboard_wireframe.xml
Souhaitez-vous aussi un CSV d’import Odoo eLearning de démo (modules/items) et/ou un script Python qui envoie ces énoncés xAPI vers un LRS (endpoint + clé) ?