📐
Maths Trainer
Documentation & Wiki
← Retour à l'appli

Aperçu de Maths Trainer

Maths Trainer est un outil de révision 100 % local pour les lycéens de Terminale. Il génère des exercices aléatoires à partir de modules écrits en JavaScript, sans serveur ni connexion requise — il suffit d'ouvrir index.html.

Utiliser Maths Trainer sur ton ordinateur
Pour ajouter des modules, créer des classes ou utiliser le script Python, tu dois télécharger le projet en local.
Télécharger sur GitHub
🗂️
Modules JS
Un fichier par chapitre — génère des exercices aléatoires
🐍
Script Python
Importation en 3 clics sans toucher au code
🤖
IA + mega-prompt
Génère le module JS depuis ta description

Structure du projet

Maths trainer/
├── index.html              ← L'application (ouvrir dans le navigateur)
├── wiki.html               ← Cette documentation
├── import_module.py        ← Script d'import graphique (Python)
├── assets/
│   ├── css/style.css
│   └── js/
│       ├── engine.js       ← Utilitaires maths (randInt, gcd…)
│       ├── registry.js     ← Arborescence sidebar (à modifier pour ajouter un chapitre)
│       └── app.js          ← Logique Alpine.js
└── modules/
    ├── maths-spe/          ← Modules Terminale Spé
    │   ├── pgcd.js
    │   └── ...
    └── maths-expertes/     ← Modules Maths Expertes
        └── gauss-jordan.js

Outil d'import Python

C'est la méthode recommandée pour les professeurs — pas besoin de toucher au code. Le script Python affiche un formulaire graphique et effectue automatiquement les trois modifications nécessaires.

⚠ Prérequis

Le script Python fait partie du projet — il faut d'abord télécharger le projet sur GitHub et l'extraire sur ton ordinateur. Le script ne fonctionne pas sur la version en ligne.

⬇ Télécharger le projet (GitHub) Python 3 requis — gratuit sur python.org

Comment lancer le script

🚮 Windows

Double-clic sur import_module.py
(Python doit être installé avec Add to PATH coché)

🍎 Mac

Clic droit → Ouvrir avec → Python Launcher
ou dans le Terminal : python3 import_module.py

🐧 Linux

Dans le Terminal :
python3 import_module.py

⚠ Important

Le fichier import_module.py doit se trouver dans le dossier racine du projet (le même dossier que index.html).

Les 3 étapes du formulaire

1
Sélectionner le fichier JS

Clique sur Parcourir… et ouvre le fichier .js généré par l'IA. Le script lit automatiquement l'identifiant, le titre du chapitre et la notion.

2
Choisir la spécialité / classe

Sélectionne dans la liste la spécialité cible. Si elle n'existe pas encore, clique sur + Nouvelle spécialité.

3
Choisir la section

Sélectionne la section thématique (ex. Analyse, Algèbre…). Si elle n'existe pas, clique sur + Nouvelle section.

Clique enfin sur ⬇ Importer le module. Le script :

  • Copie le fichier JS dans le bon sous-dossier de modules/
  • Ajoute l'entrée dans assets/js/registry.js (sidebar)
  • Ajoute la balise <script> dans index.html

Créer une nouvelle classe / spécialité

Une spécialité (ou classe) est le premier niveau de l'arborescence : par exemple Maths Spé — Terminale, 1ère Spé, Tronc Commun… Elle apparaît comme un grand titre dans la barre latérale de l'appli.

Via le script Python (recommandé)

  1. Lance import_module.py
  2. À l'Étape 2, clique sur + Nouvelle spécialité
  3. Remplis les champs :
    ChampExempleRôle
    Nom *1ère SpéTitre affiché dans la sidebar
    Sous-titrePremière — SpécialitéPetit texte gris sous le titre
    Icône (emoji)📘Icône à gauche du titre
  4. L'identifiant est généré automatiquement (ex. 1ere-spe)
  5. Clique ✓ Créer la spécialité

Manuellement dans registry.js

Dans assets/js/registry.js, ajoute un bloc à la fin du tableau tree: :

// Dans registry.js → tree: [ ..., ← ajouter ici
{
  id: '1ere-spe',
  label: '1ère Spé',
  sublabel: 'Première — Spécialité',
  icon: '📘',
  open: false,
  sections: [],   // on ajoutera des sections ensuite
},
Tip

L'id doit être unique, en minuscules sans accents ni espaces (seuls les tirets sont autorisés).

Créer une nouvelle section

Une section est un regroupement thématique de chapitres à l'intérieur d'une spécialité — par exemple Analyse, Algèbre & Arithmétique, Probabilités

Via le script Python (recommandé)

  1. Sélectionne d'abord la spécialité cible à l'Étape 2
  2. À l'Étape 3, clique sur + Nouvelle section
  3. Saisis le nom de la section (ex. Probabilités)
  4. L'ID est généré : 1ere-spe-probabilites
  5. Clique ✓ Créer la section

Manuellement dans registry.js

// Dans la spécialité cible, dans son tableau sections: [ ..., ← ajouter ici
{
  id: '1ere-spe-probabilites',
  label: 'Probabilités',
  open: true,
  chapters: [],   // les modules s'ajouteront ici
},

Étape 1 — Préparer son contenu

Avant de parler à l'IA, prépare ces 6 éléments sur papier ou dans un doc :

A
Titre du chapitre
ex. : Calcul de limites — forme indéterminée ∞−∞
B
Notion travaillée (une seule phrase)
ex. : Lever une forme ∞−∞ en factorisant par le terme dominant
C
Méthode étape par étape — exactement comme tu l'écrirais au tableau
Sois précis : l'IA implémentera exactement ce que tu décris.
D
Variables aléatoires : noms, types (entier/réel), plages, contraintes
ex. : a : entier dans [2, 8], n : entier dans [2, 5]
E
Exemple d'énoncé avec de vraies valeurs numériques
F
Correction complète de cet exemple, étape par étape
Pourquoi être précis ?

L'IA est capable d'inventer une méthode correcte mais différente de la tienne. En fournissant un exemple complet, tu garantis que le code généré enseigne exactement ce que tu as prévu.

Étape 2 — Mega-prompt à donner à l'IA

Copie l'intégralité du texte ci-dessous dans ChatGPT, Claude ou toute autre IA, puis remplace les parties entre [crochets] par ton contenu.

Astuce

Utilise le bouton "Copier" en haut à droite du bloc de code, ou sélectionne tout le texte avec Ctrl+A dans la zone.

===========================================================================
Tu es un développeur JavaScript spécialisé en mathématiques de lycée (Terminale française).

Je veux que tu génères un module d'exercice pour un outil web de révision.
L'outil utilise les bibliothèques déjà chargées (KaTeX, Alpine.js).
Un objet global `Engine` est disponible avec ces utilitaires :

  Engine.randInt(min, max)           → entier aléatoire dans [min, max]
  Engine.gcd(a, b)                   → PGCD de a et b
  Engine.lcm(a, b)                   → PPCM de a et b
  Engine.reduceFraction(num, den)    → {num, den} fraction irréductible
  Engine.latexFraction(num, den)     → chaîne LaTeX : "\dfrac{n}{d}" ou "n"
  Engine.randIntWhere(min, max, fn)  → entier satisfaisant fn(v) === true
  Engine.coprimePair(minQ, maxP)     → {p, q} avec pgcd(p,q)=1 et p>q≥minQ
  Engine.euclidSteps(a, b)           → {steps, pgcd} de l'algorithme d'Euclide
  Engine.shuffle(array)              → copie mélangée du tableau

FORMAT OBLIGATOIRE — le fichier doit contenir exactement ceci :

MathsTrainer.register({
  id: 'identifiant-sans-espaces-ni-accents',
  chapitre: 'Titre affiché',
  notion: 'Une phrase décrivant ce que l\'élève apprend à faire',
  methode: [
    'Étape 1 avec $LaTeX$ si besoin.',
    'Étape 2...',
  ],
  generate() {
    const enonce = `...texte avec $LaTeX$ inline et $$LaTeX$$ en bloc...`;
    const correction = `...HTML avec $LaTeX$ et $$LaTeX$$...`;
    return { enonce, correction };
  },
});

RÈGLES LATEX DANS LES CHAÎNES JAVASCRIPT :
- Formule inline       : $formule$
- Bloc display centré  : $$formule$$
- Tout \ LaTeX devient \\ en JS  (ex: \frac → \\frac, \times → \\times)
- Saut de ligne dans aligned : \\\\ en JS
- Macros disponibles sans les redéfinir : \\pgcd  \\ppcm  \\N  \\Z  \\R  \\Q  \\C

HTML AUTORISÉ dans la correction :
  <p>texte</p>
  <strong>texte</strong>
  <div class="my-4 overflow-x-auto">$$...$$</div>      ← pour un bloc display
  <div class="result-highlight">$$résultat final$$</div>  ← encadre le résultat

IMPORTANT :
- N'invente PAS la méthode : implémente EXACTEMENT les étapes que je fournis
- Génère UNIQUEMENT le contenu du fichier JS, sans explications avant ni après
- L'id doit être en minuscules, sans espaces, sans accents (tirets autorisés)

VOICI LE CHAPITRE À IMPLÉMENTER :

CHAPITRE: [écrire le nom du chapitre ici]
NOTION: [une phrase]

MÉTHODE:
Étape 1 — [ta description]
Étape 2 — [ta description]
Étape 3 — [ta description]
(ajouter autant d'étapes que nécessaire)

VARIABLES:
[nom]: entier, plage [min, max]
[nom]: entier, plage [min, max], contrainte : [décrire]

ÉNONCÉ EXEMPLE (avec des vraies valeurs) :
[coller ici un exemple d'énoncé complet avec des valeurs concrètes]

CORRECTION EXEMPLE (de l'énoncé ci-dessus) :
[coller ici la correction complète, étape par étape]
===========================================================================

Exemple rempli

CHAPITRE: Suites géométriques — terme général
NOTION: Calculer un terme u_n connaissant u_0 et la raison q

MÉTHODE:
Étape 1 — Rappeler la formule : u_n = u_0 × q^n
Étape 2 — Substituer u_0, q et n
Étape 3 — Calculer q^n puis multiplier par u_0

VARIABLES:
u0 : entier dans [1, 10]
q  : entier dans [2, 5]
n  : entier dans [2, 5]
(contrainte : u0 × q^n ≤ 10 000 pour rester lisible)

ÉNONCÉ EXEMPLE :
Soit (u_n) une suite géométrique de premier terme u_0 = 3 et de raison q = 2.
Calculer u_4.

CORRECTION EXEMPLE :
On applique la formule : u_n = u_0 × q^n
Donc u_4 = 3 × 2^4 = 3 × 16 = 48

Étape 3 — Vérifier le code généré

Avant d'importer, vérifie rapidement que le module respecte le format :

VérificationÀ chercher dans le code
✅ Commence bien MathsTrainer.register({
✅ Champs présents id:, chapitre:, notion:, methode:, generate()
✅ Se termine bien }); seul sur la dernière ligne
✅ Méthode correcte Les étapes correspondent à ce que tu as écrit
✅ Retour valide return { enonce, correction }; dans generate()
Si quelque chose cloche

Dis à l'IA : "Relance la génération en respectant exactement la méthode que j'ai fournie, et génère uniquement le code JS sans commentaires autour."

Étape 4 — Importer le module

Deux approches : le script Python (recommandé) ou la méthode manuelle.

Avec le script Python

  1. Sauvegarde le code généré par l'IA dans un fichier .js n'importe où sur ton ordinateur
  2. Lance import_module.py
  3. Étape 1 → Parcourir… → sélectionne ton fichier
  4. Étape 2 → choisis la spécialité
  5. Étape 3 → choisis la section
  6. Clique ⬇ Importer le module

Manuellement

Voir la section Méthode manuelle ci-dessous.

Étape 5 — Tester le module

  1. Double-clique sur index.html — il s'ouvre dans le navigateur
  2. Dans la sidebar, trouve ton chapitre — il doit apparaître sans badge bientôt
  3. Clique dessus — l'exercice doit se générer
  4. Clique sur Nouvel exercice plusieurs fois (5–6 fois minimum) pour vérifier que toutes les valeurs produites sont correctes
  5. Vérifie la correction en cliquant sur Voir la correction
Test rapide de qualité

Génère ~10 exercices et vérifie : les valeurs sont-elles raisonnables ? Les calculs dans la correction sont-ils exacts ? La mise en forme est-elle propre ?

Méthode manuelle (VS Code)

Pour les utilisateurs à l'aise avec l'édition de code.

1. Créer le fichier JS

  1. Dans VS Code, ouvre le dossier Maths trainer (Fichier → Ouvrir un dossier)
  2. Dans l'arborescence, clic droit sur modules/maths-spe/Nouveau fichier
  3. Nomme-le avec l'id du module : ex. suites-geo.js
  4. Colle le code généré par l'IA → Ctrl+S

2. Ajouter la balise script dans index.html

  1. Ouvre index.html
  2. Cherche (Ctrl+F) : /MODULES
  3. Juste avant la ligne <!-- /MODULES -->, ajoute :
  <script src="modules/maths-spe/suites-geo.js"></script>
  <!-- /MODULES -->

3. Ajouter le chapitre dans registry.js

  1. Ouvre assets/js/registry.js
  2. Cherche la section cible (ex. spe-analyse)
  3. Dans son tableau chapters:, ajoute une ligne :
chapters: [
  // ... chapitres existants ...
  { id: 'suites-geo', label: 'Suites géométriques — terme général' },
],
Attention

L'id dans registry.js doit être exactement identique à l'id: déclaré dans le fichier JS du module — casse, tirets compris.

Format du module JS — référence complète

MathsTrainer.register({

  // ── Identifiant ────────────────────────────────────────────────────────
  // Même valeur que l'entrée dans registry.js.
  // Minuscules, sans espaces ni accents, tirets autorisés.
  id: 'mon-module',

  // ── Affiché dans l'interface ────────────────────────────────────────────
  chapitre: 'Titre complet affiché en haut de la page',
  notion:   'Une phrase décrivant ce que l\'élève s\'entraîne à faire.',

  // ── Méthode ─────────────────────────────────────────────────────────────
  // Tableau de strings. Chaque string = une étape numérotée.
  // Supporte HTML inline et LaTeX entre $...$ (rendu par KaTeX).
  methode: [
    'Étape 1 — reconnaître le type de $f$ : polynôme, $\\sin$, $e^x$…',
    'Étape 2 — trouver une primitive $F$ vérifiant $F\'(x) = f(x)$.',
    'Étape 3 — calculer $F(b) - F(a)$ et simplifier.',
  ],

  // ── Générateur d'exercice ────────────────────────────────────────────────
  // Appelé à chaque "Nouvel exercice".
  // Doit renvoyer EXACTEMENT { enonce, correction } (deux chaînes).
  generate() {

    // Variables aléatoires
    const a = Engine.randInt(1, 5);
    const n = Engine.randInt(2, 4);

    // Énoncé — texte avec LaTeX inline $...$
    const enonce = `Calculer $\\displaystyle\\int_0^1 ${a}x^{${n}}\\,dx$.`;

    // Correction — HTML avec LaTeX $...$ et $$...$$
    const correction =
      `<p>La primitive de $f(x) = ${a}x^{${n}}$ est
           $F(x) = ${Engine.latexFraction(a, n+1)}x^{${n+1}}$.</p>` +
      `<div class="my-4 overflow-x-auto">
         $$\\begin{aligned}
           \\int_0^1 ${a}x^{${n}}\\,dx &= \\Bigl[F(x)\\Bigr]_0^1 \\\\
                                        &= ${Engine.latexFraction(a, n+1)}
         \\end{aligned}$$
       </div>` +
      `<div class="result-highlight">$$\\text{résultat} = ${Engine.latexFraction(a, n+1)}$$</div>`;

    return { enonce, correction };
  },

});

API Engine — référence

L'objet Engine est disponible globalement dans tous les modules.

Méthode Retour Description
Engine.randInt(min, max) number Entier aléatoire dans [min, max] inclus
Engine.gcd(a, b) number PGCD de a et b (algorithme d'Euclide)
Engine.lcm(a, b) number PPCM de a et b
Engine.reduceFraction(num, den) { num, den } Fraction irréductible
Engine.latexFraction(num, den) string Renvoie "n" si den=1, sinon "\\dfrac{n}{d}"
Engine.randIntWhere(min, max, fn) number Entier dans [min,max] satisfaisant fn(v) === true
Engine.coprimePair(minQ, maxP) { p, q } Paire première entre elle avec p > q ≥ minQ
Engine.euclidSteps(a, b) { steps, pgcd } Étapes de l'algorithme d'Euclide (voir pgcd.js)
Engine.signedInt(n, isFirst) string "+3" ou "-3" selon le signe et la position
Engine.shuffle(array) array Copie mélangée (Fisher-Yates) — utile pour les QCM

Exemples d'usage

// Entier aléatoire
const a = Engine.randInt(2, 10);   // ex. 7

// Fraction aléatoire irréductible
const { p, q } = Engine.coprimePair(2, 9);  // ex. {p: 7, q: 3}
const frac = Engine.latexFraction(p, q);    // "\\dfrac{7}{3}"

// Contrainte : a pair
const a = Engine.randIntWhere(2, 20, v => v % 2 === 0);

// Étapes Euclide
const { steps, pgcd } = Engine.euclidSteps(48, 18);
// steps[0] = { dividend: 48, divisor: 18, quotient: 2, remainder: 12 }

LaTeX dans les chaînes JavaScript

Règle fondamentale

Dans une chaîne JS, chaque \ LaTeX s'écrit \\. Donc \frac devient \\frac, et le saut de ligne LaTeX \\ devient \\\\.

Tableau de conversion

Tu veux écrire en LaTeXTu écris dans JS
\frac{a}{b}\\frac{a}{b}
\dfrac{a}{b}\\dfrac{a}{b}
\times\\times
\sqrt{x}\\sqrt{x}
\int_a^b\\int_a^b
\begin{aligned}\\begin{aligned}
\\ (saut de ligne dans aligned)\\\\
\displaystyle\\displaystyle
\operatorname{pgcd}\\operatorname{pgcd}

Modes d'affichage

ModeSyntaxe JSRendu
Inline (dans le texte) `La valeur de $a^2$ est…` La valeur de est…
Bloc centré `$$\\frac{a}{b}$$` Fraction centrée sur sa propre ligne
Bloc aligné `$$\\begin{aligned} a &= b \\\\ c &= d \\end{aligned}$$` Calculs alignés sur le signe =

Macros pré-définies

Macro JSRenduÀ utiliser pour
\\pgcdpgcd (romain)PGCD de deux entiers
\\ppcmppcm (romain)PPCM de deux entiers
\\NEntiers naturels
\\ZEntiers relatifs
\\RRéels
\\QRationnels
\\CComplexes

Exemple de correction complète

const correction =
  `<p>On développe le calcul :</p>` +
  `<div class="my-4 overflow-x-auto">` +
  `$$\\begin{aligned}` +
  `  ${a}^{${n}} &= ${Array(n).fill(a).join(' \\\\times ')} \\\\` +
  `              &= ${Math.pow(a, n)}` +
  `\\end{aligned}$$` +
  `</div>` +
  `<div class="result-highlight">$$${a}^{${n}} = ${Math.pow(a, n)}$$</div>`;

Classes CSS disponibles dans la correction

ClasseUsageAperçu
result-highlight Encadre le résultat final avec un fond jaune
$$a^n = 8$$
my-4 overflow-x-auto Bloc display centré avec défilement horizontal si formule large <div class="my-4 overflow-x-auto">$$...$$</div>
mt-1 text-xs text-slate-500 Petite note grise sous un bloc de calcul On utilise ln(e) = 1 et ln(1) = 0.
Toutes les classes Tailwind sont utilisables

L'application charge Tailwind CSS en CDN. Tu peux donc utiliser n'importe quelle classe utilitaire Tailwind dans le HTML de ta correction : font-bold, text-blue-600, border, etc.

Dépannage

Le chapitre apparaît avec le badge "bientôt"

L'id dans registry.js et l'id: dans le fichier JS ne correspondent pas exactement. Vérifie les majuscules et les tirets.

// registry.js
{ id: 'pgcd', label: '...' }    ← doit être identique ↓

// pgcd.js
MathsTrainer.register({ id: 'pgcd', ... })

Page blanche ou écran d'erreur au chargement

Ouvre la console du navigateur avec F12 → onglet Console. L'erreur rouge indique le fichier et la ligne problématiques. Copie ce message et donne-le à l'IA :

Prompt de correction rapide

"J'ai ce message d'erreur dans la console du navigateur, corrige le fichier JS : [message d'erreur]"

Les formules n'apparaissent pas (tu vois le LaTeX brut)

KaTeX se charge via internet (CDN). Vérifie ta connexion internet et recharge la page. Si tu travailles hors-ligne, télécharge KaTeX localement.

Le script Python ne se lance pas

Python 3 n'est pas installé ou n'est pas dans le PATH.

  1. Télécharge Python 3 sur python.org
  2. Lors de l'installation Windows, coche "Add Python to PATH"
  3. Relance le script

Le script Python dit "Dossier incorrect"

Le fichier import_module.py doit se trouver dans le même dossier que index.html. Ne le déplace pas dans un sous-dossier.

Les valeurs générées sont parfois impossibles

L'IA a choisi des plages trop larges. Ouvre le fichier JS, repère les Engine.randInt() et ajuste les bornes. Utilise Engine.randIntWhere() pour ajouter une contrainte :

// Forcer un résultat ≤ 100
const n = Engine.randIntWhere(2, 5, v => u0 * Math.pow(q, v) <= 100);