126 lines
8.2 KiB
Markdown
126 lines
8.2 KiB
Markdown
# LPIC-Prüfungssimulator
|
||
|
||
> Stand: 29.10.2026 · Statische Web-Anwendung (reveal.js 5.1.0, Dracula-Theme), läuft direkt von `file://` und von jedem statischen Webserver.
|
||
> Inoffizielles Lernwerkzeug, nicht mit dem Linux Professional Institute (LPI) verbunden. „LPIC“ ist eine Marke des LPI.
|
||
> Die Nutzungsrechte an Fragen und Code klärt jeder Empfänger selbst; reveal.js steht unter MIT-Lizenz (`vendor/reveal/LICENSE`).
|
||
|
||
## Dokumente
|
||
| Datei | Inhalt |
|
||
|---|---|
|
||
| [docs/exam_format.md](docs/exam_format.md) | LPIC-1: Prüfungsformat, Objectives 5.0 mit Gewicht, LPI-Regeln, Quellen |
|
||
| [docs/question_rules.md](docs/question_rules.md) | Regeln für Fragen (technisch und inhaltlich) |
|
||
| [docs/decisions.md](docs/decisions.md) | Festlegungen mit Begründung, offene Punkte |
|
||
| [docs/REVIEW.md](docs/REVIEW.md) | Anleitung für Prüfer |
|
||
| [AGENTS.md](AGENTS.md) | Hinweise für KI-Assistenten der Prüfer |
|
||
|
||
## Benutzung
|
||
| Weg | Aufruf |
|
||
|---|---|
|
||
| Lokal | `index.html` im Browser öffnen (Doppelklick genügt, kein Server nötig) |
|
||
| Export + Webserver | `python3 tools/build_bank.py -e` schreibt nur die Laufzeitdateien nach `dist/` (ohne `data/`, `tools/`, `tests/`); andere Dateien in `dist/` bleiben erhalten, ein laufender Server liefert sofort den neuen Stand. Start: `python3 -m http.server 8080 -d dist` |
|
||
|
||
**Startseite:** Prüfung wählen (LPIC-1 101 oder 102), Modus wählen, im Lernmodus optional Topics, Anzahl und Reihenfolge.
|
||
|
||
| Modus | Ablauf |
|
||
|---|---|
|
||
| Lernmodus | Antwort wählen → **Weiter** (→, Leertaste, „Auflösen ▸“) zeigt die Auflösung: richtig/falsch, Erläuterung je Option, Gesamterläuterung, Manpage-Verweis. Nochmal Weiter → nächste Frage. Aufgelöste Fragen sind gesperrt. |
|
||
| Prüfungsmodus | 60 Fragen, 90 Minuten Countdown, Auswahl gewichtet nach Objectives (Gewicht = Fragenzahl wie in der echten Prüfung). Fragen markieren, frei vor/zurück, Abgabe auf der letzten Folie (automatisch bei Zeitablauf). Danach Auswertung je Topic und Auflösung aller Fragen. |
|
||
|
||
Tasten: → / Leertaste weiter · ← zurück · `1`–`5` Antwort wählen · Enter im Textfeld = weiter.
|
||
|
||
## Speichern, Pause, Fortsetzen
|
||
- Jede Eingabe wird sofort im Browser gespeichert (`localStorage`, Schlüssel `lpic_sim.session`). Beim nächsten Öffnen bietet die Startseite **Fortsetzen** an.
|
||
- **Export** (Werkzeugleiste) lädt die Sitzung als JSON herunter (`lpic_sim_<prüfung>_<modus>_<zeit>.json`). Die Datei enthält die Fragen selbst; sie bleibt damit auch nach Änderungen an der Fragenbank und auf anderen Rechnern nutzbar.
|
||
- **Import** erkennt das Format selbst: Eine Sitzung wird an der gespeicherten Stelle fortgesetzt, ein Fragenpaket in die Bank übernommen (und im Browser gemerkt).
|
||
- `localStorage` gilt je Browser und Herkunft: `file://` und `http://…` sehen getrennte Daten – dafür Export/Import nutzen.
|
||
|
||
## Fragen ergänzen
|
||
1. Datei `data/<prüfung>/questions_<topic>.json` bearbeiten oder neu anlegen (Schema: [`data/schema/questions.schema.json`](data/schema/questions.schema.json) – VSCode/VSCodium validiert über den `$schema`-Eintrag).
|
||
2. `python3 tools/build_bank.py -c` prüft alle Fragen und zeigt Prüfstatus und Abdeckung je Objective.
|
||
3. `python3 tools/build_bank.py` erzeugt `js/bank.js` (diese Datei nie von Hand ändern), mit `-e` zusätzlich den Export `dist/`.
|
||
|
||
Ohne Build-Schritt: dieselbe JSON-Datei im Simulator über **Import** laden.
|
||
|
||
### Quelltext vs. ausgelieferte Bank
|
||
| | Quelltext `data/*.json` | `js/bank.js` / Export |
|
||
|---|---|---|
|
||
| Form | Klartext-JSON, für Prüfer lesbar und kommentierbar | ChaCha20-verschlüsselt (RFC 8439), Base64 |
|
||
| Zweck | Durchsicht, Freigabe/Ablehnung, Pflege | Auslieferung, kein Klartext auf der Platte |
|
||
|
||
- **PSK:** Umgebung `LPIC_SIM_PSK`, sonst `tools/.psk` (beim ersten Build zufällig erzeugt, Rechte 600, nicht weitergeben – im Prüferpaket nicht enthalten). Der Schlüssel ist `SHA-256("lpic-sim/bank/v1:" + PSK)` und steht als `build`-Kennung in `bank.js`, die Nonce als `rev` – der PSK selbst nirgends.
|
||
- **Grenze:** Der Browser muss ohne Eingabe entschlüsseln können, also wird der Schlüssel mit ausgeliefert. Das verhindert Klartext auf der Platte, Suchen mit `grep` und zufälliges Mitlesen, schützt aber **nicht** vor jemandem, der gezielt `app.js` und `bank.js` analysiert.
|
||
- **Weiterhin im Klartext:** exportierte Sitzungen (JSON-Datei), die gespeicherte Sitzung und importierte Pakete im `localStorage` – sie enthalten die Fragen der jeweiligen Sitzung.
|
||
|
||
### Prüfvermerk (Review)
|
||
Prüfer tragen je Frage einen Vermerk ein; ohne Vermerk gilt `pending`:
|
||
```json
|
||
"review": { "status": "rejected", "by": "Prüfer A", "date": "2026-10-30", "note": "Option C ebenfalls korrekt" }
|
||
```
|
||
| Status | Wirkung beim Build |
|
||
|---|---|
|
||
| `pending` | übernommen (Standard), mit `--approved-only` nicht |
|
||
| `approved` | übernommen |
|
||
| `rejected` | nie übernommen; bleibt im Quelltext zur Nachbearbeitung |
|
||
|
||
Der Vermerk selbst wird nicht in die Bank übernommen. Freigabe-Build: `python3 tools/build_bank.py --approved-only -e`.
|
||
|
||
### Format einer Frage
|
||
```json
|
||
{
|
||
"id": "103.4-007",
|
||
"objective": "103.4",
|
||
"type": "single",
|
||
"difficulty": 2,
|
||
"question": "Text mit `Code` und **Betonung**",
|
||
"code": "optionaler\nmehrzeiliger Block",
|
||
"options": [
|
||
{ "id": "a", "text": "…", "correct": true, "explanation": "warum richtig" },
|
||
{ "id": "b", "text": "…", "correct": false, "explanation": "warum falsch" }
|
||
],
|
||
"explanation": "Gesamterläuterung",
|
||
"references": ["man 1 bash"]
|
||
}
|
||
```
|
||
| `type` | Regel (geprüft von `build_bank.py` und beim Import) |
|
||
|---|---|
|
||
| `single` | genau 5 Optionen `a`–`e`, genau 1 richtig |
|
||
| `multi` | genau 5 Optionen, 2–4 richtig; der Simulator zeigt „Wählen Sie ZWEI/DREI“ und begrenzt die Auswahl |
|
||
| `fill` | keine Optionen, `answers` = akzeptierte Antworten (erste = Musterlösung), Leerraum wird normalisiert, `case_sensitive` (Standard `true`) |
|
||
|
||
### Regeln für Fragen
|
||
Verbindlich in [docs/question_rules.md](docs/question_rules.md); Prüfablauf in [docs/REVIEW.md](docs/REVIEW.md).
|
||
|
||
## Weitere Prüfungen (z. B. LPIC-2)
|
||
Ordner `data/lpic2_201/` mit `exam.json` (Aufbau wie [`data/lpic1_101/exam.json`](data/lpic1_101/exam.json): `level`, `code`, `questions`, `duration_min`, Topics/Objectives mit Gewicht) und `questions_*.json` anlegen, dann `build_bank.py`. Die Startseite gruppiert automatisch nach `level`.
|
||
Alternativ zur Laufzeit: ein Fragenpaket mit zusätzlichem Schlüssel `"definition"` (Inhalt einer `exam.json`) importieren.
|
||
|
||
## Inhalt
|
||
| Pfad | Inhalt |
|
||
|---|---|
|
||
| `index.html` | Einstieg |
|
||
| `js/app.js` | Logik (Sitzung, Bewertung, Speichern, Import, Darstellung); reine Funktionen unter `window.LPICSim.core` |
|
||
| `js/bank.js` | **erzeugt** – verschlüsselte Fragenbank als `window.LPIC_BANK` (Script statt JSON, damit es unter `file://` lädt) |
|
||
| `dist/` | **erzeugt** mit `build_bank.py -e` – Export zum Ausliefern |
|
||
| `release/` | **erzeugt** mit `build_bank.py -b` – Prüferpaket `lpic-sim_<datum>.tar.gz` |
|
||
| `docs/`, `AGENTS.md` | Dokumente (siehe oben) |
|
||
| `css/simulator.css` | Ergänzungen zum Dracula-Theme |
|
||
| `data/` | Quelle der Fragen: je Prüfung `exam.json` + `questions_*.json`, Schema unter `schema/` |
|
||
| `tools/build_bank.py` | Prüfung und Build der Fragenbank (nur Python-Standardbibliothek) |
|
||
| `tests/selftest.html` | Tests der Kernlogik inkl. ChaCha20-Testvektor RFC 8439 (44 Prüfungen) |
|
||
| `tests/ui_smoke.html` | UI-Rauchtest im iframe: Lernmodus, Prüfungsmodus, Abgabe, Import (27 Prüfungen) |
|
||
| `vendor/reveal/` | reveal.js 5.1.0 unverändert (MIT), Herkunft und Prüfsumme in `VERSION.txt` |
|
||
|
||
## Tests
|
||
```bash
|
||
cd simulator
|
||
python3 tools/build_bank.py -c
|
||
chromium --headless --allow-file-access-from-files --virtual-time-budget=5000 --dump-dom tests/selftest.html | grep -o 'RESULT[^<]*'
|
||
chromium --headless --allow-file-access-from-files --virtual-time-budget=40000 --dump-dom tests/ui_smoke.html | grep -oE '(FAIL|RESULT)[^<]*'
|
||
```
|
||
`--allow-file-access-from-files` braucht nur der iframe-Test, nicht der Simulator selbst.
|
||
|
||
## Pflege
|
||
- Fragen: Bediener und Agent; nach jeder Änderung `build_bank.py -c` und Build, `bank.js` mit einchecken.
|
||
- Neue Objectives-Version: `exam.json` anpassen (Version, Abrufdatum), betroffene Fragen prüfen.
|
||
- reveal.js-Update: neue `dist/`-Dateien nach `vendor/reveal/`, `VERSION.txt` aktualisieren, Tests laufen lassen.
|