This commit is contained in:
lrdlg
2026-09-21 07:57:23 +02:00
parent efac1da67a
commit 5c644d17fc
14 changed files with 0 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
Déposez ici le site de la 2e commune (Informatique).
Son fichier d'accueil doit s'appeler index.html et se trouver directement dans ce dossier.
Tous les liens internes du site doivent être relatifs (ex. "css/style.css", pas "/css/style.css"),
sinon ils pointeront vers la racine du domaine et casseront.
Supprimez ce fichier une fois le site en place.
+402
View File
@@ -0,0 +1,402 @@
/* Moteur d'exercices hors ligne. Aucune dependance externe.
Types supportes : qcm, vf, assoc, tri, ordre, hotspot, calcul, texte, intrus. */
var TOTAL = 0, REUSSIS = 0, TENTES = 0;
function norm(s){
return (s || "").toString().toLowerCase()
.normalize("NFD").replace(/[\u0300-\u036f]/g, "")
.replace(/[^a-z0-9]/g, "");
}
function el(tag, cls, txt){
var e = document.createElement(tag);
if (cls) e.className = cls;
if (txt !== undefined) e.textContent = txt;
return e;
}
function melange(t){
var a = t.slice();
for (var i = a.length - 1; i > 0; i--){
var j = Math.floor(Math.random() * (i + 1));
var x = a[i]; a[i] = a[j]; a[j] = x;
}
return a;
}
function compter(ok){
TENTES++; if (ok) REUSSIS++;
majScore();
}
function majScore(){
var s = document.getElementById("score");
if (!s) return;
var pct = TOTAL ? Math.round(REUSSIS / TOTAL * 100) : 0;
s.querySelector(".txt").innerHTML = "Exercices reussis : <strong>" + REUSSIS +
" / " + TOTAL + "</strong> (" + pct + " %)";
s.querySelector(".barre span").style.width = pct + "%";
}
function retour(box, ok, msg){
var r = box.querySelector(".retour");
r.className = "retour " + (ok ? "ok" : "ko");
r.textContent = (ok ? "Correct. " : "Ce n'est pas cela. ") + (msg || "");
}
function cadre(d){
var box = el("article", "ex");
var c = el("p", "consigne", d.consigne || "Exercice");
box.appendChild(c);
if (d.enonce) box.appendChild(el("p", "enonce", d.enonce));
return box;
}
function finir(box){
box.appendChild(el("div", "retour"));
return box;
}
/* ---------- QCM ---------- */
function faireQcm(d){
var box = cadre(d), fini = false;
d.options.forEach(function(txt, i){
var b = el("button", "opt", txt);
b.onclick = function(){
if (fini) return;
fini = true;
var ok = (i === d.reponse);
b.classList.add(ok ? "juste" : "faux");
if (!ok) box.querySelectorAll(".opt")[d.reponse].classList.add("juste");
box.querySelectorAll(".opt").forEach(function(o){ o.disabled = true; });
retour(box, ok, d.explication || "");
compter(ok);
};
box.appendChild(b);
});
return finir(box);
}
/* ---------- Vrai / Faux ---------- */
function faireVf(d){
var box = cadre(d), fini = false;
["Vrai", "Faux"].forEach(function(txt, i){
var b = el("button", "jeton", txt);
b.onclick = function(){
if (fini) return;
fini = true;
var ok = ((i === 0) === d.reponse);
b.classList.add(ok ? "juste" : "faux");
box.querySelectorAll(".jeton").forEach(function(o){ o.disabled = true; });
retour(box, ok, d.explication || "");
compter(ok);
};
box.appendChild(b);
});
return finir(box);
}
/* ---------- Association (clic gauche puis clic droit) ---------- */
function faireAssoc(d){
var box = cadre(d);
var zone = el("div", "deux-col");
var g = el("div"), dr = el("div");
g.appendChild(el("h4", null, "Colonne A"));
dr.appendChild(el("h4", null, "Colonne B"));
var choisi = null, trouves = 0;
var droite = melange(d.paires.map(function(p, i){ return { t: p[1], i: i }; }));
d.paires.forEach(function(p, i){
var b = el("button", "jeton", p[0]);
b.style.display = "block"; b.dataset.i = i;
b.onclick = function(){
if (b.disabled) return;
if (choisi) choisi.classList.remove("choisi");
choisi = b; b.classList.add("choisi");
};
g.appendChild(b);
});
droite.forEach(function(o){
var b = el("button", "jeton", o.t);
b.style.display = "block";
b.onclick = function(){
if (!choisi || b.disabled) return;
var ok = (parseInt(choisi.dataset.i, 10) === o.i);
if (ok){
choisi.classList.remove("choisi");
choisi.classList.add("juste"); b.classList.add("juste");
choisi.disabled = true; b.disabled = true;
choisi = null; trouves++;
if (trouves === d.paires.length){
retour(box, true, d.explication || "Toutes les paires sont correctes.");
compter(true);
}
} else {
b.classList.add("faux");
setTimeout(function(){ b.classList.remove("faux"); }, 600);
retour(box, false, "Essaie une autre correspondance.");
}
};
dr.appendChild(b);
});
zone.appendChild(g); zone.appendChild(dr);
box.appendChild(zone);
return finir(box);
}
/* ---------- Tri dans des paniers ---------- */
function faireTri(d){
var box = cadre(d);
var reserve = el("div", "reserve");
var choisi = null, places = 0;
melange(d.items).forEach(function(it){
var b = el("button", "item", it[0]);
b.dataset.p = it[1];
b.onclick = function(){
if (b.disabled) return;
if (choisi) choisi.classList.remove("choisi");
choisi = b; b.classList.add("choisi");
};
reserve.appendChild(b);
});
box.appendChild(reserve);
var paniers = el("div", "paniers");
d.paniers.forEach(function(nom, pi){
var p = el("div", "panier");
p.appendChild(el("h4", null, nom));
p.onclick = function(){
if (!choisi) return;
var ok = (parseInt(choisi.dataset.p, 10) === pi);
if (ok){
choisi.classList.remove("choisi");
choisi.classList.add("juste");
choisi.disabled = true;
p.appendChild(choisi);
choisi = null; places++;
if (places === d.items.length){
retour(box, true, d.explication || "Tout est bien classe.");
compter(true);
}
} else {
p.classList.add("vise");
setTimeout(function(){ p.classList.remove("vise"); }, 500);
retour(box, false, "Ce n'est pas le bon panier.");
}
};
paniers.appendChild(p);
});
box.appendChild(paniers);
return finir(box);
}
/* ---------- Remise en ordre ---------- */
function faireOrdre(d){
var box = cadre(d);
var liste = el("div");
var ordre = melange(d.etapes.map(function(t, i){ return { t: t, i: i }; }));
function dessiner(){
liste.innerHTML = "";
ordre.forEach(function(o, pos){
var ligne = el("div", "item");
ligne.style.display = "block";
ligne.textContent = (pos + 1) + ". " + o.t;
var up = el("button", "jeton", "monter");
var dn = el("button", "jeton", "descendre");
up.onclick = function(){
if (pos === 0) return;
var x = ordre[pos - 1]; ordre[pos - 1] = ordre[pos]; ordre[pos] = x; dessiner();
};
dn.onclick = function(){
if (pos === ordre.length - 1) return;
var x = ordre[pos + 1]; ordre[pos + 1] = ordre[pos]; ordre[pos] = x; dessiner();
};
ligne.appendChild(document.createTextNode(" "));
ligne.appendChild(up); ligne.appendChild(dn);
liste.appendChild(ligne);
});
}
dessiner();
box.appendChild(liste);
var v = el("button", "action", "Verifier l'ordre");
var fini = false;
v.onclick = function(){
if (fini) return;
var ok = ordre.every(function(o, pos){ return o.i === pos; });
if (ok){
fini = true; v.disabled = true;
liste.querySelectorAll(".item").forEach(function(i){ i.classList.add("juste"); });
retour(box, true, d.explication || "");
compter(true);
} else {
retour(box, false, "L'ordre n'est pas encore correct, recommence.");
}
};
box.appendChild(v);
return finir(box);
}
/* ---------- Zones cliquables sur schema ---------- */
function faireHotspot(d){
var box = cadre(d);
var wrap = el("div");
wrap.innerHTML = d.svg;
box.appendChild(wrap);
var question = el("p", "enonce");
box.appendChild(question);
var restants = melange(d.zones.slice());
var trouves = 0;
function demander(){
if (!restants.length){
retour(box, true, d.explication || "Toutes les zones ont ete trouvees.");
compter(true);
question.textContent = "Termine.";
return;
}
question.innerHTML = "Clique sur : <strong>" + restants[0] + "</strong>";
}
wrap.querySelectorAll(".zone").forEach(function(z){
z.addEventListener("click", function(){
if (!restants.length) return;
if (z.dataset.zone === restants[0]){
z.classList.add("juste");
restants.shift(); trouves++;
demander();
} else {
z.classList.add("faux");
setTimeout(function(){ z.classList.remove("faux"); }, 500);
retour(box, false, "Ce n'est pas cet element.");
}
});
});
demander();
return finir(box);
}
/* ---------- Calcul ou reponse courte ---------- */
function faireSaisie(d){
var box = cadre(d);
var champ = el("input", "court");
champ.type = "text";
var v = el("button", "action", "Verifier");
var fini = false;
v.onclick = function(){
if (fini) return;
var ok;
if (d.type === "calcul"){
var n = parseFloat(champ.value.replace(",", ".").replace(/[^0-9.\-]/g, ""));
ok = !isNaN(n) && Math.abs(n - d.reponse) <= (d.tolerance || 0);
} else {
ok = d.acceptees.some(function(a){ return norm(a) === norm(champ.value); });
}
if (ok){
fini = true; v.disabled = true; champ.disabled = true;
retour(box, true, d.explication || "");
compter(true);
} else {
retour(box, false, d.indice || "Relis la theorie du chapitre et reessaie.");
}
};
box.appendChild(champ);
box.appendChild(document.createTextNode(" "));
box.appendChild(v);
return finir(box);
}
/* ---------- Chasse a l'intrus (plusieurs affirmations fausses) ---------- */
function faireIntrus(d){
var box = cadre(d);
var restants = d.items.filter(function(i){ return i[1]; }).length;
var erreurs = 0;
d.items.forEach(function(it){
var b = el("button", "opt", it[0]);
b.onclick = function(){
if (b.disabled) return;
b.disabled = true;
if (it[1]){
b.classList.add("juste");
restants--;
if (restants === 0){
retour(box, erreurs === 0, d.explication || "");
compter(erreurs === 0);
}
} else {
b.classList.add("faux");
erreurs++;
retour(box, false, "Cette affirmation est correcte, ce n'est pas un intrus.");
}
};
box.appendChild(b);
});
return finir(box);
}
/* ---------- Serie chronometree ---------- */
function faireChrono(d){
var box = cadre(d);
var minuteur = el("span", "chrono", "");
box.querySelector(".consigne").appendChild(minuteur);
var zone = el("div"); box.appendChild(zone);
var idx = 0, bons = 0, temps = d.secondes || 60, timer = null, encours = false;
var demarrer = el("button", "action", "Demarrer la serie");
box.appendChild(demarrer);
demarrer.onclick = function(){
if (encours) return;
encours = true; demarrer.style.display = "none";
idx = 0; bons = 0; temps = d.secondes || 60;
minuteur.textContent = temps + " s";
timer = setInterval(function(){
temps--; minuteur.textContent = temps + " s";
if (temps <= 0) terminer();
}, 1000);
poser();
};
function poser(){
zone.innerHTML = "";
if (idx >= d.questions.length){ terminer(); return; }
var q = d.questions[idx];
zone.appendChild(el("p", "enonce", (idx + 1) + ". " + q.enonce));
q.options.forEach(function(t, i){
var b = el("button", "jeton", t);
b.onclick = function(){
if (i === q.reponse) bons++;
idx++; poser();
};
zone.appendChild(b);
});
}
function terminer(){
clearInterval(timer); encours = false;
zone.innerHTML = "";
var seuil = Math.ceil(d.questions.length * 0.7);
var ok = bons >= seuil;
retour(box, ok, "Score : " + bons + " / " + d.questions.length +
". Seuil de reussite : " + seuil + ".");
compter(ok);
demarrer.textContent = "Recommencer la serie";
demarrer.style.display = "inline-block";
}
return finir(box);
}
/* ---------- Construction de la page ---------- */
var FABRIQUES = {
qcm: faireQcm, vf: faireVf, assoc: faireAssoc, tri: faireTri,
ordre: faireOrdre, hotspot: faireHotspot, calcul: faireSaisie,
texte: faireSaisie, intrus: faireIntrus, chrono: faireChrono
};
function construire(data){
var cible = document.getElementById("exercices");
TOTAL = data.length; REUSSIS = 0; TENTES = 0;
var s = el("div", "score");
s.id = "score";
var t = el("div", "txt"); s.appendChild(t);
var b = el("div", "barre"); b.appendChild(el("span")); s.appendChild(b);
var rz = el("button", "action secondaire", "Tout recommencer");
rz.onclick = function(){ location.reload(); };
s.appendChild(rz);
cible.parentNode.insertBefore(s, cible);
data.forEach(function(d){
var f = FABRIQUES[d.type];
if (f) cible.appendChild(f(d));
});
majScore();
}
window.addEventListener("DOMContentLoaded", function(){
if (window.DATA) construire(window.DATA);
});
+98
View File
@@ -0,0 +1,98 @@
:root{
--bleu:#1f4e79;
--bleu-clair:#dbe7f3;
--vert:#2e7d32;
--rouge:#c62828;
--gris:#f4f5f7;
--bordure:#c9d2dc;
--texte:#1c2733;
}
*{box-sizing:border-box}
body{
margin:0;
font-family:"Segoe UI",Calibri,Arial,sans-serif;
font-size:17px;
line-height:1.55;
color:var(--texte);
background:#fff;
}
header.site{
background:var(--bleu);
color:#fff;
padding:14px 24px;
}
header.site h1{margin:0;font-size:1.35rem}
header.site p{margin:4px 0 0;font-size:.9rem;opacity:.85}
nav.blocs{
display:flex;flex-wrap:wrap;gap:6px;
background:var(--bleu-clair);
padding:8px 24px;
border-bottom:2px solid var(--bordure);
}
nav.blocs a{
text-decoration:none;color:var(--bleu);font-weight:600;
padding:6px 12px;border-radius:4px;background:#fff;
border:1px solid var(--bordure);font-size:.92rem;
}
nav.blocs a.actif{background:var(--bleu);color:#fff}
main{max-width:900px;margin:0 auto;padding:24px}
h2{color:var(--bleu);border-bottom:2px solid var(--bleu-clair);padding-bottom:6px;margin-top:38px}
h3{color:var(--bleu);margin-bottom:6px}
.theorie{
background:var(--gris);
border-left:5px solid var(--bleu);
padding:14px 18px;border-radius:0 6px 6px 0;margin:18px 0;
}
.theorie h3{margin-top:0}
.theorie ul{margin:8px 0 0 18px}
.ex{
border:1px solid var(--bordure);
border-radius:8px;padding:16px 18px;margin:18px 0;
background:#fff;
}
.ex .consigne{font-weight:700;margin:0 0 4px;color:var(--bleu)}
.ex .enonce{margin:0 0 12px}
.opt,.jeton,.cible,.item{
display:inline-block;margin:4px 6px 4px 0;padding:8px 13px;
border:1px solid var(--bordure);border-radius:6px;background:#fff;
cursor:pointer;font-size:.97rem;
}
.opt{display:block;width:100%;text-align:left}
.opt:hover,.jeton:hover,.item:hover{background:var(--bleu-clair)}
.opt.juste,.jeton.juste,.item.juste{background:#e3f4e4;border-color:var(--vert)}
.opt.faux,.jeton.faux,.item.faux{background:#fbe3e3;border-color:var(--rouge)}
.opt.choisi,.jeton.choisi{background:var(--bleu);color:#fff;border-color:var(--bleu)}
.opt[disabled],.jeton[disabled]{cursor:default}
.paniers{display:flex;flex-wrap:wrap;gap:12px;margin-top:12px}
.panier{
flex:1 1 180px;min-height:90px;border:2px dashed var(--bordure);
border-radius:8px;padding:8px;background:var(--gris);
}
.panier h4{margin:0 0 6px;font-size:.92rem;color:var(--bleu)}
.panier.vise{border-color:var(--bleu);background:var(--bleu-clair)}
.deux-col{display:flex;gap:18px;flex-wrap:wrap}
.deux-col>div{flex:1 1 220px}
.retour{margin-top:10px;font-size:.93rem;padding:8px 10px;border-radius:6px;display:none}
.retour.ok{display:block;background:#e3f4e4;border:1px solid var(--vert)}
.retour.ko{display:block;background:#fbe3e3;border:1px solid var(--rouge)}
.chrono{float:right;font-weight:700;color:var(--rouge)}
.barre{height:12px;background:var(--bordure);border-radius:6px;overflow:hidden;margin:6px 0 0}
.barre span{display:block;height:100%;background:var(--vert);width:0;transition:width .3s}
.score{
position:sticky;top:0;z-index:5;background:#fff;
border:1px solid var(--bordure);border-radius:8px;padding:10px 14px;margin-bottom:10px;
}
.score strong{color:var(--bleu)}
button.action{
background:var(--bleu);color:#fff;border:none;border-radius:6px;
padding:9px 15px;font-size:.95rem;cursor:pointer;margin-top:10px;
}
button.action.secondaire{background:#fff;color:var(--bleu);border:1px solid var(--bleu)}
svg .zone{fill:#ffffff00;stroke:var(--bleu);stroke-width:2;cursor:pointer}
svg .zone:hover{fill:#1f4e7933}
svg .zone.juste{fill:#2e7d3255;stroke:var(--vert)}
svg .zone.faux{fill:#c6282855;stroke:var(--rouge)}
svg text{font-size:13px;fill:var(--texte);font-family:inherit}
input.court{padding:8px;border:1px solid var(--bordure);border-radius:6px;font-size:1rem;width:160px}
footer{margin:40px 0 0;padding:16px 24px;background:var(--gris);border-top:2px solid var(--bordure);font-size:.85rem}
@media print{nav.blocs,button.action{display:none}}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+42
View File
@@ -0,0 +1,42 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Module 1 - accueil</title>
<link rel="stylesheet" href="assets/style.css">
</head>
<body>
<header class="site">
<h1>Module 1 : la machine et son vocabulaire</h1>
<p>Activite complementaire EPT Informatique, 2e commune, M. Courcelle</p>
</header>
<nav class="blocs"><a href="index.html" class="actif">Accueil</a><a href="bloc2.html">Bloc 2</a><a href="bloc3.html">Bloc 3</a><a href="bloc4.html">Bloc 4</a><a href="bloc5.html">Bloc 5</a><a href="bloc6.html">Bloc 6</a></nav>
<main>
<h2>Accueil</h2>
<p>Ce site accompagne le module 1 du cours. Chaque page correspond a un bloc de deux periodes
et reprend d'abord la theorie du chapitre, puis les exercices et les jeux.</p>
<p>Toutes les notions utilisees dans les jeux figurent dans le cours papier. Si tu bloques,
la reponse est dans ton cours, au chapitre indique en bas de page.</p>
<div class="theorie"><h3>Les cinq blocs</h3><ul>
<li><strong>Bloc 2</strong> : ce qui compose un ordinateur, chapitre 1</li>
<li><strong>Bloc 3</strong> : les ports de connexion, chapitre 2</li>
<li><strong>Bloc 4</strong> : allumer, verrouiller, eteindre, chapitre 3</li>
<li><strong>Bloc 5</strong> : se reperer dans Windows, chapitre 4</li>
<li><strong>Bloc 6</strong> : memoire vive et stockage, chapitre 5</li>
</ul></div>
<div class="theorie"><h3>Comment ca marche</h3><ul>
<li>Le compteur en haut de page indique combien d'exercices tu as reussis.</li>
<li>Pour les associations et les tris : clique d'abord sur l'etiquette, puis sur sa destination.</li>
<li>Les series chronometrees demandent au moins 70 pour cent de bonnes reponses.</li>
<li>Le bouton "Tout recommencer" remet la page a zero.</li>
</ul></div>
<p>Le site fonctionne sans connexion Internet. Il peut etre lance depuis une cle USB.</p>
</main>
<footer>Support d'exercices hors ligne. Toute la theorie utilisee ici figure dans le cours papier, chapitre .</footer>
</body>
</html>