refactoring Claude

This commit is contained in:
arnaud 2026-03-15 18:54:48 +01:00
parent 97359d172b
commit 13d65f8995
6 changed files with 150 additions and 229 deletions

View file

@ -14,16 +14,17 @@ const nombresChinois = [
]; ];
const pronomsChinois = [ const pronomsChinois = [
{ hanzi: "我", pinyin: "wǒ", francais: "je / moi" }, { hanzi: "它们", pinyin: "tāmen", valeur: "ils/elles (objets, animaux)" },
{ hanzi: "你", pinyin: "nǐ", francais: "tu / toi" }, { hanzi: "我", pinyin: "wǒ", valeur: "je / moi" },
{ hanzi: "您", pinyin: "nín", francais: "vous (politesse)" }, { hanzi: "你", pinyin: "nǐ", valeur: "tu / toi" },
{ hanzi: "他", pinyin: "tā", francais: "il / lui" }, { hanzi: "您", pinyin: "nín", valeur: "vous (politesse)" },
{ hanzi: "她", pinyin: "tā", francais: "elle" }, { hanzi: "他", pinyin: "tā", valeur: "il / lui" },
{ hanzi: "它", pinyin: "tā", francais: "il/elle (objet, animal)" }, { hanzi: "她", pinyin: "tā", valeur: "elle" },
{ hanzi: "我们", pinyin: "wǒmen", francais: "nous" }, { hanzi: "它", pinyin: "tā", valeur: "il/elle (objet, animal)" },
{ hanzi: "你们", pinyin: "nǐmen", francais: "vous (pluriel)" }, { hanzi: "我们", pinyin: "wǒmen", valeur: "nous" },
{ hanzi: "他们", pinyin: "tāmen", francais: "ils (masculin ou mixte)" }, { hanzi: "你们", pinyin: "nǐmen", valeur: "vous (pluriel)" },
{ hanzi: "她们", pinyin: "tāmen", francais: "elles (féminin)" }, { hanzi: "他们", pinyin: "tāmen", valeur: "ils (masculin ou mixte)" },
{ hanzi: "它们", pinyin: "tāmen", francais: "ils/elles (objets, animaux)" } { hanzi: "她们", pinyin: "tāmen", valeur: "elles (féminin)" },
{ hanzi: "它们", pinyin: "tāmen", valeur: "ils/elles (objets, animaux)" }
]; ];
</script> </script>

View file

@ -1,19 +1,10 @@
<div id="challenge"></div> <div id="hanzi_nbr_help_widget"></div>
<div id="canvas" class="hanzi-canvas-container"></div>
<button id="valid">Vérifier</button>
<p id="feedback"></p>
<script>
const module1 = createMyReusableModule();
module1.init({ <script>
challengeID: "challenge", const id1s = hanziApp.newWidget("hanzi_nbr_help_widget");
canvasID: "canvas", hanziApp.init({
feedbackID: "feedback", ...id1s,
button_OK_ID: "valid", view_settings: { showCharacter: true, showOutline: true },
view_settings: {
showCharacter: true,
showOutline: true,
},
datas: nombresChinois datas: nombresChinois
}); });
</script> </script>

View file

@ -1,19 +1,10 @@
<div id="challenge1"></div> <div id="hanzi_nbr_wohelp_widget"></div>
<div id="canvas1" class="hanzi-canvas-container"></div>
<button id="valid1">Vérifier</button>
<p id="feedback1"></p>
<script>
const module2 = createMyReusableModule();
module2.init({ <script>
challengeID: "challenge1", const id2s = hanziApp.newWidget("hanzi_nbr_wohelp_widget");
canvasID: "canvas1", hanziApp.init({
feedbackID: "feedback1", ...id2s,
button_OK_ID: "valid1", view_settings: { showCharacter: false, showOutline: false },
view_settings: {
showCharacter: false,
showOutline: false,
},
datas: nombresChinois datas: nombresChinois
}); });
</script> </script>

View file

@ -1,19 +1,10 @@
<div id="challenge3"></div> <div id="hanzi_pronom_help_widget"></div>
<div id="canvas3" class="hanzi-canvas-container"></div>
<button id="valid3">Vérifier</button>
<p id="feedback3"></p>
<script>
const module3 = createMyReusableModule();
module3.init({ <script>
challengeID: "challenge3", const id3s = hanziApp.newWidget("hanzi_pronom_help_widget");
canvasID: "canvas3", hanziApp.init({
feedbackID: "feedback3", ...id3s,
button_OK_ID: "valid3", view_settings: { showCharacter: true, showOutline: true },
view_settings: {
showCharacter: true,
showOutline: true,
},
datas: pronomsChinois datas: pronomsChinois
}); });
</script> </script>

View file

@ -1,115 +1,93 @@
<script src="https://cdn.jsdelivr.net/npm/hanzi-writer@3.5/dist/hanzi-writer.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/hanzi-writer@3.5/dist/hanzi-writer.min.js"></script>
<script> <script>
function createMyReusableModule() { const hanziApp = (() => {
function init(options = {}) { // ---------------------------------------------------------
// CRÉE LE HTML D'UN WIDGET et retourne les IDs
// ---------------------------------------------------------
function newWidget(rootID) {
const root = document.getElementById(rootID);
const uid = rootID;
let iNb = 0; root.innerHTML = `
let datas = options.datas; <div id="challenge_${uid}"></div>
let datas_length = datas.length; <div id="canvas_${uid}"></div>
<button id="valid_${uid}">Vérifier</button>
<p id="feedback_${uid}"></p>
`;
displayChallenge( return {
options.challengeID, challengeID: `challenge_${uid}`,
datas[iNb].valeur, canvasID: `canvas_${uid}`,
datas[iNb].pinyin feedbackID: `feedback_${uid}`,
); button_OK_ID: `valid_${uid}`
};
// --- INITIALISATION MULTICANVAS ---
let { writers, okArray } = initMultiCanvas(
options.canvasID,
datas[iNb].hanzi,
options.view_settings
);
startMultiQuiz(writers, okArray);
const bouton = document.querySelector("#" + options.button_OK_ID);
const handleClick = () => {
let isOK = checkAll(okArray, options.feedbackID);
switch (isOK) {
case 0:
// incorrect → rien
break;
case 1:
// correct → mot suivant
iNb++;
if (iNb >= datas_length) {
document.getElementById(options.feedbackID).textContent = "Fini !";
return -1;
} }
displayChallenge( // ---------------------------------------------------------
options.challengeID, // INITIALISE UN WIDGET
datas[iNb].valeur, // ---------------------------------------------------------
datas[iNb].pinyin function init(options = {}) {
); let iNb = 0;
const datas = options.datas;
// Réinitialiser les canvas pour le nouveau mot let writers = [], okArray = [];
let res = initMultiCanvas(
options.canvasID,
datas[iNb].hanzi,
options.view_settings
);
function loadNext() {
displayChallenge(options.challengeID, datas[iNb]);
const res = initMultiCanvas(options.canvasID, datas[iNb].hanzi, options.view_settings);
writers = res.writers; writers = res.writers;
okArray = res.okArray; okArray = res.okArray;
startMultiQuiz(writers, okArray); startMultiQuiz(writers, okArray);
break;
} }
};
bouton.addEventListener("click", handleClick); function handleClick() {
const allOK = checkAll(okArray, options.feedbackID);
if (!allOK) return;
iNb++;
if (iNb >= datas.length) {
document.getElementById(options.feedbackID).textContent = "Fini !";
document.getElementById(options.button_OK_ID).removeEventListener("click", handleClick);
return;
}
loadNext();
}
loadNext();
document.getElementById(options.button_OK_ID).addEventListener("click", handleClick);
} }
// --------------------------------------------------------- // ---------------------------------------------------------
// AFFICHAGE DU CHALLENGE // AFFICHAGE DU CHALLENGE
// --------------------------------------------------------- // ---------------------------------------------------------
function displayChallenge(divName, chineseChar, pinyin) { function displayChallenge(divID, item) {
document.getElementById(divName).textContent = document.getElementById(divID).textContent =
"Écrire : " + chineseChar + " / " + pinyin; "Écrire : " + item.valeur + " / " + item.pinyin;
} }
// --------------------------------------------------------- // ---------------------------------------------------------
// CRÉATION MULTICANVAS // CRÉATION MULTI-CANVAS
// --------------------------------------------------------- // ---------------------------------------------------------
function initMultiCanvas(containerID, hanzi, view_settings) { function initMultiCanvas(containerID, hanzi, view_settings) {
const CHAR_SIZE = 150;
const chars = [...hanzi]; // "十一" → ["十","一"] const chars = [...hanzi];
const container = document.getElementById(containerID); const container = document.getElementById(containerID);
container.innerHTML = ""; // reset container.innerHTML = "";
container.style.cssText = "display:flex;flex-direction:row;flex-wrap:nowrap;align-items:flex-start;gap:12px";
let writers = []; const okArray = new Array(chars.length).fill(false);
let okArray = new Array(chars.length).fill(false); const writers = chars.map((char, index) => {
const div = document.createElement("div");
chars.forEach((char, index) => { div.id = `${containerID}_${index}`;
container.appendChild(div);
const c = document.createElement("div"); const hw = HanziWriter.create(div.id, char, {
c.id = `${containerID}_${index}`; width: CHAR_SIZE, height: CHAR_SIZE,
c.style.display = "inline-block"; showCharacter: view_settings?.showCharacter ?? true,
c.style.marginRight = "10px"; showOutline: view_settings?.showOutline ?? true,
container.appendChild(c); showHintAfterMisses: 1, highlightOnComplete: false, padding: 5
const hw = HanziWriter.create(c.id, char, {
width: 150,
height: 150,
showCharacter: view_settings.showCharacter,
showOutline: view_settings.showOutline,
showHintAfterMisses: 1,
highlightOnComplete: false,
padding: 5
}); });
div.style.cssText = `display:inline-block;width:${CHAR_SIZE}px;height:${CHAR_SIZE}px;flex-shrink:0`;
writers.push(hw); return hw;
}); });
return { writers, okArray }; return { writers, okArray };
} }
@ -117,14 +95,9 @@ function createMyReusableModule() {
// LANCER UN QUIZ PAR CANVAS // LANCER UN QUIZ PAR CANVAS
// --------------------------------------------------------- // ---------------------------------------------------------
function startMultiQuiz(writers, okArray) { function startMultiQuiz(writers, okArray) {
writers.forEach((hw, idx) => { writers.forEach((hw, idx) => {
okArray[idx] = false; // reset
hw.quiz({ hw.quiz({
onMistake: () => { okArray[idx] = false; }, onMistake: () => { okArray[idx] = false; },
onCorrectStroke: () => {},
onComplete: () => { okArray[idx] = true; } onComplete: () => { okArray[idx] = true; }
}); });
}); });
@ -134,25 +107,16 @@ function createMyReusableModule() {
// CHECK GLOBAL // CHECK GLOBAL
// --------------------------------------------------------- // ---------------------------------------------------------
function checkAll(okArray, feedbackId) { function checkAll(okArray, feedbackId) {
const el = document.getElementById(feedbackId);
const allOK = okArray.every(v => v === true); const allOK = okArray.every(Boolean);
el.textContent = allOK ? "✔️ Bravo !" : "❌ Incorrect, continuez !";
if (allOK) { el.style.color = allOK ? "green" : "red";
document.getElementById(feedbackId).textContent = "✔️ Bravo !"; return allOK;
document.getElementById(feedbackId).style.color = "green";
return 1;
} else {
document.getElementById(feedbackId).textContent = "❌ Incorrect, continue !";
document.getElementById(feedbackId).style.color = "red";
return 0;
}
} }
// --------------------------------------------------------- // ---------------------------------------------------------
// EXPORT // EXPORT
// --------------------------------------------------------- // ---------------------------------------------------------
return { return { newWidget, init };
init })();
};
}
</script> </script>

View file

@ -1,17 +0,0 @@
<style>
.hanzi-canvas-container {
display: flex !important;
flex-direction: row !important;
gap: 12px;
align-items: flex-start;
flex-wrap: nowrap !important;
margin-bottom: 10px;
border: 2px solid #000;
padding: 10px;
}
.hanzi-canvas-container > div {
display: inline-flex !important;
flex: 0 0 auto !important;
}
</style>