Didaktisches Upgrade: Interaktive Parsons-Puzzles, Traceback-Dolmetscher & offizielle Abschluss-Zertifikate
This commit is contained in:
parent
e74c243259
commit
c428db6a5c
36 changed files with 740 additions and 6 deletions
|
|
@ -10,5 +10,5 @@
|
||||||
"streak_tage": 1,
|
"streak_tage": 1,
|
||||||
"letzter_aktiver_tag": "2026-08-29",
|
"letzter_aktiver_tag": "2026-08-29",
|
||||||
"historie": [],
|
"historie": [],
|
||||||
"zuletzt_aktualisiert": "2026-08-29T15:07:09.451191"
|
"zuletzt_aktualisiert": "2026-08-29T15:40:02.637013"
|
||||||
}
|
}
|
||||||
59
assets/certificate.js
Normal file
59
assets/certificate.js
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
/**
|
||||||
|
* 🎓 OFFIZIELLES LEISTUNGS-ZERTIFIKAT 🎓
|
||||||
|
* =======================================
|
||||||
|
* Generiert ein ausdruckbares Abschlusszertifikat nach Abschluss eines Lehrpfads.
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
window.zeigeZertifikatModal = function (lehrpfadNummer) {
|
||||||
|
const data = window.GAMIFICATION_DATA || { spieler_name: "Python-Entwicklerin", level: 1 };
|
||||||
|
const dateStr = new Date().toLocaleDateString("de-DE", { day: "2-digit", month: "long", year: "numeric" });
|
||||||
|
|
||||||
|
let titel = "Grundlagen der Python-Programmierung";
|
||||||
|
let moduleDesc = "10 Module: Zahlen & Rechnen, Datentypen, f-Strings, Kontrollstrukturen, Funktionen, Listen, Strings, Dictionaries, Sets & Comprehensions";
|
||||||
|
|
||||||
|
if (lehrpfadNummer === 2) {
|
||||||
|
titel = "Einstieg in die Objektorientierung (OOP) & Entwickler-Tools";
|
||||||
|
moduleDesc = "9 Module: Klassen, Konstruktor __init__, self, Methoden, UML-Diagramme, VS Code, Git-Versionskontrolle, Komposition & Tamagotchi-Projekt";
|
||||||
|
} else if (lehrpfadNummer === 3) {
|
||||||
|
titel = "Fortgeschrittenes OOP, Softwarequalität & Desktop-GUIs";
|
||||||
|
moduleDesc = "10 Module: Speicher-Referenzen, Dunder-Methoden, TDD Unit Testing, Vererbung, Polymorphie, Exceptions, JSON-Persistenz, Tkinter GUIs, Container & Masterprojekt";
|
||||||
|
} else if (lehrpfadNummer === "master") {
|
||||||
|
titel = "Master of Python Software Engineering";
|
||||||
|
moduleDesc = "Vollständiger Abschluss aller 3 Lehrpfade (27 Module, 188 bestandene automatisierte Unittests, Model-View-Controller Desktop-App)";
|
||||||
|
}
|
||||||
|
|
||||||
|
const modal = document.createElement("div");
|
||||||
|
modal.className = "certificate-overlay";
|
||||||
|
modal.innerHTML = `
|
||||||
|
<div class="certificate-container">
|
||||||
|
<div class="certificate-border">
|
||||||
|
<div class="certificate-inner">
|
||||||
|
<div class="certificate-badge">🎓 OFFIZIELLES ZERTIFIKAT 🎓</div>
|
||||||
|
<h1 class="certificate-headline">Erfolgreicher Abschluss</h1>
|
||||||
|
<p class="certificate-sub">Hiermit wird bescheinigt, dass</p>
|
||||||
|
<div class="certificate-student-name">${data.spieler_name || "Python-Entwicklerin"}</div>
|
||||||
|
<p class="certificate-text">den anspruchsvollen Lehrpfad</p>
|
||||||
|
<h2 class="certificate-track-title">${titel}</h2>
|
||||||
|
<p class="certificate-desc">${moduleDesc}</p>
|
||||||
|
<div class="certificate-meta">
|
||||||
|
<div>
|
||||||
|
<strong>Erreichtes Level:</strong> Level ${data.level || 1} (${data.titel || "Entwicklerin"})
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<strong>Datum:</strong> ${dateStr}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="certificate-seal">🏆 EXZELLENZ-SIEGEL</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="certificate-actions">
|
||||||
|
<button onclick="window.print()" class="btn" style="background: var(--success);">🖨️ Zertifikat drucken / Als PDF speichern</button>
|
||||||
|
<button onclick="document.querySelector('.certificate-overlay').remove()" class="btn btn-secondary">Schließen</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
document.body.appendChild(modal);
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
@ -11,7 +11,7 @@ window.GAMIFICATION_DATA = {
|
||||||
"streak_tage": 1,
|
"streak_tage": 1,
|
||||||
"letzter_aktiver_tag": "2026-08-29",
|
"letzter_aktiver_tag": "2026-08-29",
|
||||||
"historie": [],
|
"historie": [],
|
||||||
"zuletzt_aktualisiert": "2026-08-29T15:07:09.451191"
|
"zuletzt_aktualisiert": "2026-08-29T15:40:02.637013"
|
||||||
};
|
};
|
||||||
window.GAMIFICATION_BADGES_KATALOG = {
|
window.GAMIFICATION_BADGES_KATALOG = {
|
||||||
"rechenkonegin": {
|
"rechenkonegin": {
|
||||||
|
|
|
||||||
170
assets/interpreter.js
Normal file
170
assets/interpreter.js
Normal file
|
|
@ -0,0 +1,170 @@
|
||||||
|
/**
|
||||||
|
* 🩺 PYTHON TRACEBACK & FEHLER-DOLMETSCHER 🩺
|
||||||
|
* ============================================
|
||||||
|
* Basiert auf der didaktischen Fehlerforschung (Brett Becker et al., SIGCSE).
|
||||||
|
* Übersetzt kryptische Python-Fehlermeldungen in einfühlsames, klares Deutsch
|
||||||
|
* mit konkreten Handlungsanweisungen für Schülerinnen und Schüler.
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
const ERROR_RULES = [
|
||||||
|
{
|
||||||
|
type: "IndentationError",
|
||||||
|
pattern: /IndentationError: (expected an indented block|unindent does not match)/i,
|
||||||
|
title: "📐 Einrückungsfehler (IndentationError)",
|
||||||
|
explanation: "Python nutzt Einrückungen (Standard: genau 4 Leerzeichen), um zu erkennen, welcher Code zu einer Funktion, `if`-Bedingung oder Schleife gehört.",
|
||||||
|
causes: [
|
||||||
|
"Nach einem Doppelpunkt (<code>def ...:</code>, <code>if ...:</code>, <code>for ...:</code>) fehlt die Einrückung.",
|
||||||
|
"Leerzeichen und Tabulatoren wurden versehentlich gemischt."
|
||||||
|
],
|
||||||
|
fix: "Drücke nach dem Doppelpunkt <kbd>Enter</kbd> und rücke die Zeile mit <kbd>Tab</kbd> oder 4 Leerzeichen ein. Mit <kbd>Umschalt</kbd> + <kbd>Tab</kbd> kannst du Zeilen wieder nach links rücken."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "TypeError NoneType",
|
||||||
|
pattern: /TypeError: 'NoneType' object is not (subscriptable|iterable|callable)/i,
|
||||||
|
title: "🕳️ Zugriff auf 'None' (TypeError)",
|
||||||
|
explanation: "Du versuchst auf ein Objekt zuzugreifen, das gar nicht existiert oder den Wert <code>None</code> hat.",
|
||||||
|
causes: [
|
||||||
|
"Eine aufgerufene Funktion hat vergessen, ihr Ergebnis mit <code>return</code> zurückzugeben.",
|
||||||
|
"Eine Listen-Methode wie <code>liste.sort()</code> oder <code>liste.append()</code> gibt immer <code>None</code> zurück (sie verändert die Liste direkt!)."
|
||||||
|
],
|
||||||
|
fix: "Prüfe in deinen Funktionen, ob am Ende ein <code>return ergebnis</code> steht. Schreibe niemals <code>x = liste.sort()</code>, sondern nur <code>liste.sort()</code>."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "AttributeError",
|
||||||
|
pattern: /AttributeError: '([^']+)' object has no attribute '([^']+)'/i,
|
||||||
|
title: "🔍 Unbekanntes Attribut oder Methode (AttributeError)",
|
||||||
|
explanation: "Python konnte an dem Objekt die gewünschte Methode oder Eigenschaft nicht finden.",
|
||||||
|
causes: [
|
||||||
|
"Tippfehler im Namen der Methode oder Variable (z.B. <code>anhängen</code> statt <code>append</code>).",
|
||||||
|
"Groß- und Kleinschreibung nicht beachtet (z.B. <code>.Name</code> statt <code>.name</code>).",
|
||||||
|
"In der Klassen-Methode wurde <code>self.</code> vergessen (z.B. <code>alter</code> statt <code>self.alter</code>)."
|
||||||
|
],
|
||||||
|
fix: "Überprüfe die Schreibweise des Attributs exakt Buchstabe für Buchstabe. Nutze in Klassen immer <code>self.attributname</code>."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "TypeError self missing",
|
||||||
|
pattern: /TypeError: ([^\(]+)\(\) takes \d+ positional arguments? but \d+ were given/i,
|
||||||
|
title: "🧩 Fehlendes 'self' in Methoden-Definition (TypeError)",
|
||||||
|
explanation: "Eine Methode in einer Klasse erwartet weniger oder mehr Parameter als übergeben wurden.",
|
||||||
|
causes: [
|
||||||
|
"Der klassische Anfängerfehler: Du hast im Methodenkopf das <code>self</code> als ersten Parameter vergessen! (z.B. <code>def fahren():</code> statt <code>def fahren(self):</code>)."
|
||||||
|
],
|
||||||
|
fix: "Schreibe in jeder Methode deiner Klasse als allerersten Parameter immer <code>self</code>: z.B. <code>def beschleunigen(self, kmh):</code>."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "IndexError",
|
||||||
|
pattern: /IndexError: (list index out of range|string index out of range)/i,
|
||||||
|
title: "🎯 Index außerhalb des gültigen Bereichs (IndexError)",
|
||||||
|
explanation: "Du greifst auf eine Position (Index) in einer Liste oder einem String zu, die gar nicht existiert.",
|
||||||
|
causes: [
|
||||||
|
"Off-by-One Fehler: In Python beginnt die Zählung bei <code>0</code>! Eine Liste mit 3 Elementen hat nur die Indizes <code>0, 1, 2</code> (nicht 3).",
|
||||||
|
"Die Liste ist noch leer."
|
||||||
|
],
|
||||||
|
fix: "Prüfe die Länge der Liste mit <code>len(liste)</code>. Das letzte Element erreichst du immer sicher mit <code>liste[-1]</code>."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "KeyError",
|
||||||
|
pattern: /KeyError: (.+)/i,
|
||||||
|
title: "🔑 Schlüssel nicht im Dictionary gefunden (KeyError)",
|
||||||
|
explanation: "Du hast versucht, aus einem Dictionary <code>dict[schluessel]</code> einen Eintrag abzufragen, der nicht existiert.",
|
||||||
|
causes: [
|
||||||
|
"Der gesuchte Key ist nicht im Dictionary vorhanden oder falsch geschrieben."
|
||||||
|
],
|
||||||
|
fix: "Nutze die sichere Abfrage mit <code>dict.get(key, standardwert)</code> statt der eckigen Klammern, um Abstürze zu vermeiden!"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "NameError",
|
||||||
|
pattern: /NameError: name '([^']+)' is not defined/i,
|
||||||
|
title: "❓ Name nicht definiert (NameError)",
|
||||||
|
explanation: "Python kennt das Wort oder die Variable an dieser Stelle nicht.",
|
||||||
|
causes: [
|
||||||
|
"Die Variable wurde weiter unten oder in einer anderen Funktion definiert (Gültigkeitsbereich/Scope).",
|
||||||
|
"Ein Tippfehler im Variablennamen.",
|
||||||
|
"Ein Modul wie <code>import math</code> wurde noch nicht importiert."
|
||||||
|
],
|
||||||
|
fix: "Prüfe, ob du die Variable vor ihrer Benutzung angelegt hast und ob alle benötigten Module oben mit <code>import ...</code> eingebunden sind."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "ZeroDivisionError",
|
||||||
|
pattern: /ZeroDivisionError: division by zero/i,
|
||||||
|
title: "➗ Division durch Null (ZeroDivisionError)",
|
||||||
|
explanation: "In der Mathematik und in Python ist das Teilen durch <code>0</code> nicht erlaubt.",
|
||||||
|
causes: [
|
||||||
|
"Der Nenner / Teiler hat den Wert <code>0</code>."
|
||||||
|
],
|
||||||
|
fix: "Sichere die Division mit einer <code>if teiler != 0:</code> Bedingung oder fange sie mit <code>try-except ZeroDivisionError:</code> ab."
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
window.interpretiereTraceback = function (errorText) {
|
||||||
|
if (!errorText || !errorText.trim()) {
|
||||||
|
return {
|
||||||
|
matched: false,
|
||||||
|
title: "💡 Bitte füge eine Fehlermeldung ein",
|
||||||
|
explanation: "Kopiere deinen Traceback aus dem Terminal und füge ihn hier ein.",
|
||||||
|
fix: "Starte dein Skript im Terminal mit python3 test_aufgabe.py"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let rule of ERROR_RULES) {
|
||||||
|
if (rule.pattern.test(errorText)) {
|
||||||
|
return {
|
||||||
|
matched: true,
|
||||||
|
type: rule.type,
|
||||||
|
title: rule.title,
|
||||||
|
explanation: rule.explanation,
|
||||||
|
causes: rule.causes,
|
||||||
|
fix: rule.fix
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
matched: false,
|
||||||
|
title: "🔍 Allgemeiner Python-Fehler",
|
||||||
|
explanation: "Lies den Traceback immer von ganz unten nach oben: In der allerletzten Zeile nennt Python die genaue Fehlerart und Zeilennummer.",
|
||||||
|
causes: ["Syntax- oder Logikfehler in deinem Code."],
|
||||||
|
fix: "Überprüfe die in der letzten Zeile genannte Zeilennummer in deiner aufgabe.py Datei."
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Widget rendern, falls Container vorhanden
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
const interpreterEl = document.getElementById("error-interpreter-widget");
|
||||||
|
if (!interpreterEl) return;
|
||||||
|
|
||||||
|
interpreterEl.innerHTML = `
|
||||||
|
<div class="card" style="border-left: 5px solid var(--secondary);">
|
||||||
|
<h2>🩺 Interaktiver Python-Fehler-Dolmetscher</h2>
|
||||||
|
<p>Du verstehst eine Fehlermeldung aus dem Terminal nicht? Füge sie hier ein und erhalte sofort eine schülerfreundliche deutsche Erklärung mit Reparatur-Anleitung!</p>
|
||||||
|
|
||||||
|
<textarea id="traceback-input" placeholder="Füge hier deinen Traceback ein (z.B. TypeError: ... oder IndexError: list index out of range)" style="width: 100%; height: 90px; padding: 12px; font-family: var(--font-mono); font-size: 0.88rem; border-radius: var(--radius-sm); border: 1px solid var(--border-color); margin-bottom: 12px;"></textarea>
|
||||||
|
|
||||||
|
<button id="btn-interpret" class="btn" style="background: var(--secondary);">🔍 Fehlermeldung übersetzen</button>
|
||||||
|
|
||||||
|
<div id="interpreter-result" style="margin-top: 15px; display: none;"></div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
const input = document.getElementById("traceback-input");
|
||||||
|
const btn = document.getElementById("btn-interpret");
|
||||||
|
const result = document.getElementById("interpreter-result");
|
||||||
|
|
||||||
|
btn.addEventListener("click", () => {
|
||||||
|
const res = window.interpretiereTraceback(input.value);
|
||||||
|
result.innerHTML = `
|
||||||
|
<div class="box ${res.matched ? 'box-warning' : 'box-tipp'}">
|
||||||
|
<div class="box-title">${res.title}</div>
|
||||||
|
<p><strong>Was bedeutet das?</strong> ${res.explanation}</p>
|
||||||
|
${res.causes ? `<p><strong>Mögliche Ursachen:</strong></p><ul style="margin-left: 20px;">${res.causes.map(c => `<li>${c}</li>`).join("")}</ul>` : ''}
|
||||||
|
<div style="margin-top: 10px; padding-top: 10px; border-top: 1px solid rgba(0,0,0,0.1);">
|
||||||
|
<strong>🔧 So behebst du den Fehler:</strong>
|
||||||
|
<p style="margin-top: 4px;">${res.fix}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
result.style.display = "block";
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})();
|
||||||
182
assets/parsons.js
Normal file
182
assets/parsons.js
Normal file
|
|
@ -0,0 +1,182 @@
|
||||||
|
/**
|
||||||
|
* 🧩 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 = `
|
||||||
|
<div class="parsons-header">
|
||||||
|
<div class="parsons-title">
|
||||||
|
<span>🧩 Code-Puzzle (Parsons Problem)</span>
|
||||||
|
<span class="parsons-badge">${this.isSolved ? '✅ Gelöst (+'+this.xpReward+' XP)' : '⭐ +'+this.xpReward+' XP'}</span>
|
||||||
|
</div>
|
||||||
|
<p class="parsons-instruction">
|
||||||
|
Bringe die Code-Blöcke in die richtige logische Reihenfolge, bevor du selbst programmierst:
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="parsons-board" id="board-${this.puzzleId}">
|
||||||
|
${this.currentLines.map((line, idx) => `
|
||||||
|
<div class="parsons-line" draggable="true" data-index="${idx}">
|
||||||
|
<div class="parsons-handle">☰</div>
|
||||||
|
<div class="parsons-code"><code>${this.escapeHtml(line)}</code></div>
|
||||||
|
<div class="parsons-actions">
|
||||||
|
<button type="button" class="btn-parsons-move btn-up" data-dir="-1" title="Nach oben" ${idx === 0 ? 'disabled' : ''}>▲</button>
|
||||||
|
<button type="button" class="btn-parsons-move btn-down" data-dir="1" title="Nach unten" ${idx === this.currentLines.length - 1 ? 'disabled' : ''}>▼</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`).join("")}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="parsons-controls">
|
||||||
|
<button type="button" class="btn btn-parsons-check" id="check-${this.puzzleId}">
|
||||||
|
${this.isSolved ? '🔄 Erneut prüfen' : '✨ Lösung prüfen'}
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-secondary btn-parsons-hint" id="hint-${this.puzzleId}">
|
||||||
|
💡 Ersten Block verraten
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="parsons-feedback" id="feedback-${this.puzzleId}" style="${this.isSolved ? 'display: block;' : 'display: none;'}">
|
||||||
|
${this.isSolved ? `<div class="box box-success"><div class="box-title">🎉 Perfekt gelöst!</div>${this.explanation}</div>` : ''}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
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 = `<div class="box box-tipp"><div class="box-title">💡 Tipp:</div>Der erste Block <code>${this.escapeHtml(correctFirst)}</code> wurde an den Anfang gesetzt!</div>`;
|
||||||
|
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 = `
|
||||||
|
<div class="box box-success" style="animation: fadeIn 0.3s ease;">
|
||||||
|
<div class="box-title">🎉 Bravo! Alle Blöcke sind in der perfekten Reihenfolge!</div>
|
||||||
|
<p>${this.explanation}</p>
|
||||||
|
<p style="margin-top: 8px; font-weight: bold; color: var(--success);">
|
||||||
|
⭐ Du hast <strong>+${this.xpReward} XP</strong> für deinen Entwickler-Pass freigeschaltet!
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
feedback.style.display = "block";
|
||||||
|
this.saveSolvedState();
|
||||||
|
this.isSolved = true;
|
||||||
|
} else {
|
||||||
|
feedback.innerHTML = `
|
||||||
|
<div class="box box-warning" style="animation: fadeIn 0.3s ease;">
|
||||||
|
<div class="box-title">🤔 Noch nicht ganz...</div>
|
||||||
|
<p>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?</p>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
feedback.style.display = "block";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialisiere alle Puzzle-Widgets auf der Seite
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
document.querySelectorAll(".parsons-puzzle").forEach(el => {
|
||||||
|
new ParsonsWidget(el);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})();
|
||||||
240
assets/style.css
240
assets/style.css
|
|
@ -283,7 +283,7 @@ kbd {
|
||||||
margin: 0 2px;
|
margin: 0 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Extension Cards (for VS Code Guide) */
|
/* Extension Cards */
|
||||||
.extension-grid {
|
.extension-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
|
||||||
|
|
@ -402,7 +402,7 @@ summary:hover {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Grid & Roadmap Cards (for Overview) */
|
/* Grid & Roadmap Cards */
|
||||||
.roadmap-grid {
|
.roadmap-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
|
||||||
|
|
@ -735,6 +735,242 @@ summary:hover {
|
||||||
color: #64748b;
|
color: #64748b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
PARSONS PUZZLES & PRIMM WIDGETS
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
.parsons-box {
|
||||||
|
background: #ffffff;
|
||||||
|
border: 2px solid var(--primary-light);
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
padding: 20px;
|
||||||
|
margin: 25px 0;
|
||||||
|
box-shadow: var(--shadow-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.parsons-header {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.parsons-title {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 1.15rem;
|
||||||
|
font-weight: 800;
|
||||||
|
color: var(--primary);
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.parsons-badge {
|
||||||
|
background: var(--warning-light);
|
||||||
|
color: #b45309;
|
||||||
|
padding: 3px 10px;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.parsons-instruction {
|
||||||
|
font-size: 0.92rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.parsons-board {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
margin: 15px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.parsons-line {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
background: #f8fafc;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
border-radius: var(--radius-sm);
|
||||||
|
padding: 10px 14px;
|
||||||
|
cursor: grab;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.parsons-line:hover {
|
||||||
|
border-color: var(--primary);
|
||||||
|
background: var(--primary-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
.parsons-handle {
|
||||||
|
color: var(--text-muted);
|
||||||
|
font-size: 1.1rem;
|
||||||
|
cursor: grab;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.parsons-code {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.parsons-code code {
|
||||||
|
background: transparent;
|
||||||
|
color: var(--text-main);
|
||||||
|
font-size: 0.95rem;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.parsons-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-parsons-move {
|
||||||
|
background: #ffffff;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 2px 8px;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
cursor: pointer;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-parsons-move:hover:not(:disabled) {
|
||||||
|
background: var(--primary);
|
||||||
|
color: white;
|
||||||
|
border-color: var(--primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-parsons-move:disabled {
|
||||||
|
opacity: 0.3;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.parsons-controls {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
margin-top: 15px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
OFFICIAL CERTIFICATE MODAL
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
.certificate-overlay {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background: rgba(15, 23, 42, 0.85);
|
||||||
|
backdrop-filter: blur(4px);
|
||||||
|
z-index: 9999;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.certificate-container {
|
||||||
|
background: #ffffff;
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
padding: 20px;
|
||||||
|
max-width: 750px;
|
||||||
|
width: 100%;
|
||||||
|
max-height: 90vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.certificate-border {
|
||||||
|
border: 6px double #d97706;
|
||||||
|
border-radius: var(--radius-sm);
|
||||||
|
padding: 30px;
|
||||||
|
text-align: center;
|
||||||
|
background: #fffdfa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.certificate-badge {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
font-weight: 800;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
color: #b45309;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.certificate-headline {
|
||||||
|
font-size: 2rem;
|
||||||
|
color: #1e293b;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.certificate-sub {
|
||||||
|
color: var(--text-muted);
|
||||||
|
font-size: 0.95rem;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.certificate-student-name {
|
||||||
|
font-size: 1.8rem;
|
||||||
|
font-weight: 800;
|
||||||
|
color: var(--primary);
|
||||||
|
text-decoration: underline;
|
||||||
|
text-decoration-color: #fbbf24;
|
||||||
|
text-underline-offset: 6px;
|
||||||
|
margin: 15px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.certificate-text {
|
||||||
|
color: var(--text-muted);
|
||||||
|
font-size: 0.95rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.certificate-track-title {
|
||||||
|
font-size: 1.35rem;
|
||||||
|
color: #0f172a;
|
||||||
|
margin: 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.certificate-desc {
|
||||||
|
font-size: 0.88rem;
|
||||||
|
color: #64748b;
|
||||||
|
max-width: 550px;
|
||||||
|
margin: 0 auto 20px auto;
|
||||||
|
line-height: 1.45;
|
||||||
|
}
|
||||||
|
|
||||||
|
.certificate-meta {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: #334155;
|
||||||
|
margin: 20px 0;
|
||||||
|
padding: 12px 0;
|
||||||
|
border-top: 1px solid #e2e8f0;
|
||||||
|
border-bottom: 1px solid #e2e8f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.certificate-seal {
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 800;
|
||||||
|
color: #b45309;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.certificate-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 12px;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
body * { visibility: hidden; }
|
||||||
|
.certificate-container, .certificate-container * { visibility: visible; }
|
||||||
|
.certificate-overlay { position: static; background: transparent; padding: 0; }
|
||||||
|
.certificate-actions { display: none; }
|
||||||
|
}
|
||||||
|
|
||||||
/* Responsive */
|
/* Responsive */
|
||||||
@media (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
header h1 { font-size: 1.6rem; }
|
header h1 { font-size: 1.6rem; }
|
||||||
|
|
|
||||||
33
index.html
33
index.html
|
|
@ -486,6 +486,32 @@ object has no attribute 'gang'</code></pre>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<!-- Interaktiver Traceback-Dolmetscher -->
|
||||||
|
<section id="error-interpreter-widget"></section>
|
||||||
|
|
||||||
|
<!-- Lehrpfad-Zertifikate Card -->
|
||||||
|
<section class="card" style="border-left: 5px solid #d97706; background: linear-gradient(180deg, #ffffff 0%, #fffdfa 100%);">
|
||||||
|
<h2>🏆 Offizielle Lehrpfad-Abschlusszertifikate</h2>
|
||||||
|
<p>
|
||||||
|
Sobald du einen Lehrpfad oder das gesamte Portal abgeschlossen hast, kannst du dir hier dein persönliches, ausdruckbares <strong>Abschluss-Zertifikat</strong> mit deinen freigeschalteten Leistungsnachweisen generieren!
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px; margin-top: 15px;">
|
||||||
|
<button onclick="window.zeigeZertifikatModal(1)" class="btn" style="background: #1e40af; justify-content: center;">
|
||||||
|
🌱 Zertifikat Lehrpfad 1
|
||||||
|
</button>
|
||||||
|
<button onclick="window.zeigeZertifikatModal(2)" class="btn" style="background: #4338ca; justify-content: center;">
|
||||||
|
🏗️ Zertifikat Lehrpfad 2
|
||||||
|
</button>
|
||||||
|
<button onclick="window.zeigeZertifikatModal(3)" class="btn" style="background: #15803d; justify-content: center;">
|
||||||
|
🚀 Zertifikat Lehrpfad 3
|
||||||
|
</button>
|
||||||
|
<button onclick="window.zeigeZertifikatModal('master')" class="btn" style="background: #b45309; justify-content: center; font-weight: bold;">
|
||||||
|
👑 Master-Zertifikat
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
<!-- FAQ & Troubleshooting Card -->
|
<!-- FAQ & Troubleshooting Card -->
|
||||||
<section class="card">
|
<section class="card">
|
||||||
<h2>🩺 Häufige Fragen & Troubleshooting</h2>
|
<h2>🩺 Häufige Fragen & Troubleshooting</h2>
|
||||||
|
|
@ -509,7 +535,7 @@ object has no attribute 'gang'</code></pre>
|
||||||
<details>
|
<details>
|
||||||
<summary>❌ Wie wechsle ich im Terminal zwischen den Ordnern hin und her?</summary>
|
<summary>❌ Wie wechsle ich im Terminal zwischen den Ordnern hin und her?</summary>
|
||||||
<div class="details-content">
|
<div class="details-content">
|
||||||
<p><strong>In einen Unterordner hinein:</strong> <code>cd g01_erste_schritte_taschenrechner</code></p>
|
<p><strong>In einen Unterordner hinein:</strong> <code>cd lehrpfad_1_grundlagen/01_erste_schritte_taschenrechner</code></p>
|
||||||
<p><strong>Einen Ordner nach oben zurück:</strong> <code>cd ..</code></p>
|
<p><strong>Einen Ordner nach oben zurück:</strong> <code>cd ..</code></p>
|
||||||
<p><strong>Inhalt des aktuellen Ordners auflisten:</strong> <code>ls</code> (oder <code>dir</code> auf Windows)</p>
|
<p><strong>Inhalt des aktuellen Ordners auflisten:</strong> <code>ls</code> (oder <code>dir</code> auf Windows)</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -518,8 +544,11 @@ object has no attribute 'gang'</code></pre>
|
||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
<!-- Lokale Didaktik- & Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
||||||
<script src="assets/gamification_data.js"></script>
|
<script src="assets/gamification_data.js"></script>
|
||||||
<script src="assets/gamification.js"></script>
|
<script src="assets/gamification.js"></script>
|
||||||
|
<script src="assets/interpreter.js"></script>
|
||||||
|
<script src="assets/certificate.js"></script>
|
||||||
|
<script src="assets/parsons.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -305,5 +305,7 @@
|
||||||
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
||||||
<script src="../../assets/gamification_data.js"></script>
|
<script src="../../assets/gamification_data.js"></script>
|
||||||
<script src="../../assets/gamification.js"></script>
|
<script src="../../assets/gamification.js"></script>
|
||||||
|
<script src="../../assets/parsons.js"></script>
|
||||||
|
<script src="../../assets/interpreter.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -256,5 +256,7 @@
|
||||||
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
||||||
<script src="../../assets/gamification_data.js"></script>
|
<script src="../../assets/gamification_data.js"></script>
|
||||||
<script src="../../assets/gamification.js"></script>
|
<script src="../../assets/gamification.js"></script>
|
||||||
|
<script src="../../assets/parsons.js"></script>
|
||||||
|
<script src="../../assets/interpreter.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -259,5 +259,7 @@ return f"Steckbrief: {name} | Größe: {groesse_m:.2f} m | Gewicht: {gewicht_kg:
|
||||||
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
||||||
<script src="../../assets/gamification_data.js"></script>
|
<script src="../../assets/gamification_data.js"></script>
|
||||||
<script src="../../assets/gamification.js"></script>
|
<script src="../../assets/gamification.js"></script>
|
||||||
|
<script src="../../assets/parsons.js"></script>
|
||||||
|
<script src="../../assets/interpreter.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -291,5 +291,7 @@ return False</code></pre>
|
||||||
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
||||||
<script src="../../assets/gamification_data.js"></script>
|
<script src="../../assets/gamification_data.js"></script>
|
||||||
<script src="../../assets/gamification.js"></script>
|
<script src="../../assets/gamification.js"></script>
|
||||||
|
<script src="../../assets/parsons.js"></script>
|
||||||
|
<script src="../../assets/interpreter.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -332,5 +332,7 @@
|
||||||
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
||||||
<script src="../../assets/gamification_data.js"></script>
|
<script src="../../assets/gamification_data.js"></script>
|
||||||
<script src="../../assets/gamification.js"></script>
|
<script src="../../assets/gamification.js"></script>
|
||||||
|
<script src="../../assets/parsons.js"></script>
|
||||||
|
<script src="../../assets/interpreter.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -285,5 +285,7 @@
|
||||||
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
||||||
<script src="../../assets/gamification_data.js"></script>
|
<script src="../../assets/gamification_data.js"></script>
|
||||||
<script src="../../assets/gamification.js"></script>
|
<script src="../../assets/gamification.js"></script>
|
||||||
|
<script src="../../assets/parsons.js"></script>
|
||||||
|
<script src="../../assets/interpreter.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -276,5 +276,7 @@
|
||||||
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
||||||
<script src="../../assets/gamification_data.js"></script>
|
<script src="../../assets/gamification_data.js"></script>
|
||||||
<script src="../../assets/gamification.js"></script>
|
<script src="../../assets/gamification.js"></script>
|
||||||
|
<script src="../../assets/parsons.js"></script>
|
||||||
|
<script src="../../assets/interpreter.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -231,5 +231,7 @@
|
||||||
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
||||||
<script src="../../assets/gamification_data.js"></script>
|
<script src="../../assets/gamification_data.js"></script>
|
||||||
<script src="../../assets/gamification.js"></script>
|
<script src="../../assets/gamification.js"></script>
|
||||||
|
<script src="../../assets/parsons.js"></script>
|
||||||
|
<script src="../../assets/interpreter.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -305,5 +305,7 @@
|
||||||
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
||||||
<script src="../../assets/gamification_data.js"></script>
|
<script src="../../assets/gamification_data.js"></script>
|
||||||
<script src="../../assets/gamification.js"></script>
|
<script src="../../assets/gamification.js"></script>
|
||||||
|
<script src="../../assets/parsons.js"></script>
|
||||||
|
<script src="../../assets/interpreter.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -255,5 +255,7 @@
|
||||||
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
||||||
<script src="../../assets/gamification_data.js"></script>
|
<script src="../../assets/gamification_data.js"></script>
|
||||||
<script src="../../assets/gamification.js"></script>
|
<script src="../../assets/gamification.js"></script>
|
||||||
|
<script src="../../assets/parsons.js"></script>
|
||||||
|
<script src="../../assets/interpreter.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -209,5 +209,7 @@
|
||||||
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
||||||
<script src="../../assets/gamification_data.js"></script>
|
<script src="../../assets/gamification_data.js"></script>
|
||||||
<script src="../../assets/gamification.js"></script>
|
<script src="../../assets/gamification.js"></script>
|
||||||
|
<script src="../../assets/parsons.js"></script>
|
||||||
|
<script src="../../assets/interpreter.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -291,5 +291,7 @@
|
||||||
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
||||||
<script src="../../assets/gamification_data.js"></script>
|
<script src="../../assets/gamification_data.js"></script>
|
||||||
<script src="../../assets/gamification.js"></script>
|
<script src="../../assets/gamification.js"></script>
|
||||||
|
<script src="../../assets/parsons.js"></script>
|
||||||
|
<script src="../../assets/interpreter.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -218,5 +218,7 @@
|
||||||
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
||||||
<script src="../../assets/gamification_data.js"></script>
|
<script src="../../assets/gamification_data.js"></script>
|
||||||
<script src="../../assets/gamification.js"></script>
|
<script src="../../assets/gamification.js"></script>
|
||||||
|
<script src="../../assets/parsons.js"></script>
|
||||||
|
<script src="../../assets/interpreter.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -198,5 +198,7 @@
|
||||||
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
||||||
<script src="../../assets/gamification_data.js"></script>
|
<script src="../../assets/gamification_data.js"></script>
|
||||||
<script src="../../assets/gamification.js"></script>
|
<script src="../../assets/gamification.js"></script>
|
||||||
|
<script src="../../assets/parsons.js"></script>
|
||||||
|
<script src="../../assets/interpreter.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -205,5 +205,7 @@
|
||||||
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
||||||
<script src="../../assets/gamification_data.js"></script>
|
<script src="../../assets/gamification_data.js"></script>
|
||||||
<script src="../../assets/gamification.js"></script>
|
<script src="../../assets/gamification.js"></script>
|
||||||
|
<script src="../../assets/parsons.js"></script>
|
||||||
|
<script src="../../assets/interpreter.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -318,5 +318,7 @@ sudo snap install --classic code</code></pre>
|
||||||
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
||||||
<script src="../../assets/gamification_data.js"></script>
|
<script src="../../assets/gamification_data.js"></script>
|
||||||
<script src="../../assets/gamification.js"></script>
|
<script src="../../assets/gamification.js"></script>
|
||||||
|
<script src="../../assets/parsons.js"></script>
|
||||||
|
<script src="../../assets/interpreter.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -214,5 +214,7 @@
|
||||||
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
||||||
<script src="../../assets/gamification_data.js"></script>
|
<script src="../../assets/gamification_data.js"></script>
|
||||||
<script src="../../assets/gamification.js"></script>
|
<script src="../../assets/gamification.js"></script>
|
||||||
|
<script src="../../assets/parsons.js"></script>
|
||||||
|
<script src="../../assets/interpreter.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -201,5 +201,7 @@
|
||||||
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
||||||
<script src="../../assets/gamification_data.js"></script>
|
<script src="../../assets/gamification_data.js"></script>
|
||||||
<script src="../../assets/gamification.js"></script>
|
<script src="../../assets/gamification.js"></script>
|
||||||
|
<script src="../../assets/parsons.js"></script>
|
||||||
|
<script src="../../assets/interpreter.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -179,5 +179,7 @@
|
||||||
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
||||||
<script src="../../assets/gamification_data.js"></script>
|
<script src="../../assets/gamification_data.js"></script>
|
||||||
<script src="../../assets/gamification.js"></script>
|
<script src="../../assets/gamification.js"></script>
|
||||||
|
<script src="../../assets/parsons.js"></script>
|
||||||
|
<script src="../../assets/interpreter.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -215,5 +215,7 @@
|
||||||
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
||||||
<script src="../../assets/gamification_data.js"></script>
|
<script src="../../assets/gamification_data.js"></script>
|
||||||
<script src="../../assets/gamification.js"></script>
|
<script src="../../assets/gamification.js"></script>
|
||||||
|
<script src="../../assets/parsons.js"></script>
|
||||||
|
<script src="../../assets/interpreter.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -280,5 +280,7 @@
|
||||||
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
||||||
<script src="../../assets/gamification_data.js"></script>
|
<script src="../../assets/gamification_data.js"></script>
|
||||||
<script src="../../assets/gamification.js"></script>
|
<script src="../../assets/gamification.js"></script>
|
||||||
|
<script src="../../assets/parsons.js"></script>
|
||||||
|
<script src="../../assets/interpreter.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -299,5 +299,7 @@
|
||||||
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
||||||
<script src="../../assets/gamification_data.js"></script>
|
<script src="../../assets/gamification_data.js"></script>
|
||||||
<script src="../../assets/gamification.js"></script>
|
<script src="../../assets/gamification.js"></script>
|
||||||
|
<script src="../../assets/parsons.js"></script>
|
||||||
|
<script src="../../assets/interpreter.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -359,5 +359,7 @@
|
||||||
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
||||||
<script src="../../assets/gamification_data.js"></script>
|
<script src="../../assets/gamification_data.js"></script>
|
||||||
<script src="../../assets/gamification.js"></script>
|
<script src="../../assets/gamification.js"></script>
|
||||||
|
<script src="../../assets/parsons.js"></script>
|
||||||
|
<script src="../../assets/interpreter.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -392,5 +392,7 @@
|
||||||
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
||||||
<script src="../../assets/gamification_data.js"></script>
|
<script src="../../assets/gamification_data.js"></script>
|
||||||
<script src="../../assets/gamification.js"></script>
|
<script src="../../assets/gamification.js"></script>
|
||||||
|
<script src="../../assets/parsons.js"></script>
|
||||||
|
<script src="../../assets/interpreter.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -259,5 +259,7 @@
|
||||||
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
||||||
<script src="../../assets/gamification_data.js"></script>
|
<script src="../../assets/gamification_data.js"></script>
|
||||||
<script src="../../assets/gamification.js"></script>
|
<script src="../../assets/gamification.js"></script>
|
||||||
|
<script src="../../assets/parsons.js"></script>
|
||||||
|
<script src="../../assets/interpreter.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -247,5 +247,7 @@
|
||||||
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
||||||
<script src="../../assets/gamification_data.js"></script>
|
<script src="../../assets/gamification_data.js"></script>
|
||||||
<script src="../../assets/gamification.js"></script>
|
<script src="../../assets/gamification.js"></script>
|
||||||
|
<script src="../../assets/parsons.js"></script>
|
||||||
|
<script src="../../assets/interpreter.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -352,5 +352,7 @@
|
||||||
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
||||||
<script src="../../assets/gamification_data.js"></script>
|
<script src="../../assets/gamification_data.js"></script>
|
||||||
<script src="../../assets/gamification.js"></script>
|
<script src="../../assets/gamification.js"></script>
|
||||||
|
<script src="../../assets/parsons.js"></script>
|
||||||
|
<script src="../../assets/interpreter.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -316,5 +316,7 @@
|
||||||
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
||||||
<script src="../../assets/gamification_data.js"></script>
|
<script src="../../assets/gamification_data.js"></script>
|
||||||
<script src="../../assets/gamification.js"></script>
|
<script src="../../assets/gamification.js"></script>
|
||||||
|
<script src="../../assets/parsons.js"></script>
|
||||||
|
<script src="../../assets/interpreter.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -327,5 +327,7 @@
|
||||||
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
<!-- Lokale Gamification-Scripts (funktionieren auch offline per Doppelklick via file://) -->
|
||||||
<script src="../../assets/gamification_data.js"></script>
|
<script src="../../assets/gamification_data.js"></script>
|
||||||
<script src="../../assets/gamification.js"></script>
|
<script src="../../assets/gamification.js"></script>
|
||||||
|
<script src="../../assets/parsons.js"></script>
|
||||||
|
<script src="../../assets/interpreter.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue