# Guide de rédaction des questions — QCM v2 (modèles paramétriques)

Ce guide explique le format YAML des questions de la v2. La grande nouveauté :
les questions sont des **modèles génératifs**. Vous écrivez UNE question avec des
variables et des expressions calculées, et la plateforme génère des **centaines de
variantes** — valeurs tirées au hasard, propositions recalculées, 4 propositions
affichées parmi votre pool.

## Table des matières

1. [L'idée en 30 secondes](#lidée-en-30-secondes)
2. [Structure d'un modèle](#structure-dun-modèle)
3. [Variables et expressions {{ }}](#variables-et-expressions--)
4. [Types de questions (A, K-Prim)](#types-de-questions)
5. [Le pool de propositions](#le-pool-de-propositions)
6. [Math inline (KaTeX)](#math-inline-katex)
7. [Schémas (Typst + CeTZ)](#schémas-typst--cetz)
8. [Import par lot](#import-par-lot)
9. [Erreurs fréquentes](#erreurs-fréquentes)

## L'idée en 30 secondes

```yaml
id: distance_vitesse_temps
subject: A
type: A
variables:
  v: [10, 20, 30, 40]        # km/h — une valeur est tirée au hasard
  t: [1, 2, 3, 4]            # h
statement: "Une voiture roule à {{v}} km/h pendant {{t}} h. Quelle distance parcourt-elle ?"
propositions:
  - { text: "{{ v * t }} km",     correct: true }    # la bonne formule
  - { text: "{{ v + t }} km",     correct: false }   # erreur classique
  - { text: "{{ v * t / 2 }} km", correct: false }
  - { text: "{{ v / t }} km",     correct: false }
  # ... visez 12+ propositions, 4 seront affichées
```

À chaque affichage : le serveur tire `v` et `t`, recalcule toutes les `{{ }}`,
choisit 4 propositions distinctes (type A : exactement 1 correcte), les mélange,
et **n'envoie jamais** au navigateur laquelle est la bonne.

## Structure d'un modèle

| Champ | Requis | Description |
|---|---|---|
| `id` | ✅ | Slug unique : minuscules, chiffres, `_` ou `-`. Ex : `chute_libre_h` |
| `subject` | ✅ | Code du sujet (A, B, C…) |
| `type` | ✅ | `A` ou `K-Prim` (voir plus bas) |
| `statement` | ✅ | L'énoncé (math `$...$`, valeurs `{{ }}`) |
| `propositions` | ✅ | Le pool de propositions (voir plus bas) |
| `title` | — | Titre court pour les listes de l'admin |
| `show` | — | Nombre de propositions affichées (défaut : 4) |
| `variables` | — | Variables aléatoires ; omettre pour une question statique |
| `correction` | — | Explication générale montrée après la réponse |
| `diagram` | — | Source Typst/CeTZ du schéma (voir plus bas) |
| `comment` | — | Note interne, jamais montrée aux étudiants |

Une question **statique** (sans variables) est simplement un modèle sans champ
`variables` — le format reste le même.

## Variables et expressions {{ }}

### Déclarer des variables

```yaml
variables:
  v: [10, 20, 30, 40]                          # forme courte
  m: { values: [0.5, 1, 1.5], unit: "kg" }     # forme longue (unit = documentation)
```

Chaque variable est une **liste de valeurs** ; une valeur est tirée au hasard par
affichage. Choisissez des valeurs qui donnent des résultats « propres ».

### Utiliser des expressions

`{{ ... }}` est recalculé à chaque affichage, dans l'énoncé, les propositions,
les explications et la correction :

- `{{ v }}` — la valeur de la variable
- `{{ v * t }}` — n'importe quelle formule arithmétique : `+ - * / % ^ ( )`
- `{{ round(v / t, 1) }}` — contrôle du nombre de décimales affichées
  (`round(x, 2)` affiche toujours 2 décimales, ex : `3.00`)

Fonctions disponibles : `round(x, n)`, `sqrt`, `abs`, `pow(a, b)`, `exp`, `ln`,
`log10`, `sin`, `cos`, `tan`, `asin`, `acos`, `atan`, `floor`, `ceil`,
`min(...)`, `max(...)`. Constantes : `pi`, `e`.
Attention : `-v^2` se lit `-(v^2)`, comme en mathématiques.

⚠️ `{{v}}` (valeur calculée) et `$v$` (symbole mathématique) sont deux choses
différentes : « roule à {{v}} km/h » affiche un nombre ; « la vitesse $\vec{v}$ »
affiche le symbole. Les accolades LaTeX simples (`\vec{v}`) ne sont pas touchées —
seules les **doubles** accolades sont interprétées.

## Types de questions

- **Type A** — une seule bonne réponse. 4 propositions affichées : exactement
  1 correcte + 3 distracteurs tirés du pool. Score : 1 ou 0.
- **Type K-Prim** — l'étudiant juge chaque proposition affichée **vraie ou
  fausse**. Barème : tout juste → 1 point ; une seule erreur → 0.5 ; sinon → 0.
  (`type: K`, ancien alias, est accepté à l'import et normalisé en K-Prim.)

## Le pool de propositions

```yaml
propositions:
  - text: "{{ v * t }} km"
    correct: true
    explanation: "$d = v \\cdot t$"          # montrée dans la correction
  - text: "{{ v + t }} km"
    correct: false
    explanation: "Unités incompatibles."
```

Règles :

- `correct` est **fixe** : la proposition correcte est la *bonne formule* (juste
  pour toute valeur des variables) ; les distracteurs sont des *formules fausses*
  (erreurs classiques d'étudiants). Pas de « correct si v > 20 » — c'est voulu.
- **Type A : visez 12+ propositions** (1–3 correctes équivalentes, le reste en
  distracteurs). Plus le pool est grand, moins l'étudiant peut mémoriser.
- Le serveur garantit que les propositions affichées ont des **textes distincts** :
  si deux formules donnent le même nombre pour un tirage, il retire les dés —
  d'où l'intérêt de valeurs de variables bien choisies.
- Écrivez une `explanation` par proposition : c'est ce qui fait la valeur
  pédagogique de la correction.

## Math inline (KaTeX)

La notation est le LaTeX habituel : `$\vec{v}$`, `$\frac{1}{2}mv^2$`,
`$$...$$` pour le mode display. Le rendu est fait par **KaTeX** (plus de MathJax) :
instantané, sans sauts de mise en page, y compris sur mobile. En YAML, utilisez
des guillemets simples `'...'` ou un bloc `|` pour ne pas doubler les backslashs.

## Schémas (Typst + CeTZ)

Les schémas sont écrits en **Typst + CeTZ** (plus de TikZ/PNG) et rendus en
**SVG** — nets à tous les zooms. Règle d'or : gardez le schéma **symbolique**
(étiquettes `$arrow(v)$`, points `A`, `B`), **pas de valeurs numériques** — ainsi
le même SVG sert à toutes les variantes de la question.

```yaml
diagram: |
  #import "@preview/cetz:0.4.2"
  #set page(width: auto, height: auto, margin: 6pt)
  #cetz.canvas(length: 1cm, {
    import cetz.draw: *
    circle((0,0), radius: 3)
    content((1, 0.2), $A$)
    content((2.5, 0.7), $B$)
  })
```

Note : dans les étiquettes CeTZ, la math est en syntaxe **Typst**
(`$arrow(v)$`, pas `\vec{v}`).

## Import par lot

Un fichier peut contenir **un seul modèle** (comme ci-dessus) ou une **liste de
modèles** :

```yaml
- id: question_un
  subject: A
  type: A
  statement: "..."
  propositions: [...]

- id: question_deux
  subject: B
  type: K-Prim
  statement: "..."
  propositions: [...]
```

Chaque modèle est validé à l'import (structure, expressions, variables déclarées,
génération possible) ; les erreurs indiquent le champ fautif.

## Erreurs fréquentes

| Erreur | Cause |
|---|---|
| `Variable « x » utilisée mais non déclarée` | `{{x}}` dans un texte, mais pas de `x:` sous `variables:` |
| `Division by zero` | Une valeur de variable rend un dénominateur nul — retirez-la de la liste |
| `impossible de générer 4 propositions distinctes` | Des formules coïncident trop souvent (ex : `v*t` et `v+t` avec v=t=2) — choisissez des valeurs qui les séparent |
| `Type A : il faut au moins une proposition correcte` | Aucun `correct: true` dans le pool |
| Backslashs cassés | Utilisez `'...'` (guillemets simples) ou un bloc `\|` pour le LaTeX |

Des exemples complets et validés se trouvent dans `admin/templates/examples/`
(le bouton « Télécharger l'exemple » de la console en fournit un).
