Annuaire › Code ouvert
Code publié par son auteur, en lecture seule. « Copier dans mon espace » crée un nouveau site à vous (non publié) que vous pouvez modifier librement.
README.md · 3.6 Ko
# Quiz Antalaha et Madagascar
**Niveau : avancé**
## Cas d'usage
Un quiz pour les élèves, les visiteurs ou les amateurs de culture locale : une dizaine de questions
prudentes sur Antalaha, la vanille, l'océan Indien, les pirogues, le ravenala… Trois niveaux de difficulté
(plus ou moins de temps par question), un minuteur, un score qui récompense la rapidité, un meilleur score
par niveau et des effets sonores. Le but pédagogique : montrer comment organiser un programme JavaScript
de taille moyenne **sans modules ni bibliothèque**, en séparant clairement les rôles.
## Arborescence
```
js-quiz-antalaha/
├── index.html Les 3 écrans (accueil, question, fin) et l'ordre des scripts
├── site.json Titre, description, mots-clés
├── README.md Ce fichier
├── css/
│ └── style.css Apparence mobile d'abord, états bonne/mauvaise réponse, focus visible
├── data/
│ └── questions.js DONNÉES : NIVEAUX, QUESTIONS (const globales, pas de fetch)
├── js/
│ ├── sons.js Objet Sons : jouer/activer les effets sonores
│ ├── quiz.js LOGIQUE : objet Quiz, état unique « state », minuteur, score, records
│ ├── ui.js AFFICHAGE : objet UI, lit state et dessine la page
│ └── main.js CHEF D'ORCHESTRE : relie Quiz, UI et Sons
└── medias/
├── antalaha-ravenala-paysage.svg Illustration d'en-tête
└── clic.wav, pop.wav, succes.wav, erreur.wav, victoire.wav Sons (médiathèque libre de droits)
```
**Ordre de chargement** (voir le bas de `index.html`) : `questions.js` → `sons.js` → `quiz.js` → `ui.js` → `main.js`.
Chaque fichier n'utilise que ce qui a été défini avant lui.
## Notions abordées
- Séparation données / logique / affichage, avec des objets globaux comme espaces de noms (IIFE + `const Quiz = (function () {...})()`)
- Un **état unique** (`state`) : l'écran se redessine toujours à partir de lui
- Patron « observateur » : `Quiz.abonner(fonction)` et événements (`question`, `tick`, `reponse`, `fin`)
- Mélange **Fisher-Yates** (questions et propositions), et pourquoi `sort(() => Math.random() - 0.5)` est à éviter
- Minuteur avec `setInterval` / `clearInterval` (et l'erreur classique : deux minuteurs en même temps)
- Score avec bonus de rapidité, meilleur score par niveau
- `localStorage` dans un `try/catch` avec repli en mémoire (obligatoire dans le bac à sable du Portail)
- Données dans un fichier `.js` plutôt qu'un `.json` chargé avec `fetch` (CORS en bac à sable)
- Création de l'interface par `createElement`, délégation d'événements (`closest`, `dataset`)
- Accessibilité : navigation au clavier (Tab, touches 1 à 4, Entrée), gestion du focus, `aria-live`, `fieldset/legend`, symboles ✔ ✖ en plus des couleurs, `prefers-reduced-motion`
- Sons avec `Audio` déclenchés après un clic (règle anti-autoplay) et `play()` dont on attrape le refus
## Idées d'exercices
1. Ajoutez 5 questions dans `data/questions.js` (respectez le format décrit en tête du fichier).
2. Ajoutez un 4e niveau « Expert » avec 6 secondes par question : il suffit presque de l'ajouter dans `NIVEAUX` et d'écrire des questions.
3. Faites perdre 20 points pour une mauvaise réponse (modifiez uniquement `quiz.js`).
4. Ajoutez un thème (« vanille », « nature », « mer ») dans chaque question et un filtre sur l'écran d'accueil.
5. Ajoutez un bouton « 50/50 » qui masque deux mauvaises propositions (la logique dans `quiz.js`, le bouton dans `ui.js`).
6. Utilisez le son `clic.wav` pour chaque réponse choisie, et mesurez la différence de ressenti.