Initial commit: Modernes Harry Potter Escape Quiz Portal (FastAPI & MariaDB)

This commit is contained in:
kobold-ai
2026-09-21 11:29:18 +02:00
commit c3a21369ef
50 changed files with 3346 additions and 0 deletions
+54
View File
@@ -0,0 +1,54 @@
let daten = [];
async function load() {
const res = await fetch("fragen.json");
daten = await res.json();
render();
}
function render() {
const container = document.getElementById("fragen");
container.innerHTML = "";
daten.forEach((f, i) => {
container.innerHTML += `
<div class="box">
<strong>Frage ${i+1}</strong>
<input value="${f.frage}" onchange="edit(${i}, 'frage', this.value)">
<input value="${f.antwort}" onchange="edit(${i}, 'antwort', this.value)">
<input value="${f.tipp}" onchange="edit(${i}, 'tipp', this.value)">
<button onclick="removeFrage(${i})">Löschen</button>
</div>
`;
});
}
function edit(i, field, value) {
daten[i][field] = value;
save();
}
function addFrage() {
daten.push({
frage: document.getElementById("newFrage").value,
antwort: document.getElementById("newAntwort").value,
tipp: document.getElementById("newTipp").value
});
save();
}
function removeFrage(i) {
daten.splice(i, 1);
save();
}
async function save() {
await fetch("save.php", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(daten)
});
load();
}
load();
+10
View File
@@ -0,0 +1,10 @@
function getParam(name) {
const params = new URLSearchParams(window.location.search);
return params.get(name);
}
const score = getParam("score") || 0;
const max = getParam("max") || 10;
document.getElementById("scoreText").innerText =
`Du hast ${score} von ${max} möglichen Hauspunkten erreicht.`;
+110
View File
@@ -0,0 +1,110 @@
function levenshtein(a, b) {
const matrix = Array.from({ length: a.length + 1 }, (_, i) =>
Array.from({ length: b.length + 1 }, (_, j) =>
i === 0 ? j : j === 0 ? i : 0
)
);
for (let i = 1; i <= a.length; i++) {
for (let j = 1; j <= b.length; j++) {
matrix[i][j] = Math.min(
matrix[i - 1][j] + 1,
matrix[i][j - 1] + 1,
matrix[i - 1][j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1)
);
}
}
return matrix[a.length][b.length];
}
let fragen = [];
let index = 0;
let punkte = 0;
let versuche = [];
function startGame() {
document.getElementById("envelope").classList.add("open");
setTimeout(() => {
document.getElementById("intro").classList.add("hidden");
document.getElementById("bgm").play();
loadQuestions();
}, 900);
}
async function loadQuestions() {
const res = await fetch("fragen.json");
fragen = await res.json();
versuche = Array(fragen.length).fill(0);
renderFrage();
updateProgress();
}
function renderFrage() {
const f = fragen[index];
document.getElementById("questions").innerHTML = `
<div class="box" id="frageBox">
<h2>Frage ${index + 1}</h2>
<p>${f.frage}</p>
<input id="antwort">
<button onclick="check()">Prüfen</button>
<button onclick="showTip()">Tipp</button>
<p class="tip hidden" id="tipp">${f.tipp}</p>
<p id="versuche">Versuche: 0 / 3</p>
<p id="feedback"></p>
</div>
`;
}
function showTip() {
document.getElementById("tipp").classList.remove("hidden");
}
function check() {
const input = document.getElementById("antwort").value.toLowerCase().trim();
const korrekt = fragen[index].antwort.toLowerCase().trim();
versuche[index]++;
document.getElementById("versuche").innerText = `Versuche: ${versuche[index]} / 3`;
const dist = levenshtein(input, korrekt);
if (dist <= 2) {
punkte++;
addSparkle();
next();
return;
}
if (versuche[index] >= 3) {
next();
return;
}
document.getElementById("feedback").innerText = "Leider falsch.";
}
function addSparkle() {
const el = document.getElementById("frageBox");
el.classList.add("sparkle");
setTimeout(() => el.classList.remove("sparkle"), 700);
}
function next() {
index++;
updateProgress();
if (index >= fragen.length) {
window.location.href = `finale.html?score=${punkte}&max=${fragen.length}`;
return;
}
renderFrage();
}
function updateProgress() {
const percent = (index / fragen.length) * 100;
document.getElementById("progressBar").style.width = percent + "%";
document.getElementById("progressLabel").innerText = `Hauspunkte: ${punkte}`;
}
+17
View File
@@ -0,0 +1,17 @@
async function load() {
const res = await fetch("fragen.json");
const fragen = await res.json();
const container = document.getElementById("loesungen");
fragen.forEach((f, i) => {
container.innerHTML += `
<div class="box">
${i + 1}. ${f.frage}<br>
<strong>${f.antwort}</strong>
</div>
`;
});
}
load();
+31
View File
@@ -0,0 +1,31 @@
async function send() {
const frage = document.getElementById("frage").value.trim();
const antwort = document.getElementById("antwort").value.trim();
const tipp = document.getElementById("tipp").value.trim();
if (!frage || !antwort) {
alert("Bitte mindestens Frage und Antwort ausfüllen.");
return;
}
const payload = {
frage: frage,
antwort: antwort,
tipp: tipp
};
const res = await fetch("save_vorschlag.php", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload)
});
if (res.ok) {
alert("Danke! Dein Vorschlag wurde gespeichert.");
document.getElementById("frage").value = "";
document.getElementById("antwort").value = "";
document.getElementById("tipp").value = "";
} else {
alert("Fehler beim Speichern. Bitte später erneut versuchen.");
}
}