feat: quiz, cheat sheets, admin modules - MC quiz, search, user mgmt, content import

Dieser Commit ist enthalten in:
hafroese 2026-04-02 23:41:19 +02:00
Ursprung 03778e4bed
Commit 3cd865ccbc
6 geänderte Dateien mit 425 neuen und 0 gelöschten Zeilen

77
edu/api/quiz.php Normale Datei
Datei anzeigen

@ -0,0 +1,77 @@
<?php
$user_id = require_auth();
// GET /api/quiz/generate?deck={slug}&count=10
if (get_method() === 'GET' && ($segments[1] ?? '') === 'generate') {
$slug = get_param('deck', '');
$count = max(1, min(50, (int) get_param('count', 10)));
$query = "SELECT c.id, c.question, c.answer, c.level, d.slug AS deck_slug, d.name AS deck_name
FROM cards c JOIN decks d ON d.id = c.deck_id";
$params = [];
if ($slug) {
$query .= " WHERE d.slug = :slug";
$params[':slug'] = $slug;
}
$query .= " ORDER BY RANDOM() LIMIT " . $count;
$stmt = $pdo->prepare($query);
$stmt->execute($params);
$cards = $stmt->fetchAll();
$all_answers = $pdo->query("SELECT DISTINCT answer FROM cards ORDER BY RANDOM() LIMIT 200")->fetchAll(PDO::FETCH_COLUMN);
$questions = [];
foreach ($cards as $card) {
$wrong = [];
$shuffled = $all_answers;
shuffle($shuffled);
foreach ($shuffled as $a) {
if ($a !== $card['answer'] && count($wrong) < 3) {
$wrong[] = mb_substr($a, 0, 120) . (mb_strlen($a) > 120 ? '...' : '');
}
}
$correct_short = mb_substr($card['answer'], 0, 120) . (mb_strlen($card['answer']) > 120 ? '...' : '');
$options = $wrong;
$options[] = $correct_short;
shuffle($options);
$questions[] = [
'card_id' => $card['id'],
'question' => $card['question'],
'options' => $options,
'correct_index' => array_search($correct_short, $options),
'full_answer' => $card['answer'],
'deck_name' => $card['deck_name']
];
}
json_ok(['questions' => $questions, 'deck' => $slug ?: 'all']);
}
// POST /api/quiz/submit
if (get_method() === 'POST' && ($segments[1] ?? '') === 'submit') {
$body = get_json_body();
$total = (int) ($body['total'] ?? 0);
$correct = (int) ($body['correct'] ?? 0);
$score = $total > 0 ? round(($correct / $total) * 100) : 0;
$stmt = $pdo->prepare("
INSERT INTO quiz_results (user_id, deck_slug, quiz_type, score_percent, total_questions, correct_answers)
VALUES (:uid, :deck, 'multiple_choice', :score, :total, :correct)
");
$stmt->execute([':uid' => $user_id, ':deck' => $body['deck'] ?? 'all', ':score' => $score, ':total' => $total, ':correct' => $correct]);
json_ok(['score' => $score]);
}
// GET /api/quiz/history
if (get_method() === 'GET' && ($segments[1] ?? '') === 'history') {
$stmt = $pdo->prepare("
SELECT deck_slug, quiz_type, score_percent, total_questions, correct_answers, created_at
FROM quiz_results WHERE user_id = :uid ORDER BY created_at DESC LIMIT 20
");
$stmt->execute([':uid' => $user_id]);
json_ok(['results' => $stmt->fetchAll()]);
}
json_error('Unbekannter Quiz-Endpunkt', 404);