prepare(" SELECT d.id, d.slug, d.name, d.description, d.card_count, COUNT(cp.id) AS reviewed, COUNT(cp.id) FILTER (WHERE cp.last_rating IN ('easy','medium')) AS correct, COUNT(cp.id) FILTER (WHERE cp.next_review <= CURRENT_DATE) AS due FROM decks d LEFT JOIN cards c ON c.deck_id = d.id LEFT JOIN card_progress cp ON cp.card_id = c.id AND cp.user_id = :uid GROUP BY d.id ORDER BY d.sort_order, d.name "); $stmt->execute([':uid' => $user_id]); json_ok(['decks' => $stmt->fetchAll()]); } // GET /api/decks/export-anki — download all cards as Anki TSV if (get_method() === 'GET' && ($segments[1] ?? '') === 'export-anki') { $stmt = $pdo->query(" SELECT d.name AS deck_name, c.question, c.answer, c.level FROM cards c JOIN decks d ON d.id = c.deck_id ORDER BY d.sort_order, d.name, c.sort_order "); $cards = $stmt->fetchAll(); header('Content-Type: text/tab-separated-values; charset=utf-8'); header('Content-Disposition: attachment; filename="sol2_training_anki_' . date('Y-m-d') . '.txt"'); header('Cache-Control: no-cache'); // Clean markdown formatting for Anki: backticks -> , ** -> function anki_format($text) { $t = $text; $t = preg_replace('/```(\w*)\n(.*?)```/s', '
$2
', $t); $t = str_replace('`', '', $t); $t = preg_replace('/\*\*(.+?)\*\*/', '$1', $t); $t = str_replace("\n", '
', $t); $t = str_replace("\t", ' ', $t); return $t; } foreach ($cards as $c) { $q = anki_format($c['question']); $a = anki_format($c['answer']); echo $q . "\t" . $a . "\t" . 'Sol2-Training::' . $c['deck_name'] . "\t" . $c['level'] . "\n"; } exit; } // GET /api/decks/{slug} if (get_method() === 'GET' && !empty($segments[1])) { $stmt = $pdo->prepare("SELECT * FROM decks WHERE slug = :s"); $stmt->execute([':s' => $segments[1]]); $deck = $stmt->fetch(); if (!$deck) json_error('Deck nicht gefunden', 404); json_ok(['deck' => $deck]); } json_error('Methode nicht erlaubt', 405);