/** * 🧩 INTERAKTIVES PARSONS-PUZZLE & PRIMM WIDGET 🧩 * ================================================= * Basiert auf der Forschung von Dale Parsons & Barbara Ericson. * Ermöglicht Schülerinnen und Schülern das Sortieren von Code-Blöcken * mit sofortigem Feedback und Gamification-XP. */ (function () { class ParsonsWidget { constructor(container) { this.container = container; this.puzzleId = container.dataset.puzzleId || "puzzle_" + Math.random().toString(36).substr(2, 9); this.initialLines = JSON.parse(container.dataset.lines || "[]"); this.solution = JSON.parse(container.dataset.solution || "[]"); this.explanation = container.dataset.explanation || "Sehr gut! Du hast die Logik fehlerfrei aufgebaut."; this.xpReward = parseInt(container.dataset.xp || "25", 10); this.currentLines = [...this.initialLines]; this.isSolved = this.loadSolvedState(); this.render(); } loadSolvedState() { try { const solved = JSON.parse(localStorage.getItem("parsons_solved") || "{}"); return !!solved[this.puzzleId]; } catch (e) { return false; } } saveSolvedState() { try { const solved = JSON.parse(localStorage.getItem("parsons_solved") || "{}"); solved[this.puzzleId] = true; localStorage.setItem("parsons_solved", JSON.stringify(solved)); // Gamification XP Bonus gutschreiben if (window.GAMIFICATION_DATA) { window.GAMIFICATION_DATA.xp = (window.GAMIFICATION_DATA.xp || 0) + this.xpReward; if (typeof renderGamificationHUD === "function") { renderGamificationHUD(); } } } catch (e) { console.error("Fehler beim Speichern des Puzzle-Status:", e); } } render() { this.container.classList.add("parsons-box"); this.container.innerHTML = `
🧩 Code-Puzzle (Parsons Problem) ${this.isSolved ? '✅ Gelöst (+'+this.xpReward+' XP)' : '⭐ +'+this.xpReward+' XP'}

Bringe die Code-Blöcke in die richtige logische Reihenfolge, bevor du selbst programmierst:

${this.currentLines.map((line, idx) => `
☰
${this.escapeHtml(line)}
`).join("")}
${this.isSolved ? `
🎉 Perfekt gelöst!
${this.explanation}
` : ''}
`; this.attachEvents(); } escapeHtml(text) { const div = document.createElement("div"); div.textContent = text; return div.innerHTML; } attachEvents() { const board = document.getElementById(`board-${this.puzzleId}`); const checkBtn = document.getElementById(`check-${this.puzzleId}`); const hintBtn = document.getElementById(`hint-${this.puzzleId}`); // Up / Down Buttons board.querySelectorAll(".btn-parsons-move").forEach(btn => { btn.addEventListener("click", (e) => { const lineEl = e.target.closest(".parsons-line"); const idx = parseInt(lineEl.dataset.index, 10); const dir = parseInt(e.target.dataset.dir, 10); const targetIdx = idx + dir; if (targetIdx >= 0 && targetIdx < this.currentLines.length) { const temp = this.currentLines[idx]; this.currentLines[idx] = this.currentLines[targetIdx]; this.currentLines[targetIdx] = temp; this.render(); } }); }); // Check Button checkBtn.addEventListener("click", () => this.checkSolution()); // Hint Button hintBtn.addEventListener("click", () => { const correctFirst = this.solution[0]; const currentFirstIdx = this.currentLines.indexOf(correctFirst); if (currentFirstIdx > 0) { this.currentLines.splice(currentFirstIdx, 1); this.currentLines.unshift(correctFirst); this.render(); const feedback = document.getElementById(`feedback-${this.puzzleId}`); feedback.innerHTML = `
💡 Tipp:
Der erste Block ${this.escapeHtml(correctFirst)} wurde an den Anfang gesetzt!
`; feedback.style.display = "block"; } }); } checkSolution() { const feedback = document.getElementById(`feedback-${this.puzzleId}`); let correct = true; for (let i = 0; i < this.solution.length; i++) { if (this.currentLines[i] !== this.solution[i]) { correct = false; break; } } if (correct) { feedback.innerHTML = `
🎉 Bravo! Alle Blöcke sind in der perfekten Reihenfolge!

${this.explanation}

⭐ Du hast +${this.xpReward} XP für deinen Entwickler-Pass freigeschaltet!

`; feedback.style.display = "block"; this.saveSolvedState(); this.isSolved = true; } else { feedback.innerHTML = `
🤔 Noch nicht ganz...

Einige Zeilen stehen noch an der falschen Stelle. Überlege Schritt für Schritt: Was muss zuerst initialisiert oder berechnet werden, bevor der nächste Schritt ausgeführt werden kann?

`; feedback.style.display = "block"; } } } // Initialisiere alle Puzzle-Widgets auf der Seite document.addEventListener("DOMContentLoaded", () => { document.querySelectorAll(".parsons-puzzle").forEach(el => { new ParsonsWidget(el); }); }); })();