# LAPractice Karteikarten-Trainer für die LAP-Theoriefragen. Fragen kommen als JSON herein, Fragen und Antwort-Statistik liegen danach in einer SQLite-Datei. Der Ablauf beim Üben ist bewusst selbstkontrolliert: **Frage sehen → im Kopf (oder dem Partner) beantworten → Karte aufdecken → RICHTIG / FALSCH.** ## Starten ```sh npm start # http://127.0.0.1:4173 npm run dev # dasselbe, startet bei Dateiänderungen neu ``` Keine Abhängigkeiten – der Server nutzt nur die Node-Standardbibliothek (`node:http`, `node:sqlite`). Voraussetzung ist **Node 22.5+**. Konfiguration über Umgebungsvariablen: `PORT`, `HOST`, `LAP_DB` (Pfad zur Datenbank, Standard `data/lapractice.db`). ## Fragenset-Format ```jsonc { "title": "Arbeitsunterlagen und Repetitionsfragen zur LAP …", "categories": [ { "id": 1, // optional "title": "Netzwerktechnik", "subcategories": [ { "name": "Grundlagen", "questions": [ { "q": "Erklären Sie den Begriff TP-Kabel.", "a": "Twisted-Pair-Kabel …" } ] } ] } ] } ``` Toleranzen beim Import: `name` statt `title`, `question`/`answer` statt `q`/`a`, und eine Kategorie darf ihre `questions` auch direkt (ohne `subcategories`) tragen. Fragen ohne Text oder ohne Antwort werden übersprungen. **Erneuter Import:** Ein Set mit gleichem `title` wird zusammengeführt statt dupliziert – Fragen werden über Kategorie + Unterkategorie + Fragetext wiedererkannt, geänderte Antworten aktualisiert, neue ergänzt und die Statistik bleibt erhalten. Fragen, die in der neuen Datei fehlen, werden archiviert (nicht gelöscht) und tauchen beim Üben nicht mehr auf. ## Üben * **Auswahl:** Kategorien und Unterkategorien einzeln an-/abwählbar, die Auswahl wird pro Fragenset im Browser gemerkt. * **Fragen** (Filter): alle · nur zuletzt falsch beantwortete · nur noch nie gesehene. Die Poolgröße im Startbalken zeigt, wie viele Karten übrig bleiben. * **Fragen mischen:** an = zufällige Reihenfolge, aus = Reihenfolge des Skriptums. * **Schwächen zuerst:** jede dritte Karte ist eine fällige Wiederholung, der Rest neues Material. Lässt sich mit dem Mischen frei kombinieren – aus/aus ergibt exakt die Skriptum-Reihenfolge. * **Endlos üben:** die Runde läuft, bis du sie selbst beendest (`Esc` oder „Beenden"). Ist ein Stapel durch, wird der nächste mit dem aktuellen Wissensstand geholt; falsch beantwortete Karten kommen zusätzlich noch in derselben Runde wieder. Die Anzahl gilt dann als Karten *pro Runde*. * **Tastatur:** `Leertaste` aufdecken · `1`/`←` falsch · `2`/`→` richtig · `S` überspringen (zählt nicht in die Statistik) · `Esc` Runde beenden. * Nach der Runde: Zusammenfassung mit Trefferquote und allen Karten, dazu „Falsche wiederholen" für einen direkten zweiten Durchgang. Als *fällig* gilt eine Frage, deren letzte Antwort falsch war, deren Trefferquote unter 70 % liegt oder die länger als 7 Tage nicht dran war. ## Datenmodell ``` sets ─┬─ categories ─┬─ subcategories ─┬─ questions ─┬─ reviews │ │ │ │ title title name q, a, archived correct, created_at ``` `reviews` speichert jede einzelne Bewertung mit Zeitstempel; alle Kennzahlen (Trefferquote, schwächste Fragen, Tagesverlauf) werden daraus berechnet. Das Zurücksetzen des Fortschritts löscht nur `reviews`, nie die Fragen. ## API | Methode | Pfad | Zweck | | -------- | --------------------------- | --------------------------------------- | | `GET` | `/api/sets` | Fragensets mit Fortschritt | | `POST` | `/api/sets` | Import (`{ data, filename }`) | | `GET` | `/api/sets/:id` | Kategoriebaum mit Zählern | | `DELETE` | `/api/sets/:id` | Set samt Statistik löschen | | `POST` | `/api/sets/:id/reset` | nur die Statistik löschen | | `GET` | `/api/sets/:id/stats` | Auswertung | | `POST` | `/api/sets/:id/session` | Runde zusammenstellen (`filter`, `shuffle`, `smart`, `limit`) | | `POST` | `/api/reviews` | Bewertung speichern |