Feature: 40 bilingual questions, random 10 game run, difficulty levels, and full i18n support

This commit is contained in:
kobold-ai
2026-09-21 12:33:34 +02:00
parent eafa1f833e
commit cf89cd31c7
15 changed files with 1369 additions and 138 deletions
+119 -9
View File
@@ -1,32 +1,136 @@
const SUGGESTION_TEXT = {
de: {
title: "✨ Neue Frage für das Quiz vorschlagen ✨",
subtitle: "Bereichere das magische Quiz mit kniffligen Harry-Potter- oder Escape-Rätseln!",
alert: "ℹ️ <strong>Hinweis zur Moderation:</strong> Eingereichte Fragen werden nicht sofort öffentlich sichtbar, sondern erhalten automatisch den Status <em>„Prüfung ausstehend“</em>. Unser Zaubereiministerium prüft und testet die Antwort, bevor die Frage freigeschaltet wird.",
nameLabel: "Dein Name / Zauberer-Alias (optional):",
namePlaceholder: "z. B. Hermine Granger",
frageLabel: "Deine Frage: *",
fragePlaceholder: "z. B. Wie heißt der Schulleiter von Hogwarts?",
diffLabel: "Schwierigkeitsgrad:",
typeLabel: "Art der Frage:",
optText: "🔤 Freitext-Antwort (Tippen mit Fehlertoleranz)",
optMC: "🔘 Multiple Choice (Auswahl aus 4 Antwortmöglichkeiten)",
antwortLabelText: "Richtige Antwort:",
antwortLabelMC: "Richtige Antwort (die korrekte Option):",
antwortHelpText: "Unser System gleicht Tippfehler und Groß-/Kleinschreibung automatisch ab.",
antwortHelpMC: "Diese Antwort wird zusammen mit den falschen Optionen zufällig für den Spieler angeordnet.",
wrongLabel: "Falsche Antwortmöglichkeiten (zur Auswahl für die Spieler):",
wrongPlaceholder1: "Falsche Option 1 (z. B. Severus Snape)",
wrongPlaceholder2: "Falsche Option 2 (z. B. Minerva McGonagall)",
wrongPlaceholder3: "Falsche Option 3 (z. B. Rubeus Hagrid)",
tippLabel: "Tipp / Hinweis (optional):",
tippPlaceholder: "z. B. Er trägt eine Halbmondbrille.",
submitBtn: "📜 Vorschlag an das Ministerium senden",
submitBtnCasting: "✨ Vorschlag wird übertragen...",
alertFillRequired: "Bitte gib mindestens die Frage und die richtige Antwort ein.",
alertMCRequired: "Bitte gib bei Multiple-Choice mindestens eine falsche Antwortmöglichkeit an.",
successHeader: "✨ Vorschlag erfolgreich übermittelt! ✨"
},
en: {
title: "✨ Suggest a New Quiz Question ✨",
subtitle: "Enrich the magical quiz with tricky Harry Potter or escape puzzles!",
alert: "ℹ️ <strong>Moderation Note:</strong> Submitted questions are not immediately public; they automatically receive the status <em>'Pending Review'</em>. The Ministry of Magic tests and verifies the answer before approval.",
nameLabel: "Your Name / Wizard Alias (optional):",
namePlaceholder: "e.g. Hermione Granger",
frageLabel: "Your Question: *",
fragePlaceholder: "e.g. Who is the Headmaster of Hogwarts?",
diffLabel: "Difficulty Level:",
typeLabel: "Question Type:",
optText: "🔤 Free-Text Input (with typo tolerance)",
optMC: "🔘 Multiple Choice (Selection of 4 options)",
antwortLabelText: "Correct Answer:",
antwortLabelMC: "Correct Answer (the winning option):",
antwortHelpText: "Our system automatically matches minor typos and casing.",
antwortHelpMC: "This option will be shuffled together with the false choices.",
wrongLabel: "Wrong Answer Options (for player to choose from):",
wrongPlaceholder1: "Wrong Option 1 (e.g. Severus Snape)",
wrongPlaceholder2: "Wrong Option 2 (e.g. Minerva McGonagall)",
wrongPlaceholder3: "Wrong Option 3 (e.g. Rubeus Hagrid)",
tippLabel: "Hint / Clue (optional):",
tippPlaceholder: "e.g. He wears half-moon spectacles.",
submitBtn: "📜 Submit Proposal to the Ministry",
submitBtnCasting: "✨ Transmitting proposal...",
alertFillRequired: "Please enter at least the question and the correct answer.",
alertMCRequired: "For Multiple Choice, please provide at least one incorrect option.",
successHeader: "✨ Question successfully submitted! ✨"
}
};
function onLanguageChange(lang) {
const t = SUGGESTION_TEXT[lang] || SUGGESTION_TEXT.de;
const title = document.getElementById("suggTitle");
const subtitle = document.getElementById("suggSubtitle");
const alertBox = document.getElementById("suggAlert");
const nameLabel = document.getElementById("suggNameLabel");
const nameInput = document.getElementById("name");
const frageLabel = document.getElementById("suggFrageLabel");
const frageInput = document.getElementById("frage");
const diffLabel = document.getElementById("suggDiffLabel");
const typeLabel = document.getElementById("suggTypeLabel");
const optText = document.getElementById("optText");
const optMC = document.getElementById("optMC");
const mcWrongLabel = document.getElementById("mcWrongLabel");
const tippLabel = document.getElementById("suggTippLabel");
const tippInput = document.getElementById("tipp");
const submitBtn = document.getElementById("submitBtn");
if (title) title.innerText = t.title;
if (subtitle) subtitle.innerText = t.subtitle;
if (alertBox) alertBox.innerHTML = t.alert;
if (nameLabel) nameLabel.innerText = t.nameLabel;
if (nameInput) nameInput.placeholder = t.namePlaceholder;
if (frageLabel) frageLabel.innerText = t.frageLabel;
if (frageInput) frageInput.placeholder = t.fragePlaceholder;
if (diffLabel) diffLabel.innerText = t.diffLabel;
if (typeLabel) typeLabel.innerText = t.typeLabel;
if (optText) optText.innerText = t.optText;
if (optMC) optMC.innerText = t.optMC;
if (mcWrongLabel) mcWrongLabel.innerText = t.wrongLabel;
if (tippLabel) tippLabel.innerText = t.tippLabel;
if (tippInput) tippInput.placeholder = t.tippPlaceholder;
if (submitBtn && !submitBtn.disabled) submitBtn.innerText = t.submitBtn;
const qType = document.getElementById("q_type");
if (qType) toggleVorschlagType(qType.value);
}
function toggleVorschlagType(type) {
const lang = (typeof currentLang !== "undefined") ? currentLang : (localStorage.getItem("quiz_lang") || "de");
const t = SUGGESTION_TEXT[lang] || SUGGESTION_TEXT.de;
const mcGroup = document.getElementById("mcOptionsGroup");
const antwortLabel = document.getElementById("antwortLabel");
const antwortHelp = document.getElementById("antwortHelp");
if (type === "multiple_choice") {
mcGroup.classList.remove("hidden");
antwortLabel.innerText = "Richtige Antwort (die korrekte Option):";
antwortHelp.innerText = "Diese Antwort wird zusammen mit den falschen Optionen zufällig für den Spieler angeordnet.";
antwortLabel.innerText = t.antwortLabelMC;
antwortHelp.innerText = t.antwortHelpMC;
} else {
mcGroup.classList.add("hidden");
antwortLabel.innerText = "Richtige Antwort:";
antwortHelp.innerText = "Unser System gleicht Tippfehler und Groß-/Kleinschreibung automatisch ab.";
antwortLabel.innerText = t.antwortLabelText;
antwortHelp.innerText = t.antwortHelpText;
}
}
async function submitSuggestion(event) {
event.preventDefault();
const lang = (typeof currentLang !== "undefined") ? currentLang : (localStorage.getItem("quiz_lang") || "de");
const t = SUGGESTION_TEXT[lang] || SUGGESTION_TEXT.de;
const name = document.getElementById("name").value.trim();
const frage = document.getElementById("frage").value.trim();
const antwort = document.getElementById("antwort").value.trim();
const tipp = document.getElementById("tipp").value.trim();
const qType = document.getElementById("q_type").value;
const diff = document.getElementById("diff_select") ? document.getElementById("diff_select").value : "medium";
const submitBtn = document.getElementById("submitBtn");
const resultBox = document.getElementById("resultMessage");
if (!frage || !antwort) {
alert("Bitte gib mindestens die Frage und die richtige Antwort ein.");
alert(t.alertFillRequired);
return;
}
@@ -38,13 +142,13 @@ async function submitSuggestion(event) {
falscheAntworten = [w1, w2, w3].filter(x => x.length > 0);
if (falscheAntworten.length === 0) {
alert("Bitte gib bei Multiple-Choice mindestens eine falsche Antwortmöglichkeit an.");
alert(t.alertMCRequired);
return;
}
}
submitBtn.disabled = true;
submitBtn.innerText = "✨ Vorschlag wird übertragen...";
submitBtn.innerText = t.submitBtnCasting;
try {
const payload = {
@@ -53,6 +157,7 @@ async function submitSuggestion(event) {
antwort: antwort,
tipp: tipp || null,
question_type: qType,
difficulty: diff,
falsche_antworten: falscheAntworten
};
@@ -67,7 +172,7 @@ async function submitSuggestion(event) {
if (res.ok && data.success) {
resultBox.innerHTML = `
<div style="background: rgba(46, 204, 113, 0.2); border: 1px solid #2ecc71; color: #55efc4; padding: 15px; border-radius: 8px;">
<h3>✨ Vorschlag erfolgreich übermittelt! ✨</h3>
<h3>${t.successHeader}</h3>
<p>${data.message}</p>
</div>
`;
@@ -91,6 +196,11 @@ async function submitSuggestion(event) {
resultBox.classList.remove("hidden");
} finally {
submitBtn.disabled = false;
submitBtn.innerText = "📜 Vorschlag an das Ministerium senden";
submitBtn.innerText = t.submitBtn;
}
}
document.addEventListener("DOMContentLoaded", () => {
const lang = (typeof currentLang !== "undefined") ? currentLang : (localStorage.getItem("quiz_lang") || "de");
onLanguageChange(lang);
});