Samstag, 13 September 2025

Top 5 diese Woche

Ähnliche Tutorials

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>
Vorheriges Tutorial
Nächstes Tutorial

Hier etwas für dich dabei?