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; navigator.clipboard.writeText(text).then(() => { alert('Format wurde in die Zwischenablage kopiert!'); }).catch(err => { console.error('Konnte nicht kopieren: ', err); }); }); // 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 = []; for (let block of wortBlocks) { const lines = block.trim().split("\n").map(line => line.trim()); if (lines.length !== 5) { console.warn("Block übersprungen (falsches Format):", block); continue; } const wortObj = { id: crypto.randomUUID(), englisch: lines[0], ipa: lines[1], beispielEN: lines[2], deutsch: lines[3], beispielDE: lines[4] }; wortListe.push(wortObj); } return wortListe; } // Gibt beide Seiten als Objekt zurück. function createPagePair() { const frontPage = document.createElement("div"); frontPage.className = "page page-front"; const backPage = document.createElement("div"); backPage.className = "page page-back"; return { frontPage, backPage }; } const button = document.getElementById("kartenErstellen"); 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 < wordArray.length; i += 8) { const { frontPage, backPage } = createPagePair(); wordArray.slice(i, i + 8).forEach((karte) => { const frontCard = document.createElement("div"); frontCard.className = "card card-en"; frontCard.innerHTML = `

${karte.englisch}

${karte.ipa}
${karte.beispielEN}
`; frontPage.appendChild(frontCard); const backCard = document.createElement("div"); backCard.className = "card card-de"; backCard.innerHTML = `

${karte.deutsch}

${karte.beispielDE}
`; backPage.appendChild(backCard); }); 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; }