diff --git a/docs/superpowers/specs/2026-08-31-generation-ponderee-questions-design.md b/docs/superpowers/specs/2026-08-31-generation-ponderee-questions-design.md new file mode 100644 index 0000000..1244d7b --- /dev/null +++ b/docs/superpowers/specs/2026-08-31-generation-ponderee-questions-design.md @@ -0,0 +1,46 @@ +# Design : Génération pondérée des questions (moins de questions faciles) + +Date : 2026-08-31 +Statut : Validé par le produit (approche 1 choisie) + +## 1. Objectif + +Le tirage uniforme des facteurs produit ~16 % de questions triviales (facteur 1 : `1 × 2`, `3 × ? = 3`) et beaucoup de petits produits trop faciles. On remplace le tirage uniforme par une **pondération progressive** : les grands facteurs reviennent plus souvent, les petits restent rares mais possibles. + +## 2. Décision + +| Décision | Choix | +|---|---| +| Mécanisme | Poids sur chaque facteur, tirés indépendamment | +| Poids | Linéaire : P(k) ∝ k, sur 1..maxTable | +| Formes | Direct / MissingFactor inchangées (~50/50) | +| Anti-répétition | Pas de doublon consécutif (inchangé) | + +Rejeté : poids sur le produit (nécessite une factorisation, biaise les tables) ; rejet par score de difficulté (boucle de rejet, terminaison fragile pour maxTable ≤ 2, coupe net les petits facteurs au lieu de les rendre rares). + +## 3. Comportement + +- `QuestionGenerator.next()` tire `a` et `b` dans 1..maxTable avec poids ∝ facteur. + Exemple maxTable = 10 : P(1) ≈ 1,8 %, P(2) ≈ 3,6 %, P(5) ≈ 9 %, P(10) ≈ 18 %. +- Termination garantie : tout facteur a un poids > 0, pas de boucle de rejet sur la difficulté. Pour maxTable = 1, la seule question possible (`1 × 1`) reste générée. +- La boucle « pas deux fois la même question de suite » est conservée (le tirage est relancé en cas d'égalité). +- `GameConfig`, `Question`, les écrans et le reste du moteur ne changent pas : le joueur limite toujours la difficulté via maxTable. + +## 4. Implémentation + +`QuestionGenerator.kt` uniquement : construction d'une table de poids cumulés 1..maxTable (somme = maxTable·(maxTable+1)/2), tirage via `random.nextDouble(totalWeight)` puis recherche du facteur. Aucune autre dépendance. + +## 5. Tests (commonTest, `QuestionGeneratorTest`) + +Mise à jour/ajouts : + +1. Bornes : facteurs dans 1..maxTable (inchangé). +2. Formes Direct et MissingFactor produites (inchangé). +3. Pas de doublon consécutif (inchangé). +4. **Nouveau** — biais progressif : avec une graine fixe et 5 000 tirages (maxTable = 10), la fréquence des questions contenant un facteur 1 est < 1/10 de celle contenant un facteur 10 (attendu ≈ 3,6 % vs ≈ 32,7 %). +5. **Nouveau** — les petits facteurs restent possibles : avec une graine fixe et 5 000 tirages (maxTable = 10), au moins une question contient un facteur 1 (attendu ≈ 3,6 %, soit ~180 occurrences). + +## 6. Hors périmètre + +- Courbe de difficulté progressive au fil de la partie +- Sélection fine de tables, modes alternatifs (cf. spec v1)