Freitag, 19 Dezember 2025

Diese Woche am beliebtesten

Vertiefendes Material

Quiz Master

Mit dem Dreamcodes Quiz Master liefern wir dir eine vollständige Quiz Plattform. Diese vereint Benutzerverwaltung, OAuth-Authentifizierung, JWT-Session, mehrsprachige Oberfläche in sechs Sprachen, Kategorien- und Fragenverwaltung mit bereits 10 eingebauten Kategorien und 100 Fragen und Antworten, sowie ein interaktives Quiz mit Zeit-Challenges und Fortschrittsstatistiken. Geil oder? 😉

Hauptfunktionen

  • Benutzerregistrierung, Login und Logout mit bcrypt-Passworthashing
  • OAuth-Login via Google und JWT-basierte API-Authentifizierung
  • Rollenbasiertes System für Admins und jeweilige User
  • Mehrsprachige Oberfläche (Deutsch, Englisch, Französisch, Italienisch, Spanisch, Türkisch)
  • Nutzerprofile mit individuellem Sprachprofil und Fortschrittsverlauf
  • Kategorienverwaltung im Admin-Dashboard
  • Fragenverwaltung: Anlegen, Löschen, Anzeigen aller Fragen
  • Quiz-Modus mit Filter nach Kategorie, Schwierigkeit und Fragezahl
  • Challenge-Modi: Standard, zeitbasiert pro Kategorie und zeitbasiert pro Schwierigkeit
  • Echtzeit-Timer, Fortschrittsbalken und AJAX-Submission
  • Speicherung aller Quiz-Ergebnisse in SQLite mit Zeitstempel
  • CSV- und JSON-Export aller Statistiken für Admins
<?php
session_start();
require __DIR__ . '/vendor/autoload.php';   // Composer-Autoloader für firebase/php-jwt
use Firebase\JWT\JWT;

// --- KONSTANTEN & OAUTH‐CONFIG ------------------------------------------------
const JWT_SECRET  = 'DEIN_SECRET_KEY_HIER_EINFÜGEN';
const OAUTH_GOOGLE_CLIENT_ID     = 'DEINE_GOOGLE_CLIENT_ID';
const OAUTH_GOOGLE_CLIENT_SECRET = 'DEIN_GOOGLE_CLIENT_SECRET';
const OAUTH_REDIRECT_URI         = 'https://deinedomain.de/index.php?oauth=google';

// --- DATENBANK‐SETUP & MIGRATION ---------------------------------------------
$pdo = new PDO('sqlite:' . __DIR__ . '/quiz.sqlite');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->exec('PRAGMA foreign_keys = ON');

// Tabellen anlegen
$pdo->exec("
CREATE TABLE IF NOT EXISTS users (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  username TEXT UNIQUE,
  password TEXT,
  role TEXT NOT NULL CHECK(role IN('admin','user')) DEFAULT 'user',
  provider TEXT,
  oauth_id TEXT
);
CREATE TABLE IF NOT EXISTS profiles (
  user_id INTEGER PRIMARY KEY,
  lang TEXT NOT NULL DEFAULT 'de',
  FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS categories (
  id   INTEGER PRIMARY KEY AUTOINCREMENT,
  name TEXT UNIQUE NOT NULL
);
CREATE TABLE IF NOT EXISTS questions (
  id             INTEGER PRIMARY KEY AUTOINCREMENT,
  question       TEXT    NOT NULL,
  option_a       TEXT    NOT NULL,
  option_b       TEXT    NOT NULL,
  option_c       TEXT    NOT NULL,
  option_d       TEXT    NOT NULL,
  correct_option TEXT    NOT NULL CHECK(correct_option IN('a','b','c','d')),
  category_id    INTEGER NOT NULL,
  difficulty     TEXT    NOT NULL CHECK(difficulty IN('Easy','Medium','Hard')),
  FOREIGN KEY(category_id) REFERENCES categories(id) ON DELETE CASCADE
);
INSERT OR IGNORE INTO categories (name) VALUES
  ('Allgemeinwissen'),
  ('Wissenschaft'),
  ('Geschichte'),
  ('Geographie'),
  ('Sport'),
  ('Unterhaltung'),
  ('Literatur'),
  ('Technologie'),
  ('Mathematik'),
  ('Kunst');
INSERT OR IGNORE INTO questions
  (question, option_a, option_b, option_c, option_d, correct_option, category_id, difficulty)
VALUES
('Wie viele Kontinente gibt es auf der Erde?', '5', '6', '7', '8', 'c',
  (SELECT id FROM categories WHERE name='Allgemeinwissen'), 'Easy'),
('Welches Tier ist das größte lebende Landtier?', 'Elefant', 'Giraffe', 'Flusspferd', 'Nashorn', 'a',
  (SELECT id FROM categories WHERE name='Allgemeinwissen'), 'Easy'),
('Welches Element macht den größten Teil der Erdatmosphäre aus?', 'Sauerstoff', 'Stickstoff', 'Kohlendioxid', 'Argon', 'b',
  (SELECT id FROM categories WHERE name='Allgemeinwissen'), 'Easy'),
('Welche Farbe entsteht durch Mischen von Blau und Gelb?', 'Grün', 'Lila', 'Orange', 'Braun', 'a',
  (SELECT id FROM categories WHERE name='Allgemeinwissen'), 'Easy'),
('Welches Land hat die größte Bevölkerung?', 'China', 'Indien', 'USA', 'Indonesien', 'a',
  (SELECT id FROM categories WHERE name='Allgemeinwissen'), 'Medium'),
('Wie viele Elemente hat das Periodensystem (Stand 2021)?', '118', '120', '115', '113', 'a',
  (SELECT id FROM categories WHERE name='Allgemeinwissen'), 'Medium'),
('Welches Organ pumpt Blut durch den Körper?', 'Leber', 'Lunge', 'Herz', 'Niere', 'c',
  (SELECT id FROM categories WHERE name='Allgemeinwissen'), 'Medium'),
('Wann endete der Zweite Weltkrieg?', '1945', '1944', '1939', '1950', 'a',
  (SELECT id FROM categories WHERE name='Allgemeinwissen'), 'Medium'),
('Wer schrieb die „Kritik der reinen Vernunft“?', 'Immanuel Kant', 'Georg Hegel', 'Friedrich Nietzsche', 'Arthur Schopenhauer', 'a',
  (SELECT id FROM categories WHERE name='Allgemeinwissen'), 'Hard'),
('Welche Sprache ist Amtssprache in Brasilien?', 'Spanisch', 'Portugiesisch', 'Französisch', 'Englisch', 'b',
  (SELECT id FROM categories WHERE name='Allgemeinwissen'), 'Hard'),
('Was ist die Einheit der elektrischen Spannung?', 'Volt', 'Ampere', 'Ohm', 'Watt', 'a',
  (SELECT id FROM categories WHERE name='Wissenschaft'), 'Easy'),
('Welches Gas atmen wir am meisten ein?', 'Sauerstoff', 'Stickstoff', 'Kohlendioxid', 'Helium', 'b',
  (SELECT id FROM categories WHERE name='Wissenschaft'), 'Easy'),
('Wie heißt die Lehre von den Pflanzen?', 'Zoologie', 'Botanik', 'Geologie', 'Meteorologie', 'b',
  (SELECT id FROM categories WHERE name='Wissenschaft'), 'Easy'),
('Welche Grundkraft wirkt zwischen allen Massen?', 'Gravitation', 'Magnetismus', 'Elektrizität', 'Reibung', 'a',
  (SELECT id FROM categories WHERE name='Wissenschaft'), 'Easy'),
('Was beschreibt die Formel E=mc²?', 'Energie-Äquivalenz', 'Geschwindigkeit', 'Elektrische Feldstärke', 'Dichte', 'a',
  (SELECT id FROM categories WHERE name='Wissenschaft'), 'Medium'),
('Wie viele Chromosomen hat die Zelle des Menschen?', '46', '23', '44', '92', 'a',
  (SELECT id FROM categories WHERE name='Wissenschaft'), 'Medium'),
('Welches Vitamin wird durch Sonnenlicht gebildet?', 'Vitamin C', 'Vitamin D', 'Vitamin B12', 'Vitamin A', 'b',
  (SELECT id FROM categories WHERE name='Wissenschaft'), 'Medium'),
('Welcher pH-Wert gilt als neutral?', '7', '1', '14', '0', 'a',
  (SELECT id FROM categories WHERE name='Wissenschaft'), 'Medium'),
('Wer entdeckte die Röntgenstrahlen?', 'Wilhelm Röntgen', 'Marie Curie', 'Albert Einstein', 'Max Planck', 'a',
  (SELECT id FROM categories WHERE name='Wissenschaft'), 'Hard'),
('Welche Teilchen vermitteln die starke Kernkraft?', 'Photon', 'Gluon', 'W-Boson', 'Neutron', 'b',
  (SELECT id FROM categories WHERE name='Wissenschaft'), 'Hard'),
('Wer war der erste Bundeskanzler der Bundesrepublik Deutschland?', 'Konrad Adenauer', 'Helmut Schmidt', 'Helmut Kohl', 'Willy Brandt', 'a',
  (SELECT id FROM categories WHERE name='Geschichte'), 'Easy'),
('In welchem Jahr fiel die Berliner Mauer?', '1989', '1990', '1987', '1991', 'a',
  (SELECT id FROM categories WHERE name='Geschichte'), 'Easy'),
('Wer „entdeckte“ Amerika 1492?', 'Christoph Kolumbus', 'Ferdinand Magellan', 'Vasco da Gama', 'Amerigo Vespucci', 'a',
  (SELECT id FROM categories WHERE name='Geschichte'), 'Easy'),
('Welche Zivilisation baute die Pyramiden von Gizeh?', 'Ägypter', 'Maya', 'Azteken', 'Römer', 'a',
  (SELECT id FROM categories WHERE name='Geschichte'), 'Easy'),
('Wer komponierte Beethovens „Neunte Symphonie“?', 'Ludwig van Beethoven', 'Wolfgang Amadeus Mozart', 'Johann Sebastian Bach', 'Joseph Haydn', 'a',
  (SELECT id FROM categories WHERE name='Geschichte'), 'Medium'),
('Was bezeichnet die Reformation im 16. Jahrhundert?', 'Kirchenspaltung', 'Kriegserklärung', 'Industrielle Revolution', 'Französische Revolution', 'a',
  (SELECT id FROM categories WHERE name='Geschichte'), 'Medium'),
('Welche Dynastie herrschte während der Han-Zeit in China?', 'Han', 'Ming', 'Qing', 'Song', 'a',
  (SELECT id FROM categories WHERE name='Geschichte'), 'Medium'),
('Wann begann der Erste Weltkrieg?', '1914', '1918', '1939', '1920', 'a',
  (SELECT id FROM categories WHERE name='Geschichte'), 'Medium'),
('Wer war Pharao zum Bau der Cheops-Pyramide?', 'Cheops', 'Ramses II.', 'Tutanchamun', 'Mykerinos', 'a',
  (SELECT id FROM categories WHERE name='Geschichte'), 'Hard'),
('In welchem Jahr endete das Weströmische Reich?', '476', '1453', '1492', '395', 'a',
  (SELECT id FROM categories WHERE name='Geschichte'), 'Hard'),
('Welcher Fluss gilt traditionell als längster der Welt?', 'Nil', 'Amazonas', 'Jangtse', 'Mississippi', 'a',
  (SELECT id FROM categories WHERE name='Geographie'), 'Easy'),
('Welcher Kontinent liegt südlich von Europa?', 'Afrika', 'Asien', 'Nordamerika', 'Australien', 'a',
  (SELECT id FROM categories WHERE name='Geographie'), 'Easy'),
('Was ist die Hauptstadt von Frankreich?', 'Berlin', 'London', 'Paris', 'Rom', 'c',
  (SELECT id FROM categories WHERE name='Geographie'), 'Easy'),
('Welches Land hat die größte Fläche?', 'Russland', 'Kanada', 'China', 'USA', 'a',
  (SELECT id FROM categories WHERE name='Geographie'), 'Easy'),
('In welchem Land liegt der Kilimandscharo?', 'Kenia', 'Tansania', 'Südafrika', 'Angola', 'b',
  (SELECT id FROM categories WHERE name='Geographie'), 'Medium'),
('Welcher Staat ist der kleinste der Welt?', 'Vatikanstadt', 'Monaco', 'Nauru', 'San Marino', 'a',
  (SELECT id FROM categories WHERE name='Geographie'), 'Medium'),
('Welche Wüste ist flächenmäßig die größte?', 'Sahara', 'Gobi', 'Kalahari', 'Antarktis', 'd',
  (SELECT id FROM categories WHERE name='Geographie'), 'Medium'),
('Wo liegt der tiefste Punkt der Erdoberfläche?', 'Marianengraben', 'Totes Meer', 'Baikalsee', 'Grand Canyon', 'a',
  (SELECT id FROM categories WHERE name='Geographie'), 'Medium'),
('Wie hoch ist der Mount Everest?', '8848 m', '8636 m', '8000 m', '8950 m', 'a',
  (SELECT id FROM categories WHERE name='Geographie'), 'Hard'),
('Welche Insel ist die größte der Welt?', 'Grönland', 'Neuguinea', 'Borneo', 'Madagaskar', 'a',
  (SELECT id FROM categories WHERE name='Geographie'), 'Hard'),
('Wie viele Spieler stehen auf dem Feld bei einer Fußballmannschaft?', '11', '9', '7', '5', 'a',
  (SELECT id FROM categories WHERE name='Sport'), 'Easy'),
('Welcher Sport ist kein Teil der Olympischen Winterspiele?', 'Beachvolleyball', 'Ski Alpin', 'Eishockey', 'Biathlon', 'a',
  (SELECT id FROM categories WHERE name='Sport'), 'Easy'),
('Wie lang ist ein Marathon in Kilometern?', '42,195 km', '40 km', '45 km', '50 km', 'a',
  (SELECT id FROM categories WHERE name='Sport'), 'Easy'),
('Wie oft hat Deutschland die Fußball-WM gewonnen (Stand 2021)?', '4', '3', '5', '2', 'a',
  (SELECT id FROM categories WHERE name='Sport'), 'Easy'),
('Wer hält den Rekord für die meisten Grand-Slam-Titel im Herrentennis?', 'Roger Federer', 'Rafael Nadal', 'Novak Djokovic', 'Pete Sampras', 'c',
  (SELECT id FROM categories WHERE name='Sport'), 'Medium'),
('Wie viele Ringe sind auf der Olympischen Flagge?', '5', '4', '6', '7', 'a',
  (SELECT id FROM categories WHERE name='Sport'), 'Medium'),
('Welches Land gewann die erste Fußball-WM 1930?', 'Uruguay', 'Argentinien', 'Brasilien', 'Italien', 'a',
  (SELECT id FROM categories WHERE name='Sport'), 'Medium'),
('Wie viele Minuten dauert ein NBA-Spiel?', '48', '40', '60', '36', 'a',
  (SELECT id FROM categories WHERE name='Sport'), 'Medium'),
('Wer gewann die Tour de France 2020?', 'Tadej Pogačar', 'Egan Bernal', 'Primož Roglič', 'Chris Froome', 'a',
  (SELECT id FROM categories WHERE name='Sport'), 'Hard'),
('Wie viele olympische Medaillen hat Michael Phelps insgesamt gewonnen?', '28', '22', '26', '24', 'a',
  (SELECT id FROM categories WHERE name='Sport'), 'Hard'),
('Wer spielte den Joker in „The Dark Knight“?', 'Heath Ledger', 'Jack Nicholson', 'Jared Leto', 'Joaquin Phoenix', 'a',
  (SELECT id FROM categories WHERE name='Unterhaltung'), 'Easy'),
('In welcher Serie ist Walter White die Hauptfigur?', 'Breaking Bad', 'Narcos', 'The Wire', 'Ozark', 'a',
  (SELECT id FROM categories WHERE name='Unterhaltung'), 'Easy'),
('Wer sang den Hit „Thriller“?', 'Michael Jackson', 'Prince', 'Madonna', 'Elton John', 'a',
  (SELECT id FROM categories WHERE name='Unterhaltung'), 'Easy'),
('Welches Studio produziert die Original-Star-Wars-Filme?', 'Lucasfilm', 'Marvel', 'Pixar', 'Warner Bros.', 'a',
  (SELECT id FROM categories WHERE name='Unterhaltung'), 'Easy'),
('Wer schrieb die „Harry Potter“-Romane?', 'J.K. Rowling', 'Stephen King', 'J.R.R. Tolkien', 'C.S. Lewis', 'a',
  (SELECT id FROM categories WHERE name='Unterhaltung'), 'Medium'),
('Welcher Film gewann 2020 den Oscar für den Besten Film?', 'Parasite', '1917', 'Joker', 'Once Upon a Time in Hollywood', 'a',
  (SELECT id FROM categories WHERE name='Unterhaltung'), 'Medium'),
('Welche Band veröffentlichte „Bohemian Rhapsody“?', 'Queen', 'The Beatles', 'Pink Floyd', 'Led Zeppelin', 'a',
  (SELECT id FROM categories WHERE name='Unterhaltung'), 'Medium'),
('Welche Schauspielerin verkörpert „Black Widow“?', 'Scarlett Johansson', 'Gal Gadot', 'Brie Larson', 'Zoe Saldana', 'a',
  (SELECT id FROM categories WHERE name='Unterhaltung'), 'Medium'),
('Wer führte Regie bei „2001: A Space Odyssey“?', 'Stanley Kubrick', 'Steven Spielberg', 'George Lucas', 'Ridley Scott', 'a',
  (SELECT id FROM categories WHERE name='Unterhaltung'), 'Hard'),
('Welcher Film hat laut IMDb die höchste Bewertung (Stand 2021)?', 'The Shawshank Redemption', 'The Godfather', 'The Dark Knight', 'Pulp Fiction', 'a',
  (SELECT id FROM categories WHERE name='Unterhaltung'), 'Hard'),
('Wer schrieb „Die Leiden des jungen Werther“?', 'Johann Wolfgang von Goethe', 'Friedrich Schiller', 'Franz Kafka', 'Thomas Mann', 'a',
  (SELECT id FROM categories WHERE name='Literatur'), 'Easy'),
('Wer ist Autor von „Der kleine Prinz“?', 'Antoine de Saint-Exupéry', 'Jules Verne', 'Hermann Hesse', 'Albert Camus', 'a',
  (SELECT id FROM categories WHERE name='Literatur'), 'Easy'),
('Welche Romanfigur stammt von William Shakespeare?', 'Hamlet', 'Moby Dick', 'Faust', 'Odyssee', 'a',
  (SELECT id FROM categories WHERE name='Literatur'), 'Easy'),
('Wer schrieb „Der Herr der Ringe“?', 'J.R.R. Tolkien', 'J.K. Rowling', 'George R.R. Martin', 'C.S. Lewis', 'a',
  (SELECT id FROM categories WHERE name='Literatur'), 'Easy'),
('Wer schrieb „Hundert Jahre Einsamkeit“?', 'Gabriel García Márquez', 'Pablo Neruda', 'Jorge Luis Borges', 'Octavio Paz', 'a',
  (SELECT id FROM categories WHERE name='Literatur'), 'Medium'),
('In welcher Epoche lebte Goethe?', 'Aufklärung', 'Romantik', 'Renaissance', 'Barock', 'a',
  (SELECT id FROM categories WHERE name='Literatur'), 'Medium'),
('Wer ist Protagonist in „1984“?', 'Winston Smith', 'John Doe', 'Guy Montag', 'Holden Caulfield', 'a',
  (SELECT id FROM categories WHERE name='Literatur'), 'Medium'),
('Welches Buch beginnt mit „Es war die beste aller Zeiten“?', 'A Tale of Two Cities', 'Great Expectations', 'War and Peace', 'Jane Eyre', 'a',
  (SELECT id FROM categories WHERE name='Literatur'), 'Medium'),
('Wer übersetzte Homers „Ilias“ ins Deutsche?', 'Johann Heinrich Voss', 'Goethe', 'Schiller', 'Gottfried Herder', 'a',
  (SELECT id FROM categories WHERE name='Literatur'), 'Hard'),
('Welches Werk schrieb Dante Alighieri?', 'Die göttliche Komödie', 'Paradise Lost', 'Inferno', 'La Vita Nuova', 'a',
  (SELECT id FROM categories WHERE name='Literatur'), 'Hard'),
('Wofür steht die Abkürzung CPU?', 'Central Processing Unit', 'Computer Personal Unit', 'Central Performance Unit', 'Computer Processing Unit', 'a',
  (SELECT id FROM categories WHERE name='Technologie'), 'Easy'),
('Welche Sprache ist allgegenwärtig in der Webentwicklung?', 'JavaScript', 'Fortran', 'COBOL', 'Pascal', 'a',
  (SELECT id FROM categories WHERE name='Technologie'), 'Easy'),
('Was ist ein Betriebssystem?', 'Software zur Hardwareverwaltung', 'Programmiersprache', 'Datenbank', 'Browser', 'a',
  (SELECT id FROM categories WHERE name='Technologie'), 'Easy'),
('Welcher Dienst ist bekannt für Cloud-Speicher?', 'Dropbox', 'VLC', 'WinRAR', 'Flash', 'a',
  (SELECT id FROM categories WHERE name='Technologie'), 'Easy'),
('Welcher Standard definiert WLAN-Netze?', 'IEEE 802.11', 'IEEE 802.3', 'IEEE 802.5', 'IEEE 803.2', 'a',
  (SELECT id FROM categories WHERE name='Technologie'), 'Medium'),
('Welcher Algorithmus sortiert durchschnittlich sehr effizient?', 'Quicksort', 'Bubblesort', 'Insertionsort', 'Selectionsort', 'a',
  (SELECT id FROM categories WHERE name='Technologie'), 'Medium'),
('Aus welchem Speichertyp bestehen SSDs hauptsächlich?', 'Flash-Speicher', 'Magnetplatten', 'Bandlaufwerke', 'Optische Scheiben', 'a',
  (SELECT id FROM categories WHERE name='Technologie'), 'Medium'),
('Was beschreibt REST in Web-APIs?', 'Architekturprinzip', 'Programmiersprache', 'Datenbank', 'Verschlüsselung', 'a',
  (SELECT id FROM categories WHERE name='Technologie'), 'Medium'),
('Was besagt das CAP-Theorem?', 'Konsistenz-Verfügbarkeit-Partitionstoleranz', 'Konsistenz-Parallelität-Performance', 'Cache-Availability-Partitioning', 'Consistency-Atomicity-Performance', 'a',
  (SELECT id FROM categories WHERE name='Technologie'), 'Hard'),
('Wofür steht JSON?', 'JavaScript Object Notation', 'Java Source Open Network', 'JavaScript Oriented Notation', 'Just Some Object Notation', 'a',
  (SELECT id FROM categories WHERE name='Technologie'), 'Hard'),
('Was ist 2 + 2?', '3', '4', '5', '6', 'b',
  (SELECT id FROM categories WHERE name='Mathematik'), 'Easy'),
('Wie nennt man ein Viereck mit vier gleichen Seiten?', 'Quadrat', 'Rechteck', 'Raute', 'Kreis', 'a',
  (SELECT id FROM categories WHERE name='Mathematik'), 'Easy'),
('Wie viele Grad hat ein rechter Winkel?', '90', '180', '45', '60', 'a',
  (SELECT id FROM categories WHERE name='Mathematik'), 'Easy'),
('Wert von π (ungefähr)?', '3.14', '2.72', '1.62', '4.13', 'a',
  (SELECT id FROM categories WHERE name='Mathematik'), 'Easy'),
('Lösung der Gleichung x + 3 = 7?', '4', '5', '3', '10', 'a',
  (SELECT id FROM categories WHERE name='Mathematik'), 'Medium'),
('Ableitung von x²?', '2x', 'x', 'x²', '1', 'a',
  (SELECT id FROM categories WHERE name='Mathematik'), 'Medium'),
('Formel für Kreisfläche?', 'π·r²', '2·π·r', 'π·d', 'π·r', 'a',
  (SELECT id FROM categories WHERE name='Mathematik'), 'Medium'),
('Nullstelle einer Funktion f(x)?', 'Wert von x bei f(x)=0', 'Maximum', 'Minimum', 'Durchschnitt', 'a',
  (SELECT id FROM categories WHERE name='Mathematik'), 'Medium'),
('Binomische Formel (a+b)²?', 'a² + 2ab + b²', 'a² − 2ab + b²', 'a² + b²', '2a² + 2b² + ab', 'a',
  (SELECT id FROM categories WHERE name='Mathematik'), 'Hard'),
('limₓ→0 sin(x)/x?', '1', '0', '∞', '-1', 'a',
  (SELECT id FROM categories WHERE name='Mathematik'), 'Hard'),
('Wer malte die Mona Lisa?', 'Leonardo da Vinci', 'Michelangelo', 'Raphael', 'Pablo Picasso', 'a',
  (SELECT id FROM categories WHERE name='Kunst'), 'Easy'),
('Welche Farbe erhält man aus Rot + Weiß?', 'Rosa', 'Lila', 'Orange', 'Braun', 'a',
  (SELECT id FROM categories WHERE name='Kunst'), 'Easy'),
('Was ist eine Skulptur?', 'Dreidimensionales Kunstwerk', 'Gemälde', 'Musikstück', 'Gedicht', 'a',
  (SELECT id FROM categories WHERE name='Kunst'), 'Easy'),
('Wer komponierte die „Mondscheinsonate“?', 'Ludwig van Beethoven', 'Wolfgang Amadeus Mozart', 'Johann Sebastian Bach', 'Frédéric Chopin', 'a',
  (SELECT id FROM categories WHERE name='Kunst'), 'Easy'),
('Welcher Stil wird häufig mit Pablo Picasso verbunden?', 'Kubismus', 'Impressionismus', 'Surrealismus', 'Barock', 'a',
  (SELECT id FROM categories WHERE name='Kunst'), 'Medium'),
('Wer schuf die Skulptur „David“?', 'Michelangelo', 'Donatello', 'Bernini', 'Rodin', 'a',
  (SELECT id FROM categories WHERE name='Kunst'), 'Medium'),
('Welches Kunstwerk malte Edvard Munch?', 'Der Schrei', 'Die Sternennacht', 'Die Erschaffung Adams', 'Guernica', 'a',
  (SELECT id FROM categories WHERE name='Kunst'), 'Medium'),
('In welcher Epoche entstanden die Höhlenmalereien von Lascaux?', 'Prähistorie', 'Renaissance', 'Barock', 'Moderne', 'a',
  (SELECT id FROM categories WHERE name='Kunst'), 'Medium'),
('Welcher Maler war ein Hauptvertreter des Surrealismus?', 'Salvador Dalí', 'Claude Monet', 'Caravaggio', 'Vincent van Gogh', 'a',
  (SELECT id FROM categories WHERE name='Kunst'), 'Hard'),
('Wer schuf das Gemälde „Die Schule von Athen“?', 'Raffael', 'Leonardo da Vinci', 'Hieronymus Bosch', 'Peter Paul Rubens', 'a',
  (SELECT id FROM categories WHERE name='Kunst'), 'Hard');
CREATE TABLE IF NOT EXISTS stats (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  user_id INTEGER,
  score INTEGER NOT NULL,
  total INTEGER NOT NULL,
  challenge_type TEXT,
  challenge_ref INTEGER,
  timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE SET NULL
);
");

// Ersten Admin anlegen, falls keiner existiert
$adminCount = $pdo->query("SELECT COUNT(*) FROM users WHERE role='admin'")->fetchColumn();
if ($adminCount == 0) {
  $hash = password_hash('admin123', PASSWORD_DEFAULT);
  $pdo->prepare("INSERT INTO users(username,password,role) VALUES('admin',?, 'admin')")
      ->execute([$hash]);
}

// Standard‐Kategorie anlegen, falls keine existiert
$catCount = $pdo->query("SELECT COUNT(*) FROM categories")->fetchColumn();
if ($catCount == 0) {
  $pdo->exec("INSERT INTO categories(name) VALUES('Allgemein')");
}

// --- INTERNATIONALISIERUNG ---------------------------------------------------
$available = ['de','en','fr','it','es','tr'];
if (isset($_GET['lang']) && in_array($_GET['lang'],$available)) {
  $_SESSION['lang'] = $_GET['lang'];
}
$lang = $_SESSION['lang'] ?? 'de';
$T = [
  'de'=>[
    'welcome'=>'Willkommen',
    'login'=>'Login',
    'register'=>'Registrieren',
    'logout'=>'Logout',
    'start_quiz'=>'Quiz starten',
    'admin_dashboard'=>'Admin-Dashboard',
    'categories'=>'Kategorien verwalten',
    'profile'=>'Profil',
    'progress'=>'Fortschritt',
    'question_management'=>'Fragenverwaltung',
    'stats'=>'Statistiken',
    'export'=>'Exportieren',
    'challenge_mode'=>'Challenge-Modus',
    'standard'=>'Standard',
    'time_category'=>'Zeit-Kategorie',
    'time_difficulty'=>'Zeit-Schwierigkeit',
    'category'=>'Kategorie',
    'difficulty'=>'Schwierigkeit',
    'limit'=>'Fragenanzahl',
    'fill_all'=>'Bitte alle Felder ausfüllen.',
    'user_exists'=>'Benutzername existiert bereits.',
    'register_success'=>'Registrierung erfolgreich.',
    'login_failed'=>'Login fehlgeschlagen.'
  ],
  'en'=>[
    'welcome'=>'Welcome',
    'login'=>'Login',
    'register'=>'Register',
    'logout'=>'Logout',
    'start_quiz'=>'Start Quiz',
    'admin_dashboard'=>'Admin Dashboard',
    'categories'=>'Manage Categories',
    'profile'=>'Profile',
    'progress'=>'Progress',
    'question_management'=>'Manage Questions',
    'stats'=>'Statistics',
    'export'=>'Export',
    'challenge_mode'=>'Challenge Mode',
    'standard'=>'Standard',
    'time_category'=>'Time by Category',
    'time_difficulty'=>'Time by Difficulty',
    'category'=>'Category',
    'difficulty'=>'Difficulty',
    'limit'=>'Number of Questions',
    'fill_all'=>'Please fill all fields.',
    'user_exists'=>'Username already exists.',
    'register_success'=>'Registration successful.',
    'login_failed'=>'Login failed.'
  ],
  'fr'=>[
    'welcome'=>'Bienvenue',
    'login'=>'Connexion',
    'register'=>'S’inscrire',
    'logout'=>'Déconnexion',
    'start_quiz'=>'Commencer le quiz',
    'admin_dashboard'=>'Tableau de bord',
    'categories'=>'Gérer les catégories',
    'profile'=>'Profil',
    'progress'=>'Progrès',
    'question_management'=>'Gérer les questions',
    'stats'=>'Statistiques',
    'export'=>'Exporter',
    'challenge_mode'=>'Mode défi',
    'standard'=>'Standard',
    'time_category'=>'Temps-par-catégorie',
    'time_difficulty'=>'Temps-par-difficulté',
    'category'=>'Catégorie',
    'difficulty'=>'Difficulté',
    'limit'=>'Nombre de questions',
    'fill_all'=>'Veuillez remplir tous les champs.',
    'user_exists'=>'Nom d’utilisateur déjà existant.',
    'register_success'=>'Inscription réussie.',
    'login_failed'=>'Échec de la connexion.'
  ],
  'it'=>[
    'welcome'=>'Benvenuto',
    'login'=>'Accesso',
    'register'=>'Registrati',
    'logout'=>'Esci',
    'start_quiz'=>'Inizia quiz',
    'admin_dashboard'=>'Pannello Admin',
    'categories'=>'Gestisci categorie',
    'profile'=>'Profilo',
    'progress'=>'Progresso',
    'question_management'=>'Gestione domande',
    'stats'=>'Statistiche',
    'export'=>'Esporta',
    'challenge_mode'=>'Modalità sfida',
    'standard'=>'Standard',
    'time_category'=>'Tempo-per-categoria',
    'time_difficulty'=>'Tempo-per-difficoltà',
    'category'=>'Categoria',
    'difficulty'=>'Difficoltà',
    'limit'=>'Numero di domande',
    'fill_all'=>'Compila tutti i campi.',
    'user_exists'=>'Nome utente già esistente.',
    'register_success'=>'Registrazione avvenuta con successo.',
    'login_failed'=>'Accesso fallito.'
  ],
  'es'=>[
    'welcome'=>'Bienvenido',
    'login'=>'Iniciar sesión',
    'register'=>'Registrarse',
    'logout'=>'Cerrar sesión',
    'start_quiz'=>'Iniciar cuestionario',
    'admin_dashboard'=>'Panel Admin',
    'categories'=>'Gestionar categorías',
    'profile'=>'Perfil',
    'progress'=>'Progreso',
    'question_management'=>'Gestionar preguntas',
    'stats'=>'Estadísticas',
    'export'=>'Exportar',
    'challenge_mode'=>'Modo desafío',
    'standard'=>'Estándar',
    'time_category'=>'Tiempo-por-categoría',
    'time_difficulty'=>'Tiempo-por-dificultad',
    'category'=>'Categoría',
    'difficulty'=>'Dificultad',
    'limit'=>'Número de preguntas',
    'fill_all'=>'Por favor completa todos los campos.',
    'user_exists'=>'El nombre de usuario ya existe.',
    'register_success'=>'Registro exitoso.',
    'login_failed'=>'Error de inicio de sesión.'
  ],
  'tr'=>[
    'welcome'=>'Hoş geldiniz',
    'login'=>'Giriş',
    'register'=>'Kayıt ol',
    'logout'=>'Çıkış',
    'start_quiz'=>'Quiz’i Başlat',
    'admin_dashboard'=>'Admin Paneli',
    'categories'=>'Kategorileri Yönet',
    'profile'=>'Profil',
    'progress'=>'İlerleme',
    'question_management'=>'Soruları Yönet',
    'stats'=>'İstatistikler',
    'export'=>'Dışa Aktar',
    'challenge_mode'=>'Meydan Okuma Modu',
    'standard'=>'Standart',
    'time_category'=>'Kategoriye Göre Süre',
    'time_difficulty'=>'Zorluk’a Göre Süre',
    'category'=>'Kategori',
    'difficulty'=>'Zorluk',
    'limit'=>'Soru Sayısı',
    'fill_all'=>'Lütfen tüm alanları doldurun.',
    'user_exists'=>'Kullanıcı adı zaten var.',
    'register_success'=>'Kayıt başarılı.',
    'login_failed'=>'Giriş başarısız.'
  ]
];
function t($key){ global $T,$lang; return $T[$lang][$key] ?? $key; }

// --- JWT‐HELPER --------------------------------------------------------------
function generateJWT($uid){
  $payload = ['sub'=>$uid, 'iat'=>time(), 'exp'=>time()+3600];
  return JWT::encode($payload, JWT_SECRET, 'HS256');
}
function verifyJWT(){
  if (!isset($_SERVER['HTTP_AUTHORIZATION'])) return false;
  list(,$jwt)=explode(' ', $_SERVER['HTTP_AUTHORIZATION']);
  try {
    $p = JWT::decode($jwt, JWT_SECRET, ['HS256']);
    return $p->sub;
  } catch(Exception $e){
    return false;
  }
}

// --- OAUTH GOOGLE FLOW -------------------------------------------------------
if (isset($_GET['oauth']) && $_GET['oauth'] === 'google') {
  // Callback
  if (isset($_GET['code'])) {
    $post = http_build_query([
      'code'=>$_GET['code'],
      'client_id'=>OAUTH_GOOGLE_CLIENT_ID,
      'client_secret'=>OAUTH_GOOGLE_CLIENT_SECRET,
      'redirect_uri'=>OAUTH_REDIRECT_URI,
      'grant_type'=>'authorization_code'
    ]);
    $opts = ['http'=>[
      'method'=>'POST',
      'header'=>"Content-Type: application/x-www-form-urlencoded",
      'content'=>$post
    ]];
    $tokenRes = file_get_contents('https://oauth2.googleapis.com/token', false, stream_context_create($opts));
    $tok = json_decode($tokenRes, true);
    // Userinfo
    $info = json_decode(file_get_contents(
      "https://openidconnect.googleapis.com/v1/userinfo?access_token=".$tok['access_token']
    ), true);
    // In DB anlegen oder laden
    $stmt = $pdo->prepare("SELECT * FROM users WHERE provider='google' AND oauth_id=?");
    $stmt->execute([$info['sub']]);
    if (!$user = $stmt->fetch(PDO::FETCH_ASSOC)) {
      $pdo->prepare("INSERT INTO users(username,provider,oauth_id,role) VALUES(?,?,?,'user')")
          ->execute([$info['email'],'google',$info['sub']]);
      $uid = $pdo->lastInsertId();
      $pdo->prepare("INSERT INTO profiles(user_id) VALUES(?)")->execute([$uid]);
    } else {
      $uid = $user['id'];
    }
    $_SESSION['user_id']=$uid;
    $_SESSION['username']=$info['email'];
    $_SESSION['role']='user';
    $_SESSION['jwt']=generateJWT($uid);
    header('Location:index.php'); exit;
  }
  // Redirect zu Google
  $authUrl = 'https://accounts.google.com/o/oauth2/v2/auth?'. http_build_query([
    'client_id'=>OAUTH_GOOGLE_CLIENT_ID,
    'redirect_uri'=>OAUTH_REDIRECT_URI,
    'response_type'=>'code',
    'scope'=>'openid email profile'
  ]);
  header("Location: $authUrl"); exit;
}

// --- API‐ENDPOINTS ------------------------------------------------------------
if (isset($_GET['api'])) {
  header('Content-Type: application/json');
  $uid = verifyJWT();
  switch($_GET['api']) {
    // Fragen abrufen
    case 'questions':
      $cat  = intval($_GET['category']   ?? 0);
      $diff = $_GET['difficulty'] ?? '';
      $lim  = intval($_GET['limit'] ?? 5);
      $sql = "SELECT q.id,q.question,q.option_a,q.option_b,q.option_c,q.option_d,
                     c.name AS category,q.difficulty
              FROM questions q
              JOIN categories c ON c.id=q.category_id WHERE 1";
      $params = [];
      if ($cat)  { $sql .= " AND q.category_id=?";   $params[]=$cat; }
      if ($diff) { $sql .= " AND q.difficulty=?";     $params[]=$diff; }
      $sql .= " ORDER BY RANDOM() LIMIT $lim";
      $stmt = $pdo->prepare($sql);
      $stmt->execute($params);
      echo json_encode($stmt->fetchAll(PDO::FETCH_ASSOC));
      break;

    // Antworten auswerten
    case 'submit':
      $data = json_decode(file_get_contents('php://input'), true);
      $answers = $data['answers'] ?? [];
      $challenge = $data['challenge'] ?? 'standard';
      $category  = intval($data['category'] ?? 0);
      $score = 0; $total = count($answers);
      foreach ($answers as $qid => $ans) {
        $c = $pdo->prepare("SELECT correct_option FROM questions WHERE id=?");
        $c->execute([$qid]);
        if ($c->fetchColumn() === $ans) $score++;
      }
      $pdo->prepare("
        INSERT INTO stats(user_id,score,total,challenge_type,challenge_ref)
        VALUES(?,?,?,?,?)
      ")->execute([ $uid, $score, $total, $challenge, $category ]);
      echo json_encode(['score'=>$score,'total'=>$total]);
      break;

    // Export CSV/JSON (nur Admin)
    case 'export':
      if (($_SESSION['role'] ?? '') !== 'admin') {
        echo json_encode([]); exit;
      }
      $fmt = $_GET['format'] ?? 'json';
      $rows = $pdo->query("
        SELECT s.id,u.username,s.score,s.total,s.challenge_type,s.challenge_ref,s.timestamp
        FROM stats s
        LEFT JOIN users u ON u.id=s.user_id
        ORDER BY s.timestamp DESC
      ")->fetchAll(PDO::FETCH_ASSOC);

      if ($fmt === 'csv') {
        header('Content-Type: text/csv');
        header('Content-Disposition: attachment;filename=stats.csv');
        $out = fopen('php://output', 'w');
        fputcsv($out, array_keys($rows[0] ?? []));
        foreach ($rows as $r) fputcsv($out, $r);
        fclose($out);
      } else {
        echo json_encode($rows);
      }
      break;
  }
  exit;
}

// --- FORMULAR‐HANDLER --------------------------------------------------------
// Registrierung
if (isset($_POST['do_register'])) {
  $u = trim($_POST['username']); $p = $_POST['password'];
  if ($u && $p) {
    $h = password_hash($p, PASSWORD_DEFAULT);
    try {
      $pdo->prepare("INSERT INTO users(username,password) VALUES(?,?)")
          ->execute([$u,$h]);
      $uid = $pdo->lastInsertId();
      $pdo->prepare("INSERT INTO profiles(user_id) VALUES(?)")
          ->execute([$uid]);
      $msg = "✅ " . t('register_success');
    } catch(Exception $e) {
      $msg = "⚠️ " . t('user_exists');
    }
  } else {
    $msg = "⚠️ " . t('fill_all');
  }
}

// Login
if (isset($_POST['do_login'])) {
  $u = trim($_POST['username']); $p = $_POST['password'];
  $st = $pdo->prepare("SELECT * FROM users WHERE username=?");
  $st->execute([$u]); $usr = $st->fetch(PDO::FETCH_ASSOC);
  if ($usr && password_verify($p, $usr['password'])) {
    $_SESSION['user_id']   = $usr['id'];
    $_SESSION['username']  = $usr['username'];
    $_SESSION['role']      = $usr['role'];
    $_SESSION['jwt']       = generateJWT($usr['id']);
    header("Location:index.php"); exit;
  } else {
    $msg = "⚠️ " . t('login_failed');
  }
}

// Logout
if (isset($_GET['action']) && $_GET['action'] === 'logout') {
  session_destroy(); header("Location:index.php"); exit;
}

// Admin: Kategorie CRUD
if (isset($_POST['do_add_cat']) && ($_SESSION['role'] ?? '')==='admin') {
  $name = trim($_POST['cat_name']);
  if ($name) {
    $pdo->prepare("INSERT INTO categories(name) VALUES(?)")
        ->execute([$name]);
    $msg = "✅ " . t('categories') . " angelegt.";
  } else {
    $msg = "⚠️ " . t('fill_all');
  }
}
if (isset($_POST['do_del_cat']) && ($_SESSION['role'] ?? '')==='admin') {
  $pdo->prepare("DELETE FROM categories WHERE id=?")
      ->execute([ $_POST['cat_id'] ]);
  $msg = "🗑️ Kategorie gelöscht.";
}

// Admin: Frage CRUD
if (isset($_POST['do_add_q']) && ($_SESSION['role'] ?? '')==='admin') {
  $f = ['question','option_a','option_b','option_c','option_d','correct_option','category_id','difficulty'];
  foreach($f as $k) $$k = $_POST[$k] ?? '';
  if ($question && $option_a && $option_b && $option_c && $option_d && $correct_option && $category_id && $difficulty) {
    $pdo->prepare("
      INSERT INTO questions
        (question,option_a,option_b,option_c,option_d,correct_option,category_id,difficulty)
      VALUES (?,?,?,?,?,?,?,?)
    ")->execute([$question,$option_a,$option_b,$option_c,$option_d,$correct_option,$category_id,$difficulty]);
    $msg = "✅ Frage gespeichert.";
  } else {
    $msg = "⚠️ " . t('fill_all');
  }
}
if (isset($_POST['do_del_q']) && ($_SESSION['role'] ?? '')==='admin') {
  $pdo->prepare("DELETE FROM questions WHERE id=?")
      ->execute([ $_POST['qid'] ]);
  $msg = "🗑️ Frage gelöscht.";
}

// --- PAGE OUTPUT ------------------------------------------------------------
$logged = isset($_SESSION['user_id']);
?>
<!DOCTYPE html>
<html lang="<?=$lang?>">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <title>Dreamcodes - Quiz Master</title>
  <style>
    * { box-sizing:border-box; margin:0; padding:0 }
    body { font-family:'Segoe UI',sans-serif; background:#1f1c2c; color:#eee; }
    header, main, footer { max-width:900px; margin:auto; padding:1rem }
    a { color:#0af; text-decoration:none }
    button,input,select,textarea { font:inherit }
    header { display:flex; justify-content:space-between; align-items:center }
    nav select { background:#2c2c3c; color:#eee; border:none; padding:.5rem; }
    .msg { margin:1rem 0; padding:.75rem 1rem; border-radius:5px }
    .success { background:#184f2e; color:#b5f5c1 }
    .error   { background:#4f1e1e; color:#f5b5b5 }
    form { background:#2c2c3c; padding:1rem; border-radius:8px; margin:1rem 0 }
    form > * + * { margin-top:.75rem }
    input,select,textarea { width:100%; padding:.5rem; border:none; border-radius:4px }
    button { padding:.6rem 1rem; background:#0af; color:#1f1c2c; border:none; border-radius:4px; cursor:pointer }
    button:hover { background:#06f }
    table { width:100%; border-collapse:collapse; margin:1rem 0 }
    th,td { padding:.5rem; border:1px solid #444; text-align:left }
    th { background:#333 }
    section { margin:2rem 0 }
    .grid { display:grid; gap:1rem; }
    @media(min-width:600px){ .grid-2 { grid-template-columns:1fr 1fr } }
  </style>
</head>
<body>

<header>
  <h1>🧠 Quiz Master</h1>
  <nav>
    <?php if($logged): ?>
      <span><?=htmlspecialchars($_SESSION['username'])?></span>
      <a href="?action=logout"><?=t('logout')?></a>
      <select onchange="location='?lang='+this.value">
        <?php foreach($available as $l): ?>
          <option <?=$l===$lang?'selected':''?> value="<?=$l?>"><?=$l?></option>
        <?php endforeach; ?>
      </select>
    <?php else: ?>
      <select onchange="location='?lang='+this.value">
        <?php foreach($available as $l): ?>
          <option <?=$l===$lang?'selected':''?> value="<?=$l?>"><?=$l?></option>
        <?php endforeach; ?>
      </select>
    <?php endif; ?>
  </nav>
</header>

<main>
  <?php if(!empty($msg)): ?>
    <div class="msg <?=strpos($msg,'✅')===0?'success':'error'?>">
      <?=$msg?>
    </div>
  <?php endif; ?>

  <?php if(!$logged): ?>
    <!-- PUBLIC: Registrieren & Login -->
    <div class="grid grid-2">
      <form method="post">
        <h2><?=t('register')?></h2>
        <input name="username" placeholder="<?=t('register')?>" required>
        <input name="password" type="password" placeholder="<?=t('register')?>" required>
        <button name="do_register"><?=t('register')?></button>
      </form>
      <form method="post">
        <h2><?=t('login')?></h2>
        <input name="username" placeholder="<?=t('login')?>" required>
        <input name="password" type="password" placeholder="<?=t('login')?>" required>
        <button name="do_login"><?=t('login')?></button>
      </form>
    </div>
    <p>— oder —</p>
    <a href="?oauth=google">Mit Google anmelden</a>

  <?php else: ?>
    <!-- USER PROFILE & PROGRESS -->
    <section id="profile">
      <h2><?=t('profile')?> — <?=t('welcome')?>, <?=htmlspecialchars($_SESSION['username'])?></h2>
      <h3><?=t('progress')?></h3>
      <table>
        <tr><th><?=t('stats')?></th><th><?=t('progress')?></th><th><?=t('challenge_mode')?></th><th><?=t('start_quiz')?></th></tr>
        <?php
        $ps = $pdo->prepare("
          SELECT score,total,challenge_type,challenge_ref,timestamp
          FROM stats WHERE user_id=? ORDER BY timestamp DESC LIMIT 10
        "); $ps->execute([$_SESSION['user_id']]);
        while($r=$ps->fetch(PDO::FETCH_ASSOC)){
          echo "<tr>
                  <td>{$r['timestamp']}</td>
                  <td>{$r['score']}/{$r['total']}</td>
                  <td>{$r['challenge_type']}</td>
                  <td></td>
                </tr>";
        }
        ?>
      </table>
    </section>

    <?php if($_SESSION['role']==='admin'): ?>
      <!-- ADMIN DASHBOARD -->
      <section id="admin">
        <h2><?=t('admin_dashboard')?></h2>

        <!-- Kategorienverwaltung -->
        <h3><?=t('categories')?></h3>
        <form method="post" class="grid grid-2">
          <input name="cat_name" placeholder="<?=t('category')?>" required>
          <button name="do_add_cat"><?=t('categories')?></button>
        </form>
        <table>
          <tr><th>ID</th><th><?=t('category')?></th><th>Aktion</th></tr>
          <?php
          $cats = $pdo->query("SELECT * FROM categories")->fetchAll(PDO::FETCH_ASSOC);
          foreach($cats as $c){
            echo "<tr>
                    <td>{$c['id']}</td>
                    <td>{$c['name']}</td>
                    <td>
                      <form method='post' style='display:inline'>
                        <input type='hidden' name='cat_id' value='{$c['id']}'>
                        <button name='do_del_cat'>🗑️</button>
                      </form>
                    </td>
                  </tr>";
          }
          ?>
        </table>

        <!-- Fragenverwaltung -->
        <h3><?=t('question_management')?></h3>
        <form method="post" class="grid grid-2">
          <textarea name="question" placeholder="Frage" required></textarea>
          <div>
            <input name="option_a" placeholder="Antwort A" required>
            <input name="option_b" placeholder="Antwort B" required>
            <input name="option_c" placeholder="Antwort C" required>
            <input name="option_d" placeholder="Antwort D" required>
            <select name="correct_option" required>
              <option value=""><?=t('correct_option')?></option>
              <option value="a">A</option><option value="b">B</option>
              <option value="c">C</option><option value="d">D</option>
            </select>
            <select name="category_id" required>
              <option value=""><?=t('category')?></option>
              <?php foreach($cats as $c) echo "<option value='{$c['id']}'>{$c['name']}</option>"; ?>
            </select>
            <select name="difficulty" required>
              <option value=""><?=t('difficulty')?></option>
              <option>Easy</option><option>Medium</option><option>Hard</option>
            </select>
          </div>
          <button name="do_add_q">✓ Frage anlegen</button>
        </form>
        <table>
          <tr><th>ID</th><th>Frage (Kurz)</th><th>Kategorie</th><th>Diff.</th><th>Aktion</th></tr>
          <?php
          $allQ = $pdo->query("
            SELECT q.id,q.question,c.name AS cat,q.difficulty
            FROM questions q JOIN categories c ON c.id=q.category_id
            ORDER BY q.id DESC
          ")->fetchAll(PDO::FETCH_ASSOC);
          foreach($allQ as $q){
            $short = mb_substr($q['question'],0,50) . (mb_strlen($q['question'])>50?'…':'');
            echo "<tr>
                    <td>{$q['id']}</td>
                    <td>{$short}</td>
                    <td>{$q['cat']}</td>
                    <td>{$q['difficulty']}</td>
                    <td>
                      <form method='post' style='display:inline'>
                        <input type='hidden' name='qid' value='{$q['id']}'>
                        <button name='do_del_q'>🗑️</button>
                      </form>
                    </td>
                  </tr>";
          }
          ?>
        </table>

        <!-- Statistiken & Export -->
        <h3><?=t('stats')?></h3>
        <a href="?api=export&format=json"><?=t('export')?> JSON</a> |
        <a href="?api=export&format=csv"><?=t('export')?> CSV</a>
      </section>
    <?php endif; ?>

    <!-- QUIZ‐INTERFACE -->
    <section id="quiz">
      <h2><?=t('start_quiz')?></h2>
      <div class="grid grid-2">
        <label>
          <?=t('category')?>:
          <select id="quiz-cat">
            <option value="0"><?=t('all')?></option>
            <?php foreach($cats as $c) echo "<option value='{$c['id']}'>{$c['name']}</option>"; ?>
          </select>
        </label>
        <label>
          <?=t('difficulty')?>:
          <select id="quiz-diff">
            <option value=""><?=t('all')?></option>
            <option>Easy</option><option>Medium</option><option>Hard</option>
          </select>
        </label>
        <label>
          <?=t('limit')?>:
          <select id="quiz-limit">
            <option value="5">5</option><option value="10">10</option>
            <option value="15">15</option>
          </select>
        </label>
        <label>
          <?=t('challenge_mode')?>:
          <select id="quiz-challenge">
            <option value="standard"><?=t('standard')?></option>
            <option value="time_category"><?=t('time_category')?></option>
            <option value="time_difficulty"><?=t('time_difficulty')?></option>
          </select>
        </label>
      </div>
      <button id="start-quiz"><?=t('start_quiz')?></button>

      <div id="quiz-area" style="display:none; margin-top:1rem">
        <div class="timer">⏱ <span id="time">0</span>s</div>
        <div class="progress"><div id="prog-bar" class="progress-bar"></div></div>
        <form id="quiz-form">
          <div id="questions-container"></div>
          <button type="submit"><?=t('submit')?></button>
        </form>
        <div id="quiz-result"></div>
      </div>
    </section>
  <?php endif; ?>
</main>

<footer>
  <p style="text-align:center; padding:1rem 0; font-size:.9em">
    &copy; <?= date('Y') ?> <a href="http://www.dreamcodes.net" target="_blank">
      Dreamcodes
    </a>
  </p>
</footer>

<script>
const JWT = "<?= $_SESSION['jwt'] ?? '' ?>";
function apiFetch(path, opts={}){
  opts.headers = opts.headers || {};
  opts.headers['Authorization'] = 'Bearer ' + JWT;
  return fetch(path, opts);
}

// Quiz‐Logik
let questions = [], timerInt;
document.getElementById('start-quiz').addEventListener('click', ()=>{
  const cat  = document.getElementById('quiz-cat').value;
  const diff = document.getElementById('quiz-diff').value;
  const lim  = document.getElementById('quiz-limit').value;
  const ch   = document.getElementById('quiz-challenge').value;
  apiFetch(`?api=questions&category=${cat}&difficulty=${diff}&limit=${lim}`)
    .then(r=>r.json()).then(data=>{
      questions = data;
      renderQuiz(data, ch, cat);
    });
});

function renderQuiz(data, challenge, category){
  document.getElementById('quiz-area').style.display = 'block';
  const container = document.getElementById('questions-container');
  container.innerHTML = '';
  data.forEach((q,i)=>{
    const div = document.createElement('div');
    div.className = 'question';
    div.innerHTML = `
      <p><strong>${i+1}.</strong> ${q.question}
      <br><em>${q.category} / ${q.difficulty}</em></p>
      ${['a','b','c','d'].map(opt=>`
        <label>
          <input type="radio" name="ans_${q.id}" value="${opt}" required>
          ${q['option_'+opt]}
        </label><br>
      `).join('')}
    `;
    container.appendChild(div);
  });

  const timeSpan = document.getElementById('time');
  const progBar = document.getElementById('prog-bar');
  let t = 60;
  if (challenge==='time_category' || challenge==='time_difficulty') {
    t = (challenge==='time_category') 
      ? 15 * data.length
      : Math.max(...data.map(q=> ({Easy:30,Medium:45,Hard:60}[q.difficulty] )));
  }
  timeSpan.textContent = t;
  progBar.style.width = '0%';

  clearInterval(timerInt);
  timerInt = setInterval(()=>{
    t--;
    timeSpan.textContent = t;
    progBar.style.width = ((timerSpan=>(((parseInt(timerSpan.textContent)||0) / (t+1))*100)+'%')(timeSpan)) ;
    if (t<=0) {
      clearInterval(timerInt);
      submitQuiz(challenge, category);
    }
  },1000);

  document.getElementById('quiz-form').onsubmit = e => {
    e.preventDefault();
    clearInterval(timerInt);
    submitQuiz(challenge, category);
  };
}

function submitQuiz(challenge, category){
  const answers = {};
  document.querySelectorAll('#questions-container input:checked').forEach(inp=>{
    answers[inp.name.replace('ans_','')] = inp.value;
  });
  apiFetch('?api=submit', {
    method:'POST',
    headers:{ 'Content-Type':'application/json' },
    body: JSON.stringify({answers, challenge, category})
  })
  .then(r=>r.json())
  .then(res=>{
    document.getElementById('quiz-result').innerHTML = `
      <div class="msg success">
        Du hast <strong>${res.score}</strong> von <strong>${res.total}</strong> Punkten!
      </div>`;
  });
}
</script>

</body>
</html>
Dreamcodes Redaktion
Dreamcodes Redaktion
Jeder auf Dreamcodes bereitgestellte Codeschnipsel sowie jede Tutorial Anleitung basiert auf geprüften Best Practices und fundierter Praxiserfahrung. Ziel ist es, ein belastbares technisches Fundament bereitzustellen und keine unausgereiften oder experimentellen Lösungen zu veröffentlichen. Die konkrete Nutzung, Integration, Anpassung und Absicherung der Inhalte obliegt jedoch dem Anwender. Vor dem produktiven Einsatz sind sämtliche Inhalte eigenverantwortlich zu prüfen, zu testen und gegebenenfalls abzusichern. Dreamcodes stellt die technische Grundlage zur Verfügung, die finale Umsetzung und Verantwortung verbleibt beim Nutzer.
Vorheriges Tutorial
Nächstes Tutorial

Vielleicht einen Blick WERT?