diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a4d6d9c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.vs/ \ No newline at end of file diff --git a/MainPage/Abdelaziz/CrossWords.html b/MainPage/Abdelaziz/CrossWords.html deleted file mode 100644 index 7e03488..0000000 --- a/MainPage/Abdelaziz/CrossWords.html +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - Crossword Puzzle - - - -
-

Crossword Puzzle - 21×21

- -
-
-
- -
-
-

Across

-
-
-
-
-

Down

-
-
-
-
-
- - - - \ No newline at end of file diff --git a/MainPage/Abdelaziz/kreuzwortratsel.html b/MainPage/Abdelaziz/kreuzwortratsel.html new file mode 100644 index 0000000..c5558ba --- /dev/null +++ b/MainPage/Abdelaziz/kreuzwortratsel.html @@ -0,0 +1,285 @@ + + + + +Rätsel + + + +

Rätsel

+
+ Deutsch: + + + + + English: + + +
+
+
+
+ + +
+
+
+ + + +
+
+
+
+
+ + + \ No newline at end of file diff --git a/MainPage/MainPage.html b/MainPage/MainPage.html index e8db003..e070af6 100644 --- a/MainPage/MainPage.html +++ b/MainPage/MainPage.html @@ -10,7 +10,7 @@

Team Game Platform

-
+

Game 1

Member 1

@@ -25,7 +25,7 @@

Wörter lernen

-
+

CrossWord

Abdelaziz

diff --git a/MainPage/saad/index.html b/MainPage/saad/index.html new file mode 100644 index 0000000..44567eb --- /dev/null +++ b/MainPage/saad/index.html @@ -0,0 +1,692 @@ + + + + + +WORDLE + + + + + +
+ +
+

Wordle

+
Guess the five-letter word
+
+ +
+
+
+
Brilliant!
+
+ The word was + +
+
+
0
Played
+
0
Wins
+
0
Streak
+
+ +
+
+
+ + + + \ No newline at end of file diff --git a/MainPage/stas/WoerterLernen.html b/MainPage/stas/WoerterLernen.html index 217bf2f..fbef0e3 100644 --- a/MainPage/stas/WoerterLernen.html +++ b/MainPage/stas/WoerterLernen.html @@ -11,43 +11,80 @@

Flashcards Generator

-
-
- -
-
-
-                Bitte formatiere meine Wortliste exakt nach folgendem Schema.
-                Jeder Eintrag muss durch eine Leerzeile getrennt sein.
+        
+
+
+ +
+
+
+                    Bitte formatiere meine Wortliste exakt nach folgendem Schema.
+                    Jeder Eintrag muss durch eine Leerzeile getrennt sein.
 
-                Englisches Wort
-                [IPA-Transkription]
-                Beispielsatz auf Englisch
-                Deutsche Übersetzung des Wortes
-                Beispielsatz auf Deutsch
-                
- + Englisches Wort + [IPA-Transkription] + Beispielsatz auf Englisch + Deutsche Übersetzung des Wortes + Beispielsatz auf Deutsch +
+ +
+
+
+ + +
+
-
- - +
+
- + + -
+
+
+
+ +
+
+ +
+ +
+

Wählt eine Trainingsart:

+ +
+ + + + + +
+
+ + + + + + + +
+ +
+
+ +
- -
-<<<<<<< HEAD:WoerterLernen.html -======= - -
- -
- ->>>>>>> a18b892e86a6b427b23c2eb100b9986d3c15121c:MainPage/stas/WoerterLernen.html + +
\ No newline at end of file diff --git a/MainPage/stas/drucker.jfif b/MainPage/stas/drucker.jfif new file mode 100644 index 0000000..2b0d101 Binary files /dev/null and b/MainPage/stas/drucker.jfif differ diff --git a/MainPage/stas/eigenerCode.js b/MainPage/stas/eigenerCode.js index db8e605..2bd6707 100644 --- a/MainPage/stas/eigenerCode.js +++ b/MainPage/stas/eigenerCode.js @@ -1,5 +1,15 @@ let parsedArray = []; +// Mischt ein Array zufällig mit dem Fisher-Yates-Algorithmus +// und gibt das gemischte Array zurück. +function mischeArray(array) { + for (let i = array.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [array[i], array[j]] = [array[j], array[i]]; + } + return array; +} + document.getElementById('copyButton').addEventListener('click', () => { const text = document.getElementById('formatText').innerText; @@ -8,31 +18,9 @@ document.getElementById('copyButton').addEventListener('click', () => { }).catch(err => { console.error('Konnte nicht kopieren: ', err); }); - - for (let i = 0; i < parsedArray.length; i += 8) { - const pageFront = document.createElement("div"); - pageFront.className = "page_front"; - const pageBack = document.createElement("div"); - pageBack.className = "page_back"; - - const currentSlice = parsedArray.slice(i, i + 8); - currentSlice.forEach(karte => { - const frontCard = document.createElement("div"); - frontCard.className = "card"; - frontCard.innerHTML = `

${karte.englisch}

${karte.ipa}

${karte.beispielEN}

`; - pageFront.appendChild(frontCard); - - const backCard = document.createElement("div"); - backCard.className = "card"; - backCard.innerHTML = `

${karte.deutsch}

${karte.beispielDE}

`; - pageBack.appendChild(backCard); - }); - - container.appendChild(pageFront); - container.appendChild(pageBack); - } }); +// Analysiert den eingegebenen Text und wandelt ihn in ein Array von Wort-Objekten um. function parseWordText(inputText) { const wortBlocks = inputText.trim().split("\n\n"); const wortListe = []; @@ -46,6 +34,7 @@ function parseWordText(inputText) { } const wortObj = { + id: crypto.randomUUID(), englisch: lines[0], ipa: lines[1], beispielEN: lines[2], @@ -59,6 +48,7 @@ function parseWordText(inputText) { return wortListe; } +// Gibt beide Seiten als Objekt zurück. function createPagePair() { const frontPage = document.createElement("div"); frontPage.className = "page page-front"; @@ -70,23 +60,38 @@ function createPagePair() { } const button = document.getElementById("kartenErstellen"); -const onlineContainer = document.getElementById("kartenContainer"); -const frontPage = document.querySelector(".page_front"); -const backPage = document.querySelector(".page_back"); button.addEventListener("click", () => { const inputText = document.getElementById("inputText").value; parsedArray = parseWordText(inputText); + if(parsedArray.length === 0) { + alert("Kein gültiges Format erkannt. Bitte überprüfe deine Eingabe."); + return; + } + + alert("Karten erfolgreich erstellt!"); + + + document.getElementById("startScreen").style.display = "none"; + document.getElementById("modusAuswahlSeite").style.display = "block"; +}); + +// Erstellt druckfertige PDF-Seiten mit jeweils 8 Karten pro Seite. +function createPDFPages(wordArray) { + + const kartenContainer = document.getElementById("kartenContainer"); + const druckenBtn = document.getElementById("druckenBtn"); + kartenContainer.innerHTML = ""; kartenContainer.style.display = "flex"; kartenContainer.style.flexDirection = "column"; - for (let i = 0; i < parsedArray.length; i += 8) { + for (let i = 0; i < wordArray.length; i += 8) { const { frontPage, backPage } = createPagePair(); - parsedArray.slice(i, i + 8).forEach((karte) => { + wordArray.slice(i, i + 8).forEach((karte) => { const frontCard = document.createElement("div"); frontCard.className = "card card-en"; @@ -109,4 +114,771 @@ button.addEventListener("click", () => { kartenContainer.appendChild(frontPage); kartenContainer.appendChild(backPage); } + + druckenBtn.style.display = "block"; + + alert("PDF-Seiten wurden erstellt! Du kannst sie jetzt drucken."); +} + + +document.getElementById("druckenBtn").addEventListener("click", () => { + window.print(); }); + +const modusBtns = document.querySelectorAll('.modus-btn'); + +modusBtns.forEach(btn => { + btn.addEventListener('click', () => { + const modus = btn.dataset.modus; + + if (modus === 'druck') { + showMode('pdfPages'); + createPDFPages(parsedArray); + } + + else if (modus === 'training_einfach') { + showMode('onlineTraining'); + } + + else if (modus === 'statistik') { + console.log("Statistik anzeigen..."); + } + }); +}); + +// Blendet alle Trainingslevel-Ansichten aus +function showMode(id) { + + document.getElementById("pdfPages").style.display = "none"; + document.getElementById("onlineTraining").style.display = "none"; + + document.getElementById(id).style.display = "block"; +} + +function showLevel(id) { + document.querySelectorAll("#onlineTraining .training-view").forEach(view => { + if (view.id !== "trainingLevels") { + view.classList.add("hidden"); + } + }); + + document.getElementById(id).classList.remove("hidden"); +} + +document.querySelectorAll(".level-btn").forEach(btn => { + btn.addEventListener("click", () => { + const type = btn.dataset.level; + console.log("Trainingsart:", type); + + if (type === "flip") { + showLevel("trainingFlip"); + startFlipTraining(); + document.getElementById("checkBtn").style.display = "none"; + } + + if (type === "matching") { + showLevel("trainingMatching"); + startMittelTraining(); + document.getElementById("checkBtn").style.display = "block"; + } + + if (type === "multiple") { + showLevel("trainingMultiple"); + startMultipleTraining(); + document.getElementById("checkBtn").style.display = "none"; + } + + if (type === "hint") { + showLevel("trainingHint"); + startHintTraining(); + document.getElementById("checkBtn").style.display = "none"; + } + + if (type === "write") { + showLevel("trainingWrite"); + startWriteTraining(); + document.getElementById("checkBtn").style.display = "none"; + } + }); +}); + +class TrainingsEngine { + + constructor(kartenListe) { + this.kartenQueue = []; + this.letzteKarteId = null; + this.gelernt = []; + this.nichtGelernt = []; + + // Initialisierung aller Richtungen + kartenListe.forEach(karte => { + ["EN_DE", "DE_EN"].forEach(richtung => { + this.kartenQueue.push({ + karte: karte, + richtung: richtung, + korrektInFolge: 0, + versuche: 0, + maxVersuche: 3, + status: "learning" + }); + }); + }); + + this.#mischeQueue(); + } + + //ÖFFENTLICHE API + + naechstesElement() { + if (this.kartenQueue.length === 0) return null; + + // Verhindert direkte Wiederholung derselben Karte + if ( + this.kartenQueue.length > 1 && + this.kartenQueue[0].karte.id === this.letzteKarteId + ) { + const alternativeIndex = this.kartenQueue.findIndex( + el => el.karte.id !== this.letzteKarteId + ); + + if (alternativeIndex !== -1) { + const [element] = this.kartenQueue.splice(alternativeIndex, 1); + this.kartenQueue.unshift(element); + } + } + + const aktuellesElement = this.kartenQueue.shift(); + this.letzteKarteId = aktuellesElement.karte.id; + + return aktuellesElement; + } + + antwortVerarbeiten(element, istKorrekt) { + if (!element || element.status !== "learning") return; + + element.versuche++; + + if (istKorrekt) { + element.korrektInFolge++; + + if (element.korrektInFolge >= 3) { + element.status = "gelernt"; + this.gelernt.push(element); + this.kartenQueue = this.kartenQueue.filter(e => e !== element); + return; + } + + this.#wiederEinreihen(element, 8, 10); + + } else { + element.korrektInFolge = 0; + element.maxVersuche = 5; + + if (element.versuche >= element.maxVersuche) { + element.status = "nichtGelernt"; + this.nichtGelernt.push(element); + this.kartenQueue = this.kartenQueue.filter(e => e !== element); + return; + } + + this.#wiederEinreihen(element, 2, 3); + } + } + + istBeendet() { + return this.kartenQueue.length === 0; + } + + statistik() { + const alle = [...this.kartenQueue]; + + return { + verbleibend: this.kartenQueue.length, + gelernt: alle.filter(e => e.status === "gelernt").length, + nichtGelernt: alle.filter(e => e.status === "nichtGelernt").length + }; + } + + exportiereZustand() { + return JSON.stringify({ + kartenQueue: this.kartenQueue, + letzteKarteId: this.letzteKarteId + }); + } + + ladeZustand(json) { + const daten = JSON.parse(json); + this.kartenQueue = daten.kartenQueue; + this.letzteKarteId = daten.letzteKarteId; + } + + //PRIVATE METHODEN + #wiederEinreihen(element, minAbstand, maxAbstand) { + const zufall = + Math.floor(Math.random() * (maxAbstand - minAbstand + 1)) + minAbstand; + + const position = Math.min(zufall, this.kartenQueue.length); + this.kartenQueue.splice(position, 0, element); + } + + #mischeQueue() { + for (let i = this.kartenQueue.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [this.kartenQueue[i], this.kartenQueue[j]] = + [this.kartenQueue[j], this.kartenQueue[i]]; + } + } +} + +let flipEngine; + +function startFlipTraining() { + flipEngine = new TrainingsEngine(parsedArray); + zeigeNaechsteFlipKarte(); +} + +function zeigeNaechsteFlipKarte() { + const element = flipEngine.naechstesElement(); + + const container = document.getElementById("trainingFlip"); + container.innerHTML = ""; + + if (!element) { + container.classList.remove("hidden"); + container.innerHTML = `
🎉 Training beendet!
Gelernt: ${flipEngine.gelernt.length}
Nicht gelernt: ${flipEngine.nichtGelernt.length}
`; + return; + } + + const cardEl = document.createElement("div"); + cardEl.className = "training-card"; + + cardEl.innerHTML = ` +
+ +
+
+

${element.richtung === "EN_DE" ? element.karte.englisch : element.karte.deutsch}

+ ${element.richtung === "EN_DE" && element.karte.ipa + ? `
${element.karte.ipa}
` + : `` + } +
+
+ ${element.richtung === "EN_DE" + ? element.karte.beispielEN || "" + : element.karte.beispielDE || "" + } +
+
+ +
+
+

${element.richtung === "EN_DE" ? element.karte.deutsch : element.karte.englisch}

+ ${element.richtung !== "EN_DE" && element.karte.ipa + ? `
${element.karte.ipa}
` + : `` + } +
+
+ ${element.richtung === "EN_DE" + ? element.karte.beispielDE || "" + : element.karte.beispielEN || "" + } +
+
+ +
+`; + + cardEl.onclick = () => cardEl.classList.toggle("flip"); + + const actions = document.createElement("div"); + actions.className = "training-actions"; + const knowBtn = document.createElement("button"); + knowBtn.innerText = "Weiß ich"; + const dontKnowBtn = document.createElement("button"); + dontKnowBtn.innerText = "Weiß ich nicht"; + + knowBtn.onclick = () => { + flipEngine.antwortVerarbeiten(element, true); + zeigeNaechsteFlipKarte(); + }; + dontKnowBtn.onclick = () => { + flipEngine.antwortVerarbeiten(element, false); + zeigeNaechsteFlipKarte(); + }; + + actions.appendChild(knowBtn); + actions.appendChild(dontKnowBtn); + + container.appendChild(cardEl); + container.appendChild(actions); +} + +let multipleEngine; + +function startMultipleTraining() { + multipleEngine = new TrainingsEngine(parsedArray); + zeigeNaechsteMultipleKarte(); +} + +let aktuelleKarte = null; +let ersteAntwort = true; + +function zeigeNaechsteMultipleKarte() { + const container = document.getElementById("trainingMultiple"); + container.innerHTML = ""; + + const element = multipleEngine.naechstesElement(); + + if (!element) { + container.innerHTML = `
🎉 Training beendet!
Gelernt: ${multipleEngine.gelernt.length}
Nicht gelernt: ${multipleEngine.nichtGelernt.length}
`; + return; + } + + aktuelleKarte = element; + ersteAntwort = true; + + const frage = document.createElement("div"); + frage.className = "multiple-frage"; + frage.innerHTML = `

${element.richtung === "EN_DE" ? element.karte.englisch : element.karte.deutsch}

`; + container.appendChild(frage); + + const optionen = generiereMultipleOptionen(element); + const optionContainer = document.createElement("div"); + optionContainer.className = "multiple-optionen"; + + optionen.forEach(text => { + const btn = document.createElement("button"); + btn.className = "multiple-option"; + btn.innerText = text; + + btn.onclick = () => { + const korrektText = element.richtung === "EN_DE" ? element.karte.deutsch : element.karte.englisch; + const istKorrekt = (text === korrektText); + + if (istKorrekt) { + btn.style.backgroundColor = "#a8f0a8"; + if (ersteAntwort) multipleEngine.antwortVerarbeiten(element, true); + setTimeout(() => zeigeNaechsteMultipleKarte(), 500); + + } else if (ersteAntwort) { + btn.style.backgroundColor = "#f5a8a8"; + btn.style.textDecoration = "line-through"; + multipleEngine.antwortVerarbeiten(element, false); + ersteAntwort = false; + } else { + btn.style.backgroundColor = "#f5a8a8"; + btn.style.textDecoration = "line-through"; + } + }; + + optionContainer.appendChild(btn); + }); + + container.appendChild(optionContainer); +} +function generiereMultipleOptionen(element) { + const korrekt = element.richtung === "EN_DE" ? element.karte.deutsch : element.karte.englisch; + + const falscheOptionen = parsedArray + .filter(k => k.id !== element.karte.id) + .map(k => element.richtung === "EN_DE" ? k.deutsch : k.englisch); + + mischeArray(falscheOptionen); + + const optionen = [korrekt, ...falscheOptionen.slice(0, 4)]; + return mischeArray(optionen); +} + +function mischeArray(array) { + for (let i = array.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [array[i], array[j]] = [array[j], array[i]]; + } + return array; +} + +let hintEngine; + +function startHintTraining() { + hintEngine = new TrainingsEngine(parsedArray); + zeigeNaechsteHintKarte(); +} + +function zeigeNaechsteHintKarte() { + const container = document.getElementById("trainingHint"); + container.innerHTML = ""; + + const element = hintEngine.naechstesElement(); + + if (!element) { + container.innerHTML = ` +
+ 🎉 Training beendet!
+ Gelernt: ${hintEngine.gelernt.length}
+ Nicht gelernt: ${hintEngine.nichtGelernt.length} +
+ `; + return; + } + + const korrekt = element.richtung === "EN_DE" ? element.karte.deutsch : element.karte.englisch; + + const frage = document.createElement("div"); + frage.className = "hint-frage"; + frage.innerText = element.richtung === "EN_DE" ? element.karte.englisch : element.karte.deutsch; + container.appendChild(frage); + + const clue = document.createElement("div"); + clue.className = "hint-clue"; + clue.innerText = erstelleClue(korrekt); + container.appendChild(clue); + + const input = document.createElement("input"); + input.className = "hint-input"; + input.placeholder = "Schreibe die Übersetzung..."; + input.autofocus = true; + input.style.fontSize = "18px"; + input.style.padding = "5px 10px"; + input.style.border = "2px solid #005b5b"; + input.style.borderRadius = "6px"; + input.style.width = "300px"; + input.style.caretColor = "#005b5b"; + container.appendChild(input); + + const feedback = document.createElement("div"); + feedback.className = "hint-feedback"; + feedback.style.marginTop = "10px"; + container.appendChild(feedback); + + const button = document.createElement("button"); + button.className = "hint-button"; + button.innerText = "Überprüfen"; + container.appendChild(button); + + let phase = "check"; + + const pruefeAntwort = () => { + if (phase === "check") { + const userAnswer = input.value.trim(); + if (!userAnswer) return; + + const istKorrekt = userAnswer.toLowerCase() === korrekt.toLowerCase(); + hintEngine.antwortVerarbeiten(element, istKorrekt); + + if (istKorrekt) { + input.style.backgroundColor = "#a8f0a8"; + setTimeout(() => zeigeNaechsteHintKarte(), 500); + } else { + input.style.backgroundColor = "#f5a8a8"; + feedback.innerText = `Korrekte Antwort: ${korrekt}`; + button.innerText = "Weiter"; + phase = "next"; + } + } else if (phase === "next") { + zeigeNaechsteHintKarte(); + } + }; + + button.onclick = pruefeAntwort; + + input.addEventListener("keydown", (e) => { + if (e.key === "Enter") { + e.preventDefault(); + pruefeAntwort(); + } + }); + + input.focus(); +} + +function erstelleClue(text) { + if (text.length === 1) return "*"; + + const chars = text.split(""); + let clue = chars.map(char => (char === " " ? " " : "*")); + + const visibleIndices = []; + while (visibleIndices.length < Math.max(1, Math.floor(chars.length / 2))) { + const idx = Math.floor(Math.random() * chars.length); + if (chars[idx] !== " " && !visibleIndices.includes(idx)) { + visibleIndices.push(idx); + } + } + + visibleIndices.forEach(idx => { + clue[idx] = chars[idx]; + }); + + return clue.join(""); +} + +let writeEngine; + +function startWriteTraining() { + writeEngine = new TrainingsEngine(parsedArray); + zeigeNaechsteWriteKarte(); +} + +function zeigeNaechsteWriteKarte() { + const container = document.getElementById("trainingWrite"); + container.innerHTML = ""; + + const element = writeEngine.naechstesElement(); + + if (!element) { + container.innerHTML = ` +
+ 🎉 Training beendet!
+ Gelernt: ${writeEngine.gelernt.length}
+ Nicht gelernt: ${writeEngine.nichtGelernt.length} +
+ `; + return; + } + + const korrekt = element.richtung === "EN_DE" ? element.karte.deutsch : element.karte.englisch; + + const frage = document.createElement("div"); + frage.className = "hint-frage"; + frage.innerHTML = element.richtung === "EN_DE" ? element.karte.englisch : element.karte.deutsch; + container.appendChild(frage); + + const input = document.createElement("input"); + input.className = "hint-input"; + input.placeholder = "Schreibe die Übersetzung..."; + input.autofocus = true; + input.style.fontSize = "18px"; + input.style.padding = "5px 10px"; + input.style.border = "2px solid #005b5b"; + input.style.borderRadius = "6px"; + input.style.width = "300px"; + input.style.caretColor = "#005b5b"; + container.appendChild(input); + + const feedback = document.createElement("div"); + feedback.className = "hint-feedback"; + feedback.style.marginTop = "10px"; + container.appendChild(feedback); + + const button = document.createElement("button"); + button.className = "hint-button"; + button.innerText = "Überprüfen"; + container.appendChild(button); + + let phase = "check"; + + const pruefeAntwort = () => { + if (phase === "check") { + const userAnswer = input.value.trim(); + if (!userAnswer) return; + + const istKorrekt = userAnswer.toLowerCase() === korrekt.toLowerCase(); + writeEngine.antwortVerarbeiten(element, istKorrekt); + + if (istKorrekt) { + input.style.backgroundColor = "#a8f0a8"; + setTimeout(() => zeigeNaechsteWriteKarte(), 500); + } else { + input.style.backgroundColor = "#f5a8a8"; + feedback.innerText = `Korrekte Antwort: ${korrekt}`; + button.innerText = "Weiter"; + phase = "next"; + } + } else if (phase === "next") { + zeigeNaechsteWriteKarte(); + } + }; + + button.onclick = pruefeAntwort; + input.addEventListener("keydown", (e) => { + if (e.key === "Enter") { + e.preventDefault(); + pruefeAntwort(); + } + }); + + input.focus(); +} + +let matchingEngine; +let matchingRunde = 0; +let linkeKarten = []; +let rechteKarten = []; +let aktuelleRichtung = "EN_DE"; + +function startMittelTraining() { + matchingEngine = new TrainingsEngine(parsedArray); + matchingRunde = 0; + ladeMatchingRunde(); +} + +function ladeMatchingRunde() { + const container = document.getElementById("trainingMatching"); + container.innerHTML = ""; + + aktuelleRichtung = matchingRunde % 2 === 0 ? "EN_DE" : "DE_EN"; + matchingRunde++; + + const learningCards = matchingEngine.kartenQueue.filter(e => e.status === "learning"); + + linkeKarten = learningCards + .reduce((acc, el) => { + if (!acc.find(a => a.karte.id === el.karte.id)) acc.push(el); + return acc; + }, []) + .slice(0, 4); + + rechteKarten = mischeArray([...linkeKarten]); + + const linksDiv = document.createElement("div"); + linksDiv.className = "spalte-links"; + + const rechtsDiv = document.createElement("div"); + rechtsDiv.className = "spalte-rechts"; + + linkeKarten.forEach(k => { + const dropZone = document.createElement("div"); + dropZone.className = "training-card drop-zone"; + dropZone.dataset.id = k.karte.id; + + dropZone.innerHTML = ` +
+

${aktuelleRichtung === "EN_DE" ? k.karte.englisch : k.karte.deutsch}

+ ${aktuelleRichtung === "EN_DE" && k.karte.ipa ? `
${k.karte.ipa}
` : ""} +
+
+ ${aktuelleRichtung === "EN_DE" ? k.karte.beispielEN || "" : k.karte.beispielDE || ""} +
+ `; + linksDiv.appendChild(dropZone); + }); + + rechteKarten.forEach((k, index) => { + const ziehKarte = document.createElement("div"); + ziehKarte.className = "training-card zieh-karte"; + ziehKarte.draggable = true; + ziehKarte.dataset.index = index; + + const zeigeEnglisch = aktuelleRichtung === "DE_EN"; + ziehKarte.innerHTML = ` +
+

${zeigeEnglisch ? k.karte.englisch : k.karte.deutsch}

+ ${zeigeEnglisch && k.karte.ipa ? `
${k.karte.ipa}
` : ""} +
+
+ ${zeigeEnglisch ? k.karte.beispielEN || "" : k.karte.beispielDE || ""} +
+ `; + + ziehKarte.addEventListener("dragstart", e => e.dataTransfer.setData("draggedIndex", index)); + ziehKarte.addEventListener("dragover", e => e.preventDefault()); + ziehKarte.addEventListener("drop", e => { + e.preventDefault(); + const draggedIndex = Number(e.dataTransfer.getData("draggedIndex")); + swapZiehKarten(draggedIndex, index, linksDiv, rechtsDiv); + }); + + rechtsDiv.appendChild(ziehKarte); + }); + + container.appendChild(linksDiv); + container.appendChild(rechtsDiv); +} + +function renderMatchingRechts(linksDiv, rechtsDiv) { + rechtsDiv.innerHTML = ""; + + rechteKarten.forEach((k, index) => { + const ziehKarte = document.createElement("div"); + ziehKarte.className = "training-card zieh-karte"; + ziehKarte.draggable = true; + ziehKarte.dataset.index = index; + + const zeigeEnglisch = (aktuelleRichtung === "DE_EN"); + ziehKarte.innerHTML = ` +
+

${zeigeEnglisch ? k.karte.englisch : k.karte.deutsch}

+ ${zeigeEnglisch && k.karte.ipa + ? `
${k.karte.ipa}
` + : "" + } +
+
+ ${zeigeEnglisch + ? k.karte.beispielEN || "" + : k.karte.beispielDE || "" + } +
+ `; + + ziehKarte.addEventListener("dragstart", e => e.dataTransfer.setData("draggedIndex", index)); + ziehKarte.addEventListener("dragover", e => e.preventDefault()); + ziehKarte.addEventListener("drop", e => { + e.preventDefault(); + const draggedIndex = Number(e.dataTransfer.getData("draggedIndex")); + swapZiehKarten(draggedIndex, index, linksDiv, rechtsDiv); + }); + + rechtsDiv.appendChild(ziehKarte); + }); + + const container = document.getElementById("trainingMatching"); + container.appendChild(linksDiv); + container.appendChild(rechtsDiv); +} + +function swapZiehKarten(fromIndex, toIndex, linksDiv, rechtsDiv) { + const temp = rechteKarten[fromIndex]; + rechteKarten[fromIndex] = rechteKarten[toIndex]; + rechteKarten[toIndex] = temp; + renderMatchingRechts(linksDiv, rechtsDiv); +} + +function pruefeRunde() { + const ziehElemente = document.querySelectorAll(".zieh-karte"); + + linkeKarten.forEach((k, index) => { + const gezogene = rechteKarten[index]; + const elementDiv = ziehElemente[index]; + + if (k.karte.id === gezogene.karte.id) { + elementDiv.style.backgroundColor = "#a8f0a8"; + matchingEngine.antwortVerarbeiten(gezogene, true); + } else { + elementDiv.style.backgroundColor = "#f5a8a8"; + matchingEngine.antwortVerarbeiten(gezogene, false); + } + }); + + const learningLeft = matchingEngine.kartenQueue.length; + const gelerntCount = matchingEngine.gelernt.length; + const nichtGelerntCount = matchingEngine.nichtGelernt.length; + + if (learningLeft === 0) { + const container = document.getElementById("trainingMatching"); + container.innerHTML = ` +
+ 🎉 Training beendet!
+ Gelernt: ${gelerntCount}
+ Nicht gelernt: ${nichtGelerntCount} +
+ `; + const checkBtn = document.getElementById("checkBtn"); + if (checkBtn) checkBtn.style.display = "none"; + return; + } + + setTimeout(() => { + ladeMatchingRunde(); + }, 1000); +} + +function mischeArray(array) { + for (let i = array.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [array[i], array[j]] = [array[j], array[i]]; + } + return array; +} \ No newline at end of file diff --git a/MainPage/stas/flashcards.webp b/MainPage/stas/flashcards.webp new file mode 100644 index 0000000..0baf4c7 Binary files /dev/null and b/MainPage/stas/flashcards.webp differ diff --git a/MainPage/stas/style.css b/MainPage/stas/style.css index 0b74026..d8824e6 100644 --- a/MainPage/stas/style.css +++ b/MainPage/stas/style.css @@ -16,7 +16,7 @@ h1 { position: relative; top: 0; width: 100%; - background-color: #005b5b; + background-color: #880b75; color: white; padding: 18px 0; text-align: center; @@ -36,7 +36,7 @@ h1 { margin: 0 auto; margin-top: 10px; padding: 20px; - background-color: #ffffff; + background-color: #d9cfe0; border-radius: 12px; box-shadow: 0 10px 30px rgba(0,0,0,0.08); } @@ -116,16 +116,15 @@ h1 { } .page { - width: 210mm; - height: 297mm; - /* border: px solid #005b5b; */ + width: 190mm; + height: 277mm; padding: 0; box-sizing: border-box; background: white; - display: grid; grid-template-columns: repeat(2, 1fr); grid-template-rows: repeat(4, 1fr); + page-break-after: always; } .page-back { @@ -182,7 +181,6 @@ h1 { .card .ipa { font-size: 14px; color: #666; - /* margin-bottom: 80px; */ } .card .example { @@ -190,3 +188,448 @@ h1 { font-size: 14px; color: #333; } + +.button-wrapper { + max-width: 900px; + margin: 20px auto; + padding: 10px 20px; + display: flex; + justify-content: center; +} + +#kartenErstellen { + width: 100%; + height: 100px; + font-size: 46px; + font-weight: 600; + font-family: -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", Arial, sans-serif; + color: #dc6743; + border: none; + border-radius: 8px; + cursor: pointer; + box-sizing: border-box; + background: linear-gradient(rgba(255,255,255,0.7), rgba(255,255,255,0.9)), url("flashcards.webp"); + background-size: cover; + background-position: center; +} + +#druckenBtn { + width: 500px; + height: 100px; + font-size: 46px; + font-weight: 600; + font-family: -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", Arial, sans-serif; + color: #dc6743; + border: none; + border-radius: 8px; + cursor: pointer; + box-sizing: border-box; + background: linear-gradient(rgba(255,255,255,0.7), rgba(255,255,255,0.9)), url("drucker.jfif"); + background-repeat: repeat; + background-size: 80px; +} + +.erfolgsmeldung, +.modus-auswahl { + display: none; + max-width: 600px; + margin: 20px auto; + text-align: center; +} + +.erfolgsmeldung { + background-color: #e6f4f1; + color: #005b5b; + padding: 12px; + border-radius: 6px; + font-weight: 600; +} + +.modus-auswahl p { + margin-bottom: 12px; + font-weight: 500; +} + +.modus-btn { + margin: 6px; + padding: 10px 16px; + border: none; + border-radius: 6px; + background-color: #005b5b; + color: white; + cursor: pointer; +} + +.modus-btn:hover { + background-color: #007070; +} + +@media print { + body * { + visibility: hidden; + } + #kartenContainer, #kartenContainer * { + visibility: visible; + } + #kartenContainer { + position: absolute; + left: 0; + top: 0; + width: 100%; + margin: 0; + padding: 0; + } +} + +#trainingFlip .training-card { + height: 180px; +} + +#trainingMatching .training-card { + height: 100px; + font-size: 0.9rem; + margin: 0; + margin-top: 10px; +} + +.training-card { + width: 300px; + margin: 10px auto; + perspective: 1000px; + cursor: pointer; + box-sizing: border-box; +} + +#trainingMatching .drop-zone, +#trainingMatching .zieh-karte { + min-height: 120px; + max-height: 120px; + width: 300px; + background: #fff; + border: 2px solid #666; + border-radius: 8px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + font-size: 0.9rem; + padding: 5px; + box-sizing: border-box; + text-align: center; +} + + #trainingMatching .drop-zone h2, + #trainingMatching .zieh-karte h2, + #trainingMatching .drop-zone .ipa, + #trainingMatching .zieh-karte .ipa, + #trainingMatching .drop-zone .example, + #trainingMatching .zieh-karte .example { + margin: 2px 0; + overflow: hidden; + } + +.training-card-inner { + width: 100%; + height: 100%; + position: relative; + transition: transform 0.6s; + transform-style: preserve-3d; +} + +.training-card.flip .training-card-inner { + transform: rotateY(180deg); +} + +.training-front, +.training-back { + position: absolute; + width: 100%; + height: 100%; + backface-visibility: hidden; + border: 2px solid #333; + border-radius: 10px; + padding: 15px; + box-sizing: border-box; + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: stretch; +} + +.card-top { + display: inline-flex; + flex-direction: column; + align-items: center; + gap: 2px; +} + +.card-top h2 { + margin: 0; + line-height: 1.1; +} + +.card-top h3 { + margin: 0; + line-height: 1.1; +} + +.card-top .ipa { + margin: 0; + line-height: 1.1; +} + +.card-example { + margin-top: auto; + text-align: center; + font-size: 15px; + line-height: 1.4; +} + +.ipa { + font-size: 16px; + color: #555; +} + +.training-back { + transform: rotateY(180deg); + background: #f3f3f3; +} + +.training-actions { + text-align: center; + margin-top: 15px; +} + +.training-actions button { + margin: 0 10px; + padding: 8px 16px; + font-size: 16px; + cursor: pointer; +} + +#pdfPages, +#onlineTraining { + display: none; +} + +#trainingMatching { + display: flex; + justify-content: center; + gap: 10px; + align-items: flex-start; +} + +.hidden { + display: none !important; +} + +.spalte-links { + display: flex; + flex-direction: column; + align-items: stretch; + gap: 10px; +} + +.spalte-rechts { + display: flex; + flex-direction: column; + align-items: stretch; + gap: 10px; +} + +.drop-zone, .zieh-karte { + padding: 10px; + margin: 10px 0; + background: #fff; + border: 2px solid #666; + border-radius: 8px; +} + +.zieh-karte { + cursor: grab; +} + +#checkBtn { + width: 500px; + height: 100px; + font-size: 46px; + font-weight: 600; + font-family: -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", Arial, sans-serif; + color: #dc6743; + border: none; + border-radius: 8px; + cursor: pointer; + box-sizing: border-box; + background: linear-gradient(rgba(255,255,255,0.7), rgba(255,255,255,0.9)), url("verified.jfif"); + background-repeat: repeat; + background-size: 80px; +} + +#trainingMultiple { + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-start; + gap: 20px; + margin-top: 30px; +} + +.multiple-frage { + text-align: center; + font-size: 28px; + font-weight: bold; +} + +.multiple-optionen { + display: flex; + flex-direction: column; + gap: 10px; + width: 300px; +} + +.multiple-option { + padding: 10px 15px; + font-size: 16px; + cursor: pointer; + border: 1px solid #ccc; + border-radius: 5px; + background-color: #f0f0f0; + text-align: center; + transition: background-color 0.2s, transform 0.1s; +} + +.multiple-option:hover { + background-color: #e0e0e0; + transform: scale(1.03); +} + +.multiple-option[disabled] { + text-decoration: line-through; + background-color: #f5a8a8; + color: #800; +} + +#trainingHint { + display: flex; + flex-direction: column; + align-items: center; + gap: 20px; + margin-top: 30px; +} + +.hint-frage { + text-align: center; + font-size: 28px; + font-weight: bold; +} + +.hint-input { + width: 300px; + font-size: 18px; + padding: 10px; + text-align: center; + border-radius: 6px; +} + +.hint-button { + padding: 10px 15px; + font-size: 16px; + cursor: pointer; + border-radius: 6px; + border: none; + background-color: #005b5b; + color: white; + transition: 0.2s; +} + +.hint-button:hover { + background-color: #007070; +} + +.hint-feedback { + font-size: 16px; + font-weight: 600; + margin-top: 10px; +} + +.hint-clue { + font-size: 20px; + letter-spacing: 2px; + margin-bottom: 10px; + color: #555; + text-align: center; + font-family: monospace; +} + +#trainingWrite { + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-start; + gap: 20px; + margin-top: 30px; +} + +#trainingWrite .schwer-frage { + text-align: center; + font-size: 28px; + font-weight: bold; +} + +#trainingWrite input[type="text"] { + font-size: 18px; + border-radius: 6px; +} + +#trainingWrite button { + padding: 10px 15px; + font-size: 16px; + cursor: pointer; + border-radius: 6px; + border: none; + background-color: #005b5b; + color: white; + transition: 0.2s; +} + +#trainingWrite button:hover { + background-color: #007070; +} + +#trainingLevels { + display: flex; + flex-direction: column; + gap: 15px; + width: 100%; +} + +.training-title { + margin: 0 0 10px 0; + font-size: 20px; + font-weight: 600; + text-align: left; +} + +#trainingLevels .buttons-row { + display: flex; + gap: 10px; + width: 100%; +} + +#trainingLevels .buttons-row .level-btn { + flex: 1; + padding: 12px 0; + font-size: 16px; + font-weight: 600; + border: none; + border-radius: 8px; + background-color: #f0f0f0; + cursor: pointer; + text-align: center; + transition: background-color 0.2s, transform 0.1s; +} + +#trainingLevels .buttons-row .level-btn:hover { + background-color: #e0e0e0; + transform: scale(1.02); +} diff --git a/MainPage/stas/verified.jfif b/MainPage/stas/verified.jfif new file mode 100644 index 0000000..6e5780b Binary files /dev/null and b/MainPage/stas/verified.jfif differ diff --git a/MainPage/younes/Streichholzreatsel.js b/MainPage/younes/Streichholzreatsel.js index fe8e584..ec669a7 100644 --- a/MainPage/younes/Streichholzreatsel.js +++ b/MainPage/younes/Streichholzreatsel.js @@ -1,299 +1,370 @@ + +// Die Namen der 7 Segmente (a bis g) +const SEGMENT_NAMEN = ["a", "b", "c", "d", "e", "f", "g"]; -const SEG = { a:0, b:1, c:2, d:3, e:4, f:5, g:6 }; -const segNames = ["a","b","c","d","e","f","g"]; +// Ein Mapping: Welches Segment hat welchen "Bit Wert"? +// a=1, b=2, c=4, d=8 ... das sind Zweierpotenzen. +const SEGMENT_INDEX = { a:0, b:1, c:2, d:3, e:4, f:5, g:6 }; -function maskFromSegments(list){ - let m = 0; - for(const s of list) m |= (1 << SEG[s]); - return m; +// Diese Funktion rechnet eine Liste von Segmenten (z.B. "a", "b") in eine Zahl um. +function erstelleMuster(listeVonSegmenten) { + let muster = 0; + for (const segmentBuchstabe of listeVonSegmenten) { + // 1 << X bedeutet: Schiebe die 1 um X Stellen nach links + // Das | (ODER) fügt das Bit hinzu. + muster = muster | (1 << SEGMENT_INDEX[segmentBuchstabe]); + } + return muster; } - -const DIGIT_MASK = [ - maskFromSegments(["a","b","c","d","e","f"]), - maskFromSegments(["b","c"]), - maskFromSegments(["a","b","d","e","g"]), - maskFromSegments(["a","b","c","d","g"]), - maskFromSegments(["b","c","f","g"]), - maskFromSegments(["a","c","d","f","g"]), - maskFromSegments(["a","c","d","e","f","g"]), - maskFromSegments(["a","b","c"]), - maskFromSegments(["a","b","c","d","e","f","g"]), - maskFromSegments(["a","b","c","d","f","g"]) +// Hier speichern wir das Muster für jede Ziffer von 0 bis 9 +// bitmasking: Jede Ziffer ist eine Kombination von Segmenten die an sind +const ZIFFERN_MUSTER = [ + erstelleMuster(["a","b","c","d","e","f"]), // 0 + erstelleMuster(["b","c"]), // 1 + erstelleMuster(["a","b","d","e","g"]), // 2 + erstelleMuster(["a","b","c","d","g"]), // 3 + erstelleMuster(["b","c","f","g"]), // 4 + erstelleMuster(["a","c","d","f","g"]), // 5 + erstelleMuster(["a","c","d","e","f","g"]), // 6 + erstelleMuster(["a","b","c"]), // 7 + erstelleMuster(["a","b","c","d","e","f","g"]), // 8 + erstelleMuster(["a","b","c","d","f","g"]) // 9 ]; - -const MASK_TO_DIGIT = new Map(DIGIT_MASK.map((m,d)=>[m,d])); +// Eine Rückwärts Suche: Welches Muster gehört zu welcher Zahl? +// Wir bauen eine Map (Liste), um das schnell zu finden. +const MUSTER_ZU_ZAHL = new Map(); +ZIFFERN_MUSTER.forEach((muster, zahl) => { + MUSTER_ZU_ZAHL.set(muster, zahl); +}); -function removableTargetsFromDigit(d){ - const start = DIGIT_MASK[d]; - const res = []; - for(let t=0;t<=9;t++){ - const target = DIGIT_MASK[t]; - if((target & start) === target){ - - const removed = popcount(start ^ target); - res.push({to:t, removed}); - } + + +// Zählt, wie viele Bits in einer Zahl auf 1 stehen. +// (Also: Wie viele Streichhölzer sind an?) +function zaehleStreichhoelzer(zahl) { + let anzahl = 0; + // Solange die Zahl nicht 0 ist + while (zahl > 0) { + // Ein kleiner Trick um das letzte Bit zu löschen und zu zählen + zahl = zahl & (zahl - 1); + anzahl++; } - return res; + return anzahl; } -function popcount(x){ - x = x >>> 0; - let c = 0; - while(x){ x &= (x-1); c++; } - return c; -} - -function randInt(min, max){ // inclusive +// Gibt eine zufällige Zahl zwischen min und max zurück +function zufallsZahl(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } -function pick(arr){ return arr[randInt(0, arr.length-1)]; } -let level = 1; -let targetRemove = 2; -let current = null; -let solution = null; -let removedSoFar = 0; - - -let removedSet = new Set(); - -const elEq = document.getElementById("equation"); -const elRemovedGrid = document.getElementById("removedGrid"); -const elRemovedCount = document.getElementById("removedCount"); -const elPileCount = document.getElementById("pileCount"); -const elLvl = document.getElementById("lvl"); -const elTarget = document.getElementById("target"); -const elGoalN = document.getElementById("goalN"); -const elTruthDot = document.getElementById("truthDot"); -const elTruthText = document.getElementById("truthText"); -const elHint = document.getElementById("hint"); - -document.getElementById("btnNew").addEventListener("click", () => { - level++; - generateLevel(); -}); -document.getElementById("btnReset").addEventListener("click", () => { - - resetPlayState(); - renderEquation(); - updateTruthUI(); -}); - -function segmentsFromMask(mask){ - const set = new Set(); - for(let i=0;i<7;i++){ - if(mask & (1< { + aktuellesLevel++; + starteNeuesLevel(); +}); + +document.getElementById("btnReset").addEventListener("click", () => { + // Level neu starten (aber gleiches Level) + setzeSpielZurueck(); + zeichneGleichung(); + pruefeObWahr(); +}); + + + +function setzeSpielZurueck() { + geloeschteStreichhoelzer.clear(); // Liste leeren + anzahlGeloescht = 0; + elGeloeschtGrid.innerHTML = ""; // Anzeige leeren + updateZaehlerAnzeige(); } -function equationIsTrue(){ +function updateZaehlerAnzeige() { + elZaehlerGeloescht.textContent = anzahlGeloescht; + elStapelZaehler.textContent = anzahlGeloescht; +} + +// Berechnet, welche Zahl gerade angezeigt wird (basierend auf dem was gelöscht wurde) +function berechneAngezeigteZahl(originalZahl, positionIndex) { + let maske = ZIFFERN_MUSTER[originalZahl]; + + // Wir gehen alle 7 Segmente durch + for (const seg of SEGMENT_NAMEN) { + const schluessel = positionIndex + "-" + seg; + + // Wenn dieses Segment gelöscht wurde... + if (geloeschteStreichhoelzer.has(schluessel)) { + // ... dann schalten wir das Bit in der Maske aus (mit & ~) + maske = maske & ~(1 << SEGMENT_INDEX[seg]); + } + } + + // Schauen, ob das resultierende Muster eine gültige Zahl ist + if (MUSTER_ZU_ZAHL.has(maske)) { + return MUSTER_ZU_ZAHL.get(maske); + } else { + return null; // Keine gültige Zahl (Kaputt) + } +} + +// Prüft: Ist A + B = C ? +function istGleichungWahr() { + const a = berechneAngezeigteZahl(aktuelleGleichung.A, 0); + const b = berechneAngezeigteZahl(aktuelleGleichung.B, 1); + const c = berechneAngezeigteZahl(aktuelleGleichung.C, 2); + + // Wenn irgendeine Zahl ungültig ist, ist die Gleichung falsch + if (a === null || b === null || c === null) return false; - const a = displayedDigitValue(current.A, 0); - const b = displayedDigitValue(current.B, 1); - const c = displayedDigitValue(current.C, 2); - if(a === null || b === null || c === null) return false; return (a + b) === c; } -function updateTruthUI(){ - const ok = equationIsTrue(); - elTruthDot.classList.toggle("ok", ok); - elTruthText.textContent = ok ? "Equation is TRUE" : "Equation is FALSE"; -} - - -function resetPlayState(){ - removedSet.clear(); - removedSoFar = 0; - elRemovedGrid.innerHTML = ""; - syncRemovedCounts(); -} - -function syncRemovedCounts(){ - elRemovedCount.textContent = String(removedSoFar); - elPileCount.textContent = String(removedSoFar); -} - -function renderDigit(digitValue, digitIndex, color){ - const digit = document.createElement("div"); - digit.className = "digit"; - - const baseMask = DIGIT_MASK[digitValue]; - const baseSegs = segmentsFromMask(baseMask); - - for(const s of segNames){ - if(!baseSegs.has(s)) continue; - - const seg = document.createElement("div"); - seg.className = "seg " + s; - seg.style.background = color; - - const key = digitIndex + "-" + s; - if(removedSet.has(key)) seg.classList.add("removed"); - - seg.addEventListener("click", () => { - if(removedSet.has(key)) return; - if(removedSoFar >= targetRemove) return; - - removedSet.add(key); - removedSoFar++; - - - seg.classList.add("removed"); - - - const clone = document.createElement("div"); - clone.className = "removedSeg"; - clone.style.background = color; - elRemovedGrid.appendChild(clone); - - syncRemovedCounts(); - updateTruthUI(); - - if(removedSoFar === targetRemove){ - if(equationIsTrue()){ - elHint.innerHTML = "Solved! You removed exactly the target and made the equation true. Click New level."; - } else { - elHint.innerHTML = " Not solved. You used all removals but the equation isn’t true. Click Reset level to try again."; - } - } - }); - - digit.appendChild(seg); +function pruefeObWahr() { + const istWahr = istGleichungWahr(); + + if (istWahr) { + elWahrheitPunkt.classList.add("ok"); + elWahrheitText.textContent = "Gleichung ist WAHR"; + } else { + elWahrheitPunkt.classList.remove("ok"); + elWahrheitText.textContent = "Gleichung ist FALSCH"; } - return digit; } -function renderEquation(){ - elEq.innerHTML = ""; - const colors = [ - "linear-gradient(180deg,#ff6b6b,#d64545)", - "linear-gradient(180deg,#6bcBff,#3a7bd5)", - "linear-gradient(180deg,#6bffb3,#1fae63)" +// Erstellt das HTML für EINE Ziffer +function erstelleZifferHTML(zahlenWert, positionIndex, farbe) { + const zifferContainer = document.createElement("div"); + zifferContainer.className = "digit"; + + // Welche Segmente hat die Zahl ursprünglich? + const maske = ZIFFERN_MUSTER[zahlenWert]; + + for (let i = 0; i < 7; i++) { + const segName = SEGMENT_NAMEN[i]; + + // Prüfen: Hat die Zahl dieses Segment? (Bit Test) + const hatSegment = (maske & (1 << i)) !== 0; + + if (hatSegment) { + const segElement = document.createElement("div"); + segElement.className = "seg " + segName; + segElement.style.background = farbe; + + // Eindeutige ID für dieses Segment (z.B. "0-a") + const id = positionIndex + "-" + segName; + + // Wenn schon gelöscht, Klasse hinzufügen + if (geloeschteStreichhoelzer.has(id)) { + segElement.classList.add("removed"); + } + + // Klick Event (Hier passiert die Action!) + segElement.addEventListener("click", () => { + // Abbruch wenn schon weg oder Limit erreicht + if (geloeschteStreichhoelzer.has(id)) return; + if (anzahlGeloescht >= zielAnzahlLoeschen) return; + + // Löschen durchführen + geloeschteStreichhoelzer.add(id); + anzahlGeloescht++; + segElement.classList.add("removed"); + + // Kleines Streichholz in den Mülleimer animieren + const clone = document.createElement("div"); + clone.className = "removedSeg"; + clone.style.background = farbe; + elGeloeschtGrid.appendChild(clone); + + updateZaehlerAnzeige(); + pruefeObWahr(); + + // Gewinn Prüfung + if (anzahlGeloescht === zielAnzahlLoeschen) { + if (istGleichungWahr()) { + elHinweis.innerHTML = "Gelöst! Super gemacht. Klicke auf Neu level."; + } else { + elHinweis.innerHTML = "Nicht gelöst. Alle Züge verbraucht, aber Gleichung falsch. Reset?"; + } + } + }); + + zifferContainer.appendChild(segElement); + } + } + return zifferContainer; +} + +function zeichneGleichung() { + elGleichung.innerHTML = ""; // Alles löschen + + const farben = [ + "linear-gradient(180deg,#ff6b6b,#d64545)", // Rot für A + "linear-gradient(180deg,#6bcBff,#3a7bd5)", // Blau für B + "linear-gradient(180deg,#6bffb3,#1fae63)" // Grün für C ]; + // Gruppe A bauen const g1 = document.createElement("div"); g1.className = "group"; - g1.appendChild(renderDigit(current.A, 0, colors[0])); + g1.appendChild(erstelleZifferHTML(aktuelleGleichung.A, 0, farben[0])); + // Plus Zeichen const plus = document.createElement("div"); plus.className = "symbol"; plus.textContent = "+"; + // Gruppe B bauen const g2 = document.createElement("div"); g2.className = "group"; - g2.appendChild(renderDigit(current.B, 1, colors[1])); + g2.appendChild(erstelleZifferHTML(aktuelleGleichung.B, 1, farben[1])); + // Ist Gleich Zeichen const eq = document.createElement("div"); eq.className = "symbol"; eq.textContent = "="; + // Gruppe C bauen const g3 = document.createElement("div"); g3.className = "group"; - g3.appendChild(renderDigit(current.C, 2, colors[2])); + g3.appendChild(erstelleZifferHTML(aktuelleGleichung.C, 2, farben[2])); - elEq.appendChild(g1); - elEq.appendChild(plus); - elEq.appendChild(g2); - elEq.appendChild(eq); - elEq.appendChild(g3); + // Alles zusammenfügen + elGleichung.appendChild(g1); + elGleichung.appendChild(plus); + elGleichung.appendChild(g2); + elGleichung.appendChild(eq); + elGleichung.appendChild(g3); - updateTruthUI(); + pruefeObWahr(); } -function generateLevel(){ - resetPlayState(); + // 7. LEVEL GENERATOR (Das Gehirn) + // Hier wird ein Level gebaut, das garantiert lösbar ist. + - - targetRemove = Math.min(2 + Math.floor(Math.log2(level + 1)), 6); +function starteNeuesLevel() { + setzeSpielZurueck(); + // Ziel berechnen: Level 1-2 -> 2 löschen, danach evtl mehr. Max 6. + zielAnzahlLoeschen = Math.min(2 + Math.floor(Math.log2(aktuellesLevel + 1)), 6); - let tries = 0; - while(true){ - tries++; - if(tries > 5000){ - targetRemove = Math.max(2, targetRemove - 1); - tries = 0; + let versuche = 0; + + // Endlosschleife, bis wir ein passendes Level finden + while (true) { + versuche++; + // Sicherheitsnetz: Wenn es zu lange dauert, Ziel senken + if (versuche > 5000) { + zielAnzahlLoeschen = Math.max(2, zielAnzahlLoeschen - 1); + versuche = 0; } - const As = randInt(0, 9); - const Bs = randInt(0, 9); - const Cs = As + Bs; - if(Cs < 0 || Cs > 9) continue; + // 1. Wir denken uns eine KORREKTE Lösung aus (z.B. 3 + 5 = 8) + const lsgA = zufallsZahl(0, 9); + const lsgB = zufallsZahl(0, 9); + const lsgC = lsgA + lsgB; + if (lsgC > 9) continue; // Ergebnis darf nur 1 stellig sein (0-9) + + // 2. Wir suchen Zahlen, die mehr Striche haben als unsere Lösung + // (Aus denen man die Lösung "schnitzen" kann) + const moeglicheA = findeMoeglicheUrsprungsZiffern(lsgA); + const moeglicheB = findeMoeglicheUrsprungsZiffern(lsgB); + const moeglicheC = findeMoeglicheUrsprungsZiffern(lsgC); + + // Eine zufällige Auswahl treffen + const startA = wähleZufällig(moeglicheA); + const startB = wähleZufällig(moeglicheB); + const startC = wähleZufällig(moeglicheC); + + // 3. Berechnen: Wie viele Striche müssen weg, um zur Lösung zu kommen? + // XOR (^) zeigt den Unterschied an. + const diffA = zaehleStreichhoelzer(ZIFFERN_MUSTER[startA] ^ ZIFFERN_MUSTER[lsgA]); + const diffB = zaehleStreichhoelzer(ZIFFERN_MUSTER[startB] ^ ZIFFERN_MUSTER[lsgB]); + const diffC = zaehleStreichhoelzer(ZIFFERN_MUSTER[startC] ^ ZIFFERN_MUSTER[lsgC]); - const Achoices = superDigits(As); - const Bchoices = superDigits(Bs); - const Cchoices = superDigits(Cs); + const gesamtWeg = diffA + diffB + diffC; - const Ashow = pick(Achoices); - const Bshow = pick(Bchoices); - const Cshow = pick(Cchoices); + // Passt das zu unserem Ziel? + if (gesamtWeg !== zielAnzahlLoeschen) continue; - const need = - popcount(DIGIT_MASK[Ashow] ^ DIGIT_MASK[As]) + - popcount(DIGIT_MASK[Bshow] ^ DIGIT_MASK[Bs]) + - popcount(DIGIT_MASK[Cshow] ^ DIGIT_MASK[Cs]); + // 4. Wichtig: Die angezeigte Start Gleichung muss FALSCH sein. + // Sonst gibt es ja nichts zu rätseln. + if ((startA + startB) === startC) continue; - if(need !== targetRemove) continue; - - - const shownTrue = (Ashow + Bshow) === Cshow; - if(shownTrue) continue; - - solution = { A: As, B: Bs, C: Cs }; - current = { A: Ashow, B: Bshow, C: Cshow }; - break; + // Gefunden! Speichern. + aktuelleGleichung = { A: startA, B: startB, C: startC }; + break; // Schleife beenden } - elLvl.textContent = String(level); - elTarget.textContent = String(targetRemove); - elGoalN.textContent = String(targetRemove); + // UI Updates + elLevelAnzeige.textContent = aktuellesLevel; + elZielAnzeige.textContent = zielAnzahlLoeschen; + elZielText.textContent = zielAnzahlLoeschen; - elHint.innerHTML = - `Level ${level}: Make the equation true by removing ${targetRemove} match(es). ` + - `You can only remove sticks (click them).`; + elHinweis.innerHTML = + `Level ${aktuellesLevel}: Mache die Gleichung wahr, indem du ${zielAnzahlLoeschen} Streichhölzer entfernst.`; - renderEquation(); - syncRemovedCounts(); - updateTruthUI(); + zeichneGleichung(); } -function superDigits(baseDigit){ - const base = DIGIT_MASK[baseDigit]; - const res = []; - for(let d=0; d<=9; d++){ - const m = DIGIT_MASK[d]; - if((m & base) === base){ - res.push(d); - } - } - return res; -} -generateLevel(); \ No newline at end of file +// Spiel starten! +starteNeuesLevel(); \ No newline at end of file diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..51bf035 --- /dev/null +++ b/Readme.md @@ -0,0 +1,23 @@ +# Lernplattform Projekt + +Dies ist unser Lernplattform-Projekt, entwickelt von: + +- Abdelaziz Elouazzani +- Younes El Haddoury +- Ayman Alshian +- Stanislav Kharchenko +- Saad Akki +- Ismail Amara + +--- + +## Projektbeschreibung + +Dieses Projekt ist eine Lernplattform, die verschiedene Funktionen zum Üben und Lernen bietet. + +--- + +## Abgabe & Download + +- **Git-Repository:** [Zum Repository](https://git.bib.de/PBT3H24AKH/LerningCSW.git) +- **Projekt als ZIP herunterladen:** [Download ZIP](https://git.bib.de/PBT3H24AKH/LerningCSW/archive/refs/heads/main.zip)