From 07dbc01c9292255ef7eeb5604bd4ee0b153a78cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Runden?= Date: Fri, 30 Oct 2026 10:11:43 +0100 Subject: [PATCH] rein damit --- .gitignore | 5 + AGENTS.md | 1 + README.md | 5 + ai/context/knowledge/INDEX.md | 6 + .../knowledge/research/lpi_exam_format.md | 26 + context.md | 26 +- simulator/AGENTS.md | 19 + simulator/README.md | 125 +++ simulator/css/simulator.css | 200 ++++ simulator/data/lpic1_101/exam.json | 73 ++ simulator/data/lpic1_101/questions_101.json | 173 ++++ simulator/data/lpic1_101/questions_102.json | 317 +++++++ simulator/data/lpic1_101/questions_103.json | 582 ++++++++++++ simulator/data/lpic1_101/questions_104.json | 327 +++++++ simulator/data/lpic1_102/exam.json | 81 ++ simulator/data/lpic1_102/questions_105.json | 195 ++++ simulator/data/lpic1_102/questions_106.json | 127 +++ simulator/data/lpic1_102/questions_107.json | 285 ++++++ simulator/data/lpic1_102/questions_108.json | 269 ++++++ simulator/data/lpic1_102/questions_109.json | 327 +++++++ simulator/data/lpic1_102/questions_110.json | 237 +++++ simulator/data/schema/questions.schema.json | 77 ++ simulator/docs/REVIEW.md | 34 + simulator/docs/decisions.md | 28 + simulator/docs/exam_format.md | 38 + simulator/docs/question_rules.md | 35 + simulator/index.html | 45 + simulator/js/app.js | 883 ++++++++++++++++++ simulator/js/bank.js | 13 + simulator/tests/selftest.html | 138 +++ simulator/tests/ui_smoke.html | 134 +++ simulator/tools/build_bank.py | 352 +++++++ simulator/vendor/reveal/LICENSE | 19 + simulator/vendor/reveal/VERSION.txt | 3 + simulator/vendor/reveal/reset.css | 30 + simulator/vendor/reveal/reveal.css | 8 + simulator/vendor/reveal/reveal.js | 9 + simulator/vendor/reveal/theme/dracula.css | 385 ++++++++ 38 files changed, 5632 insertions(+), 5 deletions(-) create mode 100644 ai/context/knowledge/research/lpi_exam_format.md create mode 100644 simulator/AGENTS.md create mode 100644 simulator/README.md create mode 100644 simulator/css/simulator.css create mode 100644 simulator/data/lpic1_101/exam.json create mode 100644 simulator/data/lpic1_101/questions_101.json create mode 100644 simulator/data/lpic1_101/questions_102.json create mode 100644 simulator/data/lpic1_101/questions_103.json create mode 100644 simulator/data/lpic1_101/questions_104.json create mode 100644 simulator/data/lpic1_102/exam.json create mode 100644 simulator/data/lpic1_102/questions_105.json create mode 100644 simulator/data/lpic1_102/questions_106.json create mode 100644 simulator/data/lpic1_102/questions_107.json create mode 100644 simulator/data/lpic1_102/questions_108.json create mode 100644 simulator/data/lpic1_102/questions_109.json create mode 100644 simulator/data/lpic1_102/questions_110.json create mode 100644 simulator/data/schema/questions.schema.json create mode 100644 simulator/docs/REVIEW.md create mode 100644 simulator/docs/decisions.md create mode 100644 simulator/docs/exam_format.md create mode 100644 simulator/docs/question_rules.md create mode 100644 simulator/index.html create mode 100644 simulator/js/app.js create mode 100644 simulator/js/bank.js create mode 100644 simulator/tests/selftest.html create mode 100644 simulator/tests/ui_smoke.html create mode 100644 simulator/tools/build_bank.py create mode 100644 simulator/vendor/reveal/LICENSE create mode 100644 simulator/vendor/reveal/VERSION.txt create mode 100644 simulator/vendor/reveal/reset.css create mode 100644 simulator/vendor/reveal/reveal.css create mode 100644 simulator/vendor/reveal/reveal.js create mode 100644 simulator/vendor/reveal/theme/dracula.css diff --git a/.gitignore b/.gitignore index 04732c3..a17c40f 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,8 @@ fact_caching/ *.retry # Sicherungen beim Überschreiben (bewusst lokal behalten, nicht versionieren) *.orig +# Simulator: PSK, Export, Python-Cache +simulator/tools/.psk +simulator/dist/ +__pycache__/ +simulator/release/ diff --git a/AGENTS.md b/AGENTS.md index f7054ca..381b062 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -32,6 +32,7 @@ Details und Ausnahmen: [`ai/rules/language.md`](ai/rules/language.md). | `ai/context/` | Kontext (Verantwortliche, Stil, Umgebung) | Bediener + Agent | | `ai/context/knowledge/` | Knowledge-DB (Markdown + Frontmatter, Index per Script) | Agent + Bediener | | `ai/inbox/` | Eingang: vom Bediener abgelegte `.md`-Dateien, Agent ordnet ein und verschiebt nach `done/` | Bediener → Agent | +| `simulator/` | Prüfungssimulator (statisch, reveal.js); Fragen unter `simulator/data/`, Build mit `simulator/tools/build_bank.py` ([README](simulator/README.md)) | Agent + Bediener | | `bash/` | Shell-Scripts, Übungsscripts (`ai/common/bash.md`) – bei Bedarf anlegen | Agent + Bediener | | `ansible/` | Plays, Rollen, Inventar für Lab-VMs (`ai/common/ansible.md`) – bei Bedarf anlegen | Agent + Bediener | | `stacks/` | Compose-Stacks, je Stack ein Ordner (`ai/common/docker.md`) – bei Bedarf anlegen | Agent + Bediener | diff --git a/README.md b/README.md index e244fdc..0651aca 100644 --- a/README.md +++ b/README.md @@ -18,8 +18,13 @@ lpic/ │ ├── rules/ # verbindliche Regeln (Vorrang) │ ├── common/ # Standards & Verabredungen + templates/ │ └── context/ # Verantwortliche, Stil, Umgebung + knowledge/ (Knowledge-DB, Lerninhalte unter topics/) +├── simulator/ # Prüfungssimulator (statisch, reveal.js) – index.html öffnen └── bin/ # Werkzeuge der Basis ``` + +## Prüfungssimulator +`simulator/index.html` im Browser öffnen (kein Server nötig): LPIC-1 101/102 mit je 90 Fragen, Lern- und Prüfungsmodus, +Speichern/Export/Import der Sitzung. Details und Fragenformat: [simulator/README.md](simulator/README.md). Code für Übungen und Lab (`bash/`, `ansible/`, `stacks/`) wird bei Bedarf angelegt. ## Einrichten diff --git a/ai/context/knowledge/INDEX.md b/ai/context/knowledge/INDEX.md index 70a90da..d18ee90 100644 --- a/ai/context/knowledge/INDEX.md +++ b/ai/context/knowledge/INDEX.md @@ -3,6 +3,12 @@ > Automatisch erzeugt von `bin/kb_index.sh` – nicht von Hand bearbeiten. > Format der Einträge: [README.md](README.md) +## research + +| id | Titel | Status | Stand | Tags | +|---|---|---|---|---| +| lpi_exam_format | [LPIC-1 – Prüfungsformat, Objectives 5.0 und Regeln zur Fragenerstellung](research/lpi_exam_format.md) | active | 2026-10-29 | lpic, lpic-1, pruefung, objectives, simulator | + ## services | id | Titel | Status | Stand | Tags | diff --git a/ai/context/knowledge/research/lpi_exam_format.md b/ai/context/knowledge/research/lpi_exam_format.md new file mode 100644 index 0000000..176da82 --- /dev/null +++ b/ai/context/knowledge/research/lpi_exam_format.md @@ -0,0 +1,26 @@ +--- +id: lpi_exam_format +title: LPIC-1 – Prüfungsformat, Objectives 5.0 und Regeln zur Fragenerstellung +type: research +status: active +updated: 2026-10-29 +owner: br +tags: [lpic, lpic-1, pruefung, objectives, simulator] +sources: + - https://www.lpi.org/de/exam-101-102-objectives/ + - https://www.lpi.org/value-of-certification/our-certification-development-standards/ + - https://www.lpi.org/our-certifications/lpic-1-overview/ + - https://www.lpi.org/faq/ +related: [] +classification: öffentlich +--- +# LPIC-1 – Prüfungsformat, Objectives 5.0 und Regeln zur Fragenerstellung + +> Inhalt liegt seit 29.10.2026 im Simulator, damit er mit dem Prüferpaket weitergegeben werden kann (eine Quelle): +> **[simulator/docs/exam_format.md](../../../../simulator/docs/exam_format.md)** – Fakten, LPI-Regeln, Objectives mit Gewicht, Quellen (abgerufen 29.10.2026). + +Kurzfassung: 101-500/102-500, Objectives 5.0, je 60 Fragen in 90 min (Multiple Choice + Lückentext), Skala 200–800, bestanden ab 500; Gewicht = Fragenzahl je Objective; LPI nennt keine Prozentgrenze und keine feste Optionenzahl. + +## Änderungen +- 29.10.2026 – angelegt (br, KI-unterstützt) +- 29.10.2026 – Inhalt nach `simulator/docs/exam_format.md` verschoben, hier nur Verweis diff --git a/context.md b/context.md index 093ebc2..7aab1e1 100644 --- a/context.md +++ b/context.md @@ -5,13 +5,13 @@ ## Metadaten - **Projekt:** `lpic` – Vorbereitung auf die LPIC-Zertifizierung -- **Status:** Idee +- **Status:** Umsetzung - **Angelegt:** 29.10.2026 · **Letzte Aktualisierung:** 29.10.2026 - **Verantwortlich:** `@author` br · `@owner` br (siehe `ai/context/responsible.md`) -- **Code:** in diesem Repo – Übungsscripts unter `bash/`, Lab-Aufbau unter `ansible/` bzw. `stacks/` (Ordner bei Bedarf anlegen) · Remote: +- **Code:** in diesem Repo – Prüfungssimulator unter `simulator/`, Übungsscripts unter `bash/`, Lab-Aufbau unter `ansible/` bzw. `stacks/` (Ordner bei Bedarf anlegen) · Remote: ## Ziel - +LPIC-1 (101-500 + 102-500), danach LPIC-2. Messbar am Ende: 1. 2. Jedes Prüfungsthema (Objective) hat einen Eintrag unter `ai/context/knowledge/topics/` mit Kernbefehlen, Dateien und Übungen. @@ -25,23 +25,39 @@ Messbar am Ende: - [ ] Ziel festlegen (Stufe, Prüfungen, Termin) - [ ] Objectives als Gliederung in `ai/context/knowledge/topics/` anlegen - [ ] Lab-Umgebung festlegen (lokale Container/VMs) +- [x] Prüfungssimulator LPIC-1 mit 180 Fragen (29.10.2026) +- [ ] Fragen fachlich durchsehen (br) und laufend ergänzen +- [ ] LPIC-2 (201/202) als weitere Prüfungen im Simulator ## Stand - 29.10.2026: Repo aus der 2nd-brain-Basis abgeleitet (Regeln, Standards, Kontextstruktur übernommen; 2nd-brain-Inhalte entfernt, ohne Git-Historie). +- 29.10.2026: Prüfungssimulator `simulator/` fertig: LPIC-1 101/102 je 90 Fragen (109 single, 39 multi, 32 fill), alle Objectives 5.0 mindestens mit ihrem Gewicht abgedeckt; Lern-/Prüfungsmodus, localStorage + JSON-Export/Import, Fragenpakete nachladbar. Fragen KI-erstellt, **noch nicht fachlich geprüft**. ## Entscheidungen | Datum | Entscheidung | Warum | ADR | |---|---|---|---| +| 29.10.2026 | Simulator in reinem JavaScript (klassische Scripts, kein TypeScript, kein Build für den Code) | kein node/tsc auf dem Rechner; läuft so auch unter `file://` | – | +| 29.10.2026 | Fragen als JSON (`simulator/data/`), Bundle `js/bank.js` per `tools/build_bank.py`, zusätzlich Import per Datei-Dialog | `fetch` von JSON ist unter `file://` blockiert | – | +| 29.10.2026 | Fragenregeln: genau 5 Optionen bei single/multi, Erläuterung je Option, Bewertung alles-oder-nichts; Prüfungsmodus 60 Fragen/90 min, Auswahl nach Gewicht; Richtwert Bestehen 65 % | Vorgabe Bediener + LPI-Standards; LPI nennt keine Prozentgrenze (200–800, bestanden ab 500) | – | +| 29.10.2026 | Ausgelieferte Bank `js/bank.js` ChaCha20-verschlüsselt, Schlüssel aus PSK (`LPIC_SIM_PSK` bzw. `simulator/tools/.psk`, nicht versioniert); Quelltext `data/*.json` bleibt Klartext für Prüfer; Prüfvermerk `review` (pending/approved/rejected); Export ohne Quellen nach `simulator/dist/` | kein Klartext auf der Platte; Schlüssel wird mit ausgeliefert → Verschleierung, kein Schutz gegen gezielte Analyse | – | +| 29.10.2026 | Weitergabe an Prüfer als tar.gz (kein Git); Festlegungen und LPI-Kontext liegen dafür in `simulator/docs/` (eine Quelle), Mailadresse in Headern bleibt, Lizenz klärt jeder Empfänger | Prüfer brauchen den vollständigen Kontext, nicht die AI-Basis | – | +| 29.10.2026 | reveal.js 5.1.0 unverändert unter `simulator/vendor/reveal/` (eingebautes Dracula-Theme) | offline lauffähig, kein CDN | – | | 29.10.2026 | Neues Repo ohne Historie aus 2nd-brain; Regeln, `ai/common/`, `bin/`, Umgebung und KI-Freigaben übernommen | Basis wiederverwenden, keine 2nd-brain-Inhalte in der Historie | – | | 29.10.2026 | Knowledge-Typ `topic` (`topics/`) für Lerninhalte je Prüfungsthema | LPIC-Inhalte von Umgebungswissen trennen | – | ## Offene Fragen -1. [ ] **Ziel:** Welche Stufe (LPIC-1/-2/-3) und welche Prüfungen, bis wann? +1. [ ] **Ziel:** LPIC-1 (101/102), danach LPIC-2 – Zieltermin? 2. [ ] **Remote:** Gitea-Repo anlegen (z. B. `br/lpic`) und als `origin` eintragen. 3. [ ] **Lab:** Welche Umgebung für Übungen (lokale Container, VMs, Distributionen)? +4. [ ] **Richtwert Bestehen:** 65 % ist eine Annahme (`pass_percent` in `exam.json`) – anpassen? +5. [ ] **Teilpunkte** bei Mehrfachauswahl: LPI dokumentiert nichts; Simulator wertet alles-oder-nichts. +6. [ ] **Klartext außerhalb der Bank:** Sitzungs-Export und `localStorage` enthalten die Fragen einer Sitzung im Klartext – ebenfalls verschlüsseln? ## Nächster Schritt -Betreiber legt Ziel und Prüfungen fest; danach Objectives als Gliederung unter `topics/` anlegen. +Betreiber testet den Simulator und sieht die Fragen fachlich durch (Rückmeldungen als Korrektur in `simulator/data/`); danach Objectives als Gliederung unter `topics/` anlegen. ## Sitzungsprotokoll - 29.10.2026 – Repo aus `2ndbrain` abgeleitet: Stacks, Ansible-Inventar, `architecture.md`, 2nd-brain-Knowledge (`dockweb112`, `kellerbeast`, LUKS-Recherche) entfernt; `services/sultan` (Verweis aus `docker.md`) bereinigt behalten; `environment.md` und `privacy.md` auf Projekt angepasst; Knowledge-Typ `topic` ergänzt. +- 29.10.2026 – Prüfungssimulator gebaut (`simulator/`), Objectives 5.0 und LPI-Regeln recherchiert (Knowledge `research/lpi_exam_format`). Tests lokal: `build_bank.py -c` ok (180 Fragen); `tests/selftest.html` 40/40, `tests/ui_smoke.html` 27/27 in Chromium headless unter `file://` und über lokalen `http.server`; Start und Darstellung zusätzlich in Firefox headless geprüft. Nicht getestet: Mobilgeräte (nur 400-px-Fenster), Safari. +- 29.10.2026 – Bank verschlüsselt (ChaCha20, gegen Python-`cryptography` und RFC-8439-Vektor geprüft), Prüfvermerk `review`, Export `build_bank.py -e` → `simulator/dist/`; Lückentext-Feld war links verschoben (input inline-block, `margin:auto` griff nicht) → `display:block`. Tests: selftest 44/44, ui_smoke 27/27; Export über `python3 -m http.server 8080` (alle Schnittstellen) ausgeliefert und geprüft. +- 29.10.2026 – Prüferpaket: Doku nach `simulator/docs/` (exam_format, question_rules, decisions, REVIEW) und `simulator/AGENTS.md`; `build_bank.py -b` → `simulator/release/lpic-sim_.tar.gz` (ohne PSK, `dist/`, `release/`, Caches; ohne `ai/` und Umgebungsdaten). Entpackt in leerem Verzeichnis geprüft: Build, selftest 44/44, ui_smoke 27/27, alle Doku-Links innerhalb des Pakets. Lizenz klärt jeder Prüfer selbst (Betreiber). diff --git a/simulator/AGENTS.md b/simulator/AGENTS.md new file mode 100644 index 0000000..c4d6309 --- /dev/null +++ b/simulator/AGENTS.md @@ -0,0 +1,19 @@ +# AGENTS.md – Hinweise für KI-Agenten + +> Stand: 29.10.2026 · für KI-Assistenten, die Prüfer beim Prüfen oder Ergänzen von Fragen unterstützen. + +## Lesen vor der Arbeit +1. [README.md](README.md) – Aufbau, Format einer Frage, Build. +2. [docs/question_rules.md](docs/question_rules.md) – verbindliche Regeln für Fragen. +3. [docs/exam_format.md](docs/exam_format.md) – Prüfungsformat und Objectives 5.0 (mit Quellen). +4. [docs/decisions.md](docs/decisions.md) – Festlegungen; nicht ohne Rücksprache ändern. + +## Regeln +- Sprache Deutsch mit Umlauten; Datei-/Schlüsselnamen englisch (ASCII). +- Keine Erfindungen: Befehle, Optionen, Dateipfade nur, wenn belegbar (Manpage, offizielle Doku); Unsicheres als unsicher kennzeichnen, nicht als Frage aufnehmen. +- Distraktoren eindeutig falsch; bei Zweifel lieber Option ersetzen. +- Nach jeder Änderung `python3 tools/build_bank.py -c`; Fehler beheben, bevor gebaut wird. +- `js/bank.js` und `dist/` sind erzeugt – nie von Hand ändern. `tools/.psk` nie ausgeben oder weitergeben. +- Code bleibt ohne Build und ohne externe Abhängigkeiten lauffähig unter `file://` (kein `fetch`, keine ES-Module, kein CDN). +- Datei-Header (`@file`, `@brief`, `@author`, `@owner`, `@assist`, `@version`) erhalten und bei Änderung `@version` erhöhen; `@author` ist immer ein Mensch, nie die KI. +- Tests: siehe [docs/REVIEW.md](docs/REVIEW.md#tests). diff --git a/simulator/README.md b/simulator/README.md new file mode 100644 index 0000000..a0c810e --- /dev/null +++ b/simulator/README.md @@ -0,0 +1,125 @@ +# 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/`), dann `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___.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//questions_.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_.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. diff --git a/simulator/css/simulator.css b/simulator/css/simulator.css new file mode 100644 index 0000000..b5d7d34 --- /dev/null +++ b/simulator/css/simulator.css @@ -0,0 +1,200 @@ +/** + * @file simulator.css + * @brief Ergänzungen zum reveal.js-Dracula-Theme: scrollbare Fragen-Folien, Optionen, Auflösung, Werkzeugleiste + * @author Björn Runden + * @owner Björn Runden + * @assist KI-unterstützt (Claude Opus 5.5), geprüft von Björn Runden + * @version 0.1.1 (29.10.2026) + */ + +:root { + --bg: #282a36; + --line: #44475a; + --fg: #f8f8f2; + --comment: #6272a4; + --cyan: #8be9fd; + --green: #50fa7b; + --orange: #ffb86c; + --pink: #ff79c6; + --purple: #bd93f9; + --red: #ff5555; + --yellow: #f1fa8c; + --tb-h: 3rem; + --gutter: max(16px, 4vw); + /* reveal.js skaliert hier nicht (disableLayout) – Schrift relativ zum Fenster */ + --r-main-font-size: clamp(15px, 0.6vw + 11px, 21px); + --r-heading-font: var(--r-main-font); +} + +html, body { background: var(--bg); } + +/* ---------------------------------------------------------------- Werkzeugleiste */ +.toolbar { + position: fixed; + inset: 0 0 auto 0; + z-index: 50; + min-height: var(--tb-h); + padding: calc(env(safe-area-inset-top, 0px) + 0.4rem) var(--gutter) 0.4rem; + box-sizing: border-box; + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 0.4rem 1rem; + background: #21222c; + border-bottom: 1px solid var(--line); + color: var(--fg); + font: 15px/1.3 -apple-system, BlinkMacSystemFont, "Segoe UI", Ubuntu, Cantarell, Roboto, sans-serif; +} +.tb-title { color: var(--purple); font-weight: 600; } +.tb-info { color: var(--cyan); font-variant-numeric: tabular-nums; } +#tb-timer.low { color: var(--red); font-weight: 700; } +.tb-buttons { margin-left: auto; display: flex; flex-wrap: wrap; gap: 0.3rem; } + +/* ---------------------------------------------------------------- Buttons */ +.btn { + font: inherit; + font-size: 0.9em; + color: var(--fg); + background: var(--line); + border: 1px solid var(--comment); + border-radius: 6px; + padding: 0.45em 1em; + cursor: pointer; +} +.btn:hover:not(:disabled) { border-color: var(--purple); color: var(--purple); } +.btn:disabled { opacity: 0.4; cursor: default; } +.btn.primary { background: var(--purple); border-color: var(--purple); color: var(--bg); font-weight: 600; } +.btn.primary:hover { background: var(--pink); border-color: var(--pink); color: var(--bg); } +.btn.small { padding: 0.25em 0.7em; font-size: 0.85em; } + +/* ---------------------------------------------------------------- Folien */ +.reveal .slides { text-align: left; } +.reveal .slides > section { + top: 0; + height: 100%; + overflow-y: auto; + box-sizing: border-box; + /* --tb-h wird per JS auf die tatsächliche (ggf. umbrochene) Höhe der Werkzeugleiste gesetzt */ + padding: calc(var(--tb-h) + 1.5rem) var(--gutter) 4.5rem; + line-height: 1.45; +} +.reveal .slides > section > * { max-width: 62rem; margin-left: auto; margin-right: auto; } +.reveal h1 { font-size: 2em; color: var(--purple); } +.reveal h2 { font-size: 1.6em; color: var(--purple); } +.reveal h3 { font-size: 1.15em; color: var(--pink); margin: 0 0 0.6em; } +.reveal code { font-family: var(--r-code-font); color: var(--green); font-size: 0.92em; } +.reveal small { color: var(--comment); font-size: 0.85em; } +.reveal p { margin: 0 auto 0.8em; } + +/* ---------------------------------------------------------------- Startseite */ +.card { + background: rgba(68, 71, 90, 0.35); + border: 1px solid var(--line); + border-radius: 10px; + padding: 1.2em 1.4em; + margin-bottom: 1.2em; +} +.card.resume { border-color: var(--orange); } +.setup fieldset { border: 0; padding: 0; margin: 0 0 1em; } +.setup legend { color: var(--cyan); font-weight: 600; margin-bottom: 0.3em; } +.exam-group { margin-bottom: 0.4em; } +.exam-level { display: block; color: var(--orange); font-size: 0.9em; } +.choice { display: flex; gap: 0.6em; align-items: baseline; padding: 0.2em 0; cursor: pointer; } +.choice small { display: inline-block; margin-left: 0.4em; } +.inline { display: inline-flex; gap: 0.5em; align-items: center; margin-right: 1.5em; } +.setup input[type=number], .setup select { + font: inherit; color: var(--fg); background: var(--bg); border: 1px solid var(--comment); + border-radius: 5px; padding: 0.2em 0.4em; +} +.setup input[type=number] { width: 5em; } +input[type=radio], input[type=checkbox] { accent-color: var(--purple); width: 1.05em; height: 1.05em; } +.footnote { color: var(--comment); font-size: 0.8em; } +.warn-text { color: var(--orange); } + +/* ---------------------------------------------------------------- Frage */ +.q-head { + display: flex; flex-wrap: wrap; gap: 0.3em 1.2em; align-items: baseline; + border-bottom: 1px solid var(--line); padding-bottom: 0.5em; margin-bottom: 1em; font-size: 0.85em; +} +.q-no { color: var(--purple); font-weight: 700; } +.q-obj { color: var(--comment); } +.flag { margin-left: auto; color: var(--orange); cursor: pointer; display: inline-flex; gap: 0.4em; align-items: center; } +.q-text { font-size: 1.1em; margin-bottom: 0.8em; } +.q-code { + background: #21222c; border: 1px solid var(--line); border-radius: 6px; padding: 0.7em 1em; + overflow-x: auto; font-size: 0.85em; width: auto; box-shadow: none; margin-bottom: 1em; +} +.reveal pre.q-code code { color: var(--fg); max-height: none; padding: 0; white-space: pre; } +.q-hint { color: var(--yellow); font-style: italic; } + +/* reveal-Theme setzt Listen auf inline-block mit Einzug – für Optionen/Erläuterungen aufheben */ +.reveal ol.options, .reveal ul.explain { display: block; list-style: none; padding: 0; margin: 0 auto 1em; } +.reveal ol.options > li, .reveal ul.explain > li { margin-left: 0; } +.option label { + display: flex; gap: 0.8em; align-items: baseline; padding: 0.55em 0.9em; margin-bottom: 0.45em; + border: 1px solid var(--line); border-radius: 8px; cursor: pointer; background: rgba(68, 71, 90, 0.25); +} +.option label:hover { border-color: var(--purple); } +.option:has(input:checked) label { border-color: var(--purple); background: rgba(189, 147, 249, 0.12); } +.letter { color: var(--cyan); font-weight: 700; min-width: 1.2em; } +.locked .option label { cursor: default; } +.locked .option.is-correct label { border-color: var(--green); background: rgba(80, 250, 123, 0.1); } +.locked .option.is-wrong label { border-color: var(--red); background: rgba(255, 85, 85, 0.12); } +.locked .option.is-missed label { border-style: dashed; } + +input.fill { + /* block statt inline-block: nur so greift margin:auto der Inhaltsspalte (sonst klebt das Feld links) */ + display: block; + font-family: var(--r-code-font); font-size: 1em; width: 100%; box-sizing: border-box; + color: var(--green); background: #21222c; border: 1px solid var(--comment); border-radius: 6px; + padding: 0.5em 0.8em; margin-bottom: 1em; +} +input.fill:focus { outline: none; border-color: var(--purple); } +input.fill.is-correct { border-color: var(--green); } +input.fill.is-wrong { border-color: var(--red); color: var(--red); } + +/* ---------------------------------------------------------------- Auflösung */ +.solution { + border-left: 4px solid var(--pink); background: rgba(68, 71, 90, 0.3); + border-radius: 0 8px 8px 0; padding: 1em 1.2em; margin-top: 0.5em; +} +.verdict { font-weight: 700; font-size: 1.15em; } +.verdict.right { color: var(--green); } +.verdict.wrong { color: var(--red); } +.verdict.skipped { color: var(--orange); } +.explain li { padding: 0.25em 0; } +.explain .mark { font-weight: 600; margin-right: 0.3em; } +.explain li.ok .mark { color: var(--green); } +.explain li.no .mark { color: var(--red); } +.explanation { color: var(--fg); border-top: 1px solid var(--line); padding-top: 0.6em; } +.refs { color: var(--comment); font-size: 0.85em; margin-top: 0.6em; } + +/* ---------------------------------------------------------------- Ergebnis */ +.big { font-size: 1.5em; color: var(--cyan); } +.table-wrap { overflow-x: auto; } +.reveal table { border-collapse: collapse; margin: 0 0 1em; font-size: 0.9em; } +.reveal table th, .reveal table td { border-bottom: 1px solid var(--line); padding: 0.35em 0.8em; text-align: left; } +.bar { display: inline-block; width: 6em; height: 0.6em; background: var(--line); border-radius: 3px; vertical-align: middle; } +.bar > span { display: block; height: 100%; background: var(--green); border-radius: 3px; } +.actions .btn { margin: 0 0.4em 0.4em 0; } + +/* ---------------------------------------------------------------- Meldungen */ +.toast-box { + position: fixed; z-index: 60; right: var(--gutter); bottom: calc(env(safe-area-inset-bottom, 0px) + 3.5rem); + display: flex; flex-direction: column; gap: 0.4rem; max-width: min(28rem, calc(100vw - 32px)); +} +.toast { + background: var(--line); color: var(--fg); border-left: 4px solid var(--cyan); border-radius: 6px; + padding: 0.6em 0.9em; font: 14px/1.35 -apple-system, BlinkMacSystemFont, "Segoe UI", Ubuntu, Roboto, sans-serif; + box-shadow: 0 4px 14px rgba(0, 0, 0, 0.4); +} +.toast.warn { border-left-color: var(--orange); } +.toast.error { border-left-color: var(--red); } + +/* reveal-Steuerung nicht über den Inhalt legen */ +.reveal .controls { bottom: calc(env(safe-area-inset-bottom, 0px) + 12px); right: 12px; } + +@media (max-width: 600px) { + .tb-buttons { margin-left: 0; } + .flag { margin-left: 0; } +} diff --git a/simulator/data/lpic1_101/exam.json b/simulator/data/lpic1_101/exam.json new file mode 100644 index 0000000..2bfd240 --- /dev/null +++ b/simulator/data/lpic1_101/exam.json @@ -0,0 +1,73 @@ +{ + "meta": { + "file": "exam.json", + "brief": "Prüfungsdefinition LPIC-1 101-500: Eckdaten, Topics, Objectives mit Gewichtung", + "author": "Björn Runden ", + "owner": "Björn Runden ", + "assist": "KI-unterstützt (Claude Opus 5.5), geprüft von Björn Runden ", + "version": "0.1.0 (29.10.2026)" + }, + "exam": { + "id": "lpic1-101", + "level": "LPIC-1", + "title": "LPIC-1 Prüfung 101", + "code": "101-500", + "lang": "de", + "order": 101, + "objectives_version": "5.0", + "objectives_source": "https://www.lpi.org/de/exam-101-102-objectives/", + "objectives_retrieved": "2026-10-29", + "questions": 60, + "duration_min": 90, + "pass_percent": 65 + }, + "topics": [ + { + "id": "101", + "title": "Systemarchitektur", + "objectives": [ + { "id": "101.1", "title": "Hardwareeinstellungen ermitteln und konfigurieren", "weight": 2 }, + { "id": "101.2", "title": "Das System starten", "weight": 3 }, + { "id": "101.3", "title": "Runlevel wechseln und das System anhalten oder neu starten", "weight": 3 } + ] + }, + { + "id": "102", + "title": "Linux-Installation und -Paketverwaltung", + "objectives": [ + { "id": "102.1", "title": "Festplattenaufteilung planen", "weight": 2 }, + { "id": "102.2", "title": "Einen Bootmanager installieren", "weight": 2 }, + { "id": "102.3", "title": "Shared Libraries verwalten", "weight": 1 }, + { "id": "102.4", "title": "Debian-Paketverwaltung verwenden", "weight": 3 }, + { "id": "102.5", "title": "RPM und YUM-Paketverwaltung verwenden", "weight": 3 }, + { "id": "102.6", "title": "Linux als Virtualisierungs-Gast", "weight": 1 } + ] + }, + { + "id": "103", + "title": "GNU- und Unix-Befehle", + "objectives": [ + { "id": "103.1", "title": "Auf der Befehlszeile arbeiten", "weight": 4 }, + { "id": "103.2", "title": "Textströme mit Filtern verarbeiten", "weight": 2 }, + { "id": "103.3", "title": "Grundlegende Dateiverwaltung", "weight": 4 }, + { "id": "103.4", "title": "Ströme, Pipes und Umleitungen verwenden", "weight": 4 }, + { "id": "103.5", "title": "Prozesse erzeugen, überwachen und beenden", "weight": 4 }, + { "id": "103.6", "title": "Prozess-Ausführungsprioritäten ändern", "weight": 2 }, + { "id": "103.7", "title": "Textdateien mit regulären Ausdrücken durchsuchen", "weight": 3 }, + { "id": "103.8", "title": "Grundlegendes Editieren von Dateien", "weight": 3 } + ] + }, + { + "id": "104", + "title": "Geräte, Linux-Dateisysteme, Filesystem Hierarchy Standard", + "objectives": [ + { "id": "104.1", "title": "Partitionen und Dateisysteme anlegen", "weight": 2 }, + { "id": "104.2", "title": "Die Integrität von Dateisystemen sichern", "weight": 2 }, + { "id": "104.3", "title": "Das Mounten und Unmounten von Dateisystemen steuern", "weight": 3 }, + { "id": "104.5", "title": "Dateizugriffsrechte und -eigentümerschaft verwalten", "weight": 3 }, + { "id": "104.6", "title": "Symbolische und Hardlinks anlegen und ändern", "weight": 2 }, + { "id": "104.7", "title": "Systemdateien finden und Dateien am richtigen Ort platzieren", "weight": 2 } + ] + } + ] +} diff --git a/simulator/data/lpic1_101/questions_101.json b/simulator/data/lpic1_101/questions_101.json new file mode 100644 index 0000000..14f0f01 --- /dev/null +++ b/simulator/data/lpic1_101/questions_101.json @@ -0,0 +1,173 @@ +{ + "$schema": "../schema/questions.schema.json", + "format": "lpic-sim-questions", + "meta": { + "file": "questions_101.json", + "brief": "Fragen zu Topic 101 Systemarchitektur (LPIC-1 101-500, Objectives 5.0)", + "author": "Björn Runden ", + "owner": "Björn Runden ", + "assist": "KI-unterstützt (Claude Opus 5.5), geprüft von Björn Runden ", + "version": "0.1.0 (29.10.2026)" + }, + "exam": "lpic1-101", + "questions": [ + { + "id": "101.1-001", + "objective": "101.1", + "type": "single", + "difficulty": 1, + "question": "Welcher Befehl listet alle aktuell geladenen Kernelmodule auf?", + "options": [ + { "id": "a", "text": "`lsmod`", "correct": true, "explanation": "`lsmod` formatiert den Inhalt von `/proc/modules`: Modulname, Größe und Nutzer." }, + { "id": "b", "text": "`modinfo`", "correct": false, "explanation": "`modinfo` zeigt Informationen zu einem bestimmten Modul (Autor, Parameter, Datei), listet aber nicht die geladenen Module." }, + { "id": "c", "text": "`lspci -k`", "correct": false, "explanation": "`lspci -k` zeigt nur zu PCI-Geräten den verwendeten Treiber, nicht alle geladenen Module." }, + { "id": "d", "text": "`depmod -a`", "correct": false, "explanation": "`depmod` erzeugt die Abhängigkeitsdatei `modules.dep`, es listet nichts auf." }, + { "id": "e", "text": "`insmod -l`", "correct": false, "explanation": "`insmod` lädt eine einzelne Moduldatei ohne Abhängigkeiten; eine Listen-Option gibt es nicht." } + ], + "explanation": "Geladene Module stehen in `/proc/modules`; `lsmod` ist die lesbare Darstellung davon.", + "references": ["man 8 lsmod", "/proc/modules"] + }, + { + "id": "101.1-002", + "objective": "101.1", + "type": "multi", + "difficulty": 1, + "question": "Welche Verzeichnisse sind Einhängepunkte virtueller Dateisysteme, über die der Kernel zur Laufzeit Informationen über Prozesse, Hardware und Treiber bereitstellt?", + "options": [ + { "id": "a", "text": "`/proc`", "correct": true, "explanation": "procfs: Prozessinformationen und Kernel-Daten wie `/proc/cpuinfo`, `/proc/interrupts`." }, + { "id": "b", "text": "`/sys`", "correct": true, "explanation": "sysfs: Geräte, Treiber und Busse als Verzeichnisbaum; Grundlage für udev." }, + { "id": "c", "text": "`/boot`", "correct": false, "explanation": "`/boot` ist ein normales Dateisystem mit Kernel, initramfs und Bootloader-Dateien." }, + { "id": "d", "text": "`/etc`", "correct": false, "explanation": "`/etc` enthält statische Konfigurationsdateien auf der Festplatte." }, + { "id": "e", "text": "`/var/lib`", "correct": false, "explanation": "`/var/lib` enthält dauerhafte Zustandsdaten von Programmen, keine Kernel-Schnittstelle." } + ], + "explanation": "procfs (`/proc`) und sysfs (`/sys`) existieren nur im Speicher und werden vom Kernel beim Lesen erzeugt. Werkzeuge wie `lspci`, `lsusb` und udev lesen dort.", + "references": ["man 5 proc", "man 5 sysfs"] + }, + { + "id": "101.1-003", + "objective": "101.1", + "type": "fill", + "difficulty": 1, + "question": "Mit welchem Befehl (nur der Befehlsname) lädt man ein Kernelmodul **mitsamt seinen Abhängigkeiten**?", + "answers": ["modprobe"], + "explanation": "`modprobe` löst Abhängigkeiten über `modules.dep` auf und lädt sie mit; `modprobe -r` entlädt. `insmod` lädt dagegen nur genau die angegebene Datei.", + "references": ["man 8 modprobe"] + }, + { + "id": "101.2-001", + "objective": "101.2", + "type": "single", + "difficulty": 1, + "question": "Ein Administrator möchte die Meldungen des Kernel-Ring-Buffers (z. B. Hardware-Erkennung beim Start) ansehen. Welcher Befehl gibt diesen Puffer aus?", + "options": [ + { "id": "a", "text": "`dmesg`", "correct": true, "explanation": "`dmesg` liest den Kernel-Ring-Buffer und gibt ihn aus." }, + { "id": "b", "text": "`uname -a`", "correct": false, "explanation": "`uname -a` zeigt Kernelname, Version, Architektur – keine Meldungen." }, + { "id": "c", "text": "`lsmod`", "correct": false, "explanation": "`lsmod` listet geladene Module, nicht die Kernel-Meldungen." }, + { "id": "d", "text": "`cat /proc/cmdline`", "correct": false, "explanation": "`/proc/cmdline` enthält nur die Kernel-Parameter des letzten Starts." }, + { "id": "e", "text": "`last -x`", "correct": false, "explanation": "`last -x` zeigt Anmeldungen sowie Shutdown-/Runlevel-Einträge aus `wtmp`, nicht den Ring-Buffer." } + ], + "explanation": "Der Ring-Buffer hat eine feste Größe; ältere Meldungen werden überschrieben. Bei systemd sind Kernel-Meldungen zusätzlich mit `journalctl -k` im Journal abrufbar.", + "references": ["man 1 dmesg"] + }, + { + "id": "101.2-002", + "objective": "101.2", + "type": "fill", + "difficulty": 2, + "question": "In welcher Datei (vollständiger Pfad) kann man nachlesen, mit welchen Parametern der laufende Kernel gestartet wurde?", + "answers": ["/proc/cmdline"], + "explanation": "`/proc/cmdline` enthält die vom Bootloader übergebene Kernel-Befehlszeile, z. B. `root=…`, `ro`, `quiet`.", + "references": ["man 5 proc"] + }, + { + "id": "101.2-003", + "objective": "101.2", + "type": "single", + "difficulty": 2, + "question": "In welcher Reihenfolge laufen die Phasen beim Start eines BIOS-Systems mit GRUB 2 und systemd ab?", + "options": [ + { "id": "a", "text": "Firmware (POST) → Bootloader → Kernel mit initramfs → systemd", "correct": true, "explanation": "Die Firmware prüft die Hardware und startet den Bootloader, der Kernel und initramfs lädt; der Kernel startet zuletzt den ersten Prozess." }, + { "id": "b", "text": "Bootloader → Firmware (POST) → Kernel mit initramfs → systemd", "correct": false, "explanation": "Der Bootloader wird erst von der Firmware gestartet, kann also nicht vor ihr laufen." }, + { "id": "c", "text": "Firmware (POST) → Kernel mit initramfs → Bootloader → systemd", "correct": false, "explanation": "Der Bootloader lädt den Kernel – er läuft daher vor dem Kernel." }, + { "id": "d", "text": "Firmware (POST) → Bootloader → systemd → Kernel mit initramfs", "correct": false, "explanation": "systemd ist ein Userspace-Prozess und wird vom Kernel gestartet, nicht umgekehrt." }, + { "id": "e", "text": "Firmware (POST) → initramfs → Bootloader → Kernel → systemd", "correct": false, "explanation": "Die initramfs wird vom Bootloader gemeinsam mit dem Kernel geladen und erst vom Kernel benutzt." } + ], + "explanation": "Ablauf: Firmware (BIOS/UEFI) → Bootloader (GRUB 2) → Kernel + initramfs (Treiber, Root-Dateisystem einhängen) → init-Prozess mit PID 1 (systemd oder SysV-init).", + "references": ["man 7 bootup"] + }, + { + "id": "101.2-004", + "objective": "101.2", + "type": "multi", + "difficulty": 2, + "question": "Welche Aussagen zur initramfs treffen zu?", + "options": [ + { "id": "a", "text": "Sie enthält Treiber und Werkzeuge, die nötig sind, um das eigentliche Root-Dateisystem einzuhängen.", "correct": true, "explanation": "Typisch sind Module für Storage-Controller, LVM, RAID oder Verschlüsselung." }, + { "id": "b", "text": "Sie wird vom Bootloader zusammen mit dem Kernel in den Arbeitsspeicher geladen.", "correct": true, "explanation": "GRUB lädt Kernel und initramfs (Eintrag `initrd`) gemeinsam." }, + { "id": "c", "text": "Sie ersetzt den Kernel, wenn dieser beschädigt ist.", "correct": false, "explanation": "Die initramfs ist ein Dateisystem-Abbild, kein Ersatzkernel." }, + { "id": "d", "text": "Sie wird nur bei UEFI-Systemen verwendet.", "correct": false, "explanation": "Die initramfs ist unabhängig von der Firmware; sie wird bei BIOS und UEFI genutzt." }, + { "id": "e", "text": "Sie ist unter `/sys/initramfs` dauerhaft eingehängt.", "correct": false, "explanation": "Nach dem Wechsel auf das echte Root-Dateisystem wird die initramfs verworfen; ihr Abbild liegt meist in `/boot`." } + ], + "explanation": "Die initramfs ist ein (meist komprimiertes cpio-)Abbild eines kleinen Root-Dateisystems. Sie überbrückt die Zeit, bis der Kernel das echte Root-Dateisystem einhängen kann.", + "references": ["man 8 dracut", "man 8 update-initramfs"] + }, + { + "id": "101.3-001", + "objective": "101.3", + "type": "single", + "difficulty": 1, + "question": "Welches systemd-Target entspricht dem SysV-Runlevel 3 (Mehrbenutzerbetrieb mit Netzwerk, ohne grafische Oberfläche)?", + "options": [ + { "id": "a", "text": "`multi-user.target`", "correct": true, "explanation": "`multi-user.target` entspricht den Runlevels 2–4." }, + { "id": "b", "text": "`graphical.target`", "correct": false, "explanation": "`graphical.target` entspricht Runlevel 5 (mit grafischer Anmeldung)." }, + { "id": "c", "text": "`rescue.target`", "correct": false, "explanation": "`rescue.target` entspricht Runlevel 1 (Einzelbenutzer)." }, + { "id": "d", "text": "`emergency.target`", "correct": false, "explanation": "`emergency.target` startet nur eine Notfall-Shell, Root meist nur lesend eingehängt." }, + { "id": "e", "text": "`network.target`", "correct": false, "explanation": "`network.target` ist ein Synchronisationspunkt für Netzwerkdienste, kein Systemzustand wie ein Runlevel." } + ], + "explanation": "Zuordnung: 0 → `poweroff.target`, 1 → `rescue.target`, 2–4 → `multi-user.target`, 5 → `graphical.target`, 6 → `reboot.target`.", + "references": ["man 7 systemd.special", "man 1 systemctl"] + }, + { + "id": "101.3-002", + "objective": "101.3", + "type": "fill", + "difficulty": 2, + "question": "Geben Sie den vollständigen Befehl ein, mit dem bei systemd das Standard-Target dauerhaft auf `graphical.target` gesetzt wird.", + "answers": ["systemctl set-default graphical.target", "systemctl set-default graphical"], + "explanation": "`systemctl set-default` setzt den Symlink `default.target`; wirksam beim nächsten Start. `systemctl get-default` zeigt das aktuelle Standard-Target.", + "references": ["man 1 systemctl"] + }, + { + "id": "101.3-003", + "objective": "101.3", + "type": "single", + "difficulty": 1, + "question": "Das System soll in 10 Minuten heruntergefahren werden; angemeldete Benutzer sollen die Nachricht „Wartung“ erhalten. Welcher Befehl leistet das?", + "options": [ + { "id": "a", "text": "`shutdown -h +10 \"Wartung\"`", "correct": true, "explanation": "`-h` hält/schaltet aus, `+10` bedeutet in 10 Minuten, der Text geht per wall an alle Terminals." }, + { "id": "b", "text": "`shutdown -c +10 \"Wartung\"`", "correct": false, "explanation": "`-c` bricht einen geplanten Shutdown ab." }, + { "id": "c", "text": "`shutdown -r now +10 \"Wartung\"`", "correct": false, "explanation": "`now` und `+10` widersprechen sich; `-r` würde zudem neu starten." }, + { "id": "d", "text": "`halt -t 10 \"Wartung\"`", "correct": false, "explanation": "`halt` kennt keine Zeitplanung mit Nachricht; es hält das System sofort an." }, + { "id": "e", "text": "`wall -h +10 \"Wartung\"`", "correct": false, "explanation": "`wall` sendet nur eine Nachricht, fährt aber nichts herunter." } + ], + "explanation": "Zeitangabe bei `shutdown`: `now`, `+m` (Minuten) oder `hh:mm`. `-h`/`-P` ausschalten, `-r` Neustart, `-c` abbrechen.", + "references": ["man 8 shutdown"] + }, + { + "id": "101.3-004", + "objective": "101.3", + "type": "multi", + "difficulty": 2, + "question": "Mit welchen Befehlen wechselt ein laufendes System **sofort** in den Einzelbenutzer-/Rettungsmodus?", + "options": [ + { "id": "a", "text": "`systemctl isolate rescue.target`", "correct": true, "explanation": "`isolate` startet das Target und beendet alle Units, die nicht dazugehören." }, + { "id": "b", "text": "`telinit 1`", "correct": true, "explanation": "`telinit 1` (bzw. `init 1`) wechselt in Runlevel 1; unter systemd wird das auf `rescue.target` abgebildet." }, + { "id": "c", "text": "`systemctl set-default rescue.target`", "correct": false, "explanation": "Ändert nur das Standard-Target für den nächsten Start." }, + { "id": "d", "text": "`runlevel 1`", "correct": false, "explanation": "`runlevel` zeigt nur den vorherigen und aktuellen Runlevel an; es nimmt keinen Wechsel vor." }, + { "id": "e", "text": "`systemctl reload rescue.target`", "correct": false, "explanation": "`reload` lässt laufende Dienste ihre Konfiguration neu lesen; ein Targetwechsel ist das nicht." } + ], + "explanation": "Sofortiger Wechsel: `systemctl isolate ` bzw. klassisch `telinit `/`init `. Dauerhaft für den Start: `systemctl set-default`.", + "references": ["man 1 systemctl", "man 8 telinit"] + } + ] +} diff --git a/simulator/data/lpic1_101/questions_102.json b/simulator/data/lpic1_101/questions_102.json new file mode 100644 index 0000000..fc2c8eb --- /dev/null +++ b/simulator/data/lpic1_101/questions_102.json @@ -0,0 +1,317 @@ +{ + "$schema": "../schema/questions.schema.json", + "format": "lpic-sim-questions", + "meta": { + "file": "questions_102.json", + "brief": "Fragen zu Topic 102 Linux-Installation und Paketverwaltung (LPIC-1 101-500, Objectives 5.0)", + "author": "Björn Runden ", + "owner": "Björn Runden ", + "assist": "KI-unterstützt (Claude Opus 5.5), geprüft von Björn Runden ", + "version": "0.1.0 (29.10.2026)" + }, + "exam": "lpic1-101", + "questions": [ + { + "id": "102.1-001", + "objective": "102.1", + "type": "single", + "difficulty": 1, + "question": "Welches Verzeichnis legt man typischerweise auf eine eigene Partition, damit wachsende Protokoll- und Spool-Dateien das Root-Dateisystem nicht füllen?", + "options": [ + { "id": "a", "text": "`/var`", "correct": true, "explanation": "`/var` enthält variable Daten wie Logs, Spool und Caches, die unkontrolliert wachsen können." }, + { "id": "b", "text": "`/etc`", "correct": false, "explanation": "`/etc` wird schon früh beim Start gebraucht und muss auf dem Root-Dateisystem liegen; es wächst kaum." }, + { "id": "c", "text": "`/bin`", "correct": false, "explanation": "`/bin` enthält grundlegende Programme, die beim Start verfügbar sein müssen." }, + { "id": "d", "text": "`/sbin`", "correct": false, "explanation": "`/sbin` enthält Systemprogramme für Start und Reparatur und gehört auf das Root-Dateisystem." }, + { "id": "e", "text": "`/lib`", "correct": false, "explanation": "`/lib` enthält Bibliotheken und Module, die für den Start nötig sind." } + ], + "explanation": "Kandidaten für eigene Partitionen: `/var`, `/home`, `/tmp`, ggf. `/boot` und `/opt`. Was zum Start nötig ist (`/etc`, `/bin`, `/sbin`, `/lib`, `/dev`), bleibt auf dem Root-Dateisystem.", + "references": ["man 7 hier"] + }, + { + "id": "102.1-002", + "objective": "102.1", + "type": "multi", + "difficulty": 2, + "question": "Welche Aussagen zum Logical Volume Manager (LVM) treffen zu?", + "options": [ + { "id": "a", "text": "Logical Volumes werden aus dem Speicher einer Volume Group zugeteilt.", "correct": true, "explanation": "Hierarchie: Physical Volume → Volume Group → Logical Volume." }, + { "id": "b", "text": "Eine Volume Group kann mehrere Physical Volumes umfassen.", "correct": true, "explanation": "Mehrere Platten/Partitionen lassen sich zu einer Volume Group zusammenfassen und mit `vgextend` erweitern." }, + { "id": "c", "text": "Ein Physical Volume kann immer nur genau ein Logical Volume aufnehmen.", "correct": false, "explanation": "Die Extents eines Physical Volumes können auf beliebig viele Logical Volumes verteilt sein." }, + { "id": "d", "text": "LVM setzt zwingend eine GPT-Partitionstabelle voraus.", "correct": false, "explanation": "LVM funktioniert mit MBR, GPT oder auch ganzen Platten ohne Partitionstabelle." }, + { "id": "e", "text": "Logical Volumes können nur vergrößert werden, wenn das System neu gestartet wird.", "correct": false, "explanation": "`lvextend` vergrößert im laufenden Betrieb; viele Dateisysteme lassen sich anschließend online wachsen." } + ], + "explanation": "LVM entkoppelt Dateisysteme von physischen Partitionen: `pvcreate` → `vgcreate` → `lvcreate`. Vorteil: flexible Größenänderung und Snapshots.", + "references": ["man 8 lvm"] + }, + { + "id": "102.1-003", + "objective": "102.1", + "type": "single", + "difficulty": 1, + "question": "Mit welchem Dateisystem muss die EFI-Systempartition (ESP) eines UEFI-Systems formatiert sein?", + "options": [ + { "id": "a", "text": "FAT (üblich FAT32)", "correct": true, "explanation": "Die UEFI-Spezifikation verlangt ein FAT-Dateisystem, damit die Firmware die Bootloader-Dateien lesen kann." }, + { "id": "b", "text": "ext4", "correct": false, "explanation": "ext4 kann die Firmware in der Regel nicht lesen; es eignet sich für `/` oder `/boot`." }, + { "id": "c", "text": "XFS", "correct": false, "explanation": "XFS wird von UEFI-Firmware nicht unterstützt." }, + { "id": "d", "text": "swap", "correct": false, "explanation": "swap ist Auslagerungsspeicher, kein Dateisystem für Dateien." }, + { "id": "e", "text": "Btrfs", "correct": false, "explanation": "Btrfs kann die Firmware nicht lesen." } + ], + "explanation": "Die ESP (meist eingehängt unter `/boot/efi`) enthält die `.efi`-Bootloader und ist FAT-formatiert.", + "references": ["UEFI-Spezifikation, Abschnitt EFI System Partition"] + }, + { + "id": "102.2-001", + "objective": "102.2", + "type": "single", + "difficulty": 1, + "question": "Auf einem Debian-System wurde `/etc/default/grub` geändert (z. B. `GRUB_TIMEOUT`). Welcher Befehl übernimmt die Änderung in die GRUB-2-Konfiguration?", + "options": [ + { "id": "a", "text": "`update-grub`", "correct": true, "explanation": "`update-grub` ist unter Debian ein Wrapper für `grub-mkconfig -o /boot/grub/grub.cfg`." }, + { "id": "b", "text": "`grub-mkconfig`", "correct": false, "explanation": "Ohne `-o ` gibt `grub-mkconfig` die Konfiguration nur auf stdout aus und schreibt nichts." }, + { "id": "c", "text": "`grub-install /etc/default/grub`", "correct": false, "explanation": "`grub-install` installiert den Bootloader auf ein Gerät; es erwartet ein Gerät, keine Konfigurationsdatei." }, + { "id": "d", "text": "`systemctl restart grub`", "correct": false, "explanation": "GRUB ist kein Dienst; es läuft nur beim Start, vor dem Kernel." }, + { "id": "e", "text": "`lilo`", "correct": false, "explanation": "`lilo` gehört zum veralteten Bootloader LILO und wertet `/etc/lilo.conf` aus." } + ], + "explanation": "GRUB 2: Einstellungen in `/etc/default/grub` und `/etc/grub.d/`, daraus erzeugt `grub-mkconfig` die Datei `grub.cfg`, die man nicht von Hand bearbeitet.", + "references": ["man 8 grub-mkconfig", "info grub"] + }, + { + "id": "102.2-002", + "objective": "102.2", + "type": "fill", + "difficulty": 2, + "question": "Geben Sie den vollständigen Befehl ein, der die GRUB-2-Konfiguration neu erzeugt und direkt nach `/boot/grub/grub.cfg` schreibt (ohne den Debian-Wrapper `update-grub`).", + "answers": ["grub-mkconfig -o /boot/grub/grub.cfg", "grub-mkconfig --output=/boot/grub/grub.cfg", "grub2-mkconfig -o /boot/grub2/grub.cfg"], + "explanation": "`grub-mkconfig -o` schreibt die erzeugte Konfiguration in die Datei. Distributionen der Red-Hat-Familie heißen das Werkzeug `grub2-mkconfig` und nutzen `/boot/grub2/grub.cfg`.", + "references": ["man 8 grub-mkconfig"] + }, + { + "id": "102.2-003", + "objective": "102.2", + "type": "single", + "difficulty": 2, + "question": "Wie heißt die Menü-Konfigurationsdatei von GRUB Legacy (Version 0.9x) üblicherweise?", + "options": [ + { "id": "a", "text": "`/boot/grub/menu.lst`", "correct": true, "explanation": "GRUB Legacy liest `menu.lst` (bei Red Hat auch `grub.conf`) direkt beim Start." }, + { "id": "b", "text": "`/boot/grub/grub.cfg`", "correct": false, "explanation": "`grub.cfg` ist die generierte Konfiguration von GRUB 2." }, + { "id": "c", "text": "`/etc/default/grub`", "correct": false, "explanation": "`/etc/default/grub` enthält die Einstellungen, aus denen GRUB 2 seine `grub.cfg` erzeugt." }, + { "id": "d", "text": "`/etc/lilo.conf`", "correct": false, "explanation": "Das ist die Konfiguration des Bootloaders LILO." }, + { "id": "e", "text": "`/boot/efi/grub.ini`", "correct": false, "explanation": "Eine solche Datei gibt es bei GRUB nicht." } + ], + "explanation": "Unterschied: GRUB Legacy wird direkt über `menu.lst` konfiguriert (Partitionen ab `(hd0,0)` gezählt), GRUB 2 über generierte `grub.cfg` (Partitionen ab 1, z. B. `(hd0,1)`).", + "references": ["info grub"] + }, + { + "id": "102.3-001", + "objective": "102.3", + "type": "single", + "difficulty": 1, + "question": "Welcher Befehl zeigt an, welche Shared Libraries ein Programm wie `/usr/bin/ssh` benötigt?", + "options": [ + { "id": "a", "text": "`ldd /usr/bin/ssh`", "correct": true, "explanation": "`ldd` listet die benötigten Bibliotheken und den Pfad, über den sie aufgelöst werden." }, + { "id": "b", "text": "`ldconfig /usr/bin/ssh`", "correct": false, "explanation": "`ldconfig` aktualisiert Links und den Cache `/etc/ld.so.cache`; es analysiert keine Programme." }, + { "id": "c", "text": "`ldconfig -p`", "correct": false, "explanation": "`ldconfig -p` zeigt alle Bibliotheken im Cache, nicht die eines bestimmten Programms." }, + { "id": "d", "text": "`ld /usr/bin/ssh`", "correct": false, "explanation": "`ld` ist der Linker zum Bauen von Programmen." }, + { "id": "e", "text": "`lsmod /usr/bin/ssh`", "correct": false, "explanation": "`lsmod` listet Kernelmodule, keine Bibliotheken." } + ], + "explanation": "Der dynamische Linker (`ld-linux.so`) lädt beim Start die Bibliotheken. Er sucht über `LD_LIBRARY_PATH`, den Cache `/etc/ld.so.cache` und die Standardpfade.", + "references": ["man 1 ldd", "man 8 ld.so"] + }, + { + "id": "102.3-002", + "objective": "102.3", + "type": "multi", + "difficulty": 2, + "question": "Eine Bibliothek wurde nach `/opt/app/lib` installiert und soll **dauerhaft für alle Programme** gefunden werden. Welche Schritte sind nötig?", + "options": [ + { "id": "a", "text": "Den Pfad in eine Datei unter `/etc/ld.so.conf.d/` eintragen", "correct": true, "explanation": "`/etc/ld.so.conf` bindet die Dateien aus `ld.so.conf.d/` ein; dort stehen zusätzliche Suchpfade." }, + { "id": "b", "text": "`ldconfig` ausführen", "correct": true, "explanation": "`ldconfig` liest die Pfade ein und erzeugt den Cache `/etc/ld.so.cache` neu." }, + { "id": "c", "text": "`ldd /opt/app/lib` ausführen", "correct": false, "explanation": "`ldd` zeigt nur Abhängigkeiten eines Programms an und ändert nichts." }, + { "id": "d", "text": "`LD_LIBRARY_PATH` in `/etc/ld.so.conf` setzen", "correct": false, "explanation": "In `ld.so.conf` stehen Pfade, keine Variablenzuweisungen. `LD_LIBRARY_PATH` ist eine Umgebungsvariable der Shell." }, + { "id": "e", "text": "Die Bibliothek nach `/proc/lib` kopieren", "correct": false, "explanation": "`/proc` ist ein virtuelles Dateisystem; dorthin kann man nichts dauerhaft kopieren." } + ], + "explanation": "Dauerhaft: Pfad in `/etc/ld.so.conf(.d)` und `ldconfig`. Nur vorübergehend, für eine Sitzung oder einen Aufruf: `export LD_LIBRARY_PATH=/opt/app/lib`.", + "references": ["man 8 ldconfig"] + }, + { + "id": "102.4-001", + "objective": "102.4", + "type": "single", + "difficulty": 1, + "question": "Welcher Befehl listet alle Dateien auf, die das **installierte** Debian-Paket `openssh-server` auf dem System abgelegt hat?", + "options": [ + { "id": "a", "text": "`dpkg -L openssh-server`", "correct": true, "explanation": "`-L` (`--listfiles`) listet die Dateien eines installierten Pakets." }, + { "id": "b", "text": "`dpkg -l openssh-server`", "correct": false, "explanation": "`-l` zeigt nur Status, Version und Beschreibung in Kurzform." }, + { "id": "c", "text": "`dpkg -S openssh-server`", "correct": false, "explanation": "`-S` sucht, zu welchem Paket ein Dateiname gehört." }, + { "id": "d", "text": "`dpkg -c openssh-server`", "correct": false, "explanation": "`-c` listet den Inhalt einer `.deb`-Datei, nicht eines installierten Pakets." }, + { "id": "e", "text": "`dpkg -s openssh-server`", "correct": false, "explanation": "`-s` zeigt Status und Metadaten, aber keine Dateiliste." } + ], + "explanation": "Merkhilfe: `-L` Liste der Dateien, `-l` Liste der Pakete, `-S` Suche nach Datei, `-s` Status, `-c` Inhalt einer .deb, `-I` Info zu einer .deb.", + "references": ["man 1 dpkg"] + }, + { + "id": "102.4-002", + "objective": "102.4", + "type": "fill", + "difficulty": 2, + "question": "Mit welchem dpkg-Aufruf (Befehl und Option, **ohne** Dateinamen) findet man heraus, zu welchem installierten Paket die Datei `/usr/bin/ls` gehört?", + "answers": ["dpkg -S", "dpkg --search"], + "explanation": "`dpkg -S /usr/bin/ls` liefert z. B. `coreutils: /usr/bin/ls`. Für nicht installierte Pakete hilft `apt-file search`.", + "references": ["man 1 dpkg"] + }, + { + "id": "102.4-003", + "objective": "102.4", + "type": "single", + "difficulty": 1, + "question": "Welcher Befehl lädt nur die aktuellen Paketlisten aus den konfigurierten Quellen, ohne Pakete zu installieren oder zu aktualisieren?", + "options": [ + { "id": "a", "text": "`apt-get update`", "correct": true, "explanation": "`update` aktualisiert den Paketindex aus `/etc/apt/sources.list(.d)`." }, + { "id": "b", "text": "`apt-get upgrade`", "correct": false, "explanation": "`upgrade` installiert neuere Versionen bereits installierter Pakete." }, + { "id": "c", "text": "`apt-get dist-upgrade`", "correct": false, "explanation": "`dist-upgrade` aktualisiert Pakete und darf dabei auch Pakete hinzufügen oder entfernen." }, + { "id": "d", "text": "`apt-cache update`", "correct": false, "explanation": "`apt-cache` fragt nur den Cache ab; einen Unterbefehl `update` gibt es nicht." }, + { "id": "e", "text": "`apt-get check`", "correct": false, "explanation": "`check` prüft auf defekte Abhängigkeiten und lädt nichts herunter." } + ], + "explanation": "Typische Reihenfolge: `apt-get update` (Listen), dann `apt-get upgrade` (Pakete). Paketquellen stehen in `/etc/apt/sources.list` und `/etc/apt/sources.list.d/`.", + "references": ["man 8 apt-get"] + }, + { + "id": "102.4-004", + "objective": "102.4", + "type": "multi", + "difficulty": 2, + "question": "Mit welchen Befehlen wird ein Paket **einschließlich seiner Konfigurationsdateien** entfernt?", + "options": [ + { "id": "a", "text": "`apt-get purge paket`", "correct": true, "explanation": "`purge` entfernt das Paket und seine Konfigurationsdateien." }, + { "id": "b", "text": "`dpkg -P paket`", "correct": true, "explanation": "`-P` (`--purge`) entfernt alles einschließlich Konfiguration." }, + { "id": "c", "text": "`dpkg -r paket`", "correct": false, "explanation": "`-r` (`--remove`) lässt die Konfigurationsdateien stehen (Status `rc`)." }, + { "id": "d", "text": "`apt-get remove paket`", "correct": false, "explanation": "`remove` entspricht `dpkg -r`: Konfigurationsdateien bleiben erhalten." }, + { "id": "e", "text": "`apt-get autoremove paket`", "correct": false, "explanation": "`autoremove` entfernt automatisch installierte, nicht mehr benötigte Abhängigkeiten; Konfigurationen bleiben." } + ], + "explanation": "Pakete im Zustand `rc` (removed, config-files) zeigt `dpkg -l`. Sie lassen sich nachträglich mit `dpkg -P` vollständig entfernen.", + "references": ["man 1 dpkg", "man 8 apt-get"] + }, + { + "id": "102.4-005", + "objective": "102.4", + "type": "single", + "difficulty": 2, + "question": "Bei der Installation eines Pakets wurden debconf-Fragen beantwortet. Wie lassen sich diese Fragen **erneut** stellen und die Konfiguration neu erzeugen?", + "options": [ + { "id": "a", "text": "`dpkg-reconfigure paket`", "correct": true, "explanation": "`dpkg-reconfigure` stellt die debconf-Fragen erneut und konfiguriert das Paket neu." }, + { "id": "b", "text": "`dpkg --configure paket`", "correct": false, "explanation": "`--configure` schließt die Konfiguration entpackter Pakete ab; bereits beantwortete Fragen werden nicht erneut gestellt." }, + { "id": "c", "text": "`apt-get install --reinstall paket`", "correct": false, "explanation": "Die Antworten liegen in der debconf-Datenbank und werden bei der Neuinstallation wiederverwendet." }, + { "id": "d", "text": "`apt-cache policy paket`", "correct": false, "explanation": "`policy` zeigt installierte und verfügbare Versionen sowie die Prioritäten der Quellen." }, + { "id": "e", "text": "`debconf-show paket`", "correct": false, "explanation": "`debconf-show` zeigt die gespeicherten Antworten nur an." } + ], + "explanation": "debconf speichert Antworten dauerhaft. Typisches Beispiel: `dpkg-reconfigure tzdata` oder `dpkg-reconfigure locales`.", + "references": ["man 8 dpkg-reconfigure"] + }, + { + "id": "102.5-001", + "objective": "102.5", + "type": "single", + "difficulty": 1, + "question": "Welcher rpm-Befehl ermittelt, zu welchem installierten Paket die Datei `/etc/ssh/sshd_config` gehört?", + "options": [ + { "id": "a", "text": "`rpm -qf /etc/ssh/sshd_config`", "correct": true, "explanation": "`-q` Abfrage, `-f` (file): Paket, dem die Datei gehört." }, + { "id": "b", "text": "`rpm -ql /etc/ssh/sshd_config`", "correct": false, "explanation": "`-ql` listet die Dateien eines Pakets; es erwartet einen Paketnamen." }, + { "id": "c", "text": "`rpm -qi /etc/ssh/sshd_config`", "correct": false, "explanation": "`-qi` zeigt Informationen zu einem Paket; es erwartet einen Paketnamen." }, + { "id": "d", "text": "`rpm -V /etc/ssh/sshd_config`", "correct": false, "explanation": "`-V` prüft installierte Pakete auf Änderungen gegenüber der RPM-Datenbank." }, + { "id": "e", "text": "`rpm -qa /etc/ssh/sshd_config`", "correct": false, "explanation": "`-qa` listet alle installierten Pakete (das Argument wird als Muster gelesen, nicht als Datei)." } + ], + "explanation": "Abfragen beginnen mit `-q`: `-qa` alle, `-qi` Info, `-ql` Dateien, `-qf` Besitzer einer Datei, `-qc` Konfigurationsdateien, `-qR` Abhängigkeiten, `-qp` für eine .rpm-Datei.", + "references": ["man 8 rpm"] + }, + { + "id": "102.5-002", + "objective": "102.5", + "type": "fill", + "difficulty": 1, + "question": "Geben Sie den rpm-Befehl ein, der alle Dateien des installierten Pakets `bash` auflistet.", + "answers": ["rpm -ql bash", "rpm -q -l bash", "rpm -q --list bash", "rpm --query --list bash"], + "explanation": "`-q` (query) mit `-l` (list). Für eine noch nicht installierte Datei: `rpm -qlp paket.rpm`.", + "references": ["man 8 rpm"] + }, + { + "id": "102.5-003", + "objective": "102.5", + "type": "single", + "difficulty": 2, + "question": "Welcher rpm-Aufruf aktualisiert ein Paket aus einer .rpm-Datei – und installiert es, falls es noch nicht vorhanden ist?", + "options": [ + { "id": "a", "text": "`rpm -Uvh paket.rpm`", "correct": true, "explanation": "`-U` (upgrade) aktualisiert oder installiert; `-v` ausführlich, `-h` Fortschrittsbalken." }, + { "id": "b", "text": "`rpm -Fvh paket.rpm`", "correct": false, "explanation": "`-F` (freshen) aktualisiert nur, wenn das Paket bereits installiert ist." }, + { "id": "c", "text": "`rpm -ivh paket.rpm`", "correct": false, "explanation": "`-i` installiert neu; bei installierter älterer Version entsteht ein Konflikt (Ausnahme: z. B. Kernel parallel)." }, + { "id": "d", "text": "`rpm -e paket.rpm`", "correct": false, "explanation": "`-e` (erase) entfernt ein Paket." }, + { "id": "e", "text": "`rpm -Vp paket.rpm`", "correct": false, "explanation": "`-V` prüft, es installiert nichts." } + ], + "explanation": "rpm löst keine Abhängigkeiten aus Repositories auf – dafür gibt es `dnf`/`yum` bzw. `zypper`.", + "references": ["man 8 rpm"] + }, + { + "id": "102.5-004", + "objective": "102.5", + "type": "multi", + "difficulty": 1, + "question": "Welche Werkzeuge installieren RPM-Pakete aus Repositories und lösen dabei Abhängigkeiten automatisch auf?", + "options": [ + { "id": "a", "text": "`dnf`", "correct": true, "explanation": "Nachfolger von yum, Standard bei Fedora und RHEL ab Version 8." }, + { "id": "b", "text": "`yum`", "correct": true, "explanation": "Klassisches Frontend der Red-Hat-Familie; Repos in `/etc/yum.repos.d/`." }, + { "id": "c", "text": "`zypper`", "correct": true, "explanation": "Paketverwaltung von openSUSE/SLES, ebenfalls auf RPM-Basis." }, + { "id": "d", "text": "`rpm2cpio`", "correct": false, "explanation": "`rpm2cpio` wandelt ein RPM in ein cpio-Archiv um, installiert aber nichts." }, + { "id": "e", "text": "`dpkg`", "correct": false, "explanation": "`dpkg` verwaltet Debian-Pakete und löst keine Abhängigkeiten aus Repositories auf." } + ], + "explanation": "rpm ist die Basisschicht, `dnf`/`yum`/`zypper` sind die Frontends mit Repository- und Abhängigkeitsverwaltung (vergleichbar mit dpkg und apt).", + "references": ["man 8 dnf", "man 8 zypper"] + }, + { + "id": "102.5-005", + "objective": "102.5", + "type": "single", + "difficulty": 2, + "question": "Wie entpackt man die Dateien aus `paket.rpm` in das aktuelle Verzeichnis, **ohne** das Paket zu installieren?", + "options": [ + { "id": "a", "text": "`rpm2cpio paket.rpm | cpio -idmv`", "correct": true, "explanation": "`rpm2cpio` gibt den Inhalt als cpio-Strom aus, `cpio -i` entpackt (`-d` Verzeichnisse anlegen, `-m` Zeiten erhalten)." }, + { "id": "b", "text": "`rpm -x paket.rpm`", "correct": false, "explanation": "rpm hat keine Option `-x` zum Entpacken." }, + { "id": "c", "text": "`cpio -i < paket.rpm`", "correct": false, "explanation": "Eine RPM-Datei hat einen eigenen Header vor dem Archiv; cpio kann sie nicht direkt lesen." }, + { "id": "d", "text": "`tar xf paket.rpm`", "correct": false, "explanation": "RPM ist kein tar-Archiv." }, + { "id": "e", "text": "`rpm -qlp paket.rpm`", "correct": false, "explanation": "Das listet nur die enthaltenen Dateien auf, entpackt aber nichts." } + ], + "explanation": "Nützlich, um einzelne Dateien (z. B. eine Original-Konfiguration) aus einem Paket zu holen.", + "references": ["man 8 rpm2cpio", "man 1 cpio"] + }, + { + "id": "102.6-001", + "objective": "102.6", + "type": "multi", + "difficulty": 2, + "question": "Eine Linux-VM wird aus einer Vorlage geklont. Was sollte auf jedem Klon **neu erzeugt** werden, weil es eindeutig sein muss?", + "options": [ + { "id": "a", "text": "Die D-Bus-/systemd-Maschinen-ID in `/etc/machine-id`", "correct": true, "explanation": "Die Machine-ID identifiziert das System (u. a. Journal, DHCP-Client-ID) und darf nicht doppelt vorkommen." }, + { "id": "b", "text": "Die SSH-Host-Schlüssel unter `/etc/ssh/ssh_host_*`", "correct": true, "explanation": "Gleiche Host-Schlüssel auf mehreren Systemen untergraben die Server-Authentifizierung." }, + { "id": "c", "text": "Den Kernel unter `/boot`", "correct": false, "explanation": "Der Kernel ist nicht systemspezifisch und kann identisch bleiben." }, + { "id": "d", "text": "Die Datei `/etc/services`", "correct": false, "explanation": "`/etc/services` ordnet Portnummern Dienstnamen zu und ist überall gleich." }, + { "id": "e", "text": "Die Shared Libraries unter `/usr/lib`", "correct": false, "explanation": "Bibliotheken sind Programmdateien und nicht systemspezifisch." } + ], + "explanation": "Vorlagen werden vorher \"generalisiert\": Machine-ID leeren, SSH-Host-Schlüssel löschen, ggf. Hostname und MAC-gebundene Netzkonfiguration zurücksetzen. cloud-init oder ein Erststart-Skript erzeugt sie neu.", + "references": ["man 5 machine-id", "man 8 ssh-keygen"] + }, + { + "id": "102.6-002", + "objective": "102.6", + "type": "single", + "difficulty": 1, + "question": "Welches Werkzeug richtet Cloud-Instanzen beim ersten Start anhand von Metadaten des Anbieters ein (Hostname, Benutzer, SSH-Schlüssel, Pakete)?", + "options": [ + { "id": "a", "text": "cloud-init", "correct": true, "explanation": "cloud-init liest Meta- und User-Data (z. B. `#cloud-config` in YAML) und konfiguriert das System beim ersten Start." }, + { "id": "b", "text": "Kickstart", "correct": false, "explanation": "Kickstart ist eine Antwortdatei für die automatisierte Installation mit Anaconda, nicht für den Start einer fertigen Instanz." }, + { "id": "c", "text": "`virt-install`", "correct": false, "explanation": "`virt-install` legt auf dem Host neue libvirt-VMs an; im Gast konfiguriert es nichts." }, + { "id": "d", "text": "`dmidecode`", "correct": false, "explanation": "`dmidecode` liest Hardware-Informationen (DMI/SMBIOS) aus." }, + { "id": "e", "text": "`qemu-img`", "correct": false, "explanation": "`qemu-img` erstellt und konvertiert Abbilder virtueller Festplatten." } + ], + "explanation": "Begriffe aus 102.6: Virtuelle Maschine, Linux-Container, Anwendungs-Container, Gasttreiber, SSH-Host-Schlüssel, D-Bus-Machine-ID, cloud-init.", + "references": ["https://cloudinit.readthedocs.io/"] + } + ] +} diff --git a/simulator/data/lpic1_101/questions_103.json b/simulator/data/lpic1_101/questions_103.json new file mode 100644 index 0000000..f0ba44a --- /dev/null +++ b/simulator/data/lpic1_101/questions_103.json @@ -0,0 +1,582 @@ +{ + "$schema": "../schema/questions.schema.json", + "format": "lpic-sim-questions", + "meta": { + "file": "questions_103.json", + "brief": "Fragen zu Topic 103 GNU- und Unix-Befehle (LPIC-1 101-500, Objectives 5.0)", + "author": "Björn Runden ", + "owner": "Björn Runden ", + "assist": "KI-unterstützt (Claude Opus 5.5), geprüft von Björn Runden ", + "version": "0.1.0 (29.10.2026)" + }, + "exam": "lpic1-101", + "questions": [ + { + "id": "103.1-001", + "objective": "103.1", + "type": "single", + "difficulty": 1, + "question": "Eine Shell-Variable `PROJEKT` soll auch in Programmen sichtbar sein, die aus der aktuellen Shell gestartet werden. Welcher Befehl leistet das?", + "options": [ + { "id": "a", "text": "`export PROJEKT`", "correct": true, "explanation": "`export` übernimmt die Variable in die Umgebung, die an Kindprozesse vererbt wird." }, + { "id": "b", "text": "`set PROJEKT`", "correct": false, "explanation": "`set` setzt Shell-Optionen bzw. Positionsparameter; es exportiert keine Variable." }, + { "id": "c", "text": "`env PROJEKT`", "correct": false, "explanation": "`env` würde versuchen, ein Programm namens `PROJEKT` mit der aktuellen Umgebung zu starten." }, + { "id": "d", "text": "`local PROJEKT`", "correct": false, "explanation": "`local` erzeugt eine lokale Variable innerhalb einer Shell-Funktion." }, + { "id": "e", "text": "`declare -r PROJEKT`", "correct": false, "explanation": "`declare -r` macht die Variable schreibgeschützt, exportiert sie aber nicht (das wäre `declare -x`)." } + ], + "explanation": "Shell-Variablen gelten nur in der aktuellen Shell, Umgebungsvariablen werden vererbt. Anzeige: `set` (alle Shell-Variablen und Funktionen), `env`/`printenv` (nur Umgebung).", + "references": ["man 1 bash (Abschnitt ENVIRONMENT)"] + }, + { + "id": "103.1-002", + "objective": "103.1", + "type": "single", + "difficulty": 1, + "question": "Welcher Befehl gibt den Text `$HOME` **wörtlich** aus, also ohne ihn durch den Pfad des Home-Verzeichnisses zu ersetzen?", + "options": [ + { "id": "a", "text": "`echo '$HOME'`", "correct": true, "explanation": "In einfachen Anführungszeichen findet keinerlei Ersetzung statt." }, + { "id": "b", "text": "`echo \"$HOME\"`", "correct": false, "explanation": "In doppelten Anführungszeichen werden Variablen ersetzt; nur die Worttrennung unterbleibt." }, + { "id": "c", "text": "`echo $HOME`", "correct": false, "explanation": "Ohne Quoting wird die Variable ersetzt." }, + { "id": "d", "text": "`echo ${HOME}`", "correct": false, "explanation": "`${…}` ist die ausführliche Schreibweise der Variablenersetzung." }, + { "id": "e", "text": "`echo $(HOME)`", "correct": false, "explanation": "`$(…)` ist Befehlsersetzung: Die Shell versucht, einen Befehl `HOME` auszuführen." } + ], + "explanation": "Quoting: `'…'` alles wörtlich, `\"…\"` Variablen und Befehlsersetzung aktiv, `\\` maskiert ein einzelnes Zeichen (z. B. `echo \\$HOME`).", + "references": ["man 1 bash (Abschnitt QUOTING)"] + }, + { + "id": "103.1-003", + "objective": "103.1", + "type": "fill", + "difficulty": 2, + "question": "Welches Shell-Builtin zeigt an, ob `ls` ein Alias, eine Funktion, ein Builtin oder ein Programm im `PATH` ist? (nur der Befehlsname)", + "answers": ["type"], + "explanation": "`type ls` liefert z. B. `ls is aliased to 'ls --color=auto'`. `which` sucht dagegen nur Programme im `PATH` und kennt keine Aliase oder Builtins.", + "references": ["help type"] + }, + { + "id": "103.1-004", + "objective": "103.1", + "type": "multi", + "difficulty": 2, + "question": "Welche Aussagen zur Bash-History treffen zu?", + "options": [ + { "id": "a", "text": "`!!` führt den zuletzt eingegebenen Befehl erneut aus.", "correct": true, "explanation": "History-Expansion: `!!` steht für den vorherigen Befehl, z. B. `sudo !!`." }, + { "id": "b", "text": "Die History wird standardmäßig in `~/.bash_history` gespeichert.", "correct": true, "explanation": "Die Datei legt `HISTFILE` fest; Standard ist `~/.bash_history`." }, + { "id": "c", "text": "`history -c` löscht die Datei `~/.bash_history` sofort.", "correct": false, "explanation": "`history -c` leert nur die History im Speicher der laufenden Shell." }, + { "id": "d", "text": "`HISTSIZE` legt die maximale Zeilenzahl der History-Datei fest.", "correct": false, "explanation": "`HISTSIZE` gilt für die History im Speicher, `HISTFILESIZE` für die Datei." }, + { "id": "e", "text": "`!42` zeigt Befehl Nummer 42 an, ohne ihn auszuführen.", "correct": false, "explanation": "`!42` führt den Befehl aus. Nur anzeigen: `!42:p`." } + ], + "explanation": "Weitere Expansionen: `!$` letztes Argument, `!str` letzter Befehl, der mit `str` beginnt. Strg+R sucht rückwärts in der History.", + "references": ["man 1 bash (Abschnitt HISTORY EXPANSION)"] + }, + { + "id": "103.1-005", + "objective": "103.1", + "type": "single", + "difficulty": 1, + "question": "Welcher Befehl gibt **nur** die Release-Version des laufenden Kernels aus (z. B. `6.1.0-18-amd64`)?", + "options": [ + { "id": "a", "text": "`uname -r`", "correct": true, "explanation": "`-r` (kernel release) gibt genau die Release-Bezeichnung aus." }, + { "id": "b", "text": "`uname -a`", "correct": false, "explanation": "`-a` gibt alle Informationen aus: Name, Host, Release, Version, Architektur …" }, + { "id": "c", "text": "`uname -m`", "correct": false, "explanation": "`-m` zeigt die Hardware-Architektur, z. B. `x86_64`." }, + { "id": "d", "text": "`uname -n`", "correct": false, "explanation": "`-n` zeigt den Hostnamen (nodename)." }, + { "id": "e", "text": "`uname -s`", "correct": false, "explanation": "`-s` zeigt den Kernelnamen, also `Linux`." } + ], + "explanation": "`uname -r` wird oft in Pfaden genutzt, z. B. `/lib/modules/$(uname -r)/`.", + "references": ["man 1 uname"] + }, + { + "id": "103.1-006", + "objective": "103.1", + "type": "single", + "difficulty": 2, + "question": "Wie entfernt man die Variable `TMPDIR` **vollständig** aus der aktuellen Shell?", + "options": [ + { "id": "a", "text": "`unset TMPDIR`", "correct": true, "explanation": "`unset` löscht die Variable; danach ist sie weder gesetzt noch exportiert." }, + { "id": "b", "text": "`TMPDIR=\"\"`", "correct": false, "explanation": "Die Variable bleibt gesetzt, nur ihr Wert ist leer." }, + { "id": "c", "text": "`export -n TMPDIR`", "correct": false, "explanation": "`export -n` nimmt nur das Export-Attribut weg; die Shell-Variable bleibt bestehen." }, + { "id": "d", "text": "`env -u TMPDIR`", "correct": false, "explanation": "`env -u` entfernt die Variable nur aus der Umgebung des damit gestarteten Befehls." }, + { "id": "e", "text": "`set -u TMPDIR`", "correct": false, "explanation": "`set -u` lässt die Shell bei Zugriff auf ungesetzte Variablen einen Fehler melden; `TMPDIR` wird dabei zum Positionsparameter." } + ], + "explanation": "Unterschied gesetzt/leer: `${VAR-x}` liefert `x` nur, wenn `VAR` ungesetzt ist, `${VAR:-x}` auch bei leerem Wert.", + "references": ["help unset"] + }, + { + "id": "103.2-001", + "objective": "103.2", + "type": "single", + "difficulty": 1, + "question": "Welche Befehlskette gibt genau die Zeilen 11 bis 20 einer Datei aus?", + "options": [ + { "id": "a", "text": "`head -n 20 datei | tail -n 10`", "correct": true, "explanation": "Erst die ersten 20 Zeilen, davon die letzten 10 – also 11 bis 20." }, + { "id": "b", "text": "`tail -n 20 datei | head -n 10`", "correct": false, "explanation": "Das liefert die ersten 10 der letzten 20 Zeilen der Datei." }, + { "id": "c", "text": "`sed -n '10,20p' datei`", "correct": false, "explanation": "Gibt Zeilen 10 bis 20 aus, also 11 Zeilen." }, + { "id": "d", "text": "`head -n 11-20 datei`", "correct": false, "explanation": "`head` kennt keine Bereichsangabe." }, + { "id": "e", "text": "`cut -c 11-20 datei`", "correct": false, "explanation": "`cut -c` wählt Zeichen 11 bis 20 jeder Zeile, keine Zeilen." } + ], + "explanation": "Alternativ `sed -n '11,20p' datei`. `tail -n +11` gibt alles ab Zeile 11 aus.", + "references": ["man 1 head", "man 1 tail"] + }, + { + "id": "103.2-002", + "objective": "103.2", + "type": "single", + "difficulty": 1, + "question": "Welcher Befehl gibt nur die Benutzernamen (das erste Feld) aus `/etc/passwd` aus?", + "options": [ + { "id": "a", "text": "`cut -d: -f1 /etc/passwd`", "correct": true, "explanation": "`-d:` setzt den Doppelpunkt als Trenner, `-f1` wählt das erste Feld." }, + { "id": "b", "text": "`cut -f1 /etc/passwd`", "correct": false, "explanation": "Ohne `-d` trennt `cut` an Tabulatoren; die Zeilen werden ganz ausgegeben." }, + { "id": "c", "text": "`sort -t: -k1 /etc/passwd`", "correct": false, "explanation": "Das sortiert nach dem ersten Feld, gibt aber vollständige Zeilen aus." }, + { "id": "d", "text": "`tr ':' ' ' < /etc/passwd`", "correct": false, "explanation": "`tr` ersetzt nur die Doppelpunkte durch Leerzeichen." }, + { "id": "e", "text": "`paste -d: /etc/passwd`", "correct": false, "explanation": "`paste` fügt Zeilen mehrerer Dateien nebeneinander; mit einer Datei gibt es sie unverändert aus." } + ], + "explanation": "Gleichwertig: `awk -F: '{print $1}' /etc/passwd`.", + "references": ["man 1 cut"] + }, + { + "id": "103.2-003", + "objective": "103.2", + "type": "single", + "difficulty": 2, + "question": "In einer unsortierten Datei sollen alle Zeilen mit der Anzahl ihres Vorkommens ausgegeben werden. Welche Befehlskette ist korrekt?", + "options": [ + { "id": "a", "text": "`sort datei | uniq -c`", "correct": true, "explanation": "`uniq` fasst nur benachbarte gleiche Zeilen zusammen; daher vorher sortieren." }, + { "id": "b", "text": "`uniq -c datei`", "correct": false, "explanation": "Ohne Sortierung werden gleiche, aber nicht benachbarte Zeilen getrennt gezählt." }, + { "id": "c", "text": "`sort -u datei | wc -l`", "correct": false, "explanation": "Das zählt nur die Anzahl verschiedener Zeilen." }, + { "id": "d", "text": "`uniq -d datei | sort`", "correct": false, "explanation": "`uniq -d` zeigt nur benachbarte doppelte Zeilen, ohne Zählung." }, + { "id": "e", "text": "`cat -n datei | uniq`", "correct": false, "explanation": "Durch die Zeilennummern sind alle Zeilen verschieden; nichts wird zusammengefasst." } + ], + "explanation": "Häufigste Zeilen zuerst: `sort datei | uniq -c | sort -nr`.", + "references": ["man 1 uniq", "man 1 sort"] + }, + { + "id": "103.3-001", + "objective": "103.3", + "type": "single", + "difficulty": 1, + "question": "Ein Verzeichnis soll rekursiv kopiert werden; Rechte, Eigentümer, Zeitstempel und symbolische Links sollen erhalten bleiben. Welcher Befehl ist geeignet?", + "options": [ + { "id": "a", "text": "`cp -a quelle ziel`", "correct": true, "explanation": "`-a` (archive) entspricht `-dR --preserve=all`: rekursiv, Links als Links, alle Attribute." }, + { "id": "b", "text": "`cp -r quelle ziel`", "correct": false, "explanation": "`-r` kopiert rekursiv, übernimmt aber Eigentümer und Zeitstempel nicht." }, + { "id": "c", "text": "`cp -p quelle ziel`", "correct": false, "explanation": "`-p` erhält Attribute, kopiert aber Verzeichnisse nicht rekursiv." }, + { "id": "d", "text": "`cp -l quelle ziel`", "correct": false, "explanation": "`-l` legt Hardlinks statt Kopien an." }, + { "id": "e", "text": "`mv -a quelle ziel`", "correct": false, "explanation": "`mv` verschiebt und kennt keine Option `-a`." } + ], + "explanation": "Eigentümer kann nur root übernehmen; als normaler Benutzer gehören Kopien dem Kopierenden.", + "references": ["man 1 cp"] + }, + { + "id": "103.3-002", + "objective": "103.3", + "type": "fill", + "difficulty": 2, + "question": "Geben Sie den `find`-Befehl ein, der unterhalb von `/var` alle Dateien findet, die **größer als 100 MiB** sind.", + "answers": ["find /var -size +100M", "find /var -type f -size +100M", "find /var -size +100M -type f"], + "explanation": "`-size +100M`: größer als 100 MiB (`k`, `M`, `G` als Einheiten). `-size -100M` wäre kleiner. `-type f` beschränkt auf reguläre Dateien.", + "references": ["man 1 find"] + }, + { + "id": "103.3-003", + "objective": "103.3", + "type": "single", + "difficulty": 1, + "question": "Welcher Befehl erstellt ein gzip-komprimiertes tar-Archiv `backup.tar.gz` von `/etc`?", + "options": [ + { "id": "a", "text": "`tar -czf backup.tar.gz /etc`", "correct": true, "explanation": "`c` create, `z` gzip, `f` Archivdatei." }, + { "id": "b", "text": "`tar -xzf backup.tar.gz /etc`", "correct": false, "explanation": "`x` entpackt – hier würde nur `/etc` aus dem Archiv extrahiert." }, + { "id": "c", "text": "`tar -cjf backup.tar.gz /etc`", "correct": false, "explanation": "`j` komprimiert mit bzip2; der Name `.gz` wäre irreführend." }, + { "id": "d", "text": "`tar -tzf backup.tar.gz /etc`", "correct": false, "explanation": "`t` listet den Inhalt eines vorhandenen Archivs." }, + { "id": "e", "text": "`gzip -r /etc > backup.tar.gz`", "correct": false, "explanation": "`gzip -r` komprimiert jede Datei in `/etc` einzeln an Ort und Stelle; es entsteht kein Archiv." } + ], + "explanation": "Kompression bei tar: `z` gzip, `j` bzip2, `J` xz. Modi: `c` erstellen, `x` entpacken, `t` auflisten.", + "references": ["man 1 tar"] + }, + { + "id": "103.3-004", + "objective": "103.3", + "type": "multi", + "difficulty": 2, + "question": "Welche Dateinamen passen auf das Shell-Muster `d?t[0-9]*`?", + "options": [ + { "id": "a", "text": "`dat1`", "correct": true, "explanation": "`d`, beliebiges Zeichen `a`, `t`, Ziffer `1`, danach nichts (`*` darf leer sein)." }, + { "id": "b", "text": "`dot42.txt`", "correct": true, "explanation": "`d`, `o`, `t`, Ziffer `4`, Rest `2.txt` passt auf `*`." }, + { "id": "c", "text": "`dt1`", "correct": false, "explanation": "`?` verlangt genau ein Zeichen zwischen `d` und `t`." }, + { "id": "d", "text": "`data1`", "correct": false, "explanation": "Das vierte Zeichen `a` ist keine Ziffer." }, + { "id": "e", "text": "`Dat1`", "correct": false, "explanation": "Globbing unterscheidet Groß- und Kleinschreibung; `D` ist nicht `d`." } + ], + "explanation": "Globbing: `*` beliebig viele Zeichen (auch keine), `?` genau ein Zeichen, `[…]` ein Zeichen aus der Menge, `[!…]` ein Zeichen nicht aus der Menge.", + "references": ["man 7 glob"] + }, + { + "id": "103.3-005", + "objective": "103.3", + "type": "single", + "difficulty": 1, + "question": "Welcher Befehl ermittelt den Typ einer Datei anhand ihres Inhalts (z. B. „ELF 64-bit executable“ oder „gzip compressed data“)?", + "options": [ + { "id": "a", "text": "`file`", "correct": true, "explanation": "`file` vergleicht den Inhalt mit Signaturen (Magic Numbers)." }, + { "id": "b", "text": "`stat`", "correct": false, "explanation": "`stat` zeigt Metadaten aus dem Inode (Größe, Rechte, Zeiten), nicht den Inhaltstyp." }, + { "id": "c", "text": "`type`", "correct": false, "explanation": "`type` bestimmt, wie die Shell einen Befehlsnamen auflöst." }, + { "id": "d", "text": "`ls -l`", "correct": false, "explanation": "`ls -l` zeigt nur den Dateityp im Sinne von Datei/Verzeichnis/Link usw." }, + { "id": "e", "text": "`which`", "correct": false, "explanation": "`which` sucht ein Programm im `PATH`." } + ], + "explanation": "Unter Linux bestimmt nicht die Endung den Typ, sondern der Inhalt; `file` wertet dazu die magic-Datenbank aus.", + "references": ["man 1 file"] + }, + { + "id": "103.3-006", + "objective": "103.3", + "type": "single", + "difficulty": 2, + "question": "Der Master Boot Record (erster Sektor, 512 Byte) von `/dev/sda` soll in die Datei `mbr.img` gesichert werden. Welcher Befehl ist korrekt?", + "options": [ + { "id": "a", "text": "`dd if=/dev/sda of=mbr.img bs=512 count=1`", "correct": true, "explanation": "`if` Quelle, `of` Ziel, ein Block zu 512 Byte." }, + { "id": "b", "text": "`dd if=mbr.img of=/dev/sda bs=512 count=1`", "correct": false, "explanation": "Quelle und Ziel sind vertauscht – das würde den MBR mit der Datei überschreiben." }, + { "id": "c", "text": "`dd if=/dev/sda of=mbr.img bs=512 skip=1 count=1`", "correct": false, "explanation": "`skip=1` überspringt den ersten Block der Quelle – kopiert würde der zweite Sektor, nicht der MBR." }, + { "id": "d", "text": "`dd if=/dev/sda1 of=mbr.img bs=512 count=1`", "correct": false, "explanation": "`/dev/sda1` ist die erste Partition; der MBR liegt am Anfang der ganzen Platte." }, + { "id": "e", "text": "`cp /dev/sda mbr.img`", "correct": false, "explanation": "Das würde die gesamte Platte kopieren, nicht nur den ersten Sektor." } + ], + "explanation": "Der MBR enthält Bootloader-Code (446 Byte), Partitionstabelle (64 Byte) und Signatur (2 Byte).", + "references": ["man 1 dd"] + }, + { + "id": "103.4-001", + "objective": "103.4", + "type": "single", + "difficulty": 2, + "question": "Standardausgabe **und** Fehlerausgabe eines Befehls sollen in dieselbe Datei geschrieben werden. Welche Schreibweise ist korrekt?", + "options": [ + { "id": "a", "text": "`befehl > log.txt 2>&1`", "correct": true, "explanation": "Erst stdout in die Datei, dann stderr auf das (bereits umgelenkte) stdout." }, + { "id": "b", "text": "`befehl 2>&1 > log.txt`", "correct": false, "explanation": "Reihenfolge: stderr wird auf das ursprüngliche stdout (Terminal) gelegt, erst danach stdout in die Datei." }, + { "id": "c", "text": "`befehl 2> log.txt`", "correct": false, "explanation": "Nur die Fehlerausgabe landet in der Datei." }, + { "id": "d", "text": "`befehl | log.txt`", "correct": false, "explanation": "Die Pipe erwartet einen Befehl; `log.txt` würde als Programm gesucht." }, + { "id": "e", "text": "`befehl >> log.txt 1>&2`", "correct": false, "explanation": "`1>&2` lenkt stdout anschließend wieder auf stderr (Terminal) um; die Datei bleibt leer." } + ], + "explanation": "Umleitungen werden von links nach rechts ausgewertet. Bash-Kurzform: `befehl &> log.txt`.", + "references": ["man 1 bash (Abschnitt REDIRECTION)"] + }, + { + "id": "103.4-002", + "objective": "103.4", + "type": "fill", + "difficulty": 1, + "question": "Welche Umleitung (nur die Umleitung, ohne Befehl) verwirft die **Fehlerausgabe** eines Befehls?", + "answers": ["2>/dev/null", "2> /dev/null"], + "explanation": "Dateideskriptor 2 ist stderr; `/dev/null` verwirft alles, was hineingeschrieben wird.", + "references": ["man 4 null"] + }, + { + "id": "103.4-003", + "objective": "103.4", + "type": "single", + "difficulty": 1, + "question": "Die Ausgabe eines Befehls soll auf dem Bildschirm erscheinen **und** gleichzeitig in `ausgabe.txt` gespeichert werden. Wie geht das?", + "options": [ + { "id": "a", "text": "`befehl | tee ausgabe.txt`", "correct": true, "explanation": "`tee` kopiert stdin nach stdout und zusätzlich in die Datei(en); `-a` hängt an." }, + { "id": "b", "text": "`befehl > ausgabe.txt | cat`", "correct": false, "explanation": "stdout geht vollständig in die Datei; an `cat` kommt nichts an." }, + { "id": "c", "text": "`befehl >> ausgabe.txt`", "correct": false, "explanation": "Hängt nur an die Datei an; auf dem Bildschirm erscheint nichts." }, + { "id": "d", "text": "`befehl | cat > ausgabe.txt`", "correct": false, "explanation": "Die Ausgabe landet nur in der Datei." }, + { "id": "e", "text": "`befehl 2>&1 ausgabe.txt`", "correct": false, "explanation": "`ausgabe.txt` würde als Argument an den Befehl übergeben." } + ], + "explanation": "`tee` ist wie ein T-Stück in der Pipe. Mit `sudo tee datei` schreibt man z. B. als root in geschützte Dateien.", + "references": ["man 1 tee"] + }, + { + "id": "103.4-004", + "objective": "103.4", + "type": "single", + "difficulty": 2, + "question": "Alle von `find` gefundenen `*.tmp`-Dateien sollen gelöscht werden, indem ihre Namen als **Argumente** an `rm` übergeben werden. Welche Befehlszeile tut das?", + "options": [ + { "id": "a", "text": "`find . -name '*.tmp' | xargs rm`", "correct": true, "explanation": "`xargs` liest Namen von stdin und hängt sie als Argumente an `rm`." }, + { "id": "b", "text": "`find . -name '*.tmp' | rm`", "correct": false, "explanation": "`rm` liest keine Dateinamen von stdin; es meldet fehlende Operanden." }, + { "id": "c", "text": "`find . -name '*.tmp' > rm`", "correct": false, "explanation": "Das schreibt die Liste in eine Datei namens `rm`." }, + { "id": "d", "text": "`find . -name '*.tmp' | tee rm`", "correct": false, "explanation": "`tee` schreibt die Liste in die Datei `rm` und auf den Bildschirm." }, + { "id": "e", "text": "`rm < find . -name '*.tmp'`", "correct": false, "explanation": "`<` erwartet eine Datei als Eingabe, keinen Befehl." } + ], + "explanation": "Bei Namen mit Leerzeichen: `find … -print0 | xargs -0 rm`. Alternativ ohne Pipe: `find . -name '*.tmp' -delete` oder `-exec rm {} +`.", + "references": ["man 1 xargs"] + }, + { + "id": "103.4-005", + "objective": "103.4", + "type": "multi", + "difficulty": 1, + "question": "Welche Aussagen zu Umleitungen und Pipes treffen zu?", + "options": [ + { "id": "a", "text": "`>>` hängt die Standardausgabe an eine Datei an.", "correct": true, "explanation": "Existiert die Datei nicht, wird sie angelegt." }, + { "id": "b", "text": "`<` liest die Standardeingabe aus einer Datei.", "correct": true, "explanation": "Beispiel: `sort < liste.txt`." }, + { "id": "c", "text": "`2>&1` leitet die Standardausgabe auf die Fehlerausgabe um.", "correct": false, "explanation": "Umgekehrt: stderr (2) wird dorthin geleitet, wohin stdout (1) gerade zeigt." }, + { "id": "d", "text": "`|` verbindet die Fehlerausgabe mit der Eingabe des nächsten Befehls.", "correct": false, "explanation": "Die Pipe verbindet stdout mit stdin; stderr nur mit `|&` bzw. `2>&1 |`." }, + { "id": "e", "text": "`>` hängt an, wenn die Datei bereits existiert.", "correct": false, "explanation": "`>` überschreibt (kürzt die Datei auf 0); nur `>>` hängt an." } + ], + "explanation": "Dateideskriptoren: 0 stdin, 1 stdout, 2 stderr. `set -o noclobber` verhindert versehentliches Überschreiben mit `>`.", + "references": ["man 1 bash (Abschnitt REDIRECTION)"] + }, + { + "id": "103.4-006", + "objective": "103.4", + "type": "single", + "difficulty": 1, + "question": "Mit welcher Schreibweise setzt die Bash die **Ausgabe** eines Befehls in die Kommandozeile ein, z. B. in `echo \"Heute ist …\"`?", + "options": [ + { "id": "a", "text": "`$(date +%A)`", "correct": true, "explanation": "Befehlsersetzung: Die Ausgabe von `date +%A` ersetzt den Ausdruck." }, + { "id": "b", "text": "`${date +%A}`", "correct": false, "explanation": "`${…}` ist Parameter-/Variablenersetzung und hier ein Syntaxfehler." }, + { "id": "c", "text": "`$((date +%A))`", "correct": false, "explanation": "`$((…))` ist arithmetische Expansion." }, + { "id": "d", "text": "`'date +%A'`", "correct": false, "explanation": "Einfache Anführungszeichen ergeben den Text wörtlich." }, + { "id": "e", "text": "`<(date +%A)`", "correct": false, "explanation": "Prozessersetzung liefert einen Dateinamen (z. B. `/dev/fd/63`), nicht den Text." } + ], + "explanation": "Ältere, gleichwertige Schreibweise mit Backticks (Gravis-Zeichen). `$(…)` ist besser lesbar und verschachtelbar.", + "references": ["man 1 bash (Abschnitt Command Substitution)"] + }, + { + "id": "103.5-001", + "objective": "103.5", + "type": "single", + "difficulty": 1, + "question": "Welches Signal kann ein Prozess weder abfangen noch ignorieren?", + "options": [ + { "id": "a", "text": "SIGKILL (9)", "correct": true, "explanation": "SIGKILL beendet den Prozess unmittelbar durch den Kernel; es gibt keinen Handler." }, + { "id": "b", "text": "SIGTERM (15)", "correct": false, "explanation": "SIGTERM ist die höfliche Aufforderung zum Beenden und kann abgefangen werden." }, + { "id": "c", "text": "SIGHUP (1)", "correct": false, "explanation": "SIGHUP wird oft abgefangen, z. B. um Konfiguration neu zu laden." }, + { "id": "d", "text": "SIGINT (2)", "correct": false, "explanation": "SIGINT (Strg+C) kann abgefangen werden." }, + { "id": "e", "text": "SIGUSR1 (10)", "correct": false, "explanation": "Benutzerdefiniertes Signal, das Programme frei abfangen." } + ], + "explanation": "Neben SIGKILL kann auch SIGSTOP nicht abgefangen werden. Liste aller Signale: `kill -l`.", + "references": ["man 7 signal"] + }, + { + "id": "103.5-002", + "objective": "103.5", + "type": "fill", + "difficulty": 1, + "question": "Welches Signal sendet `kill `, wenn kein Signal angegeben wird? (Name oder Nummer)", + "answers": ["SIGTERM", "TERM", "15"], + "case_sensitive": false, + "explanation": "Standard ist SIGTERM (15). Erst wenn ein Prozess darauf nicht reagiert, nimmt man SIGKILL (`kill -9`).", + "references": ["man 1 kill"] + }, + { + "id": "103.5-003", + "objective": "103.5", + "type": "single", + "difficulty": 1, + "question": "Ein Skript soll weiterlaufen, nachdem sich der Benutzer abgemeldet hat. Welche Befehlszeile ist dafür gedacht?", + "options": [ + { "id": "a", "text": "`nohup ./skript.sh &`", "correct": true, "explanation": "`nohup` ignoriert SIGHUP und leitet die Ausgabe nach `nohup.out` um; `&` startet im Hintergrund." }, + { "id": "b", "text": "`./skript.sh &`", "correct": false, "explanation": "Hintergrundjobs können beim Abmelden SIGHUP erhalten und beendet werden." }, + { "id": "c", "text": "`bg ./skript.sh`", "correct": false, "explanation": "`bg` setzt einen gestoppten Job fort und erwartet eine Jobnummer, keinen Befehl." }, + { "id": "d", "text": "`nice ./skript.sh`", "correct": false, "explanation": "`nice` ändert nur die Priorität." }, + { "id": "e", "text": "`jobs ./skript.sh`", "correct": false, "explanation": "`jobs` listet Jobs der aktuellen Shell." } + ], + "explanation": "Alternativen: `disown` für laufende Jobs, oder Terminal-Multiplexer wie `screen`/`tmux`, von denen man sich trennen und später wieder verbinden kann.", + "references": ["man 1 nohup"] + }, + { + "id": "103.5-004", + "objective": "103.5", + "type": "single", + "difficulty": 1, + "question": "`jobs` zeigt drei Jobs. Wie holt man Job Nummer 2 in den Vordergrund?", + "options": [ + { "id": "a", "text": "`fg %2`", "correct": true, "explanation": "`fg` holt den angegebenen Job in den Vordergrund; `%2` ist die Jobspezifikation." }, + { "id": "b", "text": "`bg %2`", "correct": false, "explanation": "`bg` setzt einen gestoppten Job im Hintergrund fort." }, + { "id": "c", "text": "`jobs %2`", "correct": false, "explanation": "Zeigt nur den Status von Job 2." }, + { "id": "d", "text": "`kill -CONT %2`", "correct": false, "explanation": "Setzt den Job fort, er bleibt aber im Hintergrund." }, + { "id": "e", "text": "`wait %2`", "correct": false, "explanation": "`wait` wartet auf das Ende des Jobs, ohne ihn in den Vordergrund zu holen." } + ], + "explanation": "Strg+Z stoppt den Vordergrundjob, `bg` lässt ihn im Hintergrund weiterlaufen, `fg` holt ihn zurück.", + "references": ["help fg", "help jobs"] + }, + { + "id": "103.5-005", + "objective": "103.5", + "type": "multi", + "difficulty": 2, + "question": "Mit welchen Befehlen ermittelt man die Prozess-ID(s) laufender `sshd`-Prozesse anhand des Namens?", + "options": [ + { "id": "a", "text": "`pgrep sshd`", "correct": true, "explanation": "`pgrep` gibt die PIDs aller Prozesse aus, deren Name auf das Muster passt." }, + { "id": "b", "text": "`pidof sshd`", "correct": true, "explanation": "`pidof` gibt die PIDs eines Programms mit genau diesem Namen aus." }, + { "id": "c", "text": "`pkill sshd`", "correct": false, "explanation": "`pkill` sendet ein Signal (Standard SIGTERM) an die Prozesse – Vorsicht!" }, + { "id": "d", "text": "`ps -p sshd`", "correct": false, "explanation": "`-p` erwartet eine PID-Liste, keinen Namen (richtig wäre `ps -C sshd`)." }, + { "id": "e", "text": "`top -n sshd`", "correct": false, "explanation": "`-n` legt bei `top` die Anzahl der Durchläufe fest." } + ], + "explanation": "Auch üblich: `ps aux | grep sshd`. `pgrep -a` zeigt zusätzlich die Befehlszeile, `pgrep -u` filtert nach Benutzer.", + "references": ["man 1 pgrep", "man 8 pidof"] + }, + { + "id": "103.5-006", + "objective": "103.5", + "type": "single", + "difficulty": 1, + "question": "Welcher Befehl zeigt kompakt die Laufzeit des Systems, die Anzahl angemeldeter Benutzer und die Load Average der letzten 1, 5 und 15 Minuten?", + "options": [ + { "id": "a", "text": "`uptime`", "correct": true, "explanation": "`uptime` gibt genau diese Zeile aus (Werte aus `/proc/uptime` und `/proc/loadavg`)." }, + { "id": "b", "text": "`free`", "correct": false, "explanation": "`free` zeigt Arbeitsspeicher und Swap." }, + { "id": "c", "text": "`vmstat`", "correct": false, "explanation": "`vmstat` zeigt Prozess-, Speicher-, I/O- und CPU-Statistiken, aber keine Load Average." }, + { "id": "d", "text": "`ps aux`", "correct": false, "explanation": "`ps aux` listet Prozesse." }, + { "id": "e", "text": "`watch`", "correct": false, "explanation": "`watch` führt einen Befehl wiederholt aus und zeigt seine Ausgabe." } + ], + "explanation": "Die Load Average ist die mittlere Zahl laufender bzw. auf CPU oder I/O wartender Prozesse. Sie steht auch in der ersten Zeile von `top` und `w`.", + "references": ["man 1 uptime"] + }, + { + "id": "103.6-001", + "objective": "103.6", + "type": "single", + "difficulty": 1, + "question": "In welchem Bereich liegen Nice-Werte unter Linux, und welcher Wert bedeutet die **höchste** Priorität?", + "options": [ + { "id": "a", "text": "−20 bis 19; −20 ist die höchste Priorität", "correct": true, "explanation": "Je niedriger der Nice-Wert, desto „unfreundlicher“ ist der Prozess, also desto mehr CPU-Zeit bekommt er." }, + { "id": "b", "text": "−20 bis 19; 19 ist die höchste Priorität", "correct": false, "explanation": "19 ist die niedrigste Priorität." }, + { "id": "c", "text": "0 bis 39; 39 ist die höchste Priorität", "correct": false, "explanation": "Nice-Werte sind vorzeichenbehaftet und reichen von −20 bis 19." }, + { "id": "d", "text": "1 bis 99; 99 ist die höchste Priorität", "correct": false, "explanation": "1–99 ist der Bereich der Echtzeitprioritäten, keine Nice-Werte." }, + { "id": "e", "text": "−19 bis 20; 0 ist die höchste Priorität", "correct": false, "explanation": "Falscher Bereich; 0 ist der Standardwert." } + ], + "explanation": "Standard ist 0. `nice` ohne `-n` startet mit +10. In `ps -l` erscheint der Wert in Spalte NI, in `top` als NI.", + "references": ["man 1 nice"] + }, + { + "id": "103.6-002", + "objective": "103.6", + "type": "fill", + "difficulty": 2, + "question": "Geben Sie den Befehl ein, der den Nice-Wert des laufenden Prozesses mit der PID 1234 auf 10 setzt.", + "answers": ["renice -n 10 -p 1234", "renice 10 1234", "renice -n 10 1234", "renice 10 -p 1234", "renice +10 1234", "renice +10 -p 1234", "renice -n +10 -p 1234"], + "explanation": "`renice` ändert laufende Prozesse (`-p` PID, `-u` Benutzer, `-g` Prozessgruppe); `nice` gilt nur beim Starten.", + "references": ["man 1 renice"] + }, + { + "id": "103.6-003", + "objective": "103.6", + "type": "multi", + "difficulty": 2, + "question": "Was darf ein **normaler Benutzer** (ohne besondere Limits) standardmäßig?", + "options": [ + { "id": "a", "text": "Ein Programm mit Nice-Wert 10 starten", "correct": true, "explanation": "Positive Nice-Werte (niedrigere Priorität) darf jeder setzen: `nice -n 10 programm`." }, + { "id": "b", "text": "Den Nice-Wert eines eigenen laufenden Prozesses erhöhen", "correct": true, "explanation": "Die eigene Priorität senken ist erlaubt: `renice -n 15 -p `." }, + { "id": "c", "text": "Ein Programm mit Nice-Wert −5 starten", "correct": false, "explanation": "Negative Nice-Werte erfordern root (bzw. CAP_SYS_NICE)." }, + { "id": "d", "text": "Den Nice-Wert eines Prozesses eines anderen Benutzers ändern", "correct": false, "explanation": "Nur eigene Prozesse; fremde nur als root." }, + { "id": "e", "text": "Den Nice-Wert eines eigenen Prozesses wieder unter den bisherigen Wert senken", "correct": false, "explanation": "Die Priorität wieder anheben darf standardmäßig nur root (Ausnahme: über `RLIMIT_NICE` erlaubte Bereiche)." } + ], + "explanation": "Grundregel: Jeder darf seine Prozesse „netter“ machen, nur root darf Priorität erhöhen.", + "references": ["man 1 renice", "man 2 setpriority"] + }, + { + "id": "103.7-001", + "objective": "103.7", + "type": "single", + "difficulty": 1, + "question": "Welche grep-Option gibt alle Zeilen aus, die **nicht** auf das Muster passen?", + "options": [ + { "id": "a", "text": "`-v`", "correct": true, "explanation": "`-v` (`--invert-match`) kehrt die Auswahl um." }, + { "id": "b", "text": "`-i`", "correct": false, "explanation": "`-i` ignoriert Groß-/Kleinschreibung." }, + { "id": "c", "text": "`-c`", "correct": false, "explanation": "`-c` gibt nur die Anzahl passender Zeilen aus." }, + { "id": "d", "text": "`-l`", "correct": false, "explanation": "`-l` gibt nur die Namen der Dateien mit Treffern aus." }, + { "id": "e", "text": "`-n`", "correct": false, "explanation": "`-n` stellt die Zeilennummer voran." } + ], + "explanation": "Wichtige Optionen: `-E` erweiterte RE, `-F` feste Zeichenkette, `-r` rekursiv, `-w` ganzes Wort, `-o` nur den Treffer.", + "references": ["man 1 grep"] + }, + { + "id": "103.7-002", + "objective": "103.7", + "type": "single", + "difficulty": 2, + "question": "Welcher Befehl gibt eine Konfigurationsdatei **ohne** Kommentarzeilen (beginnen mit `#`) und **ohne** Leerzeilen aus?", + "options": [ + { "id": "a", "text": "`grep -Ev '^(#|$)' datei`", "correct": true, "explanation": "Das Muster passt auf Zeilen, die mit `#` beginnen oder leer sind; `-v` kehrt um." }, + { "id": "b", "text": "`grep -v '#' datei`", "correct": false, "explanation": "Entfernt auch Zeilen mit `#` in der Mitte und lässt Leerzeilen stehen." }, + { "id": "c", "text": "`grep -E '^#|^$' datei`", "correct": false, "explanation": "Gibt nur Kommentar- und Leerzeilen aus." }, + { "id": "d", "text": "`grep -v '^#$' datei`", "correct": false, "explanation": "Entfernt nur Zeilen, die ausschließlich aus `#` bestehen." }, + { "id": "e", "text": "`grep -cv '^#' datei`", "correct": false, "explanation": "`-c` gibt nur eine Anzahl aus." } + ], + "explanation": "Anker: `^` Zeilenanfang, `$` Zeilenende; `^$` ist eine leere Zeile. `|` (Alternative) und `( )` erfordern ERE (`-E`) oder in BRE `\\|` und `\\( \\)`.", + "references": ["man 7 regex", "man 1 grep"] + }, + { + "id": "103.7-003", + "objective": "103.7", + "type": "fill", + "difficulty": 2, + "question": "Geben Sie den sed-Befehl ein, der in der Datei `datei` **jedes** Vorkommen von `foo` durch `bar` ersetzt und das Ergebnis auf stdout ausgibt.", + "answers": ["sed 's/foo/bar/g' datei", "sed \"s/foo/bar/g\" datei", "sed s/foo/bar/g datei", "sed -e 's/foo/bar/g' datei", "sed -e \"s/foo/bar/g\" datei"], + "explanation": "`s/alt/neu/` ersetzt das erste Vorkommen je Zeile, das Flag `g` alle. Mit `-i` wird die Datei selbst geändert.", + "references": ["man 1 sed"] + }, + { + "id": "103.7-004", + "objective": "103.7", + "type": "multi", + "difficulty": 2, + "question": "Welche Aussagen zu regulären Ausdrücken (grep) treffen zu?", + "options": [ + { "id": "a", "text": "`.` passt auf genau ein beliebiges Zeichen.", "correct": true, "explanation": "Für einen wörtlichen Punkt: `\\.`." }, + { "id": "b", "text": "`*` bedeutet: das vorherige Element null- oder mehrmals.", "correct": true, "explanation": "`a*` passt auch auf die leere Zeichenkette; anders als beim Shell-Globbing." }, + { "id": "c", "text": "In Basic RE (grep ohne `-E`) bedeutet `+` „ein- oder mehrmals“.", "correct": false, "explanation": "In BRE ist `+` ein normales Zeichen; GNU grep versteht dort `\\+`. Mit `-E` ist `+` ein Quantor." }, + { "id": "d", "text": "`$` verankert am Zeilenanfang.", "correct": false, "explanation": "`$` ist das Zeilenende, `^` der Zeilenanfang." }, + { "id": "e", "text": "`[^a-z]` passt auf einen Kleinbuchstaben.", "correct": false, "explanation": "`^` am Anfang einer Klammer negiert: ein Zeichen, das **kein** Kleinbuchstabe ist." } + ], + "explanation": "ERE-Zusätze: `+`, `?`, `{n,m}`, `|`, `( )`. Zeichenklassen: `[[:digit:]]`, `[[:space:]]`, `[[:alpha:]]`.", + "references": ["man 7 regex"] + }, + { + "id": "103.8-001", + "objective": "103.8", + "type": "single", + "difficulty": 1, + "question": "Mit welcher Eingabe im Befehlsmodus von vi speichert man die Datei und beendet den Editor?", + "options": [ + { "id": "a", "text": "`:wq`", "correct": true, "explanation": "`:w` schreibt, `:q` beendet. Gleichwertig: `:x` und `ZZ`." }, + { "id": "b", "text": "`:q!`", "correct": false, "explanation": "Beendet ohne zu speichern und verwirft Änderungen." }, + { "id": "c", "text": "`:w`", "correct": false, "explanation": "Speichert nur, vi bleibt offen." }, + { "id": "d", "text": "`ZQ`", "correct": false, "explanation": "`ZQ` entspricht `:q!`, also beenden ohne Speichern." }, + { "id": "e", "text": "`:e!`", "correct": false, "explanation": "Lädt die Datei neu und verwirft ungespeicherte Änderungen." } + ], + "explanation": "Mit Esc kommt man aus dem Einfügemodus in den Befehlsmodus. Doppelpunkt-Befehle sind Ex-Befehle.", + "references": ["man 1 vim", ":help ZZ"] + }, + { + "id": "103.8-002", + "objective": "103.8", + "type": "fill", + "difficulty": 1, + "question": "Welche Tastenfolge löscht in vi im Befehlsmodus die **aktuelle Zeile** (und legt sie in den Puffer)?", + "answers": ["dd"], + "explanation": "`dd` löscht die Zeile, `5dd` fünf Zeilen, `yy` kopiert, `p` fügt ein, `u` macht rückgängig.", + "references": [":help dd"] + }, + { + "id": "103.8-003", + "objective": "103.8", + "type": "single", + "difficulty": 1, + "question": "Wie sucht man in vi im Befehlsmodus **vorwärts** nach dem Wort `Port`?", + "options": [ + { "id": "a", "text": "`/Port`", "correct": true, "explanation": "`/` sucht vorwärts; `n` springt zum nächsten, `N` zum vorherigen Treffer." }, + { "id": "b", "text": "`?Port`", "correct": false, "explanation": "`?` sucht rückwärts." }, + { "id": "c", "text": "`:s/Port`", "correct": false, "explanation": "`:s` ist das Ersetzen in der aktuellen Zeile." }, + { "id": "d", "text": "`fPort`", "correct": false, "explanation": "`f` springt zum nächsten Vorkommen eines einzelnen Zeichens in der aktuellen Zeile (hier `P`)." }, + { "id": "e", "text": "`nPort`", "correct": false, "explanation": "`n` wiederholt die letzte Suche; die folgenden Zeichen würden als weitere Befehle gelesen." } + ], + "explanation": "Suchen und ersetzen in der ganzen Datei: `:%s/alt/neu/g`.", + "references": [":help /", ":help n"] + }, + { + "id": "103.8-004", + "objective": "103.8", + "type": "multi", + "difficulty": 1, + "question": "Welche Tasten wechseln in vi aus dem Befehlsmodus in den **Einfügemodus**?", + "options": [ + { "id": "a", "text": "`i`", "correct": true, "explanation": "Einfügen vor dem Cursor." }, + { "id": "b", "text": "`o`", "correct": true, "explanation": "Öffnet eine neue Zeile unterhalb und wechselt in den Einfügemodus." }, + { "id": "c", "text": "`x`", "correct": false, "explanation": "Löscht das Zeichen unter dem Cursor; man bleibt im Befehlsmodus." }, + { "id": "d", "text": "`p`", "correct": false, "explanation": "Fügt den Pufferinhalt ein (paste); man bleibt im Befehlsmodus." }, + { "id": "e", "text": "`u`", "correct": false, "explanation": "Macht die letzte Änderung rückgängig." } + ], + "explanation": "Einfügemodus auch mit `a`/`A` (nach Cursor/Zeilenende), `I` (Zeilenanfang), `O` (neue Zeile oberhalb). Der Standard-Editor wird über `EDITOR`/`VISUAL` festgelegt.", + "references": [":help insert"] + } + ] +} diff --git a/simulator/data/lpic1_101/questions_104.json b/simulator/data/lpic1_101/questions_104.json new file mode 100644 index 0000000..55aa76b --- /dev/null +++ b/simulator/data/lpic1_101/questions_104.json @@ -0,0 +1,327 @@ +{ + "$schema": "../schema/questions.schema.json", + "format": "lpic-sim-questions", + "meta": { + "file": "questions_104.json", + "brief": "Fragen zu Topic 104 Geräte, Linux-Dateisysteme, FHS (LPIC-1 101-500, Objectives 5.0)", + "author": "Björn Runden ", + "owner": "Björn Runden ", + "assist": "KI-unterstützt (Claude Opus 5.5), geprüft von Björn Runden ", + "version": "0.1.0 (29.10.2026)" + }, + "exam": "lpic1-101", + "questions": [ + { + "id": "104.1-001", + "objective": "104.1", + "type": "single", + "difficulty": 1, + "question": "Auf der ersten Partition der zweiten Festplatte (`/dev/sdb1`) soll ein ext4-Dateisystem angelegt werden. Welcher Befehl ist korrekt?", + "options": [ + { "id": "a", "text": "`mkfs.ext4 /dev/sdb1`", "correct": true, "explanation": "`mkfs.ext4` (gleichwertig `mkfs -t ext4` oder `mke2fs -t ext4`) legt das Dateisystem an." }, + { "id": "b", "text": "`mkfs.ext4 /dev/sdb`", "correct": false, "explanation": "Das würde die ganze Platte ohne Partitionstabelle formatieren, nicht die erste Partition." }, + { "id": "c", "text": "`mount -t ext4 /dev/sdb1`", "correct": false, "explanation": "`mount` hängt ein vorhandenes Dateisystem ein, es legt keines an." }, + { "id": "d", "text": "`fdisk -t ext4 /dev/sdb1`", "correct": false, "explanation": "`fdisk` bearbeitet Partitionstabellen, legt aber keine Dateisysteme an." }, + { "id": "e", "text": "`tune2fs -j /dev/sdb1`", "correct": false, "explanation": "`tune2fs -j` fügt einem bestehenden ext2 ein Journal hinzu." } + ], + "explanation": "Reihenfolge: partitionieren (`fdisk`, `gdisk`, `parted`), Dateisystem anlegen (`mkfs.*`), einhängen (`mount`), dauerhaft in `/etc/fstab`.", + "references": ["man 8 mkfs", "man 8 mke2fs"] + }, + { + "id": "104.1-002", + "objective": "104.1", + "type": "fill", + "difficulty": 1, + "question": "Die Partition `/dev/sdc2` soll als Swap-Bereich vorbereitet (initialisiert) werden. Geben Sie den vollständigen Befehl ein.", + "answers": ["mkswap /dev/sdc2"], + "explanation": "`mkswap` schreibt die Swap-Signatur; aktiviert wird mit `swapon /dev/sdc2`, dauerhaft über einen fstab-Eintrag vom Typ `swap`.", + "references": ["man 8 mkswap", "man 8 swapon"] + }, + { + "id": "104.1-003", + "objective": "104.1", + "type": "multi", + "difficulty": 2, + "question": "Welche Werkzeuge können GPT-Partitionstabellen anlegen und bearbeiten?", + "options": [ + { "id": "a", "text": "`gdisk`", "correct": true, "explanation": "`gdisk` ist ein fdisk-ähnliches Werkzeug speziell für GPT." }, + { "id": "b", "text": "`parted`", "correct": true, "explanation": "`parted` unterstützt MBR (msdos) und GPT und kann auch skriptgesteuert arbeiten." }, + { "id": "c", "text": "`fdisk` (aktuelles util-linux)", "correct": true, "explanation": "Aktuelle `fdisk`-Versionen aus util-linux unterstützen GPT (Befehl `g` legt eine leere GPT an)." }, + { "id": "d", "text": "`blkid`", "correct": false, "explanation": "`blkid` zeigt nur Attribute wie UUID, LABEL und TYPE an." }, + { "id": "e", "text": "`mkswap`", "correct": false, "explanation": "`mkswap` initialisiert einen Swap-Bereich, partitioniert aber nicht." } + ], + "explanation": "MBR: höchstens 4 primäre Partitionen (bzw. 3 primäre und eine erweiterte), max. 2 TiB. GPT: standardmäßig 128 Partitionen, sehr große Platten, Sicherungskopie der Tabelle am Plattenende.", + "references": ["man 8 gdisk", "man 8 parted", "man 8 fdisk"] + }, + { + "id": "104.2-001", + "objective": "104.2", + "type": "single", + "difficulty": 1, + "question": "Was ist zu beachten, bevor man ein ext4-Dateisystem mit `fsck` prüft und repariert?", + "options": [ + { "id": "a", "text": "Das Dateisystem darf nicht (oder höchstens nur lesend) eingehängt sein.", "correct": true, "explanation": "Eine Reparatur an einem schreibend eingehängten Dateisystem kann es zerstören." }, + { "id": "b", "text": "Das Dateisystem muss schreibend eingehängt sein.", "correct": false, "explanation": "Genau das sollte man vermeiden." }, + { "id": "c", "text": "`fsck` funktioniert nur mit XFS.", "correct": false, "explanation": "`fsck` ist ein Frontend und ruft für ext4 `e2fsck` auf; für XFS ist es gerade nicht zuständig." }, + { "id": "d", "text": "Vorher muss `mkfs` ausgeführt werden.", "correct": false, "explanation": "`mkfs` würde ein neues, leeres Dateisystem anlegen und alle Daten verlieren." }, + { "id": "e", "text": "`fsck` darf nur auf Swap-Partitionen angewendet werden.", "correct": false, "explanation": "Swap enthält kein Dateisystem und wird nicht mit `fsck` geprüft." } + ], + "explanation": "Die Root-Partition prüft man daher beim Start (sechstes Feld in `/etc/fstab`) oder aus einem Rettungssystem. `tune2fs` stellt die automatische Prüfung nach Anzahl Mounts/Zeit ein.", + "references": ["man 8 fsck", "man 8 e2fsck"] + }, + { + "id": "104.2-002", + "objective": "104.2", + "type": "single", + "difficulty": 2, + "question": "Welches Werkzeug repariert ein beschädigtes **XFS**-Dateisystem?", + "options": [ + { "id": "a", "text": "`xfs_repair`", "correct": true, "explanation": "`xfs_repair` prüft und repariert XFS; mit `-n` nur prüfen, ohne zu ändern." }, + { "id": "b", "text": "`xfs_fsr`", "correct": false, "explanation": "`xfs_fsr` defragmentiert ein eingehängtes XFS." }, + { "id": "c", "text": "`fsck.xfs`", "correct": false, "explanation": "`fsck.xfs` tut absichtlich nichts und verweist auf `xfs_repair`; XFS prüft sich beim Mounten über das Journal." }, + { "id": "d", "text": "`e2fsck`", "correct": false, "explanation": "`e2fsck` ist für ext2/3/4." }, + { "id": "e", "text": "`xfs_info`", "correct": false, "explanation": "`xfs_info` zeigt nur die Geometrie eines XFS an." } + ], + "explanation": "Weitere XFS-Werkzeuge: `xfs_db` (Debugger), `xfs_growfs` (vergrößern). ext-Werkzeuge: `e2fsck`, `tune2fs`, `dumpe2fs`, `debugfs`.", + "references": ["man 8 xfs_repair"] + }, + { + "id": "104.2-003", + "objective": "104.2", + "type": "multi", + "difficulty": 1, + "question": "Welche Befehle helfen, den **Speicherplatz** auf Dateisystemen zu überwachen?", + "options": [ + { "id": "a", "text": "`df -h`", "correct": true, "explanation": "Belegter und freier Platz je eingehängtem Dateisystem; `df -i` zeigt die Inodes." }, + { "id": "b", "text": "`du -sh /var/log`", "correct": true, "explanation": "Summe des belegten Platzes eines Verzeichnisbaums." }, + { "id": "c", "text": "`free -h`", "correct": false, "explanation": "`free` zeigt Arbeitsspeicher und Swap, keinen Plattenplatz." }, + { "id": "d", "text": "`blkid`", "correct": false, "explanation": "`blkid` zeigt UUID, Label und Typ, keine Belegung." }, + { "id": "e", "text": "`mount`", "correct": false, "explanation": "`mount` ohne Argumente listet eingehängte Dateisysteme mit Optionen, ohne Belegung." } + ], + "explanation": "Ein Dateisystem kann auch „voll“ sein, wenn noch Platz frei ist, aber keine Inodes mehr – dann hilft `df -i`.", + "references": ["man 1 df", "man 1 du"] + }, + { + "id": "104.3-001", + "objective": "104.3", + "type": "single", + "difficulty": 1, + "question": "In welcher Reihenfolge stehen die sechs Felder eines Eintrags in `/etc/fstab`?", + "options": [ + { "id": "a", "text": "Gerät · Einhängepunkt · Dateisystemtyp · Optionen · dump · fsck-Reihenfolge", "correct": true, "explanation": "Beispiel: `UUID=… /home ext4 defaults 0 2`." }, + { "id": "b", "text": "Einhängepunkt · Gerät · Dateisystemtyp · Optionen · dump · fsck-Reihenfolge", "correct": false, "explanation": "Das Gerät steht zuerst, danach der Einhängepunkt." }, + { "id": "c", "text": "Gerät · Dateisystemtyp · Einhängepunkt · Optionen · dump · fsck-Reihenfolge", "correct": false, "explanation": "Der Einhängepunkt kommt vor dem Typ." }, + { "id": "d", "text": "Gerät · Einhängepunkt · Optionen · Dateisystemtyp · fsck-Reihenfolge · dump", "correct": false, "explanation": "Typ vor Optionen; dump (5.) vor fsck-Reihenfolge (6.)." }, + { "id": "e", "text": "Gerät · Einhängepunkt · Dateisystemtyp · Benutzer · Optionen · fsck-Reihenfolge", "correct": false, "explanation": "Ein Benutzerfeld gibt es nicht; `user`/`users` sind Optionen im vierten Feld." } + ], + "explanation": "Sechstes Feld: 0 = nicht prüfen, 1 = Root-Dateisystem, 2 = andere Dateisysteme. systemd erzeugt aus fstab automatisch `.mount`-Units.", + "references": ["man 5 fstab"] + }, + { + "id": "104.3-002", + "objective": "104.3", + "type": "fill", + "difficulty": 1, + "question": "Mit welchem Befehl (mit Option) hängt man alle in `/etc/fstab` eingetragenen Dateisysteme ein, die noch nicht eingehängt sind (außer denen mit `noauto`)?", + "answers": ["mount -a", "mount --all"], + "explanation": "`mount -a` eignet sich auch zum Testen eines neuen fstab-Eintrags vor dem nächsten Neustart.", + "references": ["man 8 mount"] + }, + { + "id": "104.3-003", + "objective": "104.3", + "type": "single", + "difficulty": 2, + "question": "Welche Zeile ist ein gültiger `/etc/fstab`-Eintrag, der ein Dateisystem anhand seiner UUID nach `/data` einhängt?", + "options": [ + { "id": "a", "text": "`UUID=3f1c9a2e-77b0-4d6e-9c55-2b8e1d0a4f10 /data ext4 defaults 0 2`", "correct": true, "explanation": "Alle sechs Felder in der richtigen Reihenfolge; `UUID=` ist eine gültige Gerätekennung." }, + { "id": "b", "text": "`/data UUID=3f1c9a2e-77b0-4d6e-9c55-2b8e1d0a4f10 ext4 defaults 0 2`", "correct": false, "explanation": "Gerät und Einhängepunkt sind vertauscht." }, + { "id": "c", "text": "`UUID:3f1c9a2e-77b0-4d6e-9c55-2b8e1d0a4f10 /data ext4 defaults 0 2`", "correct": false, "explanation": "Die Schreibweise ist `UUID=` mit Gleichheitszeichen." }, + { "id": "d", "text": "`UUID=3f1c9a2e-77b0-4d6e-9c55-2b8e1d0a4f10 /data defaults ext4 0 2`", "correct": false, "explanation": "Typ und Optionen sind vertauscht." }, + { "id": "e", "text": "`/dev/disk/by-label/3f1c9a2e-77b0-4d6e-9c55-2b8e1d0a4f10 /data ext4 defaults 0 2`", "correct": false, "explanation": "`by-label` enthält Labels, keine UUIDs; der Pfad wäre `/dev/disk/by-uuid/…`." } + ], + "explanation": "UUIDs und Labels sind stabil, Gerätenamen wie `/dev/sdb1` können sich beim Hinzufügen von Platten ändern. Auch `LABEL=…` ist erlaubt.", + "references": ["man 5 fstab"] + }, + { + "id": "104.3-004", + "objective": "104.3", + "type": "multi", + "difficulty": 1, + "question": "Mit welchen Befehlen kann man die UUID des Dateisystems auf `/dev/sdb1` anzeigen?", + "options": [ + { "id": "a", "text": "`blkid /dev/sdb1`", "correct": true, "explanation": "`blkid` zeigt UUID, TYPE und ggf. LABEL." }, + { "id": "b", "text": "`lsblk -f /dev/sdb1`", "correct": true, "explanation": "`-f` ergänzt die Spalten FSTYPE, LABEL und UUID." }, + { "id": "c", "text": "`mount -U /dev/sdb1`", "correct": false, "explanation": "`mount -U ` hängt anhand einer UUID ein, zeigt aber keine an." }, + { "id": "d", "text": "`df -u /dev/sdb1`", "correct": false, "explanation": "`df` hat keine Option zur UUID-Anzeige." }, + { "id": "e", "text": "`swapon -s`", "correct": false, "explanation": "`swapon -s` listet aktive Swap-Bereiche." } + ], + "explanation": "Die UUIDs stehen auch als Symlinks unter `/dev/disk/by-uuid/`.", + "references": ["man 8 blkid", "man 8 lsblk"] + }, + { + "id": "104.5-001", + "objective": "104.5", + "type": "single", + "difficulty": 1, + "question": "Welche Rechte hat eine Datei nach `chmod 750 datei`?", + "options": [ + { "id": "a", "text": "`rwxr-x---`", "correct": true, "explanation": "7 = rwx (Eigentümer), 5 = r-x (Gruppe), 0 = --- (andere)." }, + { "id": "b", "text": "`rwxrw----`", "correct": false, "explanation": "Das wäre 760." }, + { "id": "c", "text": "`rw-r-x---`", "correct": false, "explanation": "Das wäre 650." }, + { "id": "d", "text": "`rwxr-xr-x`", "correct": false, "explanation": "Das wäre 755." }, + { "id": "e", "text": "`r-xrwx---`", "correct": false, "explanation": "Das wäre 570." } + ], + "explanation": "Wertigkeit: r = 4, w = 2, x = 1, je Stelle für Eigentümer, Gruppe, andere addiert.", + "references": ["man 1 chmod"] + }, + { + "id": "104.5-002", + "objective": "104.5", + "type": "fill", + "difficulty": 1, + "question": "Welcher oktale Modus (drei Ziffern) entspricht den Rechten `rw-r--r--`?", + "answers": ["644", "0644"], + "explanation": "rw- = 4+2 = 6, r-- = 4, r-- = 4. Typisch für normale Dateien; Verzeichnisse haben meist 755.", + "references": ["man 1 chmod"] + }, + { + "id": "104.5-003", + "objective": "104.5", + "type": "single", + "difficulty": 2, + "question": "Welche Wirkung hat das SUID-Bit auf eine ausführbare Datei (z. B. `/usr/bin/passwd`)?", + "options": [ + { "id": "a", "text": "Das Programm läuft mit den Rechten des Datei-Eigentümers statt mit denen des Aufrufers.", "correct": true, "explanation": "Deshalb kann `passwd` (Eigentümer root) `/etc/shadow` ändern." }, + { "id": "b", "text": "Neue Dateien im Verzeichnis erben die Gruppe des Verzeichnisses.", "correct": false, "explanation": "Das ist die Wirkung des SGID-Bits auf ein Verzeichnis." }, + { "id": "c", "text": "Nur der Eigentümer darf Dateien im Verzeichnis löschen.", "correct": false, "explanation": "Das ist das Sticky-Bit auf Verzeichnissen, z. B. `/tmp`." }, + { "id": "d", "text": "Die Datei kann nicht mehr geändert oder gelöscht werden.", "correct": false, "explanation": "Das beschreibt das immutable-Attribut (`chattr +i`)." }, + { "id": "e", "text": "Das Programm darf nur von root ausgeführt werden.", "correct": false, "explanation": "Ausführen dürfen alle mit x-Recht; SUID ändert die effektive Benutzer-ID." } + ], + "explanation": "Setzen: `chmod u+s datei` oder oktal 4xxx (SGID 2xxx, Sticky 1xxx). In `ls -l` erscheint `s` statt `x` beim Eigentümer.", + "references": ["man 1 chmod", "man 7 credentials"] + }, + { + "id": "104.5-004", + "objective": "104.5", + "type": "single", + "difficulty": 2, + "question": "Die umask ist `027`. Welche Rechte erhält eine neu angelegte **reguläre Datei** (z. B. mit `touch`)?", + "options": [ + { "id": "a", "text": "`640` (`rw-r-----`)", "correct": true, "explanation": "Dateien starten mit 666; davon werden 027 maskiert → 640." }, + { "id": "b", "text": "`750` (`rwxr-x---`)", "correct": false, "explanation": "Das erhält ein neues **Verzeichnis** (777 − 027)." }, + { "id": "c", "text": "`027` (`----w-rwx`)", "correct": false, "explanation": "Die umask gibt an, was entfernt wird, nicht die Rechte selbst." }, + { "id": "d", "text": "`751` (`rwxr-x--x`)", "correct": false, "explanation": "Das passt weder zu Dateien noch zu Verzeichnissen mit dieser umask." }, + { "id": "e", "text": "`600` (`rw-------`)", "correct": false, "explanation": "Das ergäbe die umask 077." } + ], + "explanation": "Programme erzeugen Dateien üblicherweise mit 666 und Verzeichnisse mit 777; die umask entfernt Bits. Anzeigen/Setzen mit `umask`, symbolisch mit `umask -S`.", + "references": ["help umask"] + }, + { + "id": "104.5-005", + "objective": "104.5", + "type": "multi", + "difficulty": 1, + "question": "Mit welchen Befehlen ändert man die **Gruppe** der Datei `bericht.txt` auf `team`?", + "options": [ + { "id": "a", "text": "`chgrp team bericht.txt`", "correct": true, "explanation": "`chgrp` ändert nur die Gruppe." }, + { "id": "b", "text": "`chown :team bericht.txt`", "correct": true, "explanation": "Bei `chown` ändert die Form `:gruppe` nur die Gruppe (auch `.gruppe` wird noch akzeptiert)." }, + { "id": "c", "text": "`chmod g=team bericht.txt`", "correct": false, "explanation": "`chmod g=` setzt Rechte der Gruppe; `team` ist keine gültige Rechteangabe." }, + { "id": "d", "text": "`newgrp team bericht.txt`", "correct": false, "explanation": "`newgrp` startet eine Shell mit anderer primärer Gruppe; es ändert keine Datei." }, + { "id": "e", "text": "`usermod -g team bericht.txt`", "correct": false, "explanation": "`usermod -g` ändert die primäre Gruppe eines Benutzers." } + ], + "explanation": "`chown benutzer:gruppe datei` ändert beides; `-R` arbeitet rekursiv. Normale Benutzer dürfen nur auf Gruppen wechseln, in denen sie Mitglied sind.", + "references": ["man 1 chgrp", "man 1 chown"] + }, + { + "id": "104.6-001", + "objective": "104.6", + "type": "single", + "difficulty": 1, + "question": "Es soll ein symbolischer Link `aktuell` angelegt werden, der auf `release-2.4` zeigt. Welcher Befehl ist korrekt?", + "options": [ + { "id": "a", "text": "`ln -s release-2.4 aktuell`", "correct": true, "explanation": "Reihenfolge wie bei `cp`: erst Ziel (Original), dann der Name des Links." }, + { "id": "b", "text": "`ln -s aktuell release-2.4`", "correct": false, "explanation": "Vertauscht: Das legt `release-2.4` als Link auf `aktuell` an (bzw. scheitert, wenn es existiert)." }, + { "id": "c", "text": "`ln release-2.4 aktuell`", "correct": false, "explanation": "Ohne `-s` entsteht ein Hardlink; für Verzeichnisse ist das nicht erlaubt." }, + { "id": "d", "text": "`link -s release-2.4 aktuell`", "correct": false, "explanation": "`link` legt nur Hardlinks an und kennt kein `-s`." }, + { "id": "e", "text": "`mklink aktuell release-2.4`", "correct": false, "explanation": "`mklink` ist ein Windows-Befehl." } + ], + "explanation": "Ein bestehenden Link umsetzen: `ln -sfn neues-ziel aktuell`.", + "references": ["man 1 ln"] + }, + { + "id": "104.6-002", + "objective": "104.6", + "type": "multi", + "difficulty": 2, + "question": "Welche Aussagen über **Hardlinks** treffen zu?", + "options": [ + { "id": "a", "text": "Alle Hardlinks einer Datei verweisen auf denselben Inode.", "correct": true, "explanation": "Ein Hardlink ist nur ein weiterer Verzeichniseintrag für denselben Inode." }, + { "id": "b", "text": "Hardlinks können nicht über Dateisystemgrenzen hinweg angelegt werden.", "correct": true, "explanation": "Inode-Nummern sind nur innerhalb eines Dateisystems eindeutig." }, + { "id": "c", "text": "Normale Benutzer können Hardlinks auf Verzeichnisse anlegen.", "correct": false, "explanation": "Hardlinks auf Verzeichnisse sind nicht erlaubt (Schleifen im Baum)." }, + { "id": "d", "text": "Wird die ursprüngliche Datei gelöscht, ist der Hardlink defekt.", "correct": false, "explanation": "Die Daten bleiben, bis der Linkzähler 0 erreicht; defekt werden nur Symlinks." }, + { "id": "e", "text": "Ein Hardlink hat eigene, vom Original unabhängige Zugriffsrechte.", "correct": false, "explanation": "Rechte stehen im Inode und gelten für alle Namen gemeinsam." } + ], + "explanation": "Der Linkzähler steht in `ls -l` in der zweiten Spalte. Symlinks haben einen eigenen Inode und enthalten den Pfad zum Ziel.", + "references": ["man 1 ln", "man 7 inode"] + }, + { + "id": "104.6-003", + "objective": "104.6", + "type": "fill", + "difficulty": 1, + "question": "Welcher Befehl mit Option zeigt beim Auflisten eines Verzeichnisses die **Inode-Nummern** der Dateien an?", + "answers": ["ls -i", "ls --inode", "ls -li", "ls -il"], + "explanation": "Gleiche Inode-Nummer = Hardlinks derselben Datei. Alternativ zeigt `stat datei` den Inode einer einzelnen Datei.", + "references": ["man 1 ls"] + }, + { + "id": "104.7-001", + "objective": "104.7", + "type": "single", + "difficulty": 1, + "question": "Wo gehören laut Filesystem Hierarchy Standard (FHS) die Protokolldateien des Systems hin?", + "options": [ + { "id": "a", "text": "`/var/log`", "correct": true, "explanation": "`/var` enthält variable Daten; `/var/log` die Protokolle." }, + { "id": "b", "text": "`/usr/log`", "correct": false, "explanation": "`/usr` ist für weitgehend statische, teilbare Daten gedacht und kann nur lesend eingehängt sein." }, + { "id": "c", "text": "`/etc/log`", "correct": false, "explanation": "`/etc` ist für hostspezifische Konfiguration gedacht." }, + { "id": "d", "text": "`/opt/log`", "correct": false, "explanation": "`/opt` ist für zusätzliche Softwarepakete gedacht; variable Daten solcher Pakete gehören nach `/var/opt`." }, + { "id": "e", "text": "`/srv/log`", "correct": false, "explanation": "`/srv` enthält Daten, die das System als Dienst ausliefert (z. B. Web, FTP)." } + ], + "explanation": "Weitere FHS-Orte: `/var/spool` (Warteschlangen), `/var/cache`, `/var/lib` (Zustandsdaten), `/tmp` (temporär), `/usr/local` (lokal installierte Software).", + "references": ["man 7 hier", "https://refspecs.linuxfoundation.org/fhs.shtml"] + }, + { + "id": "104.7-002", + "objective": "104.7", + "type": "single", + "difficulty": 1, + "question": "`locate` findet eine soeben angelegte Datei nicht. Was ist zu tun?", + "options": [ + { "id": "a", "text": "Die Datenbank mit `updatedb` aktualisieren", "correct": true, "explanation": "`locate` durchsucht eine Datenbank, die meist täglich per Cron/Timer mit `updatedb` erneuert wird." }, + { "id": "b", "text": "`hash -r` ausführen", "correct": false, "explanation": "`hash -r` leert die Tabelle der Programmpfade der Shell." }, + { "id": "c", "text": "`ldconfig` ausführen", "correct": false, "explanation": "`ldconfig` aktualisiert den Cache der Shared Libraries." }, + { "id": "d", "text": "`mandb` ausführen", "correct": false, "explanation": "`mandb` aktualisiert den Index der Manpages." }, + { "id": "e", "text": "`whereis -u` ausführen", "correct": false, "explanation": "`whereis -u` sucht nach „ungewöhnlichen“ Einträgen; mit der locate-Datenbank hat es nichts zu tun." } + ], + "explanation": "Welche Pfade `updatedb` auslässt, steht in `/etc/updatedb.conf` (z. B. `PRUNEPATHS`, `PRUNEFS`). `find` durchsucht dagegen live das Dateisystem.", + "references": ["man 8 updatedb", "man 5 updatedb.conf"] + }, + { + "id": "104.7-003", + "objective": "104.7", + "type": "multi", + "difficulty": 1, + "question": "Mit welchen Befehlen findet man heraus, wo das **Programm** `ls` im Dateisystem liegt?", + "options": [ + { "id": "a", "text": "`which ls`", "correct": true, "explanation": "`which` durchsucht den `PATH` und gibt den ersten Treffer aus." }, + { "id": "b", "text": "`whereis ls`", "correct": true, "explanation": "`whereis` zeigt Programm, Quellen und Manpages zu einem Befehl." }, + { "id": "c", "text": "`whatis ls`", "correct": false, "explanation": "`whatis` zeigt die Kurzbeschreibung aus der Manpage." }, + { "id": "d", "text": "`file ls`", "correct": false, "explanation": "`file` bestimmt den Typ einer Datei; `ls` würde im aktuellen Verzeichnis gesucht." }, + { "id": "e", "text": "`stat ls`", "correct": false, "explanation": "`stat` zeigt Inode-Daten einer Datei `ls` im aktuellen Verzeichnis." } + ], + "explanation": "Für Shell-Aliase und Builtins hilft `type`; für beliebige Dateien `find` (live) oder `locate` (Datenbank).", + "references": ["man 1 which", "man 1 whereis"] + } + ] +} diff --git a/simulator/data/lpic1_102/exam.json b/simulator/data/lpic1_102/exam.json new file mode 100644 index 0000000..1feb975 --- /dev/null +++ b/simulator/data/lpic1_102/exam.json @@ -0,0 +1,81 @@ +{ + "meta": { + "file": "exam.json", + "brief": "Prüfungsdefinition LPIC-1 102-500: Eckdaten, Topics, Objectives mit Gewichtung", + "author": "Björn Runden ", + "owner": "Björn Runden ", + "assist": "KI-unterstützt (Claude Opus 5.5), geprüft von Björn Runden ", + "version": "0.1.0 (29.10.2026)" + }, + "exam": { + "id": "lpic1-102", + "level": "LPIC-1", + "title": "LPIC-1 Prüfung 102", + "code": "102-500", + "lang": "de", + "order": 102, + "objectives_version": "5.0", + "objectives_source": "https://www.lpi.org/de/exam-101-102-objectives/", + "objectives_retrieved": "2026-10-29", + "questions": 60, + "duration_min": 90, + "pass_percent": 65 + }, + "topics": [ + { + "id": "105", + "title": "Shells und Shell-Skripte", + "objectives": [ + { "id": "105.1", "title": "Die Shell-Umgebung anpassen und verwenden", "weight": 4 }, + { "id": "105.2", "title": "Einfache Skripte anpassen oder schreiben", "weight": 4 } + ] + }, + { + "id": "106", + "title": "Benutzerschnittstellen und Desktops", + "objectives": [ + { "id": "106.1", "title": "X11 installieren und konfigurieren", "weight": 2 }, + { "id": "106.2", "title": "Grafische Desktops", "weight": 1 }, + { "id": "106.3", "title": "Barrierefreiheit", "weight": 1 } + ] + }, + { + "id": "107", + "title": "Administrative Aufgaben", + "objectives": [ + { "id": "107.1", "title": "Benutzer- und Gruppenkonten und dazugehörige Systemdateien verwalten", "weight": 5 }, + { "id": "107.2", "title": "Systemadministrationsaufgaben durch Einplanen von Jobs automatisieren", "weight": 4 }, + { "id": "107.3", "title": "Lokalisierung und Internationalisierung", "weight": 3 } + ] + }, + { + "id": "108", + "title": "Grundlegende Systemdienste", + "objectives": [ + { "id": "108.1", "title": "Die Systemzeit verwalten", "weight": 3 }, + { "id": "108.2", "title": "Systemprotokollierung", "weight": 4 }, + { "id": "108.3", "title": "Grundlagen von Mail Transfer Agents (MTA)", "weight": 3 }, + { "id": "108.4", "title": "Drucker und Druckvorgänge verwalten", "weight": 2 } + ] + }, + { + "id": "109", + "title": "Netzwerkgrundlagen", + "objectives": [ + { "id": "109.1", "title": "Grundlagen von Internetprotokollen", "weight": 4 }, + { "id": "109.2", "title": "Persistente Netzwerkkonfiguration", "weight": 4 }, + { "id": "109.3", "title": "Grundlegende Netzwerkfehlerbehebung", "weight": 4 }, + { "id": "109.4", "title": "Clientseitiges DNS konfigurieren", "weight": 2 } + ] + }, + { + "id": "110", + "title": "Sicherheit", + "objectives": [ + { "id": "110.1", "title": "Administrationsaufgaben für Sicherheit durchführen", "weight": 3 }, + { "id": "110.2", "title": "Einen Rechner absichern", "weight": 3 }, + { "id": "110.3", "title": "Daten durch Verschlüsselung schützen", "weight": 4 } + ] + } + ] +} diff --git a/simulator/data/lpic1_102/questions_105.json b/simulator/data/lpic1_102/questions_105.json new file mode 100644 index 0000000..ccdcf8a --- /dev/null +++ b/simulator/data/lpic1_102/questions_105.json @@ -0,0 +1,195 @@ +{ + "$schema": "../schema/questions.schema.json", + "format": "lpic-sim-questions", + "meta": { + "file": "questions_105.json", + "brief": "Fragen zu Topic 105 Shells und Shell-Skripte (LPIC-1 102-500, Objectives 5.0)", + "author": "Björn Runden ", + "owner": "Björn Runden ", + "assist": "KI-unterstützt (Claude Opus 5.5), geprüft von Björn Runden ", + "version": "0.1.0 (29.10.2026)" + }, + "exam": "lpic1-102", + "questions": [ + { + "id": "105.1-001", + "objective": "105.1", + "type": "single", + "difficulty": 2, + "question": "Welche Datei liest eine interaktive **Login**-Bash als erste ein?", + "options": [ + { "id": "a", "text": "`/etc/profile`", "correct": true, "explanation": "Login-Shells lesen zuerst die systemweite `/etc/profile`, danach die erste vorhandene aus `~/.bash_profile`, `~/.bash_login`, `~/.profile`." }, + { "id": "b", "text": "`~/.bashrc`", "correct": false, "explanation": "`~/.bashrc` lesen interaktive Nicht-Login-Shells; Login-Shells nur, wenn `~/.bash_profile` sie einbindet." }, + { "id": "c", "text": "`~/.bash_profile`", "correct": false, "explanation": "Wird gelesen, aber erst nach `/etc/profile`." }, + { "id": "d", "text": "`/etc/bash.bashrc`", "correct": false, "explanation": "Systemweite Datei für interaktive Nicht-Login-Shells (Debian); wird oft über `/etc/profile` eingebunden." }, + { "id": "e", "text": "`~/.bash_logout`", "correct": false, "explanation": "Wird beim Beenden einer Login-Shell ausgeführt." } + ], + "explanation": "Login-Shell: `/etc/profile` → `~/.bash_profile` | `~/.bash_login` | `~/.profile`. Nicht-Login-Shell: `/etc/bash.bashrc` (distributionsabhängig) → `~/.bashrc`.", + "references": ["man 1 bash (Abschnitt INVOCATION)"] + }, + { + "id": "105.1-002", + "objective": "105.1", + "type": "multi", + "difficulty": 1, + "question": "Welche Schreibweisen definieren in der Bash korrekt eine Funktion `gruss`?", + "options": [ + { "id": "a", "text": "`gruss() { echo Hallo; }`", "correct": true, "explanation": "POSIX-Schreibweise; vor der schließenden Klammer ist `;` oder ein Zeilenumbruch nötig." }, + { "id": "b", "text": "`function gruss { echo Hallo; }`", "correct": true, "explanation": "Bash-spezifische Schreibweise mit dem Schlüsselwort `function`." }, + { "id": "c", "text": "`def gruss(): echo Hallo`", "correct": false, "explanation": "Das ist Python-ähnliche Syntax." }, + { "id": "d", "text": "`gruss = { echo Hallo }`", "correct": false, "explanation": "Leerzeichen um `=` und diese Klammerung sind keine gültige Funktionssyntax." }, + { "id": "e", "text": "`alias gruss() echo Hallo`", "correct": false, "explanation": "Aliase werden mit `alias name='befehl'` gesetzt und haben keine Klammern." } + ], + "explanation": "Funktionen sehen Argumente als `$1`, `$2`, …; `declare -f` listet definierte Funktionen. Dauerhaft z. B. in `~/.bashrc`.", + "references": ["man 1 bash (Abschnitt FUNCTIONS)"] + }, + { + "id": "105.1-003", + "objective": "105.1", + "type": "fill", + "difficulty": 2, + "question": "Welches Bash-Builtin führt die Befehle einer Datei in der **aktuellen** Shell aus, sodass dort gesetzte Variablen danach erhalten bleiben? (Name des Builtins)", + "answers": ["source", "."], + "explanation": "`source ~/.bashrc` bzw. `. ~/.bashrc`. Ein Aufruf als `./datei` oder `bash datei` läuft dagegen in einer Subshell; deren Variablen gehen verloren.", + "references": ["help source"] + }, + { + "id": "105.1-004", + "objective": "105.1", + "type": "single", + "difficulty": 1, + "question": "Der Alias `ll='ls -l'` soll für einen Benutzer dauerhaft in jeder interaktiven Bash verfügbar sein. Wo trägt man ihn ein?", + "options": [ + { "id": "a", "text": "`~/.bashrc`", "correct": true, "explanation": "`~/.bashrc` wird von jeder interaktiven Nicht-Login-Bash gelesen und meist auch aus `~/.bash_profile` eingebunden." }, + { "id": "b", "text": "`/etc/aliases`", "correct": false, "explanation": "`/etc/aliases` enthält E-Mail-Aliase für den MTA, keine Shell-Aliase." }, + { "id": "c", "text": "`~/.bash_logout`", "correct": false, "explanation": "Wird nur beim Abmelden ausgeführt." }, + { "id": "d", "text": "`/etc/shells`", "correct": false, "explanation": "`/etc/shells` listet die zulässigen Login-Shells." }, + { "id": "e", "text": "`~/.bash_history`", "correct": false, "explanation": "Enthält nur die gespeicherte Befehls-History." } + ], + "explanation": "Ein Alias in der Shell gilt nur bis zum Ende der Sitzung; dauerhaft wird er durch einen Eintrag in einer Startdatei.", + "references": ["help alias"] + }, + { + "id": "105.1-005", + "objective": "105.1", + "type": "single", + "difficulty": 1, + "question": "Das Verzeichnis `/opt/tools/bin` soll **zusätzlich** zum bisherigen Suchpfad verwendet werden. Welcher Befehl ist korrekt?", + "options": [ + { "id": "a", "text": "`export PATH=$PATH:/opt/tools/bin`", "correct": true, "explanation": "Der alte Inhalt bleibt erhalten, das neue Verzeichnis wird mit `:` angehängt." }, + { "id": "b", "text": "`export PATH=/opt/tools/bin`", "correct": false, "explanation": "Ersetzt den Suchpfad; Standardbefehle wie `ls` werden nicht mehr gefunden." }, + { "id": "c", "text": "`export PATH=$PATH;/opt/tools/bin`", "correct": false, "explanation": "`;` trennt Befehle; die Shell würde `/opt/tools/bin` als Befehl ausführen." }, + { "id": "d", "text": "`export $PATH=$PATH:/opt/tools/bin`", "correct": false, "explanation": "Links vom `=` steht der Variablenname ohne `$`." }, + { "id": "e", "text": "`set PATH /opt/tools/bin`", "correct": false, "explanation": "Das ist csh-Syntax; in der Bash setzt `set` Positionsparameter." } + ], + "explanation": "Verzeichnisse im `PATH` werden von links nach rechts durchsucht; `$PATH` voranzustellen oder anzuhängen bestimmt die Priorität.", + "references": ["man 1 bash (Abschnitt Shell Variables)"] + }, + { + "id": "105.1-006", + "objective": "105.1", + "type": "single", + "difficulty": 1, + "question": "Welches Verzeichnis enthält die Vorlagen (z. B. `.bashrc`, `.profile`), die beim Anlegen eines Benutzers mit `useradd -m` in dessen Home-Verzeichnis kopiert werden?", + "options": [ + { "id": "a", "text": "`/etc/skel`", "correct": true, "explanation": "Der Inhalt von `/etc/skel` wird in neue Home-Verzeichnisse kopiert." }, + { "id": "b", "text": "`/etc/default/useradd`", "correct": false, "explanation": "Datei mit Standardwerten für `useradd` (u. a. `SKEL=`), kein Vorlagenverzeichnis." }, + { "id": "c", "text": "`/etc/profile.d`", "correct": false, "explanation": "Enthält Skripte, die `/etc/profile` beim Login einbindet." }, + { "id": "d", "text": "`/etc/login.defs`", "correct": false, "explanation": "Datei mit Vorgaben wie UID-Bereichen und Passwort-Alterung." }, + { "id": "e", "text": "`/home/template`", "correct": false, "explanation": "Kein Standardpfad." } + ], + "explanation": "Änderungen an `/etc/skel` wirken nur für künftig angelegte Benutzer.", + "references": ["man 8 useradd"] + }, + { + "id": "105.2-001", + "objective": "105.2", + "type": "single", + "difficulty": 1, + "question": "Welche Variable enthält in einem Shell-Skript die **Anzahl** der übergebenen Argumente?", + "options": [ + { "id": "a", "text": "`$#`", "correct": true, "explanation": "`$#` ist die Anzahl der Positionsparameter." }, + { "id": "b", "text": "`$0`", "correct": false, "explanation": "`$0` ist der Name des Skripts." }, + { "id": "c", "text": "`$@`", "correct": false, "explanation": "`$@` sind alle Argumente als einzelne Wörter." }, + { "id": "d", "text": "`$?`", "correct": false, "explanation": "`$?` ist der Exit-Status des letzten Befehls." }, + { "id": "e", "text": "`$$`", "correct": false, "explanation": "`$$` ist die PID der Shell." } + ], + "explanation": "Weitere: `$1`…`$9` Argumente, `${10}` ab dem zehnten, `$*` alle als ein Wort (in Anführungszeichen), `shift` verschiebt die Argumente.", + "references": ["man 1 bash (Abschnitt Special Parameters)"] + }, + { + "id": "105.2-002", + "objective": "105.2", + "type": "single", + "difficulty": 1, + "question": "Mit welcher Bedingung prüft ein Skript, ob `/etc/app.conf` existiert **und eine reguläre Datei** ist?", + "options": [ + { "id": "a", "text": "`[ -f /etc/app.conf ]`", "correct": true, "explanation": "`-f` ist wahr für existierende reguläre Dateien." }, + { "id": "b", "text": "`[ -d /etc/app.conf ]`", "correct": false, "explanation": "`-d` prüft auf ein Verzeichnis." }, + { "id": "c", "text": "`[ -e /etc/app.conf ]`", "correct": false, "explanation": "`-e` prüft nur auf Existenz, gleich welcher Typ (auch Verzeichnis)." }, + { "id": "d", "text": "`[ -x /etc/app.conf ]`", "correct": false, "explanation": "`-x` prüft auf Ausführbarkeit." }, + { "id": "e", "text": "`[ -L /etc/app.conf ]`", "correct": false, "explanation": "`-L` prüft auf einen symbolischen Link." } + ], + "explanation": "`[ … ]` ist der Befehl `test`; Leerzeichen innerhalb der Klammern sind Pflicht. Weitere Tests: `-s` nicht leer, `-r`/`-w` lesbar/schreibbar, `-z`/`-n` leerer/nicht leerer String.", + "references": ["man 1 test"] + }, + { + "id": "105.2-003", + "objective": "105.2", + "type": "fill", + "difficulty": 1, + "question": "Welche spezielle Variable enthält den Exit-Status (Rückgabewert) des zuletzt ausgeführten Befehls?", + "answers": ["$?"], + "explanation": "0 bedeutet Erfolg, alles andere einen Fehler. Darauf bauen `&&`, `||` und `if` auf.", + "references": ["man 1 bash (Abschnitt Special Parameters)"] + }, + { + "id": "105.2-004", + "objective": "105.2", + "type": "single", + "difficulty": 1, + "question": "Welche Schleife ist in der Bash syntaktisch korrekt?", + "options": [ + { "id": "a", "text": "`for i in 1 2 3; do echo $i; done`", "correct": true, "explanation": "Aufbau: `for in ; do … done`." }, + { "id": "b", "text": "`for i in 1 2 3; then echo $i; fi`", "correct": false, "explanation": "`then`/`fi` gehören zu `if`." }, + { "id": "c", "text": "`for (i in 1 2 3) { echo $i }`", "correct": false, "explanation": "C/JavaScript-ähnliche Syntax; die Bash kennt das nicht." }, + { "id": "d", "text": "`foreach i (1 2 3) echo $i end`", "correct": false, "explanation": "`foreach … end` ist csh-Syntax." }, + { "id": "e", "text": "`for i = 1 to 3; do echo $i; done`", "correct": false, "explanation": "BASIC-ähnlich; nicht gültig. Zahlenreihen: `$(seq 1 3)` oder `{1..3}`." } + ], + "explanation": "Weitere Schleifen: `while bedingung; do … done`, `until …`. C-Stil in der Bash: `for ((i=1; i<=3; i++)); do … done`.", + "references": ["man 1 bash (Abschnitt Compound Commands)"] + }, + { + "id": "105.2-005", + "objective": "105.2", + "type": "multi", + "difficulty": 2, + "question": "Welche Aussagen zum Ausführen von Shell-Skripten treffen zu?", + "options": [ + { "id": "a", "text": "Die erste Zeile `#!/bin/bash` legt den Interpreter fest, wenn das Skript direkt ausgeführt wird.", "correct": true, "explanation": "Der Kernel wertet die Shebang-Zeile aus und startet den angegebenen Interpreter." }, + { "id": "b", "text": "Für den Aufruf `./skript.sh` braucht die Datei das Ausführungsrecht.", "correct": true, "explanation": "Ohne `x`-Recht meldet die Shell „Permission denied“." }, + { "id": "c", "text": "Auch `bash skript.sh` funktioniert nur mit Ausführungsrecht.", "correct": false, "explanation": "Hier ist `bash` das ausgeführte Programm; es braucht nur Leserecht auf das Skript." }, + { "id": "d", "text": "Die Shebang-Zeile darf an beliebiger Stelle im Skript stehen.", "correct": false, "explanation": "Sie wirkt nur als allererste Zeile und muss mit `#!` beginnen." }, + { "id": "e", "text": "Das aktuelle Verzeichnis ist standardmäßig im `PATH`; `skript.sh` ohne `./` genügt.", "correct": false, "explanation": "Aus Sicherheitsgründen steht `.` normalerweise nicht im `PATH`." } + ], + "explanation": "SUID/SGID-Bits werden bei Skripten unter Linux ignoriert. Mit `exec` ersetzt ein Skript sich selbst durch ein anderes Programm.", + "references": ["man 2 execve"] + }, + { + "id": "105.2-006", + "objective": "105.2", + "type": "single", + "difficulty": 1, + "question": "Welcher Befehl liest in einem Skript eine Zeile von der Tastatur in die Variable `NAME` ein?", + "options": [ + { "id": "a", "text": "`read NAME`", "correct": true, "explanation": "`read` liest eine Zeile von stdin; `-p \"Text\"` zeigt vorher eine Eingabeaufforderung an." }, + { "id": "b", "text": "`input NAME`", "correct": false, "explanation": "Einen Befehl `input` gibt es in der Bash nicht." }, + { "id": "c", "text": "`echo $NAME`", "correct": false, "explanation": "Gibt den Inhalt der Variable aus, liest nichts ein." }, + { "id": "d", "text": "`NAME < /dev/stdin`", "correct": false, "explanation": "Die Shell versucht, einen Befehl namens `NAME` auszuführen; eine Variable wird nicht gesetzt." }, + { "id": "e", "text": "`get NAME`", "correct": false, "explanation": "Einen Befehl `get` gibt es in der Bash nicht." } + ], + "explanation": "Mehrere Variablen: `read VORNAME NACHNAME` verteilt die Wörter nach `IFS`. Ohne Variablenname landet die Eingabe in `REPLY`.", + "references": ["help read"] + } + ] +} diff --git a/simulator/data/lpic1_102/questions_106.json b/simulator/data/lpic1_102/questions_106.json new file mode 100644 index 0000000..5369d55 --- /dev/null +++ b/simulator/data/lpic1_102/questions_106.json @@ -0,0 +1,127 @@ +{ + "$schema": "../schema/questions.schema.json", + "format": "lpic-sim-questions", + "meta": { + "file": "questions_106.json", + "brief": "Fragen zu Topic 106 Benutzerschnittstellen und Desktops (LPIC-1 102-500, Objectives 5.0)", + "author": "Björn Runden ", + "owner": "Björn Runden ", + "assist": "KI-unterstützt (Claude Opus 5.5), geprüft von Björn Runden ", + "version": "0.1.0 (29.10.2026)" + }, + "exam": "lpic1-102", + "questions": [ + { + "id": "106.1-001", + "objective": "106.1", + "type": "single", + "difficulty": 1, + "question": "Welche Umgebungsvariable legt fest, auf welchem X-Server ein X11-Programm seine Fenster darstellt?", + "options": [ + { "id": "a", "text": "`DISPLAY`", "correct": true, "explanation": "Format `host:display.screen`, lokal meist `:0`." }, + { "id": "b", "text": "`XAUTHORITY`", "correct": false, "explanation": "Verweist auf die Datei mit den Zugriffs-Cookies (Standard `~/.Xauthority`)." }, + { "id": "c", "text": "`TERM`", "correct": false, "explanation": "Beschreibt den Typ des Text-Terminals." }, + { "id": "d", "text": "`XDG_SESSION_TYPE`", "correct": false, "explanation": "Zeigt nur an, ob die Sitzung `x11` oder `wayland` ist." }, + { "id": "e", "text": "`WAYLAND_DISPLAY`", "correct": false, "explanation": "Gibt den Socket des Wayland-Compositors an, nicht den X-Server." } + ], + "explanation": "Zugriff auf einen X-Server steuern `xhost` (host-basiert) und `xauth` (Cookies). X-Weiterleitung über SSH: `ssh -X`.", + "references": ["man 7 X"] + }, + { + "id": "106.1-002", + "objective": "106.1", + "type": "single", + "difficulty": 1, + "question": "Wo liegt die Hauptkonfiguration des Xorg-Servers bzw. wo legt man ergänzende Konfigurationsschnipsel ab?", + "options": [ + { "id": "a", "text": "`/etc/X11/xorg.conf` bzw. `/etc/X11/xorg.conf.d/`", "correct": true, "explanation": "Moderne Xorg-Server erkennen vieles automatisch; Anpassungen kommen als Dateien in `xorg.conf.d`." }, + { "id": "b", "text": "`/etc/xorg/server.conf`", "correct": false, "explanation": "Diesen Pfad gibt es nicht." }, + { "id": "c", "text": "`~/.xinitrc`", "correct": false, "explanation": "`~/.xinitrc` legt fest, was `startx` startet, nicht die Server-Hardwarekonfiguration." }, + { "id": "d", "text": "`/etc/X11/Xresources`", "correct": false, "explanation": "X-Ressourcen konfigurieren das Aussehen von Clients, nicht den Server." }, + { "id": "e", "text": "`/var/log/Xorg.0.log`", "correct": false, "explanation": "Das ist das Protokoll des Servers, hilfreich bei Fehlern, aber keine Konfiguration." } + ], + "explanation": "Abschnitte in `xorg.conf`: `Section \"Device\"`, `\"Monitor\"`, `\"Screen\"`, `\"InputDevice\"`, `\"ServerLayout\"` … Fehlersuche über `/var/log/Xorg.0.log`.", + "references": ["man 5 xorg.conf"] + }, + { + "id": "106.1-003", + "objective": "106.1", + "type": "multi", + "difficulty": 2, + "question": "Welche Aussagen zu Wayland treffen zu?", + "options": [ + { "id": "a", "text": "Unter Wayland übernimmt der Compositor zugleich die Aufgaben des Display-Servers.", "correct": true, "explanation": "Es gibt keinen getrennten Server wie Xorg; der Compositor (z. B. Mutter, KWin) zeichnet und verteilt Eingaben." }, + { "id": "b", "text": "XWayland ermöglicht es, X11-Programme in einer Wayland-Sitzung auszuführen.", "correct": true, "explanation": "XWayland ist ein X-Server, der als Wayland-Client läuft." }, + { "id": "c", "text": "Wayland wird über `/etc/X11/xorg.conf` konfiguriert.", "correct": false, "explanation": "Die Konfiguration erfolgt im jeweiligen Compositor bzw. der Desktopumgebung." }, + { "id": "d", "text": "Wayland ist wie X11 netzwerktransparent über `DISPLAY=host:0`.", "correct": false, "explanation": "Das Wayland-Protokoll selbst ist nicht netzwerktransparent; Fernzugriff läuft über Zusatzlösungen." }, + { "id": "e", "text": "Wayland setzt den Display-Manager `xdm` voraus.", "correct": false, "explanation": "Wayland-Sitzungen werden z. B. von GDM oder SDDM gestartet; `xdm` kann das nicht." } + ], + "explanation": "Ob eine Sitzung X11 oder Wayland nutzt, zeigt `echo $XDG_SESSION_TYPE`.", + "references": ["https://wayland.freedesktop.org/"] + }, + { + "id": "106.2-001", + "objective": "106.2", + "type": "single", + "difficulty": 1, + "question": "Welches Fernzugriffsverfahren für grafische Desktops basiert auf dem Remote-Framebuffer-Protokoll (RFB)?", + "options": [ + { "id": "a", "text": "VNC", "correct": true, "explanation": "VNC (Virtual Network Computing) überträgt Bildschirminhalte per RFB, Standardport 5900 + Display-Nummer." }, + { "id": "b", "text": "RDP", "correct": false, "explanation": "RDP ist das Remote Desktop Protocol von Microsoft (Port 3389), unter Linux z. B. mit xrdp." }, + { "id": "c", "text": "SPICE", "correct": false, "explanation": "SPICE ist ein eigenes Protokoll für die Anzeige virtueller Maschinen (QEMU/KVM)." }, + { "id": "d", "text": "XDMCP", "correct": false, "explanation": "XDMCP vermittelt Anmeldungen an einen entfernten X-Display-Manager, unverschlüsselt." }, + { "id": "e", "text": "SMTP", "correct": false, "explanation": "SMTP überträgt E-Mails." } + ], + "explanation": "106.2 verlangt Grundwissen zu Desktopumgebungen und Protokollen für den entfernten Desktopzugriff (X11, XDMCP, VNC, SPICE, RDP).", + "references": ["RFC 6143"] + }, + { + "id": "106.2-002", + "objective": "106.2", + "type": "multi", + "difficulty": 1, + "question": "Welche der folgenden sind **Desktopumgebungen**?", + "options": [ + { "id": "a", "text": "GNOME", "correct": true, "explanation": "Verbreitete Desktopumgebung (GTK-basiert)." }, + { "id": "b", "text": "KDE Plasma", "correct": true, "explanation": "Desktopumgebung auf Qt-Basis." }, + { "id": "c", "text": "Xfce", "correct": true, "explanation": "Ressourcenschonende Desktopumgebung (GTK-basiert)." }, + { "id": "d", "text": "Xorg", "correct": false, "explanation": "Xorg ist der X-Display-Server, auf dem Desktopumgebungen laufen können." }, + { "id": "e", "text": "systemd", "correct": false, "explanation": "systemd ist Init-System und Dienstverwaltung." } + ], + "explanation": "Weitere Desktops: Cinnamon, MATE, LXDE/LXQt. Eine Desktopumgebung bündelt Fenstermanager, Panel, Dateimanager und Einstellungen.", + "references": ["LPI 102-500 Objective 106.2"] + }, + { + "id": "106.3-001", + "objective": "106.3", + "type": "single", + "difficulty": 1, + "question": "Welches Programm ist ein verbreiteter **Bildschirmleser** (Screenreader) für grafische Linux-Desktops wie GNOME?", + "options": [ + { "id": "a", "text": "Orca", "correct": true, "explanation": "Orca gibt Bildschirminhalte per Sprachausgabe oder Braillezeile aus." }, + { "id": "b", "text": "Onboard", "correct": false, "explanation": "Onboard ist eine Bildschirmtastatur." }, + { "id": "c", "text": "xmag", "correct": false, "explanation": "`xmag` vergrößert einen Bildschirmausschnitt." }, + { "id": "d", "text": "Sticky Keys", "correct": false, "explanation": "Eine Tastatureinstellung, kein Bildschirmleser." }, + { "id": "e", "text": "`xrandr`", "correct": false, "explanation": "`xrandr` stellt Auflösung und Anordnung von Monitoren ein." } + ], + "explanation": "Hilfstechnologien: Bildschirmleser, Braillezeilen, Bildschirmlupe, Bildschirmtastatur, Hochkontrast-Themes, große Schriften, Sprachsynthese.", + "references": ["https://help.gnome.org/users/orca/stable/"] + }, + { + "id": "106.3-002", + "objective": "106.3", + "type": "single", + "difficulty": 1, + "question": "Was bewirken **einrastende Tasten** (Sticky Keys)?", + "options": [ + { "id": "a", "text": "Umschalt-, Strg- oder Alt-Taste bleiben nach dem Loslassen aktiv, sodass Tastenkombinationen nacheinander gedrückt werden können.", "correct": true, "explanation": "Hilft Menschen, die nicht mehrere Tasten gleichzeitig drücken können." }, + { "id": "b", "text": "Eine Taste muss eine Weile gehalten werden, bevor der Anschlag zählt.", "correct": false, "explanation": "Das sind die Langsamen Tasten (Slow Keys)." }, + { "id": "c", "text": "Schnell wiederholte Anschläge derselben Taste werden ignoriert.", "correct": false, "explanation": "Das sind die Springenden Tasten (Bounce Keys)." }, + { "id": "d", "text": "Der Mauszeiger wird mit dem Ziffernblock gesteuert.", "correct": false, "explanation": "Das sind die Maustasten (Mouse Keys)." }, + { "id": "e", "text": "Der Bildschirm wird in hohem Kontrast dargestellt.", "correct": false, "explanation": "Das ist ein Hochkontrast-Theme." } + ], + "explanation": "AccessX-Funktionen der Tastatur: Sticky, Slow, Bounce, Toggle Keys sowie Mouse Keys.", + "references": ["LPI 102-500 Objective 106.3"] + } + ] +} diff --git a/simulator/data/lpic1_102/questions_107.json b/simulator/data/lpic1_102/questions_107.json new file mode 100644 index 0000000..c152367 --- /dev/null +++ b/simulator/data/lpic1_102/questions_107.json @@ -0,0 +1,285 @@ +{ + "$schema": "../schema/questions.schema.json", + "format": "lpic-sim-questions", + "meta": { + "file": "questions_107.json", + "brief": "Fragen zu Topic 107 Administrative Aufgaben (LPIC-1 102-500, Objectives 5.0)", + "author": "Björn Runden ", + "owner": "Björn Runden ", + "assist": "KI-unterstützt (Claude Opus 5.5), geprüft von Björn Runden ", + "version": "0.1.0 (29.10.2026)" + }, + "exam": "lpic1-102", + "questions": [ + { + "id": "107.1-001", + "objective": "107.1", + "type": "single", + "difficulty": 1, + "question": "In welcher Datei stehen auf aktuellen Linux-Systemen die Passwort-Hashes der Benutzerkonten?", + "options": [ + { "id": "a", "text": "`/etc/shadow`", "correct": true, "explanation": "Nur für root lesbar; enthält Hash und Daten zur Passwort-Alterung." }, + { "id": "b", "text": "`/etc/passwd`", "correct": false, "explanation": "Für alle lesbar; im Passwortfeld steht nur `x` als Verweis auf `/etc/shadow`." }, + { "id": "c", "text": "`/etc/group`", "correct": false, "explanation": "Enthält Gruppen und ihre Mitglieder." }, + { "id": "d", "text": "`/etc/gshadow`", "correct": false, "explanation": "Enthält Gruppenpasswörter und Gruppenadministratoren." }, + { "id": "e", "text": "`/etc/login.defs`", "correct": false, "explanation": "Enthält Vorgaben, z. B. UID-Bereiche und Standardwerte der Passwort-Alterung." } + ], + "explanation": "Felder von `/etc/shadow`: Name, Hash, letzte Änderung, min, max, Warnung, Inaktivität, Ablaufdatum, reserviert.", + "references": ["man 5 shadow"] + }, + { + "id": "107.1-002", + "objective": "107.1", + "type": "single", + "difficulty": 1, + "question": "Was steht im **siebten** (letzten) Feld eines Eintrags in `/etc/passwd`?", + "options": [ + { "id": "a", "text": "Die Login-Shell", "correct": true, "explanation": "z. B. `/bin/bash` oder `/usr/sbin/nologin` für Konten ohne Anmeldung." }, + { "id": "b", "text": "Das Home-Verzeichnis", "correct": false, "explanation": "Das ist das sechste Feld." }, + { "id": "c", "text": "Das GECOS-Feld (Kommentar, voller Name)", "correct": false, "explanation": "Das ist das fünfte Feld." }, + { "id": "d", "text": "Die primäre Gruppen-ID", "correct": false, "explanation": "Das ist das vierte Feld." }, + { "id": "e", "text": "Die Benutzer-ID", "correct": false, "explanation": "Das ist das dritte Feld." } + ], + "explanation": "Aufbau: `name:x:UID:GID:GECOS:home:shell`, z. B. `anna:x:1001:1001:Anna:/home/anna:/bin/bash`.", + "references": ["man 5 passwd"] + }, + { + "id": "107.1-003", + "objective": "107.1", + "type": "fill", + "difficulty": 2, + "question": "Der Benutzer `anna` soll zusätzlich in die Gruppe `docker` aufgenommen werden, **ohne** seine übrigen Zusatzgruppen zu verlieren. Geben Sie den Befehl ein.", + "answers": ["usermod -aG docker anna", "usermod -a -G docker anna", "usermod -G docker -a anna", "usermod --append --groups docker anna", "gpasswd -a anna docker"], + "explanation": "`-G` allein ersetzt die Liste der Zusatzgruppen; erst `-a` (append) hängt an. Die Änderung wirkt erst nach erneuter Anmeldung (oder mit `newgrp`).", + "references": ["man 8 usermod", "man 1 gpasswd"] + }, + { + "id": "107.1-004", + "objective": "107.1", + "type": "single", + "difficulty": 1, + "question": "Mit welchem Befehl legt man den Benutzer `bob` an und erzeugt dabei gleich sein Home-Verzeichnis (mit Inhalt aus `/etc/skel`)?", + "options": [ + { "id": "a", "text": "`useradd -m bob`", "correct": true, "explanation": "`-m` (`--create-home`) legt das Home-Verzeichnis an und kopiert `/etc/skel`." }, + { "id": "b", "text": "`useradd -d /home/bob bob`", "correct": false, "explanation": "`-d` legt nur den Pfad fest, erzeugt das Verzeichnis aber nicht." }, + { "id": "c", "text": "`useradd -s /bin/bash bob`", "correct": false, "explanation": "`-s` setzt nur die Login-Shell." }, + { "id": "d", "text": "`useradd -g users bob`", "correct": false, "explanation": "`-g` setzt die primäre Gruppe." }, + { "id": "e", "text": "`useradd -k /etc/skel bob`", "correct": false, "explanation": "`-k` wählt das Vorlagenverzeichnis und wirkt nur zusammen mit `-m`." } + ], + "explanation": "Ob `useradd` ohne `-m` ein Home anlegt, hängt von `CREATE_HOME` in `/etc/login.defs` ab. Debian bietet zusätzlich das interaktive `adduser`.", + "references": ["man 8 useradd"] + }, + { + "id": "107.1-005", + "objective": "107.1", + "type": "multi", + "difficulty": 2, + "question": "Mit welchen Befehlen sperrt man das Passwort des Kontos `carl`, sodass keine Anmeldung per Passwort mehr möglich ist?", + "options": [ + { "id": "a", "text": "`usermod -L carl`", "correct": true, "explanation": "`-L` setzt ein `!` vor den Hash in `/etc/shadow`." }, + { "id": "b", "text": "`passwd -l carl`", "correct": true, "explanation": "`passwd -l` sperrt ebenfalls durch Voranstellen von `!`; `-u` entsperrt." }, + { "id": "c", "text": "`passwd -d carl`", "correct": false, "explanation": "`-d` löscht das Passwort – je nach Konfiguration ist dann sogar eine Anmeldung ohne Passwort möglich." }, + { "id": "d", "text": "`chage -l carl`", "correct": false, "explanation": "`chage -l` zeigt nur die Alterungsinformationen an." }, + { "id": "e", "text": "`userdel -l carl`", "correct": false, "explanation": "`userdel` löscht Konten; eine Option `-l` zum Sperren gibt es nicht." } + ], + "explanation": "Eine Passwortsperre verhindert keine Anmeldung per SSH-Schlüssel. Komplett sperren: zusätzlich Ablaufdatum setzen (`usermod -e 1` bzw. `chage -E 0`) oder Shell auf `nologin`.", + "references": ["man 8 usermod", "man 1 passwd"] + }, + { + "id": "107.1-006", + "objective": "107.1", + "type": "single", + "difficulty": 2, + "question": "Der Benutzer `dora` soll sein Passwort spätestens alle 90 Tage ändern müssen. Welcher Befehl setzt das?", + "options": [ + { "id": "a", "text": "`chage -M 90 dora`", "correct": true, "explanation": "`-M` setzt die maximale Gültigkeit des Passworts in Tagen." }, + { "id": "b", "text": "`chage -m 90 dora`", "correct": false, "explanation": "`-m` ist die Mindestdauer zwischen zwei Änderungen." }, + { "id": "c", "text": "`chage -W 90 dora`", "correct": false, "explanation": "`-W` legt fest, wie viele Tage vorher gewarnt wird." }, + { "id": "d", "text": "`chage -E 90 dora`", "correct": false, "explanation": "`-E` setzt das Ablaufdatum des Kontos (Datum oder Tage seit 1.1.1970)." }, + { "id": "e", "text": "`chage -I 90 dora`", "correct": false, "explanation": "`-I` legt die Inaktivitätsfrist nach Ablauf des Passworts fest." } + ], + "explanation": "`chage -l dora` zeigt die aktuellen Werte. Dieselben Felder lassen sich teils auch mit `passwd -n/-x/-w/-i` setzen.", + "references": ["man 1 chage"] + }, + { + "id": "107.1-007", + "objective": "107.1", + "type": "single", + "difficulty": 2, + "question": "Benutzer kommen teils aus `/etc/passwd`, teils aus LDAP. Welcher Befehl zeigt den Kontoeintrag von `anna` **unabhängig von der Quelle** an?", + "options": [ + { "id": "a", "text": "`getent passwd anna`", "correct": true, "explanation": "`getent` fragt die Datenbanken über NSS ab, also in der Reihenfolge aus `/etc/nsswitch.conf`." }, + { "id": "b", "text": "`grep anna /etc/passwd`", "correct": false, "explanation": "Findet nur lokale Einträge." }, + { "id": "c", "text": "`who anna`", "correct": false, "explanation": "`who` zeigt angemeldete Benutzer; ein Argument wird als Datei interpretiert." }, + { "id": "d", "text": "`last anna`", "correct": false, "explanation": "`last` zeigt die Anmeldehistorie aus `wtmp`." }, + { "id": "e", "text": "`cat /etc/nsswitch.conf`", "correct": false, "explanation": "Zeigt nur die Konfiguration der Quellen, keine Konten." } + ], + "explanation": "Analog: `getent group`, `getent hosts`, `getent shadow` (als root).", + "references": ["man 1 getent", "man 5 nsswitch.conf"] + }, + { + "id": "107.1-008", + "objective": "107.1", + "type": "multi", + "difficulty": 2, + "question": "Welche Aussagen zur Benutzer- und Gruppenverwaltung treffen zu?", + "options": [ + { "id": "a", "text": "`userdel -r anna` löscht auch das Home-Verzeichnis und das Mail-Spool von `anna`.", "correct": true, "explanation": "Ohne `-r` bleiben Home-Verzeichnis und Mail-Spool erhalten." }, + { "id": "b", "text": "Systemkonten haben üblicherweise UIDs unterhalb von `UID_MIN` aus `/etc/login.defs`.", "correct": true, "explanation": "Typisch: Systemkonten unter 1000, normale Benutzer ab 1000; `useradd -r` legt Systemkonten an." }, + { "id": "c", "text": "`groupdel` löscht eine Gruppe auch dann, wenn sie die primäre Gruppe eines Benutzers ist.", "correct": false, "explanation": "`groupdel` verweigert das; zuerst muss die primäre Gruppe des Benutzers geändert werden." }, + { "id": "d", "text": "Die UID 0 kann nur ein Konto mit dem Namen `root` haben.", "correct": false, "explanation": "Entscheidend ist die UID: Jedes Konto mit UID 0 hat Root-Rechte – ein Sicherheitsrisiko." }, + { "id": "e", "text": "`passwd` ohne Argument ändert immer das Passwort von root.", "correct": false, "explanation": "Ohne Argument ändert `passwd` das Passwort des aufrufenden Benutzers." } + ], + "explanation": "Gruppen: `groupadd`, `groupmod -n neu alt` (umbenennen), `groupdel`. Mitgliedschaften prüfen: `id anna`, `groups anna`.", + "references": ["man 8 userdel", "man 5 login.defs"] + }, + { + "id": "107.2-001", + "objective": "107.2", + "type": "single", + "difficulty": 1, + "question": "Wann läuft der Benutzer-crontab-Eintrag `30 2 * * 1 /usr/local/bin/backup.sh`?", + "options": [ + { "id": "a", "text": "Jeden Montag um 02:30 Uhr", "correct": true, "explanation": "Minute 30, Stunde 2, jeder Tag, jeder Monat, Wochentag 1 = Montag." }, + { "id": "b", "text": "Jeden Tag um 02:30 Uhr", "correct": false, "explanation": "Das wäre `30 2 * * *`." }, + { "id": "c", "text": "Am 1. jedes Monats um 02:30 Uhr", "correct": false, "explanation": "Das wäre `30 2 1 * *` (drittes Feld = Tag des Monats)." }, + { "id": "d", "text": "Im Januar täglich um 02:30 Uhr", "correct": false, "explanation": "Das wäre `30 2 * 1 *` (viertes Feld = Monat)." }, + { "id": "e", "text": "Montags alle 30 Minuten ab 02:00 Uhr", "correct": false, "explanation": "Das wäre z. B. `*/30 2-23 * * 1`." } + ], + "explanation": "Felder: Minute · Stunde · Tag des Monats · Monat · Wochentag (0 und 7 = Sonntag) · Befehl.", + "references": ["man 5 crontab"] + }, + { + "id": "107.2-002", + "objective": "107.2", + "type": "fill", + "difficulty": 1, + "question": "Mit welchem Befehl (mit Option) bearbeitet ein Benutzer seine eigene crontab?", + "answers": ["crontab -e"], + "explanation": "`crontab -e` öffnet den Editor und prüft beim Speichern die Syntax; `-l` listet, `-r` löscht. Die Dateien liegen unter `/var/spool/cron/`.", + "references": ["man 1 crontab"] + }, + { + "id": "107.2-003", + "objective": "107.2", + "type": "single", + "difficulty": 2, + "question": "Worin unterscheidet sich ein Eintrag in `/etc/crontab` (bzw. `/etc/cron.d/*`) von einem Eintrag in einer Benutzer-crontab?", + "options": [ + { "id": "a", "text": "Vor dem Befehl steht zusätzlich ein Feld mit dem Benutzernamen, unter dem der Befehl läuft.", "correct": true, "explanation": "Aufbau systemweit: fünf Zeitfelder, Benutzer, Befehl – z. B. `17 * * * * root run-parts /etc/cron.hourly`." }, + { "id": "b", "text": "Es gibt kein Feld für den Wochentag.", "correct": false, "explanation": "Die fünf Zeitfelder sind identisch." }, + { "id": "c", "text": "Die Zeitangaben stehen in Sekunden statt in Minuten.", "correct": false, "explanation": "cron arbeitet mit Minuten als kleinster Einheit." }, + { "id": "d", "text": "Die Datei wird mit `crontab -e` bearbeitet.", "correct": false, "explanation": "`/etc/crontab` wird direkt mit einem Editor bearbeitet." }, + { "id": "e", "text": "Befehle laufen dort immer als root, ein Benutzerfeld gibt es nicht.", "correct": false, "explanation": "Gerade das Benutzerfeld ist der Unterschied." } + ], + "explanation": "Daneben gibt es `/etc/cron.hourly`, `.daily`, `.weekly`, `.monthly` für Skripte ohne Zeitangabe.", + "references": ["man 5 crontab", "man 8 cron"] + }, + { + "id": "107.2-004", + "objective": "107.2", + "type": "single", + "difficulty": 1, + "question": "Ein Befehl soll **einmalig** heute um 23:00 Uhr ausgeführt werden. Welches Werkzeug ist dafür gedacht?", + "options": [ + { "id": "a", "text": "`at 23:00`", "correct": true, "explanation": "`at` liest die Befehle von stdin und führt sie einmalig zur angegebenen Zeit aus." }, + { "id": "b", "text": "`batch 23:00`", "correct": false, "explanation": "`batch` führt Aufträge aus, sobald die Systemlast es zulässt; eine Uhrzeit nimmt es nicht an." }, + { "id": "c", "text": "`crontab -t 23:00`", "correct": false, "explanation": "`crontab` hat keine Option `-t`; cron ist für wiederkehrende Aufträge." }, + { "id": "d", "text": "`sleep 23:00`", "correct": false, "explanation": "`sleep` erwartet eine Dauer, keine Uhrzeit." }, + { "id": "e", "text": "`cron 23:00`", "correct": false, "explanation": "`cron` ist der Daemon und nimmt keine Aufträge auf der Befehlszeile an." } + ], + "explanation": "`atq` listet anstehende at-Aufträge, `atrm` löscht sie. Zugriff steuern `/etc/at.allow` und `/etc/at.deny`. Mit systemd: `systemd-run --on-calendar=…`.", + "references": ["man 1 at"] + }, + { + "id": "107.2-005", + "objective": "107.2", + "type": "multi", + "difficulty": 2, + "question": "Welche Dateien steuern, welche Benutzer `crontab` verwenden dürfen?", + "options": [ + { "id": "a", "text": "`/etc/cron.allow`", "correct": true, "explanation": "Existiert sie, dürfen nur die dort genannten Benutzer crontab nutzen." }, + { "id": "b", "text": "`/etc/cron.deny`", "correct": true, "explanation": "Existiert keine `cron.allow`, sind die hier genannten Benutzer ausgeschlossen." }, + { "id": "c", "text": "`/etc/at.deny`", "correct": false, "explanation": "Steuert nur den Zugriff auf `at`." }, + { "id": "d", "text": "`/etc/crontab`", "correct": false, "explanation": "Die systemweite crontab enthält Aufträge, keine Zugriffsregeln." }, + { "id": "e", "text": "`/etc/security/access.conf`", "correct": false, "explanation": "Regelt per PAM, wer sich wo anmelden darf." } + ], + "explanation": "Fehlen beide Dateien, hängt das Verhalten von der Distribution ab (oft dürfen alle, teils nur root).", + "references": ["man 1 crontab"] + }, + { + "id": "107.2-006", + "objective": "107.2", + "type": "single", + "difficulty": 1, + "question": "Welcher Befehl listet alle systemd-Timer mit ihrem nächsten und letzten Ausführungszeitpunkt auf?", + "options": [ + { "id": "a", "text": "`systemctl list-timers`", "correct": true, "explanation": "Mit `--all` auch inaktive Timer." }, + { "id": "b", "text": "`systemctl status cron`", "correct": false, "explanation": "Zeigt den Zustand des cron-Dienstes, nicht die systemd-Timer." }, + { "id": "c", "text": "`atq`", "correct": false, "explanation": "Listet at-Aufträge." }, + { "id": "d", "text": "`crontab -l`", "correct": false, "explanation": "Listet die crontab des aktuellen Benutzers." }, + { "id": "e", "text": "`journalctl --timers`", "correct": false, "explanation": "Eine solche Option gibt es nicht." } + ], + "explanation": "Ein Timer (`name.timer`) startet die gleichnamige `name.service`-Unit; Zeitangaben z. B. `OnCalendar=daily` oder `OnBootSec=10min`.", + "references": ["man 5 systemd.timer"] + }, + { + "id": "107.3-001", + "objective": "107.3", + "type": "single", + "difficulty": 1, + "question": "Mit welchem Befehl stellt man auf einem systemd-System die Zeitzone **dauerhaft** auf Europe/Berlin?", + "options": [ + { "id": "a", "text": "`timedatectl set-timezone Europe/Berlin`", "correct": true, "explanation": "Setzt den Link `/etc/localtime` auf `/usr/share/zoneinfo/Europe/Berlin`." }, + { "id": "b", "text": "`localectl set-timezone Europe/Berlin`", "correct": false, "explanation": "`localectl` verwaltet Locale und Tastaturbelegung, keine Zeitzone." }, + { "id": "c", "text": "`export TZ=Europe/Berlin`", "correct": false, "explanation": "Gilt nur für die aktuelle Shell und ihre Kindprozesse." }, + { "id": "d", "text": "`hwclock --timezone Europe/Berlin`", "correct": false, "explanation": "`hwclock` liest und stellt die Hardware-Uhr, eine Zeitzone setzt es nicht." }, + { "id": "e", "text": "`date --zone Europe/Berlin`", "correct": false, "explanation": "`date` hat keine solche Option; man kann nur per `TZ=… date` einmalig anzeigen." } + ], + "explanation": "Ohne systemd: `/etc/localtime` von Hand verlinken bzw. unter Debian `/etc/timezone` und `dpkg-reconfigure tzdata`. Interaktiv hilft `tzselect`.", + "references": ["man 1 timedatectl", "man 8 tzselect"] + }, + { + "id": "107.3-002", + "objective": "107.3", + "type": "single", + "difficulty": 2, + "question": "Welche Variable überschreibt **alle** anderen Locale-Einstellungen (`LANG` und alle `LC_*`)?", + "options": [ + { "id": "a", "text": "`LC_ALL`", "correct": true, "explanation": "`LC_ALL` hat Vorrang vor allen einzelnen `LC_*` und vor `LANG`." }, + { "id": "b", "text": "`LANG`", "correct": false, "explanation": "`LANG` ist der Standardwert mit der niedrigsten Priorität." }, + { "id": "c", "text": "`LC_MESSAGES`", "correct": false, "explanation": "Gilt nur für die Sprache von Programmmeldungen." }, + { "id": "d", "text": "`LC_CTYPE`", "correct": false, "explanation": "Gilt nur für Zeichenklassifizierung und Zeichensatz." }, + { "id": "e", "text": "`TZ`", "correct": false, "explanation": "`TZ` legt die Zeitzone fest, keine Locale." } + ], + "explanation": "`locale` zeigt die wirksamen Werte, `locale -a` alle verfügbaren Locales. `LANG=C` bzw. `C.UTF-8` erzwingt neutrale Ausgaben, z. B. in Skripten.", + "references": ["man 7 locale"] + }, + { + "id": "107.3-003", + "objective": "107.3", + "type": "fill", + "difficulty": 1, + "question": "Welches Programm konvertiert Textdateien zwischen Zeichenkodierungen, z. B. von ISO-8859-1 nach UTF-8? (nur der Befehlsname)", + "answers": ["iconv"], + "explanation": "Beispiel: `iconv -f ISO-8859-1 -t UTF-8 alt.txt > neu.txt`; `iconv -l` listet die bekannten Kodierungen.", + "references": ["man 1 iconv"] + }, + { + "id": "107.3-004", + "objective": "107.3", + "type": "multi", + "difficulty": 2, + "question": "Welche Aussagen zu Zeichenkodierungen treffen zu?", + "options": [ + { "id": "a", "text": "UTF-8 kodiert Unicode-Zeichen mit variabler Länge (1 bis 4 Byte).", "correct": true, "explanation": "Häufige Zeichen sind kurz, seltene länger." }, + { "id": "b", "text": "ASCII-Zeichen haben in UTF-8 dieselben Byte-Werte wie in ASCII.", "correct": true, "explanation": "UTF-8 ist abwärtskompatibel zu 7-Bit-ASCII." }, + { "id": "c", "text": "ISO-8859-1 enthält das Euro-Zeichen.", "correct": false, "explanation": "Das Euro-Zeichen kam erst mit ISO-8859-15 (Latin-9)." }, + { "id": "d", "text": "UTF-8 benötigt für jedes Zeichen genau 2 Byte.", "correct": false, "explanation": "Feste 2 Byte entsprächen UCS-2; UTF-8 ist variabel." }, + { "id": "e", "text": "`LANG=C` aktiviert UTF-8 für alle Programme.", "correct": false, "explanation": "Die C/POSIX-Locale verwendet ASCII; für UTF-8 z. B. `C.UTF-8` oder `de_DE.UTF-8`." } + ], + "explanation": "Im Objective genannt: UTF-8, ISO-8859, ASCII, Unicode sowie `locale`, `iconv`, `/etc/timezone`, `/etc/localtime`, `/usr/share/zoneinfo/`.", + "references": ["man 7 utf-8", "man 7 charsets"] + } + ] +} diff --git a/simulator/data/lpic1_102/questions_108.json b/simulator/data/lpic1_102/questions_108.json new file mode 100644 index 0000000..8dfb75e --- /dev/null +++ b/simulator/data/lpic1_102/questions_108.json @@ -0,0 +1,269 @@ +{ + "$schema": "../schema/questions.schema.json", + "format": "lpic-sim-questions", + "meta": { + "file": "questions_108.json", + "brief": "Fragen zu Topic 108 Grundlegende Systemdienste (LPIC-1 102-500, Objectives 5.0)", + "author": "Björn Runden ", + "owner": "Björn Runden ", + "assist": "KI-unterstützt (Claude Opus 5.5), geprüft von Björn Runden ", + "version": "0.1.0 (29.10.2026)" + }, + "exam": "lpic1-102", + "questions": [ + { + "id": "108.1-001", + "objective": "108.1", + "type": "single", + "difficulty": 1, + "question": "Die Systemzeit ist korrekt. Mit welchem Befehl überträgt man sie in die Hardware-Uhr (RTC)?", + "options": [ + { "id": "a", "text": "`hwclock --systohc`", "correct": true, "explanation": "system to hardware clock: Systemzeit → RTC." }, + { "id": "b", "text": "`hwclock --hctosys`", "correct": false, "explanation": "Umgekehrte Richtung: RTC → Systemzeit (passiert beim Start)." }, + { "id": "c", "text": "`hwclock --show`", "correct": false, "explanation": "Zeigt die Zeit der Hardware-Uhr nur an." }, + { "id": "d", "text": "`date -s now`", "correct": false, "explanation": "`date -s` stellt die Systemzeit, nicht die Hardware-Uhr." }, + { "id": "e", "text": "`timedatectl set-ntp true`", "correct": false, "explanation": "Aktiviert die NTP-Synchronisation der Systemzeit." } + ], + "explanation": "Linux führt eine Systemuhr (Kernel) und die batteriegepufferte Hardware-Uhr. Ob die RTC in UTC oder Ortszeit läuft, zeigt `timedatectl` (RTC in local TZ).", + "references": ["man 8 hwclock"] + }, + { + "id": "108.1-002", + "objective": "108.1", + "type": "single", + "difficulty": 2, + "question": "Auf einem System läuft `chronyd`. Welcher Befehl zeigt die konfigurierten Zeitquellen und deren Zustand?", + "options": [ + { "id": "a", "text": "`chronyc sources`", "correct": true, "explanation": "Listet die Quellen; `*` markiert die aktuell gewählte. `chronyc tracking` zeigt die Abweichung." }, + { "id": "b", "text": "`ntpq -p`", "correct": false, "explanation": "`ntpq -p` gehört zum klassischen `ntpd` und fragt dessen Peers ab." }, + { "id": "c", "text": "`chronyd -q`", "correct": false, "explanation": "Stellt die Uhr einmalig und beendet sich (ähnlich `ntpdate`)." }, + { "id": "d", "text": "`timedatectl timesync-status`", "correct": false, "explanation": "Zeigt den Status von `systemd-timesyncd`, nicht von chrony." }, + { "id": "e", "text": "`hwclock -r`", "correct": false, "explanation": "Liest nur die Hardware-Uhr." } + ], + "explanation": "Konfiguration: `/etc/chrony.conf` bzw. `/etc/chrony/chrony.conf` (Debian), beim klassischen ntpd `/etc/ntp.conf`.", + "references": ["man 1 chronyc"] + }, + { + "id": "108.1-003", + "objective": "108.1", + "type": "fill", + "difficulty": 1, + "question": "Geben Sie den `timedatectl`-Befehl ein, der die automatische Zeitsynchronisation per NTP einschaltet.", + "answers": ["timedatectl set-ntp true", "timedatectl set-ntp yes", "timedatectl set-ntp on", "timedatectl set-ntp 1"], + "explanation": "`timedatectl` ohne Argumente zeigt u. a. `NTP service: active` und `System clock synchronized`.", + "references": ["man 1 timedatectl"] + }, + { + "id": "108.1-004", + "objective": "108.1", + "type": "multi", + "difficulty": 1, + "question": "Welche Aussagen zum Network Time Protocol (NTP) treffen zu?", + "options": [ + { "id": "a", "text": "NTP verwendet UDP-Port 123.", "correct": true, "explanation": "Sowohl Client als auch Server nutzen Port 123/udp." }, + { "id": "b", "text": "`pool.ntp.org` ist ein öffentlicher Verbund von NTP-Servern.", "correct": true, "explanation": "Über DNS werden wechselnde Server aus dem Pool vergeben." }, + { "id": "c", "text": "NTP verwendet TCP-Port 123.", "correct": false, "explanation": "NTP läuft über UDP." }, + { "id": "d", "text": "`ntpdate` gleicht die Uhr dauerhaft und kontinuierlich ab.", "correct": false, "explanation": "`ntpdate` stellt die Uhr einmalig und ist veraltet." }, + { "id": "e", "text": "`date` ohne Optionen stellt die Uhr nach einem Zeitserver.", "correct": false, "explanation": "`date` ohne Optionen zeigt nur Datum und Uhrzeit an." } + ], + "explanation": "Begriffe: Stratum (Abstand zur Referenzuhr), Offset, Drift. NTP-Implementierungen: ntpd, chrony, systemd-timesyncd (nur Client).", + "references": ["RFC 5905"] + }, + { + "id": "108.2-001", + "objective": "108.2", + "type": "single", + "difficulty": 1, + "question": "Wie zeigt man alle Journal-Meldungen der systemd-Unit `ssh.service` an?", + "options": [ + { "id": "a", "text": "`journalctl -u ssh.service`", "correct": true, "explanation": "`-u` filtert nach Unit." }, + { "id": "b", "text": "`journalctl -k ssh.service`", "correct": false, "explanation": "`-k` zeigt nur Kernel-Meldungen." }, + { "id": "c", "text": "`journalctl -b ssh.service`", "correct": false, "explanation": "`-b` filtert nach Boot; der Unit-Name würde als Feldfilter missverstanden." }, + { "id": "d", "text": "`systemctl log ssh.service`", "correct": false, "explanation": "`systemctl` hat keinen Unterbefehl `log`; `systemctl status` zeigt nur die letzten Zeilen." }, + { "id": "e", "text": "`journalctl -p ssh.service`", "correct": false, "explanation": "`-p` filtert nach Priorität, z. B. `-p err`." } + ], + "explanation": "Kombinierbar: `journalctl -u ssh -b -p warning --since \"1 hour ago\"`.", + "references": ["man 1 journalctl"] + }, + { + "id": "108.2-002", + "objective": "108.2", + "type": "fill", + "difficulty": 1, + "question": "Welche `journalctl`-Option zeigt neu eintreffende Meldungen fortlaufend an (wie `tail -f`)? (nur die Option)", + "answers": ["-f", "--follow"], + "explanation": "`journalctl -f` folgt dem Journal; `-n 50` zeigt zuvor die letzten 50 Zeilen.", + "references": ["man 1 journalctl"] + }, + { + "id": "108.2-003", + "objective": "108.2", + "type": "single", + "difficulty": 2, + "question": "Was bewirkt die rsyslog-Regel `mail.err /var/log/mail.err`?", + "options": [ + { "id": "a", "text": "Meldungen der Facility `mail` mit Priorität `err` **und höher** landen in der Datei.", "correct": true, "explanation": "Eine Priorität ohne Zusatz bedeutet: diese und alle schwerwiegenderen." }, + { "id": "b", "text": "Nur Meldungen der Facility `mail` mit genau der Priorität `err` landen in der Datei.", "correct": false, "explanation": "Genau eine Priorität: `mail.=err`." }, + { "id": "c", "text": "Alle Meldungen der Facility `mail` landen in der Datei.", "correct": false, "explanation": "Das wäre `mail.*`." }, + { "id": "d", "text": "Fehlermeldungen aller Facilities landen in der Datei.", "correct": false, "explanation": "Das wäre `*.err`." }, + { "id": "e", "text": "Mail-Fehler werden per E-Mail an root geschickt.", "correct": false, "explanation": "Ziel ist eine Datei; Weiterleitung an Hosts erfolgt mit `@host` bzw. `@@host`." } + ], + "explanation": "Prioritäten aufsteigend: debug, info, notice, warning, err, crit, alert, emerg. `none` schließt aus, z. B. `*.info;mail.none`.", + "references": ["man 5 rsyslog.conf"] + }, + { + "id": "108.2-004", + "objective": "108.2", + "type": "single", + "difficulty": 1, + "question": "Mit welchem Befehl schreibt ein Shell-Skript eine eigene Meldung ins Systemprotokoll?", + "options": [ + { "id": "a", "text": "`logger \"Backup beendet\"`", "correct": true, "explanation": "`logger` übergibt die Meldung an syslog/journald; `-t` setzt einen Tag, `-p` die Priorität." }, + { "id": "b", "text": "`wall \"Backup beendet\"`", "correct": false, "explanation": "`wall` sendet die Nachricht an alle Terminals." }, + { "id": "c", "text": "`journalctl --write \"Backup beendet\"`", "correct": false, "explanation": "`journalctl` liest das Journal; eine Option `--write` gibt es nicht." }, + { "id": "d", "text": "`dmesg -w \"Backup beendet\"`", "correct": false, "explanation": "`dmesg -w` wartet auf neue Kernel-Meldungen (follow)." }, + { "id": "e", "text": "`syslog \"Backup beendet\"`", "correct": false, "explanation": "Einen Befehl `syslog` gibt es nicht." } + ], + "explanation": "Beispiel mit Facility und Priorität: `logger -p local0.notice -t backup \"fertig\"`.", + "references": ["man 1 logger"] + }, + { + "id": "108.2-005", + "objective": "108.2", + "type": "multi", + "difficulty": 2, + "question": "Wie erreicht man, dass das systemd-Journal Neustarts **überdauert** (persistent gespeichert wird)?", + "options": [ + { "id": "a", "text": "In `/etc/systemd/journald.conf` `Storage=persistent` setzen", "correct": true, "explanation": "journald schreibt dann nach `/var/log/journal`." }, + { "id": "b", "text": "Das Verzeichnis `/var/log/journal` anlegen (bei `Storage=auto`)", "correct": true, "explanation": "Bei der Standardeinstellung `auto` wird persistent gespeichert, sobald das Verzeichnis existiert." }, + { "id": "c", "text": "`Storage=volatile` setzen", "correct": false, "explanation": "`volatile` speichert nur im RAM unter `/run/log/journal`." }, + { "id": "d", "text": "`journalctl --vacuum-size=1G` ausführen", "correct": false, "explanation": "Löscht alte Journal-Dateien, bis die Größe unterschritten ist." }, + { "id": "e", "text": "`logrotate` für das Journal einrichten", "correct": false, "explanation": "journald rotiert selbst; logrotate ist für Textlogs." } + ], + "explanation": "Größe begrenzen: `SystemMaxUse=` in `journald.conf`. Journal einer anderen Installation lesen: `journalctl -D `.", + "references": ["man 5 journald.conf"] + }, + { + "id": "108.2-006", + "objective": "108.2", + "type": "single", + "difficulty": 1, + "question": "Wo legt man üblicherweise die Rotationsregeln für die Logdateien **eines einzelnen Dienstes** ab?", + "options": [ + { "id": "a", "text": "In einer Datei unter `/etc/logrotate.d/`", "correct": true, "explanation": "`/etc/logrotate.conf` bindet dieses Verzeichnis per `include` ein." }, + { "id": "b", "text": "In einer Datei unter `/etc/rsyslog.d/`", "correct": false, "explanation": "Dort stehen Regeln, wohin rsyslog Meldungen schreibt, nicht wie rotiert wird." }, + { "id": "c", "text": "In `/etc/systemd/journald.conf`", "correct": false, "explanation": "Gilt nur für das Journal, nicht für Textlogs eines Dienstes." }, + { "id": "d", "text": "In `/var/log/rotate/`", "correct": false, "explanation": "Kein Standardpfad." }, + { "id": "e", "text": "In `/etc/cron.daily/`", "correct": false, "explanation": "Dort liegt das Skript, das logrotate täglich startet, nicht die Regeln." } + ], + "explanation": "Typische Direktiven: `daily`/`weekly`, `rotate 7`, `compress`, `missingok`, `notifempty`, `postrotate … endscript`.", + "references": ["man 8 logrotate"] + }, + { + "id": "108.3-001", + "objective": "108.3", + "type": "single", + "difficulty": 1, + "question": "Welches der folgenden Programme ist ein **Mail Transfer Agent (MTA)**?", + "options": [ + { "id": "a", "text": "Postfix", "correct": true, "explanation": "Postfix nimmt Mails per SMTP an und leitet sie weiter bzw. stellt sie zu." }, + { "id": "b", "text": "Dovecot", "correct": false, "explanation": "Dovecot ist ein IMAP/POP3-Server für den Abruf von Mails." }, + { "id": "c", "text": "Thunderbird", "correct": false, "explanation": "Thunderbird ist ein Mail User Agent (MUA)." }, + { "id": "d", "text": "mutt", "correct": false, "explanation": "mutt ist ein textbasierter MUA." }, + { "id": "e", "text": "procmail", "correct": false, "explanation": "procmail ist ein Mail Delivery Agent (MDA), der Mails lokal sortiert und zustellt." } + ], + "explanation": "Weitere MTAs: Sendmail, Exim. Alle bieten aus Kompatibilitätsgründen einen `sendmail`-Befehl.", + "references": ["LPI 102-500 Objective 108.3"] + }, + { + "id": "108.3-002", + "objective": "108.3", + "type": "single", + "difficulty": 1, + "question": "In `/etc/aliases` wurde `root: admin@example.org` eingetragen. Welcher Befehl muss danach ausgeführt werden?", + "options": [ + { "id": "a", "text": "`newaliases`", "correct": true, "explanation": "Erzeugt die Alias-Datenbank (z. B. `/etc/aliases.db`) neu, die der MTA liest." }, + { "id": "b", "text": "`mailq`", "correct": false, "explanation": "`mailq` zeigt die Warteschlange." }, + { "id": "c", "text": "`sendmail -q`", "correct": false, "explanation": "Arbeitet die Warteschlange ab." }, + { "id": "d", "text": "`postfix check`", "correct": false, "explanation": "Prüft die Postfix-Konfiguration, baut die Aliase aber nicht neu." }, + { "id": "e", "text": "`systemctl restart aliases`", "correct": false, "explanation": "Einen Dienst `aliases` gibt es nicht." } + ], + "explanation": "`newaliases` entspricht `sendmail -bi`.", + "references": ["man 5 aliases", "man 1 newaliases"] + }, + { + "id": "108.3-003", + "objective": "108.3", + "type": "fill", + "difficulty": 1, + "question": "Welche Datei legt ein Benutzer in seinem Home-Verzeichnis an, um seine E-Mails an eine andere Adresse weiterzuleiten? (Dateiname)", + "answers": [".forward", "~/.forward"], + "explanation": "`~/.forward` enthält die Zieladresse(n). Systemweite Weiterleitungen gehören in `/etc/aliases`.", + "references": ["man 5 forward"] + }, + { + "id": "108.3-004", + "objective": "108.3", + "type": "single", + "difficulty": 1, + "question": "Welcher Befehl zeigt die Mail-Warteschlange des lokalen MTA an?", + "options": [ + { "id": "a", "text": "`mailq`", "correct": true, "explanation": "`mailq` entspricht `sendmail -bp` und funktioniert bei Sendmail, Postfix und Exim." }, + { "id": "b", "text": "`newaliases`", "correct": false, "explanation": "Baut die Alias-Datenbank neu." }, + { "id": "c", "text": "`mail`", "correct": false, "explanation": "`mail` ist ein einfacher MUA zum Lesen und Senden." }, + { "id": "d", "text": "`postqueue -f`", "correct": false, "explanation": "`postqueue -f` versucht, die Postfix-Warteschlange sofort zuzustellen (flush)." }, + { "id": "e", "text": "`smtpd`", "correct": false, "explanation": "`smtpd` ist ein Serverprozess von Postfix." } + ], + "explanation": "Lokale Mails von Diensten (z. B. cron) landen ohne Weiterleitung im Spool unter `/var/spool/mail/` bzw. `/var/mail/`.", + "references": ["man 1 mailq"] + }, + { + "id": "108.4-001", + "objective": "108.4", + "type": "single", + "difficulty": 1, + "question": "Auf welchem TCP-Port ist die Weboberfläche von CUPS standardmäßig erreichbar?", + "options": [ + { "id": "a", "text": "631", "correct": true, "explanation": "CUPS spricht IPP auf Port 631; dort liegt auch die Weboberfläche (http://localhost:631)." }, + { "id": "b", "text": "515", "correct": false, "explanation": "515 ist der Port des alten LPD-Protokolls." }, + { "id": "c", "text": "9100", "correct": false, "explanation": "9100 ist der Port für Raw-/JetDirect-Druck direkt auf Netzwerkdrucker." }, + { "id": "d", "text": "8080", "correct": false, "explanation": "Üblicher alternativer HTTP-Port, nicht CUPS." }, + { "id": "e", "text": "443", "correct": false, "explanation": "443 ist HTTPS." } + ], + "explanation": "CUPS-Konfiguration: `/etc/cups/cupsd.conf` (Dienst), `/etc/cups/printers.conf` (Drucker, nicht von Hand bei laufendem Dienst bearbeiten).", + "references": ["man 8 cupsd"] + }, + { + "id": "108.4-002", + "objective": "108.4", + "type": "single", + "difficulty": 1, + "question": "Welcher Befehl entfernt einen Druckauftrag aus der Warteschlange?", + "options": [ + { "id": "a", "text": "`lprm`", "correct": true, "explanation": "`lprm ` löscht den Auftrag (System-V-Variante: `cancel`)." }, + { "id": "b", "text": "`lpq`", "correct": false, "explanation": "`lpq` zeigt die Warteschlange an." }, + { "id": "c", "text": "`lpr`", "correct": false, "explanation": "`lpr` druckt eine Datei." }, + { "id": "d", "text": "`lpstat`", "correct": false, "explanation": "`lpstat` zeigt Status von Druckern und Aufträgen." }, + { "id": "e", "text": "`lpadmin`", "correct": false, "explanation": "`lpadmin` richtet Drucker ein und konfiguriert sie." } + ], + "explanation": "Berkeley-Befehle: `lpr`, `lpq`, `lprm`. System-V-Befehle: `lp`, `lpstat`, `cancel`. CUPS unterstützt beide.", + "references": ["man 1 lprm"] + }, + { + "id": "108.4-003", + "objective": "108.4", + "type": "multi", + "difficulty": 2, + "question": "Welche Aussagen zum Drucken unter Linux treffen zu?", + "options": [ + { "id": "a", "text": "`lpr -P buero bericht.pdf` druckt auf dem Drucker `buero`.", "correct": true, "explanation": "`-P` wählt den Drucker; ohne Angabe gilt der Standarddrucker." }, + { "id": "b", "text": "`lpq` zeigt die Aufträge in der Warteschlange.", "correct": true, "explanation": "Mit `-P` für einen bestimmten Drucker, `-a` für alle." }, + { "id": "c", "text": "`lpq` druckt eine Datei aus.", "correct": false, "explanation": "Drucken: `lpr` bzw. `lp`." }, + { "id": "d", "text": "Die CUPS-Dienstkonfiguration liegt in `/etc/printcap.conf`.", "correct": false, "explanation": "Sie liegt in `/etc/cups/cupsd.conf`; `/etc/printcap` ist ein Überbleibsel von LPD." }, + { "id": "e", "text": "`cupsenable buero` löscht den Drucker `buero`.", "correct": false, "explanation": "`cupsenable` aktiviert einen Drucker; löschen: `lpadmin -x buero`." } + ], + "explanation": "Annahme von Aufträgen steuern `cupsaccept`/`cupsreject`, das Drucken `cupsenable`/`cupsdisable`.", + "references": ["man 1 lpr", "man 1 lpq"] + } + ] +} diff --git a/simulator/data/lpic1_102/questions_109.json b/simulator/data/lpic1_102/questions_109.json new file mode 100644 index 0000000..ae3ac1d --- /dev/null +++ b/simulator/data/lpic1_102/questions_109.json @@ -0,0 +1,327 @@ +{ + "$schema": "../schema/questions.schema.json", + "format": "lpic-sim-questions", + "meta": { + "file": "questions_109.json", + "brief": "Fragen zu Topic 109 Netzwerkgrundlagen (LPIC-1 102-500, Objectives 5.0)", + "author": "Björn Runden ", + "owner": "Björn Runden ", + "assist": "KI-unterstützt (Claude Opus 5.5), geprüft von Björn Runden ", + "version": "0.1.0 (29.10.2026)" + }, + "exam": "lpic1-102", + "questions": [ + { + "id": "109.1-001", + "objective": "109.1", + "type": "single", + "difficulty": 1, + "question": "Welche Subnetzmaske entspricht dem Präfix `/26`?", + "options": [ + { "id": "a", "text": "`255.255.255.192`", "correct": true, "explanation": "26 Bits gesetzt: 24 + 2 → letztes Oktett 11000000 = 192." }, + { "id": "b", "text": "`255.255.255.128`", "correct": false, "explanation": "Das ist `/25`." }, + { "id": "c", "text": "`255.255.255.224`", "correct": false, "explanation": "Das ist `/27`." }, + { "id": "d", "text": "`255.255.255.240`", "correct": false, "explanation": "Das ist `/28`." }, + { "id": "e", "text": "`255.255.255.252`", "correct": false, "explanation": "Das ist `/30`." } + ], + "explanation": "Werte im letzten Oktett: /25 = 128, /26 = 192, /27 = 224, /28 = 240, /29 = 248, /30 = 252.", + "references": ["RFC 4632"] + }, + { + "id": "109.1-002", + "objective": "109.1", + "type": "single", + "difficulty": 2, + "question": "Wie viele Adressen stehen in einem IPv4-Subnetz `/27` für Hosts zur Verfügung?", + "options": [ + { "id": "a", "text": "30", "correct": true, "explanation": "2^(32−27) = 32 Adressen, abzüglich Netz- und Broadcast-Adresse = 30." }, + { "id": "b", "text": "32", "correct": false, "explanation": "Das ist die Gesamtzahl der Adressen inklusive Netz- und Broadcast-Adresse." }, + { "id": "c", "text": "62", "correct": false, "explanation": "Das gilt für `/26`." }, + { "id": "d", "text": "14", "correct": false, "explanation": "Das gilt für `/28`." }, + { "id": "e", "text": "27", "correct": false, "explanation": "Das Präfix ist die Zahl der Netzbits, nicht der Hosts." } + ], + "explanation": "Hosts = 2^(32 − Präfix) − 2. Beispiel `192.0.2.32/27`: Netz .32, Hosts .33–.62, Broadcast .63.", + "references": ["RFC 950"] + }, + { + "id": "109.1-003", + "objective": "109.1", + "type": "fill", + "difficulty": 1, + "question": "Welchen TCP-Port verwendet SSH standardmäßig? (nur die Zahl)", + "answers": ["22"], + "explanation": "Zuordnungen von Ports zu Diensten stehen in `/etc/services`.", + "references": ["man 5 services"] + }, + { + "id": "109.1-004", + "objective": "109.1", + "type": "single", + "difficulty": 2, + "question": "Welche Adresse gehört zu einem **privaten** Adressbereich nach RFC 1918?", + "options": [ + { "id": "a", "text": "`172.20.1.5`", "correct": true, "explanation": "Liegt in `172.16.0.0/12` (172.16.0.0 – 172.31.255.255)." }, + { "id": "b", "text": "`172.32.0.1`", "correct": false, "explanation": "Liegt knapp außerhalb von `172.16.0.0/12`." }, + { "id": "c", "text": "`192.169.1.1`", "correct": false, "explanation": "Privat ist nur `192.168.0.0/16`." }, + { "id": "d", "text": "`100.64.0.1`", "correct": false, "explanation": "`100.64.0.0/10` ist Shared Address Space für Carrier-Grade-NAT (RFC 6598), nicht RFC 1918." }, + { "id": "e", "text": "`169.254.1.1`", "correct": false, "explanation": "`169.254.0.0/16` ist Link-Local (automatische Adressvergabe ohne DHCP)." } + ], + "explanation": "RFC 1918: `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`.", + "references": ["RFC 1918"] + }, + { + "id": "109.1-005", + "objective": "109.1", + "type": "multi", + "difficulty": 2, + "question": "Welche Aussagen zu IPv6 treffen zu?", + "options": [ + { "id": "a", "text": "Eine IPv6-Adresse ist 128 Bit lang.", "correct": true, "explanation": "Geschrieben als 8 Gruppen à 16 Bit in Hexadezimal." }, + { "id": "b", "text": "`::1` ist die Loopback-Adresse.", "correct": true, "explanation": "Entspricht `127.0.0.1` bei IPv4." }, + { "id": "c", "text": "Adressen aus `fe80::/10` sind global routbar.", "correct": false, "explanation": "`fe80::/10` ist Link-Local und wird nicht geroutet." }, + { "id": "d", "text": "IPv6 verwendet Broadcast-Adressen wie IPv4.", "correct": false, "explanation": "IPv6 kennt keinen Broadcast; stattdessen Multicast (z. B. `ff02::1`)." }, + { "id": "e", "text": "Mehrere Nullgruppen dürfen mehrfach in einer Adresse mit `::` abgekürzt werden.", "correct": false, "explanation": "`::` darf nur einmal pro Adresse vorkommen, sonst wäre sie mehrdeutig." } + ], + "explanation": "Weitere Unterschiede: SLAAC zur automatischen Konfiguration, Neighbor Discovery statt ARP, Präfix meist `/64` im LAN.", + "references": ["RFC 4291"] + }, + { + "id": "109.1-006", + "objective": "109.1", + "type": "single", + "difficulty": 1, + "question": "Welche Zuordnung von Standardport zu Dienst ist korrekt?", + "options": [ + { "id": "a", "text": "443/tcp → HTTPS", "correct": true, "explanation": "HTTP über TLS verwendet Port 443." }, + { "id": "b", "text": "25/tcp → POP3", "correct": false, "explanation": "25 ist SMTP; POP3 nutzt 110 (POP3S 995)." }, + { "id": "c", "text": "53 → NTP", "correct": false, "explanation": "53 ist DNS; NTP nutzt 123/udp." }, + { "id": "d", "text": "143/tcp → SNMP", "correct": false, "explanation": "143 ist IMAP (IMAPS 993); SNMP nutzt 161/udp." }, + { "id": "e", "text": "21/tcp → SSH", "correct": false, "explanation": "21 ist FTP (Steuerkanal); SSH nutzt 22." } + ], + "explanation": "Prüfungsrelevant: 20/21 FTP, 22 SSH, 23 Telnet, 25 SMTP, 53 DNS, 80 HTTP, 110 POP3, 123 NTP, 139 NetBIOS, 143 IMAP, 161/162 SNMP, 389 LDAP, 443 HTTPS, 465 SMTPS, 514 syslog, 636 LDAPS, 993 IMAPS, 995 POP3S.", + "references": ["man 5 services"] + }, + { + "id": "109.2-001", + "objective": "109.2", + "type": "single", + "difficulty": 1, + "question": "Welches Kommandozeilenwerkzeug verwaltet Verbindungen des NetworkManager?", + "options": [ + { "id": "a", "text": "`nmcli`", "correct": true, "explanation": "z. B. `nmcli connection show`, `nmcli device status`, `nmcli con up `." }, + { "id": "b", "text": "`ifconfig`", "correct": false, "explanation": "Altes Werkzeug (net-tools), das Schnittstellen direkt konfiguriert, ohne NetworkManager." }, + { "id": "c", "text": "`iwconfig`", "correct": false, "explanation": "Altes Werkzeug für WLAN-Parameter." }, + { "id": "d", "text": "`systemd-networkd`", "correct": false, "explanation": "Ein eigener Netzwerkdienst, kein Frontend für NetworkManager." }, + { "id": "e", "text": "`netstat`", "correct": false, "explanation": "Zeigt Verbindungen und Routen, konfiguriert nichts." } + ], + "explanation": "Textoberfläche für NetworkManager: `nmtui`. systemd-networkd wird über `.network`-Dateien und `networkctl` verwaltet.", + "references": ["man 1 nmcli"] + }, + { + "id": "109.2-002", + "objective": "109.2", + "type": "single", + "difficulty": 1, + "question": "Wie setzt man auf einem systemd-System den Hostnamen dauerhaft auf `web01`?", + "options": [ + { "id": "a", "text": "`hostnamectl set-hostname web01`", "correct": true, "explanation": "Setzt den Hostnamen sofort und schreibt ihn nach `/etc/hostname`." }, + { "id": "b", "text": "`hostname web01`", "correct": false, "explanation": "Gilt nur bis zum nächsten Neustart." }, + { "id": "c", "text": "`sysctl kernel.hostname=web01`", "correct": false, "explanation": "Ändert nur den Laufzeitwert im Kernel." }, + { "id": "d", "text": "`domainname web01`", "correct": false, "explanation": "Setzt den NIS-Domainnamen." }, + { "id": "e", "text": "Nur einen Eintrag in `/etc/hosts` ergänzen", "correct": false, "explanation": "`/etc/hosts` dient der Namensauflösung, nicht dem Setzen des Hostnamens." } + ], + "explanation": "Den eigenen Namen trotzdem in `/etc/hosts` eintragen, damit er lokal auflösbar ist.", + "references": ["man 1 hostnamectl"] + }, + { + "id": "109.2-003", + "objective": "109.2", + "type": "fill", + "difficulty": 1, + "question": "In welcher Datei (vollständiger Pfad) steht der statische Hostname des Systems?", + "answers": ["/etc/hostname"], + "explanation": "Die Datei enthält nur den Namen in einer Zeile.", + "references": ["man 5 hostname"] + }, + { + "id": "109.2-004", + "objective": "109.2", + "type": "single", + "difficulty": 1, + "question": "Welche Zeile ist in `/etc/hosts` korrekt aufgebaut?", + "options": [ + { "id": "a", "text": "`192.0.2.10 web01.example.org web01`", "correct": true, "explanation": "IP-Adresse, kanonischer Name, optional Aliase – durch Leerraum getrennt." }, + { "id": "b", "text": "`web01.example.org 192.0.2.10`", "correct": false, "explanation": "Die IP-Adresse muss am Anfang stehen." }, + { "id": "c", "text": "`192.0.2.10:web01.example.org`", "correct": false, "explanation": "Die Felder werden durch Leerraum getrennt, nicht durch Doppelpunkt." }, + { "id": "d", "text": "`host web01 = 192.0.2.10`", "correct": false, "explanation": "Keine gültige Syntax." }, + { "id": "e", "text": "`nameserver 192.0.2.10`", "correct": false, "explanation": "Das ist Syntax von `/etc/resolv.conf`." } + ], + "explanation": "Ob `/etc/hosts` vor DNS gefragt wird, legt die Zeile `hosts:` in `/etc/nsswitch.conf` fest.", + "references": ["man 5 hosts"] + }, + { + "id": "109.2-005", + "objective": "109.2", + "type": "multi", + "difficulty": 2, + "question": "Welche Befehle setzen (nicht dauerhaft) korrekt eine IPv4-Adresse bzw. das Standard-Gateway?", + "options": [ + { "id": "a", "text": "`ip addr add 192.0.2.5/24 dev eth0`", "correct": true, "explanation": "Fügt der Schnittstelle eine Adresse mit Präfix hinzu." }, + { "id": "b", "text": "`ip route add default via 192.0.2.1`", "correct": true, "explanation": "Setzt die Standardroute über das Gateway." }, + { "id": "c", "text": "`ip addr set eth0 192.0.2.5`", "correct": false, "explanation": "`ip addr` kennt kein `set`; Adressen werden mit `add` hinzugefügt." }, + { "id": "d", "text": "`ip gateway add 192.0.2.1`", "correct": false, "explanation": "Ein Objekt `gateway` gibt es bei `ip` nicht." }, + { "id": "e", "text": "`ip route default 192.0.2.1`", "correct": false, "explanation": "Es fehlen Aktion (`add`) und Schlüsselwort `via`." } + ], + "explanation": "Mit `ip` gesetzte Werte gehen beim Neustart verloren. Dauerhaft je nach System: NetworkManager, systemd-networkd, netplan oder `/etc/network/interfaces`.", + "references": ["man 8 ip-address", "man 8 ip-route"] + }, + { + "id": "109.2-006", + "objective": "109.2", + "type": "single", + "difficulty": 2, + "question": "Wo werden auf einem Debian-System mit **ifupdown** Netzwerkschnittstellen dauerhaft konfiguriert?", + "options": [ + { "id": "a", "text": "`/etc/network/interfaces`", "correct": true, "explanation": "Dort stehen z. B. `auto eth0` und `iface eth0 inet static` mit `address`, `gateway`; aktivieren mit `ifup`." }, + { "id": "b", "text": "`/etc/sysconfig/network-scripts/ifcfg-eth0`", "correct": false, "explanation": "Klassischer Ort der Red-Hat-Familie, nicht Debian." }, + { "id": "c", "text": "`/etc/netplan/01-netcfg.yaml`", "correct": false, "explanation": "netplan wird bei Ubuntu verwendet und erzeugt Konfiguration für networkd oder NetworkManager." }, + { "id": "d", "text": "`/etc/resolv.conf`", "correct": false, "explanation": "Enthält nur DNS-Einstellungen." }, + { "id": "e", "text": "`/etc/hosts`", "correct": false, "explanation": "Statische Namensauflösung, keine Schnittstellenkonfiguration." } + ], + "explanation": "Hinweis: LPI hat angekündigt, `ifup`/`ifdown` und net-tools künftig aus den Objectives zu entfernen; in Version 5.0 sind sie noch enthalten (Stand 29.10.2026).", + "references": ["man 5 interfaces"] + }, + { + "id": "109.3-001", + "objective": "109.3", + "type": "single", + "difficulty": 1, + "question": "Auf welchem Protokoll und welchen Nachrichten beruht `ping`?", + "options": [ + { "id": "a", "text": "ICMP Echo Request / Echo Reply", "correct": true, "explanation": "`ping` sendet ICMP Echo Requests und wertet die Antworten aus (IPv6: ICMPv6, `ping -6`)." }, + { "id": "b", "text": "UDP-Pakete an Port 7", "correct": false, "explanation": "Port 7 ist der echo-Dienst; `ping` nutzt ihn nicht." }, + { "id": "c", "text": "TCP-SYN-Pakete", "correct": false, "explanation": "TCP wird von `ping` nicht verwendet." }, + { "id": "d", "text": "ARP Requests", "correct": false, "explanation": "ARP löst im LAN IP- in MAC-Adressen auf (`arping` nutzt ARP)." }, + { "id": "e", "text": "DNS-Anfragen", "correct": false, "explanation": "DNS wird höchstens zur Auflösung des Zielnamens genutzt." } + ], + "explanation": "Keine Antwort auf ping heißt nicht zwingend, dass der Host aus ist – ICMP kann gefiltert sein.", + "references": ["man 8 ping"] + }, + { + "id": "109.3-002", + "objective": "109.3", + "type": "single", + "difficulty": 2, + "question": "Welcher Befehl listet alle lauschenden TCP- und UDP-Ports numerisch mit den zugehörigen Prozessen?", + "options": [ + { "id": "a", "text": "`ss -tulpn`", "correct": true, "explanation": "`-t` TCP, `-u` UDP, `-l` lauschend, `-p` Prozess, `-n` numerisch." }, + { "id": "b", "text": "`netstat -r`", "correct": false, "explanation": "`-r` zeigt die Routingtabelle." }, + { "id": "c", "text": "`ip link show`", "correct": false, "explanation": "Zeigt Schnittstellen und deren Status." }, + { "id": "d", "text": "`ss -s`", "correct": false, "explanation": "Zeigt nur eine Zusammenfassung der Sockets." }, + { "id": "e", "text": "`nc -l 22`", "correct": false, "explanation": "Startet selbst einen lauschenden Socket." } + ], + "explanation": "Die alte Entsprechung ist `netstat -tulpn` (net-tools). Prozessangaben fremder Benutzer sieht nur root.", + "references": ["man 8 ss"] + }, + { + "id": "109.3-003", + "objective": "109.3", + "type": "fill", + "difficulty": 1, + "question": "Mit welchem Befehl (nur der Name) ermittelt man die Router (Hops) auf dem Weg zu einem Zielhost?", + "answers": ["traceroute", "tracepath", "traceroute6", "tracepath6", "mtr"], + "explanation": "`traceroute` erhöht schrittweise die TTL und wertet die ICMP-Antworten „Time Exceeded“ aus. `tracepath` braucht keine Root-Rechte und ermittelt zusätzlich die Path-MTU.", + "references": ["man 8 traceroute", "man 8 tracepath"] + }, + { + "id": "109.3-004", + "objective": "109.3", + "type": "single", + "difficulty": 1, + "question": "Welcher Befehl zeigt die aktuelle Routingtabelle an?", + "options": [ + { "id": "a", "text": "`ip route`", "correct": true, "explanation": "Kurz `ip r`; zeigt u. a. die `default`-Route." }, + { "id": "b", "text": "`ip addr`", "correct": false, "explanation": "Zeigt die Adressen der Schnittstellen." }, + { "id": "c", "text": "`ip neigh`", "correct": false, "explanation": "Zeigt den Neighbor-/ARP-Cache." }, + { "id": "d", "text": "`ss -r`", "correct": false, "explanation": "`-r` löst bei `ss` Namen auf; es zeigt keine Routen." }, + { "id": "e", "text": "`host -r`", "correct": false, "explanation": "`host` ist ein DNS-Abfragewerkzeug." } + ], + "explanation": "Alte Werkzeuge: `route -n`, `netstat -rn`. Welche Route für ein Ziel gilt: `ip route get 198.51.100.7`.", + "references": ["man 8 ip-route"] + }, + { + "id": "109.3-005", + "objective": "109.3", + "type": "multi", + "difficulty": 2, + "question": "Mit welchen Befehlen kann man prüfen, ob ein Server Verbindungen auf **TCP-Port 443** annimmt?", + "options": [ + { "id": "a", "text": "`nc -zv server.example.org 443`", "correct": true, "explanation": "`-z` baut nur die Verbindung auf, ohne Daten zu senden; `-v` meldet das Ergebnis." }, + { "id": "b", "text": "`telnet server.example.org 443`", "correct": true, "explanation": "Kommt eine Verbindung zustande, nimmt der Port Verbindungen an." }, + { "id": "c", "text": "`ping -p 443 server.example.org`", "correct": false, "explanation": "`-p` legt bei ping ein Füllmuster fest; ICMP kennt keine Ports." }, + { "id": "d", "text": "`dig server.example.org 443`", "correct": false, "explanation": "`dig` stellt nur DNS-Anfragen." }, + { "id": "e", "text": "`ip neigh server.example.org 443`", "correct": false, "explanation": "Zeigt den Neighbor-Cache und prüft keine Ports." } + ], + "explanation": "Vorgehen bei Netzproblemen von unten nach oben: Link (`ip link`) → Adresse (`ip addr`) → Gateway (`ping`) → Route (`ip route`, `traceroute`) → DNS (`dig`) → Port (`nc`).", + "references": ["man 1 nc"] + }, + { + "id": "109.3-006", + "objective": "109.3", + "type": "single", + "difficulty": 2, + "question": "`ping 198.51.100.7` funktioniert, `ping www.example.org` meldet jedoch „Name or service not known“. Was sollte man als Erstes prüfen?", + "options": [ + { "id": "a", "text": "Die Namensauflösung, z. B. `/etc/resolv.conf` bzw. `resolvectl status`", "correct": true, "explanation": "IP-Verbindung und Routing funktionieren; nur der Name lässt sich nicht auflösen." }, + { "id": "b", "text": "Ob ein Standard-Gateway gesetzt ist", "correct": false, "explanation": "Der Ping an eine entfernte IP funktioniert – Routing ist also in Ordnung." }, + { "id": "c", "text": "Ob die Netzwerkkarte einen Link hat", "correct": false, "explanation": "Ohne Link wäre auch der Ping an die IP gescheitert." }, + { "id": "d", "text": "Ob eine Firewall ICMP blockiert", "correct": false, "explanation": "ICMP kommt durch, wie der erste Ping zeigt." }, + { "id": "e", "text": "Ob die MTU zu groß ist", "correct": false, "explanation": "MTU-Probleme zeigen sich nicht als Fehler bei der Namensauflösung." } + ], + "explanation": "DNS gezielt testen: `dig www.example.org`, `host www.example.org`, `getent hosts www.example.org`.", + "references": ["man 5 resolv.conf"] + }, + { + "id": "109.4-001", + "objective": "109.4", + "type": "single", + "difficulty": 2, + "question": "Welche Datei legt fest, in welcher Reihenfolge Quellen wie `files` (also `/etc/hosts`) und `dns` zur Auflösung von Hostnamen befragt werden?", + "options": [ + { "id": "a", "text": "`/etc/nsswitch.conf`", "correct": true, "explanation": "Zeile z. B. `hosts: files dns`." }, + { "id": "b", "text": "`/etc/resolv.conf`", "correct": false, "explanation": "Enthält die DNS-Server und Suchdomänen, nicht die Reihenfolge der Quellen." }, + { "id": "c", "text": "`/etc/hosts`", "correct": false, "explanation": "Ist selbst eine Quelle (`files`)." }, + { "id": "d", "text": "`/etc/hostname`", "correct": false, "explanation": "Enthält den eigenen Hostnamen." }, + { "id": "e", "text": "`/etc/systemd/resolved.conf`", "correct": false, "explanation": "Konfiguriert den Dienst systemd-resolved, nicht die NSS-Reihenfolge." } + ], + "explanation": "NSS (Name Service Switch) regelt auch `passwd`, `group` usw.; `getent` fragt genau diese Kette ab.", + "references": ["man 5 nsswitch.conf"] + }, + { + "id": "109.4-002", + "objective": "109.4", + "type": "fill", + "difficulty": 1, + "question": "Mit welchem Schlüsselwort trägt man in `/etc/resolv.conf` einen DNS-Server ein?", + "answers": ["nameserver"], + "explanation": "Beispiel: `nameserver 192.0.2.53`. Weitere Schlüsselwörter: `search`, `domain`, `options`. Bei systemd-resolved verweist die Datei oft auf den Stub `127.0.0.53`.", + "references": ["man 5 resolv.conf"] + }, + { + "id": "109.4-003", + "objective": "109.4", + "type": "multi", + "difficulty": 2, + "question": "Welche Programme stellen **gezielt DNS-Anfragen** an einen Nameserver (ohne `/etc/hosts` zu berücksichtigen)?", + "options": [ + { "id": "a", "text": "`dig`", "correct": true, "explanation": "Ausführliche Abfragen, z. B. `dig @192.0.2.53 example.org MX`." }, + { "id": "b", "text": "`host`", "correct": true, "explanation": "Kompakte Ausgabe, z. B. `host example.org`." }, + { "id": "c", "text": "`nslookup`", "correct": true, "explanation": "Älteres, interaktiv nutzbares DNS-Werkzeug." }, + { "id": "d", "text": "`getent hosts`", "correct": false, "explanation": "Fragt über NSS ab – also auch `/etc/hosts` gemäß `nsswitch.conf`." }, + { "id": "e", "text": "`ip neigh`", "correct": false, "explanation": "Zeigt den ARP-/Neighbor-Cache." } + ], + "explanation": "Ein Name ist per `dig` auflösbar, Programme finden ihn trotzdem nicht? Dann `nsswitch.conf` und `/etc/hosts` prüfen – und umgekehrt.", + "references": ["man 1 dig", "man 1 host"] + } + ] +} diff --git a/simulator/data/lpic1_102/questions_110.json b/simulator/data/lpic1_102/questions_110.json new file mode 100644 index 0000000..bb0e58d --- /dev/null +++ b/simulator/data/lpic1_102/questions_110.json @@ -0,0 +1,237 @@ +{ + "$schema": "../schema/questions.schema.json", + "format": "lpic-sim-questions", + "meta": { + "file": "questions_110.json", + "brief": "Fragen zu Topic 110 Sicherheit (LPIC-1 102-500, Objectives 5.0)", + "author": "Björn Runden ", + "owner": "Björn Runden ", + "assist": "KI-unterstützt (Claude Opus 5.5), geprüft von Björn Runden ", + "version": "0.1.0 (29.10.2026)" + }, + "exam": "lpic1-102", + "questions": [ + { + "id": "110.1-001", + "objective": "110.1", + "type": "single", + "difficulty": 2, + "question": "Welcher Befehl findet alle Dateien, bei denen das **SUID-Bit** gesetzt ist?", + "options": [ + { "id": "a", "text": "`find / -perm -4000 -type f`", "correct": true, "explanation": "`-perm -4000`: mindestens das SUID-Bit gesetzt, andere Bits beliebig." }, + { "id": "b", "text": "`find / -perm 4000 -type f`", "correct": false, "explanation": "Ohne `-` müssen die Rechte **exakt** 4000 sein – praktisch keine Datei." }, + { "id": "c", "text": "`find / -perm -2000 -type f`", "correct": false, "explanation": "2000 ist das SGID-Bit." }, + { "id": "d", "text": "`find / -type s`", "correct": false, "explanation": "`-type s` findet Sockets." }, + { "id": "e", "text": "`find / -user root -type f`", "correct": false, "explanation": "Findet alle Dateien von root, unabhängig von SUID." } + ], + "explanation": "`-perm /6000` findet Dateien mit SUID **oder** SGID. Unerwartete SUID-Programme sind ein Sicherheitsrisiko.", + "references": ["man 1 find"] + }, + { + "id": "110.1-002", + "objective": "110.1", + "type": "single", + "difficulty": 1, + "question": "Wie bearbeitet man die sudo-Konfiguration `/etc/sudoers` sicher?", + "options": [ + { "id": "a", "text": "Mit `visudo`", "correct": true, "explanation": "`visudo` sperrt die Datei und prüft die Syntax vor dem Speichern; ein Fehler könnte sonst sudo unbenutzbar machen." }, + { "id": "b", "text": "Direkt mit `vi /etc/sudoers`", "correct": false, "explanation": "Keine Syntaxprüfung – ein Tippfehler kann den Zugriff auf sudo sperren." }, + { "id": "c", "text": "Mit `sudo -l`", "correct": false, "explanation": "`sudo -l` zeigt nur die erlaubten Befehle des Benutzers." }, + { "id": "d", "text": "Mit `chmod 777 /etc/sudoers` und einem Editor", "correct": false, "explanation": "sudo verweigert den Dienst bei falschen Rechten; zudem wäre das ein Sicherheitsloch." }, + { "id": "e", "text": "Mit `su -c sudoers`", "correct": false, "explanation": "Führt einen Befehl `sudoers` als root aus – den es nicht gibt." } + ], + "explanation": "Ergänzungen besser als eigene Dateien unter `/etc/sudoers.d/` (`visudo -f /etc/sudoers.d/team`). Beispielzeile: `%admin ALL=(ALL) ALL`.", + "references": ["man 8 visudo", "man 5 sudoers"] + }, + { + "id": "110.1-003", + "objective": "110.1", + "type": "fill", + "difficulty": 1, + "question": "Welcher Befehl (nur der Name) zeigt die Liste der letzten Anmeldungen und Neustarts aus `/var/log/wtmp`?", + "answers": ["last"], + "explanation": "`last` liest `wtmp`, `lastb` die fehlgeschlagenen Anmeldungen aus `btmp`. Aktuell angemeldete Benutzer zeigen `who` und `w`.", + "references": ["man 1 last"] + }, + { + "id": "110.1-004", + "objective": "110.1", + "type": "multi", + "difficulty": 2, + "question": "Welche Aussagen treffen zu?", + "options": [ + { "id": "a", "text": "`ulimit -n` zeigt die maximale Anzahl offener Dateien für die aktuelle Shell.", "correct": true, "explanation": "`ulimit -a` zeigt alle Limits; dauerhaft per `/etc/security/limits.conf`." }, + { "id": "b", "text": "`who` zeigt die aktuell angemeldeten Benutzer.", "correct": true, "explanation": "Liest `utmp`; `w` zeigt zusätzlich deren Aktivität." }, + { "id": "c", "text": "`su -` übernimmt die Umgebung des aufrufenden Benutzers unverändert.", "correct": false, "explanation": "`su -` startet eine Login-Shell mit der Umgebung des Zielbenutzers." }, + { "id": "d", "text": "`sudo -l` zeigt das Passwort von root an.", "correct": false, "explanation": "Es listet die per sudo erlaubten Befehle." }, + { "id": "e", "text": "`chage -l anna` sperrt das Konto von `anna`.", "correct": false, "explanation": "`chage -l` zeigt nur die Passwort-Alterung an." } + ], + "explanation": "Sicherheitsrelevante Befehle aus 110.1: `find`, `passwd`, `fuser`, `lsof`, `nmap`, `chage`, `netstat`, `sudo`, `su`, `usermod`, `ulimit`, `who`, `w`, `last`.", + "references": ["help ulimit", "man 1 who"] + }, + { + "id": "110.2-001", + "objective": "110.2", + "type": "single", + "difficulty": 1, + "question": "Ein nicht benötigter Dienst soll sofort gestoppt werden und beim nächsten Start nicht mehr starten. Welcher Befehl leistet beides?", + "options": [ + { "id": "a", "text": "`systemctl disable --now dienst`", "correct": true, "explanation": "`disable` entfernt die Autostart-Verknüpfungen, `--now` stoppt zusätzlich sofort." }, + { "id": "b", "text": "`systemctl stop dienst`", "correct": false, "explanation": "Stoppt nur; beim nächsten Start läuft der Dienst wieder." }, + { "id": "c", "text": "`systemctl reload dienst`", "correct": false, "explanation": "Lässt den Dienst seine Konfiguration neu lesen." }, + { "id": "d", "text": "`systemctl status dienst`", "correct": false, "explanation": "Zeigt nur den Zustand." }, + { "id": "e", "text": "`systemctl isolate dienst`", "correct": false, "explanation": "`isolate` ist für Targets gedacht und beendet alle nicht zugehörigen Units." } + ], + "explanation": "Noch strenger: `systemctl mask` verhindert auch den manuellen Start oder den Start als Abhängigkeit. Grundsatz: Was nicht läuft, kann nicht angegriffen werden.", + "references": ["man 1 systemctl"] + }, + { + "id": "110.2-002", + "objective": "110.2", + "type": "single", + "difficulty": 2, + "question": "Was bedeutet ein `!` am Anfang des Passwortfelds eines Eintrags in `/etc/shadow`?", + "options": [ + { "id": "a", "text": "Das Passwort ist gesperrt; eine Anmeldung per Passwort ist nicht möglich.", "correct": true, "explanation": "Gesetzt z. B. durch `passwd -l` oder `usermod -L`; der ursprüngliche Hash bleibt dahinter erhalten." }, + { "id": "b", "text": "Das Konto hat kein Passwort; Anmeldung ohne Passwort ist möglich.", "correct": false, "explanation": "Ein **leeres** Feld bedeutet kein Passwort." }, + { "id": "c", "text": "Das Passwort muss bei der nächsten Anmeldung geändert werden.", "correct": false, "explanation": "Das wird über das Feld „letzte Änderung“ = 0 erreicht (`chage -d 0`)." }, + { "id": "d", "text": "Der Hash wurde mit SHA-512 erzeugt.", "correct": false, "explanation": "Das Verfahren erkennt man am Präfix, z. B. `$6$` für SHA-512 oder `$y$` für yescrypt." }, + { "id": "e", "text": "Der Benutzer ist Mitglied der Gruppe `wheel`.", "correct": false, "explanation": "Gruppenmitgliedschaften stehen in `/etc/group`." } + ], + "explanation": "`*` oder `!` allein werden für Systemkonten verwendet, die sich nie mit Passwort anmelden sollen.", + "references": ["man 5 shadow"] + }, + { + "id": "110.2-003", + "objective": "110.2", + "type": "single", + "difficulty": 2, + "question": "`/etc/hosts.allow` ist leer, `/etc/hosts.deny` enthält `ALL: ALL`. Was bewirkt das bei Diensten, die TCP-Wrapper (libwrap) verwenden?", + "options": [ + { "id": "a", "text": "Alle Zugriffe auf diese Dienste werden von allen Hosts abgewiesen.", "correct": true, "explanation": "Zuerst wird `hosts.allow` geprüft (kein Treffer), dann `hosts.deny`: Alle Dienste, alle Clients → abgelehnt." }, + { "id": "b", "text": "Die Kernel-Firewall blockiert sämtlichen Netzwerkverkehr.", "correct": false, "explanation": "TCP-Wrapper wirken nur bei Programmen, die libwrap nutzen, nicht im Kernel." }, + { "id": "c", "text": "Alle lokalen Anmeldungen an der Konsole werden verhindert.", "correct": false, "explanation": "Konsolenanmeldungen werden von TCP-Wrappern nicht erfasst." }, + { "id": "d", "text": "Alle Zugriffe werden erlaubt, weil `hosts.deny` zuerst gelesen wird.", "correct": false, "explanation": "Die Reihenfolge ist `hosts.allow`, dann `hosts.deny`." }, + { "id": "e", "text": "Nichts, weil die Syntax ungültig ist.", "correct": false, "explanation": "`dienst: client` mit `ALL` als Platzhalter ist gültig." } + ], + "explanation": "Typisches Muster: `hosts.deny` = `ALL: ALL`, Ausnahmen in `hosts.allow`, z. B. `sshd: 192.0.2.`. Laut LPI sollen TCP-Wrapper künftig aus den Objectives entfallen; in 5.0 sind sie noch enthalten (Stand 29.10.2026).", + "references": ["man 5 hosts_access"] + }, + { + "id": "110.2-004", + "objective": "110.2", + "type": "multi", + "difficulty": 1, + "question": "Mit welchen Befehlen stellt man fest, welche Netzwerkdienste auf einem Rechner erreichbar sind?", + "options": [ + { "id": "a", "text": "`ss -tuln`", "correct": true, "explanation": "Lokale Sicht: alle lauschenden TCP-/UDP-Sockets." }, + { "id": "b", "text": "`nmap localhost`", "correct": true, "explanation": "Portscan von außen bzw. lokal; nur gegen eigene Systeme oder mit Erlaubnis." }, + { "id": "c", "text": "`systemctl list-timers`", "correct": false, "explanation": "Listet systemd-Timer." }, + { "id": "d", "text": "`ip addr`", "correct": false, "explanation": "Zeigt nur Adressen der Schnittstellen." }, + { "id": "e", "text": "`lsmod`", "correct": false, "explanation": "Listet Kernelmodule." } + ], + "explanation": "Weitere: `netstat -tuln`, `lsof -i`, `fuser`. Ziel: unnötige Dienste finden und abschalten.", + "references": ["man 8 ss", "man 1 nmap"] + }, + { + "id": "110.2-005", + "objective": "110.2", + "type": "fill", + "difficulty": 1, + "question": "Welche Datei (vollständiger Pfad) verhindert, solange sie existiert, die Anmeldung aller Benutzer außer root? Ihr Inhalt wird abgewiesenen Benutzern angezeigt.", + "answers": ["/etc/nologin"], + "explanation": "Nützlich bei Wartungsarbeiten; `shutdown` legt sie kurz vor dem Herunterfahren automatisch an (bei systemd unter `/run/nologin`).", + "references": ["man 5 nologin"] + }, + { + "id": "110.3-001", + "objective": "110.3", + "type": "single", + "difficulty": 1, + "question": "Mit welchem Befehl erzeugt ein Benutzer ein neues SSH-Schlüsselpaar vom Typ Ed25519?", + "options": [ + { "id": "a", "text": "`ssh-keygen -t ed25519`", "correct": true, "explanation": "Erzeugt `~/.ssh/id_ed25519` (privat) und `~/.ssh/id_ed25519.pub` (öffentlich)." }, + { "id": "b", "text": "`ssh-add -t ed25519`", "correct": false, "explanation": "`ssh-add` lädt Schlüssel in den ssh-agent (`-t` = Lebensdauer)." }, + { "id": "c", "text": "`ssh-copy-id -t ed25519`", "correct": false, "explanation": "`ssh-copy-id` überträgt einen öffentlichen Schlüssel auf einen Server." }, + { "id": "d", "text": "`ssh-agent ed25519`", "correct": false, "explanation": "`ssh-agent` hält entschlüsselte Schlüssel im Speicher, erzeugt aber keine." }, + { "id": "e", "text": "`gpg --gen-key --ssh`", "correct": false, "explanation": "`gpg` erzeugt OpenPGP-Schlüssel; die Option `--ssh` gibt es so nicht." } + ], + "explanation": "Weitere Typen: `rsa` (mit `-b 4096`), `ecdsa`. Eine Passphrase schützt den privaten Schlüssel.", + "references": ["man 1 ssh-keygen"] + }, + { + "id": "110.3-002", + "objective": "110.3", + "type": "fill", + "difficulty": 1, + "question": "In welche Datei im Home-Verzeichnis des Zielbenutzers auf dem **Server** gehört der öffentliche Schlüssel, damit eine Anmeldung per Schlüssel möglich ist? (Pfad relativ zum Home oder mit `~`)", + "answers": ["~/.ssh/authorized_keys", ".ssh/authorized_keys", "authorized_keys"], + "explanation": "Ein Schlüssel pro Zeile; `ssh-copy-id benutzer@server` trägt ihn ein. Zu offene Rechte auf `~/.ssh` (700) oder die Datei (600) lassen sshd den Schlüssel ignorieren.", + "references": ["man 8 sshd (Abschnitt AUTHORIZED_KEYS FILE FORMAT)"] + }, + { + "id": "110.3-003", + "objective": "110.3", + "type": "single", + "difficulty": 1, + "question": "Wozu dient die Datei `~/.ssh/known_hosts` auf dem Client?", + "options": [ + { "id": "a", "text": "Sie speichert die Host-Schlüssel bereits besuchter Server, um sie bei späteren Verbindungen zu prüfen.", "correct": true, "explanation": "Ändert sich der Host-Schlüssel, warnt ssh vor einem möglichen Man-in-the-Middle-Angriff." }, + { "id": "b", "text": "Sie enthält die öffentlichen Schlüssel von Benutzern, die sich anmelden dürfen.", "correct": false, "explanation": "Das ist `~/.ssh/authorized_keys` auf dem Server." }, + { "id": "c", "text": "Sie enthält den privaten Schlüssel des Benutzers.", "correct": false, "explanation": "Private Schlüssel liegen z. B. in `~/.ssh/id_ed25519`." }, + { "id": "d", "text": "Sie listet die Hosts, die per SSH gesperrt sind.", "correct": false, "explanation": "Eine Sperrliste ist das nicht." }, + { "id": "e", "text": "Sie enthält die Client-Einstellungen wie Benutzername und Port je Host.", "correct": false, "explanation": "Das ist `~/.ssh/config`." } + ], + "explanation": "Einen veralteten Eintrag entfernt man mit `ssh-keygen -R host`. Die Host-Schlüssel des Servers liegen in `/etc/ssh/ssh_host_*`.", + "references": ["man 1 ssh (Abschnitt VERIFYING HOST KEYS)"] + }, + { + "id": "110.3-004", + "objective": "110.3", + "type": "single", + "difficulty": 2, + "question": "Die Datei `vertrag.pdf` soll mit GnuPG so verschlüsselt werden, dass nur `anna@example.org` sie entschlüsseln kann. Welcher Befehl ist korrekt?", + "options": [ + { "id": "a", "text": "`gpg --encrypt --recipient anna@example.org vertrag.pdf`", "correct": true, "explanation": "Verschlüsselt mit Annas öffentlichem Schlüssel; Ergebnis `vertrag.pdf.gpg`." }, + { "id": "b", "text": "`gpg --sign --recipient anna@example.org vertrag.pdf`", "correct": false, "explanation": "`--sign` signiert mit dem eigenen privaten Schlüssel; verschlüsselt wird nicht." }, + { "id": "c", "text": "`gpg --export anna@example.org vertrag.pdf`", "correct": false, "explanation": "`--export` gibt öffentliche Schlüssel aus." }, + { "id": "d", "text": "`gpg --decrypt --recipient anna@example.org vertrag.pdf`", "correct": false, "explanation": "`--decrypt` entschlüsselt." }, + { "id": "e", "text": "`gpg --gen-key anna@example.org vertrag.pdf`", "correct": false, "explanation": "`--gen-key` erzeugt ein neues eigenes Schlüsselpaar." } + ], + "explanation": "Dazu muss Annas öffentlicher Schlüssel importiert sein (`gpg --import`). Signatur prüfen: `gpg --verify`. Schlüssel widerrufen: Widerrufszertifikat (`--gen-revoke`).", + "references": ["man 1 gpg"] + }, + { + "id": "110.3-005", + "objective": "110.3", + "type": "multi", + "difficulty": 2, + "question": "Welche Aussagen zu OpenSSH treffen zu?", + "options": [ + { "id": "a", "text": "Mit `ssh -L 8080:localhost:80 benutzer@server` wird der lokale Port 8080 über SSH an Port 80 des Servers weitergeleitet.", "correct": true, "explanation": "Lokales Port-Forwarding; „localhost“ ist aus Sicht des Servers gemeint." }, + { "id": "b", "text": "`ssh-agent` hält entschlüsselte private Schlüssel im Speicher, sodass die Passphrase nur einmal eingegeben werden muss.", "correct": true, "explanation": "Schlüssel werden mit `ssh-add` in den Agent geladen." }, + { "id": "c", "text": "Ein privater Schlüssel sollte die Rechte 644 haben.", "correct": false, "explanation": "Private Schlüssel nur für den Eigentümer lesbar (600); sonst verweigert ssh sie." }, + { "id": "d", "text": "`ssh -R` startet auf dem Server eine grafische X11-Sitzung.", "correct": false, "explanation": "`-R` richtet Remote-Port-Forwarding ein; X11-Weiterleitung ist `-X`/`-Y`." }, + { "id": "e", "text": "Die Server-Konfiguration steht in `~/.ssh/config`.", "correct": false, "explanation": "Server: `/etc/ssh/sshd_config`; `~/.ssh/config` ist Client-Konfiguration." } + ], + "explanation": "Härtung in `sshd_config`: z. B. `PermitRootLogin no`, `PasswordAuthentication no`.", + "references": ["man 1 ssh", "man 5 sshd_config"] + }, + { + "id": "110.3-006", + "objective": "110.3", + "type": "single", + "difficulty": 1, + "question": "Nach `ssh-keygen -t ed25519` mit Standardnamen: Welche Datei ist der **private** Schlüssel?", + "options": [ + { "id": "a", "text": "`~/.ssh/id_ed25519`", "correct": true, "explanation": "Die Datei ohne Endung ist der private Schlüssel; sie darf das System nie verlassen." }, + { "id": "b", "text": "`~/.ssh/id_ed25519.pub`", "correct": false, "explanation": "`.pub` ist der öffentliche Schlüssel, der auf Server verteilt wird." }, + { "id": "c", "text": "`~/.ssh/authorized_keys`", "correct": false, "explanation": "Liste erlaubter öffentlicher Schlüssel (serverseitig)." }, + { "id": "d", "text": "`~/.ssh/known_hosts`", "correct": false, "explanation": "Host-Schlüssel bekannter Server." }, + { "id": "e", "text": "`/etc/ssh/ssh_host_ed25519_key`", "correct": false, "explanation": "Privater **Host**-Schlüssel des SSH-Servers, nicht des Benutzers." } + ], + "explanation": "Öffentliche und private Schlüssel gibt es auch beim Server (Host-Schlüssel). Benutzer- und Host-Schlüssel nicht verwechseln.", + "references": ["man 1 ssh-keygen"] + } + ] +} diff --git a/simulator/data/schema/questions.schema.json b/simulator/data/schema/questions.schema.json new file mode 100644 index 0000000..dcfc092 --- /dev/null +++ b/simulator/data/schema/questions.schema.json @@ -0,0 +1,77 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "questions.schema.json", + "title": "LPIC-Simulator: Fragendatei", + "description": "Fragenpaket für eine Prüfung. Datei-Header in 'meta' (Regel headers.md). Fachliche Regeln (genau 5 Optionen, Erläuterung je Option) prüft zusätzlich tools/build_bank.py.", + "type": "object", + "required": ["format", "exam", "questions"], + "additionalProperties": false, + "properties": { + "$schema": { "type": "string" }, + "format": { "const": "lpic-sim-questions" }, + "meta": { + "type": "object", + "properties": { + "file": { "type": "string" }, + "brief": { "type": "string" }, + "author": { "type": "string" }, + "owner": { "type": "string" }, + "assist": { "type": "string" }, + "version": { "type": "string" } + } + }, + "exam": { "type": "string", "description": "id der Prüfung aus exam.json, z. B. lpic1-101", "pattern": "^[a-z0-9-]+$" }, + "questions": { "type": "array", "items": { "$ref": "#/$defs/question" } } + }, + "$defs": { + "question": { + "type": "object", + "required": ["id", "objective", "type", "question", "explanation"], + "additionalProperties": false, + "properties": { + "id": { "type": "string", "pattern": "^[0-9]{3}\\.[0-9]+-[0-9]{3}$", "description": "-, z. B. 103.1-004" }, + "objective": { "type": "string", "pattern": "^[0-9]{3}\\.[0-9]+$" }, + "type": { "enum": ["single", "multi", "fill"], "description": "single: genau 1 richtig · multi: 2–4 richtig (Anzahl wird angezeigt) · fill: Lückentext" }, + "lang": { "type": "string", "default": "de" }, + "difficulty": { "type": "integer", "minimum": 1, "maximum": 3 }, + "question": { "type": "string", "description": "Fragetext; `Inline-Code` in Backticks, **fett** möglich" }, + "code": { "type": "string", "description": "optionaler mehrzeiliger Block (Ausgabe, Datei, Befehl)" }, + "options": { + "type": "array", + "minItems": 5, + "maxItems": 5, + "items": { + "type": "object", + "required": ["id", "text", "correct", "explanation"], + "additionalProperties": false, + "properties": { + "id": { "enum": ["a", "b", "c", "d", "e"] }, + "text": { "type": "string" }, + "correct": { "type": "boolean" }, + "explanation": { "type": "string", "description": "Warum diese Option richtig bzw. falsch ist" } + } + } + }, + "answers": { "type": "array", "minItems": 1, "items": { "type": "string" }, "description": "fill: akzeptierte Antworten (erste = Musterlösung)" }, + "case_sensitive": { "type": "boolean", "default": true }, + "explanation": { "type": "string", "description": "Gesamterläuterung zur Frage" }, + "references": { "type": "array", "items": { "type": "string" }, "description": "z. B. man 8 modprobe" }, + "review": { + "type": "object", + "description": "Prüfvermerk. Fehlt er, gilt pending. rejected wird nie in die Bank übernommen, mit --approved-only nur approved.", + "required": ["status"], + "additionalProperties": false, + "properties": { + "status": { "enum": ["pending", "approved", "rejected"] }, + "by": { "type": "string", "description": "Prüfer (Name oder Rolle)" }, + "date": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$" }, + "note": { "type": "string", "description": "Begründung, v. a. bei rejected" } + } + } + }, + "allOf": [ + { "if": { "properties": { "type": { "const": "fill" } } }, "then": { "required": ["answers"] }, "else": { "required": ["options"] } } + ] + } + } +} diff --git a/simulator/docs/REVIEW.md b/simulator/docs/REVIEW.md new file mode 100644 index 0000000..d1a38c2 --- /dev/null +++ b/simulator/docs/REVIEW.md @@ -0,0 +1,34 @@ +# Anleitung für Prüfer + +> Stand: 29.10.2026 · Ziel: jede Frage fachlich prüfen und freigeben oder ablehnen. + +## Voraussetzungen +- Python ≥ 3.11 (nur Standardbibliothek), ein aktueller Browser (Firefox, Chromium). +- Editor mit JSON-Schema-Unterstützung (z. B. VSCode/VSCodium) – validiert beim Tippen über `$schema`. + +## Ablauf +1. Paket entpacken, `index.html` öffnen und die Fragen im **Lernmodus** durchgehen (Topic-Filter auf der Startseite, Reihenfolge „nach Objective“, Optionen nicht mischen). +2. Fragen im Quelltext `data//questions_.json` prüfen – Regeln: [question_rules.md](question_rules.md), Prüfungsrahmen: [exam_format.md](exam_format.md). +3. Ergebnis je Frage als Vermerk eintragen: + ```json + "review": { "status": "approved", "by": "", "date": "2026-11-02" } + "review": { "status": "rejected", "by": "", "date": "2026-11-02", "note": "Option ‚…‘ ist ebenfalls korrekt" } + ``` + Korrekturen direkt in der Frage vornehmen und `meta.version` der Datei erhöhen. +4. Prüfen und bauen: + ```bash + python3 tools/build_bank.py -c # Regeln, Prüfstatus, Abdeckung je Objective + python3 tools/build_bank.py # js/bank.js neu (verschlüsselt, eigener PSK in tools/.psk) + python3 tools/build_bank.py --approved-only -e # nur Freigegebenes, Export nach dist/ + python3 -m http.server 8080 -d dist # Export ausliefern + ``` +5. Geänderte `questions_*.json` zurückgeben (nicht `js/bank.js`, nicht `tools/.psk`). + +## Neue Fragen +Nächste freie Nummer im Objective verwenden (`-`), Format siehe [`../README.md`](../README.md#format-einer-frage). Ohne Build testen: Datei im Simulator über **Import** laden. + +## Tests +```bash +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)[^<]*' +``` diff --git a/simulator/docs/decisions.md b/simulator/docs/decisions.md new file mode 100644 index 0000000..50802b2 --- /dev/null +++ b/simulator/docs/decisions.md @@ -0,0 +1,28 @@ +# Festlegungen + +> Stand: 29.10.2026 · getroffene Entscheidungen mit Begründung und offene Punkte. + +## Entscheidungen +| Datum | Entscheidung | Warum | +|---|---|---| +| 29.10.2026 | Zunächst LPIC-1 (101-500, 102-500), Objectives 5.0; weitere Prüfungen (LPIC-2) als zusätzliche Ordner unter `data/` | Prüfungen auswählbar, erweiterbar ohne Codeänderung | +| 29.10.2026 | Statische Web-Anwendung, läuft von `file://` **und** von jedem statischen Webserver; kein Backend | lokal ohne Installation nutzbar | +| 29.10.2026 | reveal.js 5.1.0 unverändert unter `vendor/reveal/`, eingebautes **Dracula**-Theme; kein CDN | offline lauffähig, reproduzierbar | +| 29.10.2026 | Reines JavaScript (klassische Scripts, ES2022), kein TypeScript, kein Build für den Code | ES-Module und `fetch` sind unter `file://` blockiert; kein node nötig | +| 29.10.2026 | Fragen-Quelltext als JSON unter `data/` (Klartext), Bank `js/bank.js` per `tools/build_bank.py` (nur Python-Standardbibliothek) | JSON-Schema-Prüfung im Editor; Script-Datei lädt auch unter `file://` | +| 29.10.2026 | Fragen: `single`/`multi` mit **genau 5 Optionen**, Erläuterung je Option, Gesamterläuterung; `fill` für Lückentext | Vorgabe des Betreibers; LPI-Fragetypen | +| 29.10.2026 | Lernmodus: „Weiter“ zeigt erst die Auflösung mit Erläuterungen, dann die nächste Frage | Lernen mit sofortiger Begründung | +| 29.10.2026 | Prüfungsmodus: 60 Fragen, 90 min, Auswahl gewichtet nach Objectives, Auflösung nach Abgabe | entspricht dem LPI-Format ([exam_format.md](exam_format.md)) | +| 29.10.2026 | Bewertung alles-oder-nichts; Richtwert Bestehen 65 % (`pass_percent` in `exam.json`) | LPI veröffentlicht weder Teilpunkte noch Prozentgrenze (Skala 200–800, bestanden ab 500) – **Annahme** | +| 29.10.2026 | Fortschritt automatisch im `localStorage`; Export/Import der Sitzung als JSON (enthält die Fragen der Sitzung); Fragenpakete per Import nachladbar | Pause und Fortsetzen, auch auf anderem Rechner | +| 29.10.2026 | Ausgelieferte Bank ChaCha20-verschlüsselt (RFC 8439); Schlüssel = SHA-256 über einen PSK (`LPIC_SIM_PSK` bzw. `tools/.psk`, nicht weitergeben), steht als `build`-Kennung in `bank.js` | kein Klartext auf der Platte; **Verschleierung**, kein Schutz gegen gezielte Analyse, da der Browser den Schlüssel braucht | +| 29.10.2026 | Eigene ChaCha20-Implementierung statt WebCrypto | WebCrypto fehlt bei `http://` (kein Secure Context) und kennt kein ChaCha20 | +| 29.10.2026 | Prüfvermerk `review` je Frage; `rejected` nie in der Bank, `--approved-only` für Freigabe-Builds | Durchsicht und Freigabe durch Prüfer | +| 29.10.2026 | Export `build_bank.py -e` nur mit Laufzeitdateien (ohne `data/`, `tools/`, `tests/`) | Auslieferung an Lernende ohne Quelltext | + +## Offene Punkte +1. Richtwert 65 % für „bestanden“ – anpassen? +2. Teilpunkte bei Mehrfachauswahl: von LPI nicht dokumentiert; derzeit alles-oder-nichts. +3. Sitzungs-Export und `localStorage` enthalten die Fragen einer Sitzung im Klartext. +4. Alle 180 Fragen sind KI-erstellt (Claude Opus 5.5) und **noch nicht fachlich geprüft** – Aufgabe der Prüfer ([REVIEW.md](REVIEW.md)). +5. Nicht getestet: Safari, echte Mobilgeräte. diff --git a/simulator/docs/exam_format.md b/simulator/docs/exam_format.md new file mode 100644 index 0000000..76dc9e4 --- /dev/null +++ b/simulator/docs/exam_format.md @@ -0,0 +1,38 @@ +# LPIC-1 – Prüfungsformat und Objectives 5.0 + +> Stand: 29.10.2026 · Alle Angaben von lpi.org, abgerufen am 29.10.2026. Grundlage für Prüfungsmodus und Fragenbank. +> Inoffizielles Lernwerkzeug, nicht mit dem Linux Professional Institute (LPI) verbunden. „LPIC“ ist eine Marke des LPI. + +## Fakten +| Merkmal | Wert | Quelle | +|---|---|---| +| Prüfungen | 101-500 und 102-500 | Objectives-Seite | +| Objectives-Version | 5.0 | Objectives-Seite | +| Umfang je Prüfung | 60 Fragen, 90 Minuten | LPIC-1-Übersicht („60 multiple-choice and fill-in-the-blank questions“) | +| Fragetypen | Multiple Choice (Einfach-/Mehrfachauswahl) und Lückentext | LPIC-1-Übersicht | +| Bewertung | Skala 200–800, bestanden ab 500 | FAQ („ranked on a scale from 200 to 800, with a passing score of 500“) | +| Prozentgrenze | nicht veröffentlicht; hängt von der Fragenkombination ab (psychometrische Studien, modifizierte Angoff-Studie) | FAQ, Development Standards | +| Gewichtung | Gewicht eines Objectives = Anzahl Fragen dazu; Summe je Prüfung = 60 | FAQ, Objectives-Seite | +| Teilpunkte bei Mehrfachauswahl | nicht dokumentiert | – | +| Angekündigte Änderungen | `ifup`/`ifdown`, net-tools und TCP-Wrapper sollen entfallen (ohne Termin) | Objectives-Seite | + +## Regeln zur Fragenerstellung laut LPI (Development Standards) +- Multiple Choice bevorzugt, da „more information per unit time“. +- Distraktoren müssen **falsch, aber plausibel** sein. +- Formulierung klar, auch für Nicht-Muttersprachler verständlich; verwirrende Items werden abgelehnt oder umformuliert. +- Items, die vorhandenen im Wesentlichen gleichen, werden abgelehnt. +- Fachleute prüfen Korrektheit, Relevanz und erwartete Schwierigkeit. +- Eine feste Anzahl Antwortoptionen nennt LPI **nicht**; die 5 Optionen sind eine Projektvorgabe ([decisions.md](decisions.md)). + +## Objectives 5.0 mit Gewicht +**101:** 101.1 (2) · 101.2 (3) · 101.3 (3) · 102.1 (2) · 102.2 (2) · 102.3 (1) · 102.4 (3) · 102.5 (3) · 102.6 (1) · 103.1 (4) · 103.2 (2) · 103.3 (4) · 103.4 (4) · 103.5 (4) · 103.6 (2) · 103.7 (3) · 103.8 (3) · 104.1 (2) · 104.2 (2) · 104.3 (3) · 104.5 (3) · 104.6 (2) · 104.7 (2) – 104.4 entfallen. + +**102:** 105.1 (4) · 105.2 (4) · 106.1 (2) · 106.2 (1) · 106.3 (1) · 107.1 (5) · 107.2 (4) · 107.3 (3) · 108.1 (3) · 108.2 (4) · 108.3 (3) · 108.4 (2) · 109.1 (4) · 109.2 (4) · 109.3 (4) · 109.4 (2) · 110.1 (3) · 110.2 (3) · 110.3 (4). + +Titel und Topics maschinenlesbar: [`../data/lpic1_101/exam.json`](../data/lpic1_101/exam.json), [`../data/lpic1_102/exam.json`](../data/lpic1_102/exam.json). + +## Quellen +- https://www.lpi.org/de/exam-101-102-objectives/ (abgerufen 29.10.2026) +- https://www.lpi.org/value-of-certification/our-certification-development-standards/ (abgerufen 29.10.2026) +- https://www.lpi.org/our-certifications/lpic-1-overview/ (abgerufen 29.10.2026) +- https://www.lpi.org/faq/ (abgerufen 29.10.2026) diff --git a/simulator/docs/question_rules.md b/simulator/docs/question_rules.md new file mode 100644 index 0000000..9affd8a --- /dev/null +++ b/simulator/docs/question_rules.md @@ -0,0 +1,35 @@ +# Regeln für Fragen + +> Stand: 29.10.2026 · gilt für alle Dateien `data//questions_*.json`. +> Technische Regeln prüft `tools/build_bank.py -c` (und der Import im Simulator); inhaltliche Regeln prüfen Menschen. + +## Technisch (automatisch geprüft) +| Regel | Details | +|---|---| +| Datei | `format: "lpic-sim-questions"`, `exam` = id aus `exam.json`, Schema `data/schema/questions.schema.json` | +| id | `-`, z. B. `103.4-007`, eindeutig je Prüfung; Objective muss in `exam.json` existieren | +| `single` | genau 5 Optionen `a`–`e` in dieser Reihenfolge, genau 1 richtig | +| `multi` | genau 5 Optionen, 2–4 richtig; der Simulator zeigt „Wählen Sie ZWEI/DREI/VIER“ und begrenzt die Auswahl | +| `fill` | keine Optionen; `answers` = akzeptierte Antworten, erste = Musterlösung; Leerraum wird normalisiert; `case_sensitive` Standard `true` | +| Erläuterungen | jede Option hat `explanation`, jede Frage eine Gesamt-`explanation` | +| keine doppelten Optionstexte | | +| `review.status` | `pending` (Standard), `approved`, `rejected` | + +## Inhaltlich (Prüfer) +- **Genau eine fachlich richtige Lösung** (bzw. genau die markierten bei `multi`). Distraktoren eindeutig falsch, aber plausibel – keine „auch richtig, aber nicht gemeint“-Optionen. +- Klar und kurz, auch für Nicht-Muttersprachler verständlich; keine Fangfragen über Formulierungstricks, keine doppelten Verneinungen. +- Genau einem Objective zugeordnet; Inhalt passt zu dessen Lernzielen (Objectives 5.0, [exam_format.md](exam_format.md)). +- Keine inhaltlichen Dubletten. +- Erläuterungen begründen **warum** – nicht nur „richtig/falsch“; möglichst mit `references` (Manpage). +- Erläuterungen nie auf Buchstaben beziehen („Option A“) – die Optionen werden im Simulator gemischt. +- `fill`: alle gleichwertigen Schreibweisen in `answers` aufnehmen (Lang-/Kurzoptionen, Reihenfolge der Optionen). +- Bewertung im Simulator wie vermutlich bei LPI: alles oder nichts. + +## Schreibweise +- Sprache Deutsch mit korrekten Umlauten (ä ö ü ß); Befehle, Optionen, Pfade im Original. +- Inline-Code zwischen zwei Backticks; einzelne Backticks vermeiden (Befehlsersetzung als `$(…)` schreiben). `**fett**` für Betonung. +- Mehrzeilige Ausgaben/Dateien ins Feld `code`. +- Beispieladressen und -namen aus Dokumentationsbereichen: `192.0.2.0/24`, `198.51.100.0/24`, `example.org`, `host01`, `anna`. + +## Datei-Header +Jede Datei trägt im Objekt `meta` (bei Code als Kommentar) `file`, `brief`, `author`, `owner`, `version` (`x.y.z (TT.MM.JJJJ)`), bei KI-Beteiligung `assist`. Bei inhaltlicher Änderung `version` erhöhen. diff --git a/simulator/index.html b/simulator/index.html new file mode 100644 index 0000000..1b6e239 --- /dev/null +++ b/simulator/index.html @@ -0,0 +1,45 @@ + + + + + + + LPIC-Prüfungssimulator + + + + + + +
+ LPIC-Prüfungssimulator + + + + + + + + + + +
+ +
+
+
+ +
+ + + + + + diff --git a/simulator/js/app.js b/simulator/js/app.js new file mode 100644 index 0000000..535e39e --- /dev/null +++ b/simulator/js/app.js @@ -0,0 +1,883 @@ +/** + * @file app.js + * @brief LPIC-Prüfungssimulator: Sitzungen, Bewertung, Speichern/Import und Darstellung mit reveal.js + * @author Björn Runden + * @owner Björn Runden + * @assist KI-unterstützt (Claude Opus 5.5), geprüft von Björn Runden + * @version 0.2.0 (29.10.2026) + * + * Bewusst klassisches Script (kein ES-Modul, kein fetch): läuft so auch direkt von file://. + * Die Fragenbank kommt verschlüsselt aus js/bank.js (window.LPIC_BANK, ChaCha20), weitere Pakete per Import. + * Reine Logik liegt in window.LPICSim.core und wird von tests/selftest.html geprüft. + */ +(function () { + 'use strict'; + + const STORE_SESSION = 'lpic_sim.session'; + const STORE_PACKS = 'lpic_sim.packs'; + const SESSION_FORMAT = 'lpic-sim-session'; + const PACK_FORMAT = 'lpic-sim-questions'; + const OPTION_IDS = ['a', 'b', 'c', 'd', 'e']; + const LETTERS = 'ABCDE'; + const COUNT_WORDS = { 2: 'ZWEI', 3: 'DREI', 4: 'VIER' }; + const SAVE_EVERY_S = 15; + + /* ------------------------------------------------------------------ Speicher */ + + /** localStorage mit Fehlertoleranz (privater Modus, gesperrter Speicher). */ + const store = { + get(key) { + try { const v = localStorage.getItem(key); return v ? JSON.parse(v) : null; } + catch (e) { console.warn('localStorage nicht lesbar:', e); return null; } + }, + set(key, value) { + try { localStorage.setItem(key, JSON.stringify(value)); return true; } + catch (e) { console.warn('localStorage nicht schreibbar:', e); return false; } + }, + del(key) { + try { localStorage.removeItem(key); } catch (e) { console.warn('localStorage:', e); } + }, + }; + + /* ------------------------------------------------------------------ Hilfen */ + + /** Mischt eine Kopie des Arrays (Fisher-Yates). */ + function shuffled(arr) { + const a = arr.slice(); + for (let i = a.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [a[i], a[j]] = [a[j], a[i]]; + } + return a; + } + + /** Vergleicht Objective-IDs numerisch („103.10“ nach „103.9“). */ + function cmpObjective(a, b) { + const [a1, a2] = a.split('.').map(Number); + const [b1, b2] = b.split('.').map(Number); + return a1 - b1 || a2 - b2; + } + + function esc(s) { + return String(s).replace(/[&<>"']/g, (c) => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c])); + } + + /** Mini-Markup für Fragetexte: `Code`, **fett**, Zeilenumbruch. Returns: sicheres HTML. */ + function fmt(text) { + return String(text ?? '').split(/(`[^`]+`)/).map((part) => + /^`[^`]+`$/.test(part) + ? `${esc(part.slice(1, -1))}` + : esc(part).replace(/\*\*(.+?)\*\*/g, '$1').replace(/\n/g, '
') + ).join(''); + } + + function fmtTime(sec) { + const s = Math.max(0, Math.floor(sec)); + const h = Math.floor(s / 3600), m = Math.floor((s % 3600) / 60), r = s % 60; + const mm = String(m).padStart(2, '0'), ss = String(r).padStart(2, '0'); + return h ? `${h}:${mm}:${ss}` : `${mm}:${ss}`; + } + + /** Normalisiert Freitext: Leerraum an den Rändern weg, innen auf ein Leerzeichen. */ + function normalize(s, caseSensitive) { + const n = String(s ?? '').trim().replace(/\s+/g, ' '); + return caseSensitive === false ? n.toLowerCase() : n; + } + + /* ------------------------------------------------------------------ Fragenbank entschlüsseln */ + + /** + * ChaCha20 nach RFC 8439 (Gegenstück zu tools/build_bank.py). Eigene Implementierung, weil + * WebCrypto kein ChaCha20 kennt und über http:// (kein Secure Context) ganz fehlt. + * @param {Uint8Array} key 32 Byte · @param {Uint8Array} nonce 12 Byte · @param {Uint8Array} data + * @returns {Uint8Array} ver-/entschlüsselte Daten + */ + function chacha20(key, nonce, data, counter = 1) { + const kv = new DataView(key.buffer, key.byteOffset, 32); + const nv = new DataView(nonce.buffer, nonce.byteOffset, 12); + const st = new Uint32Array(16); + st.set([0x61707865, 0x3320646e, 0x79622d32, 0x6b206574]); + for (let i = 0; i < 8; i++) st[4 + i] = kv.getUint32(i * 4, true); + for (let i = 0; i < 3; i++) st[13 + i] = nv.getUint32(i * 4, true); + const x = new Uint32Array(16); + const block = new Uint8Array(64); + const bv = new DataView(block.buffer); + const out = new Uint8Array(data.length); + const qr = (a, b, c, d) => { + x[a] += x[b]; x[d] ^= x[a]; x[d] = (x[d] << 16) | (x[d] >>> 16); + x[c] += x[d]; x[b] ^= x[c]; x[b] = (x[b] << 12) | (x[b] >>> 20); + x[a] += x[b]; x[d] ^= x[a]; x[d] = (x[d] << 8) | (x[d] >>> 24); + x[c] += x[d]; x[b] ^= x[c]; x[b] = (x[b] << 7) | (x[b] >>> 25); + }; + for (let off = 0; off < data.length; off += 64) { + st[12] = counter + off / 64; + x.set(st); + for (let r = 0; r < 10; r++) { + qr(0, 4, 8, 12); qr(1, 5, 9, 13); qr(2, 6, 10, 14); qr(3, 7, 11, 15); + qr(0, 5, 10, 15); qr(1, 6, 11, 12); qr(2, 7, 8, 13); qr(3, 4, 9, 14); + } + for (let i = 0; i < 16; i++) bv.setUint32(i * 4, (x[i] + st[i]) >>> 0, true); + const n = Math.min(64, data.length - off); + for (let i = 0; i < n; i++) out[off + i] = data[off + i] ^ block[i]; + } + return out; + } + + const hexBytes = (h) => new Uint8Array(String(h).match(/../g).map((b) => parseInt(b, 16))); + + /** Entschlüsselt window.LPIC_BANK (Felder build, rev, payload). Returns: {exams} oder wirft Error. */ + function decodeBank(raw) { + if (!raw) return { exams: [] }; + if (!raw.payload) return raw; // unverschlüsselte Bank (ältere Builds) + const bin = atob(raw.payload); + const data = new Uint8Array(bin.length); + for (let i = 0; i < bin.length; i++) data[i] = bin.charCodeAt(i); + const plain = chacha20(hexBytes(raw.build), hexBytes(raw.rev), data); + try { return JSON.parse(new TextDecoder().decode(plain)); } + catch (e) { throw new Error('Fragenbank nicht lesbar (bank.js beschädigt oder unvollständig)'); } + } + + /* ------------------------------------------------------------------ Kernlogik */ + + /** Prüft eine Frage gegen die Erstellungsregeln. Returns: Fehlertext oder null. */ + function validateQuestion(q, objectives) { + if (!q || typeof q !== 'object') return 'keine Frage'; + if (!/^\d{3}\.\d+-\d{3}$/.test(q.id || '')) return `ungültige id ${q.id}`; + if (!objectives.has(q.objective)) return `${q.id}: unbekanntes Objective ${q.objective}`; + if (!String(q.question || '').trim() || !String(q.explanation || '').trim()) return `${q.id}: question/explanation fehlt`; + if (q.type === 'fill') { + return Array.isArray(q.answers) && q.answers.length ? null : `${q.id}: answers fehlt`; + } + if (q.type !== 'single' && q.type !== 'multi') return `${q.id}: unbekannter type ${q.type}`; + const opts = q.options || []; + if (opts.map((o) => o.id).join() !== OPTION_IDS.join()) return `${q.id}: genau 5 Optionen a–e nötig`; + if (opts.some((o) => !String(o.text || '').trim() || !String(o.explanation || '').trim())) return `${q.id}: Option ohne Text/Erläuterung`; + const nOk = opts.filter((o) => o.correct === true).length; + if (q.type === 'single' && nOk !== 1) return `${q.id}: single braucht genau 1 richtige Option`; + if (q.type === 'multi' && (nOk < 2 || nOk > 4)) return `${q.id}: multi braucht 2–4 richtige Optionen`; + return null; + } + + /** Alle Objective-IDs einer Prüfung. */ + function objectiveIds(exam) { + return new Set(exam.topics.flatMap((t) => t.objectives.map((o) => o.id))); + } + + /** Objective-Metadaten (Titel, Gewicht, Topic) zu einer ID. */ + function objectiveInfo(exam, oid) { + for (const t of exam.topics) { + const o = t.objectives.find((x) => x.id === oid); + if (o) return { ...o, topic: t.id, topicTitle: t.title }; + } + return { id: oid, title: '', weight: 0, topic: oid.split('.')[0], topicTitle: '' }; + } + + /** + * Fügt ein Fragenpaket in die Bank ein (gleiche id ersetzt). + * Ein Paket mit "definition" (Inhalt einer exam.json) legt eine neue Prüfung an. + * Returns: {added, replaced, errors} + */ + function mergePack(bankExams, pack) { + const res = { added: 0, replaced: 0, errors: [] }; + if (!pack || pack.format !== PACK_FORMAT) { res.errors.push(`format muss '${PACK_FORMAT}' sein`); return res; } + let exam = bankExams.find((e) => e.id === pack.exam); + if (!exam && pack.definition && pack.definition.exam && pack.definition.exam.id === pack.exam) { + exam = { ...pack.definition.exam, topics: pack.definition.topics || [], bank: [] }; + bankExams.push(exam); + } + if (!exam) { res.errors.push(`Prüfung '${pack.exam}' unbekannt (Paket ohne "definition")`); return res; } + const objectives = objectiveIds(exam); + for (const q of pack.questions || []) { + if (q && q.review && q.review.status === 'rejected') continue; // von Prüfern abgelehnt + const err = validateQuestion(q, objectives); + if (err) { res.errors.push(err); continue; } + const idx = exam.bank.findIndex((x) => x.id === q.id); + if (idx >= 0) { exam.bank[idx] = q; res.replaced++; } else { exam.bank.push(q); res.added++; } + } + exam.bank.sort((a, b) => cmpObjective(a.objective, b.objective) || a.id.localeCompare(b.id)); + return res; + } + + /** + * Wählt n Fragen gewichtet nach Objective (wie die echte Prüfung: Gewicht = Fragenzahl). + * Fehlende Fragen eines Objectives werden zufällig aus dem Rest aufgefüllt. + */ + function pickWeighted(exam, pool, n) { + const byObj = new Map(); + for (const q of shuffled(pool)) { + if (!byObj.has(q.objective)) byObj.set(q.objective, []); + byObj.get(q.objective).push(q); + } + const objs = [...byObj.keys()].map((id) => ({ id, w: objectiveInfo(exam, id).weight || 1 })); + const total = objs.reduce((s, o) => s + o.w, 0) || 1; + const target = Math.min(n, pool.length); + for (const o of objs) { o.exact = (target * o.w) / total; o.quota = Math.min(Math.floor(o.exact), byObj.get(o.id).length); } + let left = target - objs.reduce((s, o) => s + o.quota, 0); + for (const o of objs.slice().sort((a, b) => (b.exact - Math.floor(b.exact)) - (a.exact - Math.floor(a.exact)))) { + if (left <= 0) break; + if (o.quota < byObj.get(o.id).length) { o.quota++; left--; } + } + const picked = objs.flatMap((o) => byObj.get(o.id).slice(0, o.quota)); + if (picked.length < target) { + const ids = new Set(picked.map((q) => q.id)); + picked.push(...shuffled(pool.filter((q) => !ids.has(q.id))).slice(0, target - picked.length)); + } + return picked; + } + + /** + * Legt eine neue Sitzung an. Die Fragen werden als Kopie in die Sitzung übernommen, + * damit Export/Import unabhängig vom späteren Stand der Bank funktioniert. + * @param {object} exam Prüfung aus der Bank + * @param {object} o {mode:'learn'|'exam', topics?:string[], count?:number, order?:'random'|'objective', shuffleOptions?:bool, questionIds?:string[]} + */ + function createSession(exam, o) { + const mode = o.mode === 'exam' ? 'exam' : 'learn'; + let pool = exam.bank; + if (o.questionIds) pool = pool.filter((q) => o.questionIds.includes(q.id)); + else if (mode === 'learn' && o.topics && o.topics.length) pool = pool.filter((q) => o.topics.includes(q.objective.split('.')[0])); + let list; + if (mode === 'exam') { + list = shuffled(pickWeighted(exam, pool, exam.questions || 60)); + } else { + list = o.order === 'objective' + ? pool.slice().sort((a, b) => cmpObjective(a.objective, b.objective) || a.id.localeCompare(b.id)) + : shuffled(pool); + if (o.count > 0) list = list.slice(0, o.count); + } + const questions = list.map((q) => { + const c = JSON.parse(JSON.stringify(q)); + if (c.options && o.shuffleOptions !== false) c.options = shuffled(c.options); + return c; + }); + const now = new Date().toISOString(); + return { + format: SESSION_FORMAT, + version: 1, + id: Date.now().toString(36), + exam_id: exam.id, + exam_title: exam.title, + exam_code: exam.code, + topics: exam.topics, + mode, + created: now, + updated: now, + elapsed_s: 0, + time_limit_s: mode === 'exam' ? (exam.duration_min || 90) * 60 : 0, + pass_percent: exam.pass_percent || 65, + current: 0, + submitted: false, + questions, + answers: {}, + }; + } + + /** Anzahl richtiger Optionen einer Choice-Frage. */ + function correctCount(q) { + return (q.options || []).filter((o) => o.correct).length; + } + + /** Bewertet eine Antwort (alles oder nichts, wie LPI). Returns: true/false. */ + function isCorrect(q, value) { + if (q.type === 'fill') { + const v = normalize(value, q.case_sensitive); + return v !== '' && q.answers.some((a) => normalize(a, q.case_sensitive) === v); + } + const sel = new Set(Array.isArray(value) ? value : value ? [value] : []); + const ok = q.options.filter((o) => o.correct).map((o) => o.id); + return sel.size === ok.length && ok.every((id) => sel.has(id)); + } + + /** Hat die Frage eine (nicht leere) Antwort? */ + function isAnswered(a) { + if (!a) return false; + return Array.isArray(a.value) ? a.value.length > 0 : normalize(a.value) !== ''; + } + + /** Prüft eine importierte Sitzung grob. Returns: Fehlertext oder null. */ + function validateSession(s) { + if (!s || s.format !== SESSION_FORMAT) return `format muss '${SESSION_FORMAT}' sein`; + if (s.version !== 1) return `Sitzungsversion ${s.version} wird nicht unterstützt`; + if (!Array.isArray(s.questions) || !s.questions.length) return 'Sitzung ohne Fragen'; + if (typeof s.answers !== 'object' || s.answers === null) return 'Sitzung ohne answers'; + return null; + } + + /** + * Auswertung einer Sitzung, gesamt und je Topic. + * @param {boolean} onlyRevealed im Lernmodus nur bereits aufgelöste Fragen zählen + */ + function score(session, onlyRevealed) { + const res = { total: 0, correct: 0, answered: 0, wrong: [], topics: {} }; + session.questions.forEach((q, i) => { + const a = session.answers[q.id]; + if (onlyRevealed && !(a && a.revealed)) return; + const t = q.objective.split('.')[0]; + const ts = res.topics[t] || (res.topics[t] = { total: 0, correct: 0 }); + const ok = !!a && isCorrect(q, a.value); + res.total++; ts.total++; + if (isAnswered(a)) res.answered++; + if (ok) { res.correct++; ts.correct++; } else res.wrong.push(i); + }); + res.percent = res.total ? Math.round((res.correct / res.total) * 100) : 0; + res.passed = res.percent >= session.pass_percent; + return res; + } + + const core = { chacha20, decodeBank, validateQuestion, mergePack, pickWeighted, createSession, isCorrect, isAnswered, validateSession, score, fmt, normalize, shuffled }; + + /* ------------------------------------------------------------------ Oberfläche */ + + const ui = { + exams: [], // Bank inkl. importierter Pakete + session: null, // laufende Sitzung oder null (Startseite) + tickCount: 0, + }; + + const $ = (sel, root = document) => root.querySelector(sel); + const $$ = (sel, root = document) => Array.from(root.querySelectorAll(sel)); + + /** Lädt die Bank aus bank.js und gespeicherte Pakete aus localStorage. */ + function loadBank() { + try { ui.exams = decodeBank(window.LPIC_BANK).exams || []; } + catch (e) { ui.exams = []; console.error(e); setTimeout(() => toast(e.message, 'error'), 0); } + for (const pack of store.get(STORE_PACKS) || []) mergePack(ui.exams, pack); + ui.exams.sort((a, b) => String(a.level).localeCompare(String(b.level)) || (a.order || 0) - (b.order || 0)); + } + + function save() { + if (!ui.session) return; + ui.session.updated = new Date().toISOString(); + if (!store.set(STORE_SESSION, ui.session)) toast('Speichern im Browser nicht möglich – bitte regelmäßig exportieren.', 'warn'); + } + + function toast(msg, kind = 'info') { + const box = $('#toast'); + const el = document.createElement('div'); + el.className = `toast ${kind}`; + el.textContent = msg; + box.appendChild(el); + setTimeout(() => el.remove(), kind === 'error' ? 9000 : 4500); + } + + /** Bietet Text als Datei zum Speichern an. */ + function download(name, text) { + const url = URL.createObjectURL(new Blob([text], { type: 'application/json' })); + const a = document.createElement('a'); + a.href = url; a.download = name; + document.body.appendChild(a); a.click(); a.remove(); + setTimeout(() => URL.revokeObjectURL(url), 1000); + } + + /** Setzt die Folien neu und synchronisiert reveal.js. */ + function setSlides(html, index) { + $('.reveal .slides').innerHTML = html; + Reveal.sync(); + Reveal.slide(index || 0, 0); + updateToolbar(); + } + + /* ----------------------------- Startseite */ + + function renderStart() { + ui.session = null; + const saved = store.get(STORE_SESSION); + const levels = [...new Set(ui.exams.map((e) => e.level))]; + const examChoices = levels.map((lvl) => ` +
${esc(lvl)} + ${ui.exams.filter((e) => e.level === lvl).map((e, i) => ` + `).join('')} +
`).join(''); + let resume = ''; + if (saved && !validateSession(saved)) { + const done = saved.questions.filter((q) => isAnswered(saved.answers[q.id])).length; + resume = ` +
+

Gespeicherte Sitzung

+

${esc(saved.exam_title)} · ${saved.mode === 'exam' ? 'Prüfungsmodus' : 'Lernmodus'}${saved.submitted ? ' · abgegeben' : ''} + · ${done}/${saved.questions.length} beantwortet · Stand ${esc(new Date(saved.updated).toLocaleString('de-DE'))}

+ + +
`; + } + const html = ` +
+

LPIC-Prüfungssimulator

+ ${ui.exams.length ? '' : '

Keine Fragenbank gefunden – tools/build_bank.py ausführen oder ein Fragenpaket importieren.

'} + ${resume} +
+

Neue Sitzung

+
Prüfung${examChoices}
+
Modus + + +
+
Themen
+
Ablauf + + +
+ +

+
+

Objectives laut LPI, Quelle und Version je Prüfung in data/<prüfung>/exam.json. + Stand der Fragenbank: ${esc(window.LPIC_BANK ? window.LPIC_BANK.generated : '–')}. + Tasten: → / Leertaste weiter · ← zurück · 1–5 Antwort wählen · Enter im Textfeld = weiter.

+
`; + setSlides(html, 0); + updateStartForm(); + } + + /** Aktualisiert Themenliste und Hinweise je gewählter Prüfung/Modus. */ + function updateStartForm() { + const form = $('#setup'); + if (!form) return; + const exam = ui.exams.find((e) => e.id === (form.exam && form.exam.value)); + const learn = form.mode.value === 'learn'; + $$('.learn-only', form).forEach((el) => { el.hidden = !learn; }); + if (!exam) return; + $('#exam-info').textContent = `${exam.questions} Fragen, ${exam.duration_min} Minuten, gewichtet nach Objectives, Auflösung erst nach Abgabe`; + const counts = {}; + exam.bank.forEach((q) => { const t = q.objective.split('.')[0]; counts[t] = (counts[t] || 0) + 1; }); + const list = $('#topic-list'); + if (list.dataset.exam !== exam.id) { + list.dataset.exam = exam.id; + list.innerHTML = exam.topics.map((t) => ` + `).join(''); + } + } + + function startFromForm(form) { + const exam = ui.exams.find((e) => e.id === form.exam.value); + if (!exam) { toast('Bitte eine Prüfung wählen.', 'warn'); return; } + const topics = $$('input[name=topic]:checked', form).map((i) => i.value); + const s = createSession(exam, { + mode: form.mode.value, + topics, + count: parseInt(form.count.value, 10) || 0, + order: form.order.value, + shuffleOptions: form.shuffle.checked, + }); + if (!s.questions.length) { toast('Keine Fragen für diese Auswahl.', 'warn'); return; } + startSession(s, 0); + } + + function startSession(session, index) { + ui.session = session; + save(); + renderSession(index); + } + + /* ----------------------------- Fragen-Folien */ + + function renderSession(index) { + const s = ui.session; + const slides = s.questions.map((q, i) => questionSlide(q, i)).join(''); + const last = s.mode === 'exam' && !s.submitted ? submitSlide() : resultSlide(); + setSlides(slides + last, Math.min(index ?? s.current ?? 0, s.questions.length)); + } + + /** Ist die Frage gesperrt (aufgelöst bzw. Prüfung abgegeben)? */ + function isLocked(q) { + const a = ui.session.answers[q.id]; + return ui.session.submitted || !!(a && a.revealed); + } + + function questionSlide(q, i) { + const s = ui.session; + const a = s.answers[q.id] || {}; + const locked = isLocked(q); + const info = objectiveInfo({ topics: s.topics }, q.objective); + const showSolution = s.mode === 'learn' || s.submitted; + const nOk = correctCount(q); + let hint = ''; + let body; + if (q.type === 'fill') { + hint = `Antwort eintippen${q.case_sensitive === false ? '' : ' – Groß-/Kleinschreibung beachten'}.`; + body = ``; + } else { + const multi = q.type === 'multi'; + if (multi) hint = `Wählen Sie ${COUNT_WORDS[nOk] || nOk}.`; + const sel = new Set(Array.isArray(a.value) ? a.value : []); + body = `
    ${q.options.map((o, k) => ` +
  1. `).join('')} +
`; + } + const flag = s.mode === 'exam' && !s.submitted + ? `` : ''; + const solution = showSolution ? solutionBlock(q, locked) : ''; + const learnBtn = s.mode === 'learn' && !locked ? '

' : ''; + return ` +
+
Frage ${i + 1} von ${s.questions.length} + ${esc(q.objective)} ${esc(info.title)}${info.weight ? ` · Gewicht ${info.weight}` : ''}${flag}
+
${fmt(q.question)}
+ ${q.code ? `
${esc(q.code)}
` : ''} + ${hint ? `

${hint}

` : ''} + ${body} + ${learnBtn} + ${solution} +
`; + } + + /** Auflösung: Ergebnis, Erläuterung je Option, Gesamterläuterung. Ungesperrt als reveal-Fragment. */ + function solutionBlock(q, locked) { + const a = ui.session.answers[q.id]; + let res = ''; + if (locked) { + const ok = !!a && isCorrect(q, a.value); + res = !isAnswered(a) ? '

Nicht beantwortet

' + : ok ? '

Richtig

' : '

Falsch

'; + } + let details; + if (q.type === 'fill') { + const alt = q.answers.slice(1); + details = `

Musterlösung: ${esc(q.answers[0])}${alt.length + ? ` · ebenfalls akzeptiert: ${alt.map((x) => `${esc(x)}`).join(', ')}` : ''}

` + + (a && isAnswered(a) ? `

Ihre Antwort: ${esc(a.value)}

` : ''); + } else { + details = `
    ${q.options.map((o, k) => ` +
  • ${LETTERS[k]} + ${o.correct ? '✔ richtig' : '✘ falsch'} ${fmt(o.explanation)}
  • `).join('')}
`; + } + const refs = q.references && q.references.length + ? `

Nachschlagen: ${q.references.map((r) => `${esc(r)}`).join(' · ')}

` : ''; + return ` +
+

Auflösung

${res}${details} +
${fmt(q.explanation)}
${refs} +
`; + } + + /** Markiert Optionen nach der Auflösung (richtig/falsch gewählt). */ + function markOptions(section, q) { + const a = ui.session.answers[q.id]; + const sel = new Set(a && Array.isArray(a.value) ? a.value : []); + $$('.option', section).forEach((li) => { + const o = q.options.find((x) => x.id === li.dataset.oid); + li.classList.toggle('is-correct', o.correct); + li.classList.toggle('is-wrong', !o.correct && sel.has(o.id)); + li.classList.toggle('is-missed', o.correct && !sel.has(o.id)); + }); + const fill = $('.fill', section); + if (fill) fill.classList.add(a && isCorrect(q, a.value) ? 'is-correct' : 'is-wrong'); + } + + /** Lernmodus: Frage auflösen, sperren und Auflösung dauerhaft sichtbar machen. */ + function revealQuestion(section) { + const s = ui.session; + const q = s.questions[Number(section.dataset.index)]; + const a = s.answers[q.id] || (s.answers[q.id] = { value: q.type === 'fill' ? '' : [] }); + if (a.revealed) return; + a.revealed = true; + save(); + const fresh = document.createElement('div'); + fresh.innerHTML = solutionBlock(q, true); + $('.solution', section).replaceWith(fresh.firstElementChild); + $$('input', section).forEach((i) => { i.disabled = true; }); + const btn = $('.actions', section); + if (btn) btn.remove(); + section.classList.add('locked'); + markOptions(section, q); + Reveal.syncFragments(); + $('.solution', section).scrollIntoView({ behavior: 'smooth', block: 'nearest' }); + updateToolbar(); + } + + /* ----------------------------- Abgabe & Ergebnis */ + + function submitSlide() { + const s = ui.session; + const open = [], flagged = []; + s.questions.forEach((q, i) => { + const a = s.answers[q.id]; + if (!isAnswered(a)) open.push(i); + if (a && a.flagged) flagged.push(i); + }); + const jump = (list) => list.length + ? list.map((i) => ``).join(' ') : '–'; + return ` +
+

Prüfung abgeben

+

Beantwortet: ${s.questions.length - open.length} von ${s.questions.length}

+

Offen: ${jump(open)}

+

Markiert: ${jump(flagged)}

+

+
`; + } + + function resultSlide() { + const s = ui.session; + const learn = s.mode === 'learn'; + const r = score(s, learn); + const topicTitle = (id) => (s.topics.find((t) => t.id === id) || {}).title || ''; + const rows = Object.keys(r.topics).sort().map((t) => { + const ts = r.topics[t]; + const p = Math.round((ts.correct / ts.total) * 100); + return `${esc(t)}${esc(topicTitle(t))}${ts.correct}/${ts.total} + ${p} %`; + }).join(''); + const wrong = r.wrong.length + ? r.wrong.map((i) => ``).join(' ') : '–'; + const verdict = r.total === 0 ? '' + : `

${r.passed ? 'Bestanden' : 'Nicht bestanden'} (Richtwert ${s.pass_percent} %)

`; + return ` +
+

Auswertung${learn ? ' (bisher aufgelöste Fragen)' : ''}

+

${r.correct} von ${r.total} richtig · ${r.percent} %

+ ${verdict} +

LPI bewertet auf einer Skala von 200–800 (bestanden ab 500) und veröffentlicht keine Prozentgrenze. + Der Richtwert ist eine Annahme und in exam.json (pass_percent) einstellbar.

+
+ ${rows}
TopicrichtigQuote
+

Falsch/offen (anklicken zum Ansehen): ${wrong}

+

+ ${r.wrong.length ? '' : ''} + + +

+
`; + } + + function submitExam(auto) { + const s = ui.session; + s.submitted = true; + save(); + renderSession(s.questions.length); + toast(auto ? 'Zeit abgelaufen – Prüfung automatisch abgegeben.' : 'Prüfung abgegeben.', auto ? 'warn' : 'info'); + } + + /** Neue Lernsitzung mit den falsch beantworteten Fragen der aktuellen Sitzung. */ + function retryWrong() { + const s = ui.session; + const r = score(s, s.mode === 'learn'); + const qs = r.wrong.map((i) => s.questions[i]); + const exam = { ...(ui.exams.find((e) => e.id === s.exam_id) || {}), id: s.exam_id, title: s.exam_title, + code: s.exam_code, topics: s.topics, pass_percent: s.pass_percent, bank: qs }; + startSession(createSession(exam, { mode: 'learn', order: 'random', shuffleOptions: true }), 0); + } + + /* ----------------------------- Werkzeugleiste, Timer */ + + /** Überträgt die tatsächliche Höhe der (ggf. umbrochenen) Werkzeugleiste nach CSS --tb-h. */ + function syncToolbarHeight() { + document.documentElement.style.setProperty('--tb-h', `${$('.toolbar').offsetHeight}px`); + } + + function updateToolbar() { + const s = ui.session; + $('#tb-title').textContent = s ? `${s.exam_title} · ${s.mode === 'exam' ? 'Prüfung' : 'Lernen'}` : 'LPIC-Prüfungssimulator'; + $('#tb-export').disabled = !s; + if (!s) { $('#tb-progress').textContent = ''; $('#tb-timer').textContent = ''; return; } + const done = s.questions.filter((q) => isAnswered(s.answers[q.id])).length; + $('#tb-progress').textContent = `${done}/${s.questions.length} beantwortet`; + const timer = $('#tb-timer'); + if (s.mode === 'exam' && !s.submitted) { + const rest = s.time_limit_s - s.elapsed_s; + timer.textContent = `⏱ ${fmtTime(rest)}`; + timer.classList.toggle('low', rest < 600); + } else { + timer.textContent = `⏱ ${fmtTime(s.elapsed_s)}`; + timer.classList.remove('low'); + } + } + + function tick() { + const s = ui.session; + if (!s || s.submitted) return; + s.elapsed_s++; + if (++ui.tickCount % SAVE_EVERY_S === 0) save(); + if (s.mode === 'exam' && s.elapsed_s >= s.time_limit_s) { submitExam(true); return; } + updateToolbar(); + } + + /* ----------------------------- Export / Import */ + + function exportSession() { + const s = ui.session; + if (!s) return; + save(); + const d = new Date(); + const pad = (n) => String(n).padStart(2, '0'); + const stamp = `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}_${pad(d.getHours())}${pad(d.getMinutes())}`; + download(`lpic_sim_${s.exam_id}_${s.mode}_${stamp}.json`, JSON.stringify(s, null, 1)); + } + + /** Import: erkennt Sitzung (fortsetzen) oder Fragenpaket (in Bank übernehmen). */ + function importFile(file) { + const reader = new FileReader(); + reader.onload = () => { + let doc; + try { doc = JSON.parse(reader.result); } + catch (e) { toast(`${file.name}: kein gültiges JSON (${e.message})`, 'error'); return; } + if (doc.format === SESSION_FORMAT) { + const err = validateSession(doc); + if (err) { toast(`${file.name}: ${err}`, 'error'); return; } + startSession(doc, doc.current || 0); + toast(`Sitzung „${doc.exam_title}“ geladen – weiter bei Frage ${Math.min((doc.current || 0) + 1, doc.questions.length)}.`); + } else if (doc.format === PACK_FORMAT) { + const res = mergePack(ui.exams, doc); + if (res.added + res.replaced > 0) { + const packs = (store.get(STORE_PACKS) || []).filter((p) => p.name !== file.name); + packs.push({ ...doc, name: file.name }); + store.set(STORE_PACKS, packs); + } + res.errors.slice(0, 5).forEach((e) => toast(e, 'error')); + toast(`${file.name}: ${res.added} neu, ${res.replaced} ersetzt${res.errors.length ? `, ${res.errors.length} abgelehnt` : ''}.`, + res.errors.length ? 'warn' : 'info'); + if (!ui.session) renderStart(); + } else { + toast(`${file.name}: unbekanntes Format (erwartet ${SESSION_FORMAT} oder ${PACK_FORMAT})`, 'error'); + } + }; + reader.readAsText(file); + } + + /* ----------------------------- Ereignisse */ + + function onChange(ev) { + const t = ev.target; + if (t.closest('#setup')) { updateStartForm(); return; } + const section = t.closest('section.question'); + if (!section || !ui.session) return; + const s = ui.session; + const q = s.questions[Number(section.dataset.index)]; + const a = s.answers[q.id] || (s.answers[q.id] = { value: q.type === 'fill' ? '' : [] }); + if (t.hasAttribute('data-flag')) { a.flagged = t.checked; save(); return; } + if (isLocked(q)) return; + if (q.type === 'single') a.value = [t.value]; + else if (q.type === 'multi') { + let sel = $$('.options input:checked', section).map((i) => i.value); + const max = correctCount(q); + if (sel.length > max) { + t.checked = false; + sel = sel.filter((v) => v !== t.value); + toast(`Höchstens ${max} Antworten wählbar.`, 'warn'); + } + a.value = sel; + } else a.value = t.value; + save(); + updateToolbar(); + } + + function onClick(ev) { + const btn = ev.target.closest('[data-act],[data-goto]'); + if (!btn) return; + if (btn.dataset.goto !== undefined) { Reveal.slide(Number(btn.dataset.goto)); return; } + switch (btn.dataset.act) { + case 'next': Reveal.next(); break; + case 'prev': Reveal.prev(); break; + case 'resume': { const s = store.get(STORE_SESSION); if (s) { ui.session = s; renderSession(s.current); } break; } + case 'discard': + if (window.confirm('Gespeicherte Sitzung verwerfen? (Vorher exportieren, falls sie noch gebraucht wird.)')) { + store.del(STORE_SESSION); renderStart(); + } + break; + case 'submit': { + const open = ui.session.questions.filter((q) => !isAnswered(ui.session.answers[q.id])).length; + if (!open || window.confirm(`${open} Fragen sind offen. Trotzdem abgeben?`)) submitExam(false); + break; + } + case 'retry': retryWrong(); break; + case 'export': exportSession(); break; + case 'import': $('#import-file').click(); break; + case 'menu': save(); renderStart(); break; + default: break; + } + } + + function onKey(ev) { + const t = ev.target; + if (t.matches && t.matches('input.fill')) { + if (ev.key === 'Enter') { ev.preventDefault(); t.blur(); Reveal.next(); } + return; + } + if (t.matches && t.matches('input[type=text],input[type=number],select,textarea')) return; + if (ev.ctrlKey || ev.altKey || ev.metaKey) return; + const n = Number(ev.key); + if (n >= 1 && n <= 5) { + const input = $$('.present .options input')[n - 1]; + if (input && !input.disabled) { input.click(); ev.preventDefault(); } + } + } + + function onSlideChanged(ev) { + const s = ui.session; + if (!s) return; + s.current = ev.indexh; + const sec = ev.currentSlide; + if (sec.classList.contains('result')) { + // Lernmodus: Auswertung bei jedem Aufruf neu berechnen + const fresh = document.createElement('div'); + fresh.innerHTML = resultSlide(); + sec.innerHTML = fresh.firstElementChild.innerHTML; + } else if (sec.classList.contains('submit')) { + const fresh = document.createElement('div'); + fresh.innerHTML = submitSlide(); + sec.innerHTML = fresh.firstElementChild.innerHTML; + } else if (sec.classList.contains('question')) { + const q = s.questions[Number(sec.dataset.index)]; + if (isLocked(q) && q.options) markOptions(sec, q); + sec.scrollTop = 0; + } + save(); + updateToolbar(); + } + + function onFragmentShown(ev) { + const frag = ev.fragment; + if (frag && frag.classList.contains('solution')) revealQuestion(frag.closest('section.question')); + } + + function init() { + loadBank(); + // Erst eine Platzhalter-Folie, dann reveal.js starten, dann die echte Startseite setzen + $('.reveal .slides').innerHTML = '
'; + Reveal.initialize({ + hash: false, + history: false, + controls: true, + controlsTutorial: false, + progress: true, + center: false, + disableLayout: true, + scrollActivationWidth: null, + overview: false, + touch: false, + pause: false, + transition: 'slide', + transitionSpeed: 'fast', + keyboard: { 66: null, 190: null, 79: null }, // B, Punkt, O: Pause/Übersicht aus + }).then(() => { + Reveal.on('slidechanged', onSlideChanged); + Reveal.on('fragmentshown', onFragmentShown); + const slides = $('.reveal .slides'); + slides.addEventListener('change', onChange); + slides.addEventListener('input', (ev) => { if (ev.target.matches('input.fill')) onChange(ev); }); + slides.addEventListener('submit', (ev) => { ev.preventDefault(); startFromForm(ev.target); }); + document.addEventListener('click', onClick); + document.addEventListener('keydown', onKey); + $('#import-file').addEventListener('change', (ev) => { + const f = ev.target.files && ev.target.files[0]; + if (f) importFile(f); + ev.target.value = ''; + }); + $('#tb-export').addEventListener('click', exportSession); + window.addEventListener('beforeunload', save); + new ResizeObserver(syncToolbarHeight).observe($('.toolbar')); + setInterval(tick, 1000); + renderStart(); + }); + } + + window.LPICSim = { core, ui }; + if (window.Reveal && !window.LPICSIM_NO_UI) document.addEventListener('DOMContentLoaded', init); +})(); diff --git a/simulator/js/bank.js b/simulator/js/bank.js new file mode 100644 index 0000000..16171d4 --- /dev/null +++ b/simulator/js/bank.js @@ -0,0 +1,13 @@ +/** + * @file bank.js + * @brief Fragenbank (verschlüsselt) – ERZEUGT von tools/build_bank.py, nicht von Hand bearbeiten + * @author Björn Runden + * @owner Björn Runden + * @version 2026-10-29T22:40:55Z + */ +window.LPIC_BANK = { + "generated": "2026-10-29T22:40:55Z", + "build": "179de2341e47860b1d8ad91f2d6dad734ec7915808c0fd02d276c13a6b2ed86a", + "rev": "1ae157f0c162c0674a00e01c", + "payload": "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" +}; diff --git a/simulator/tests/selftest.html b/simulator/tests/selftest.html new file mode 100644 index 0000000..98db9a7 --- /dev/null +++ b/simulator/tests/selftest.html @@ -0,0 +1,138 @@ + + + +Selbsttest LPIC-Simulator + + + +

+
+
+
+
+
+
diff --git a/simulator/tests/ui_smoke.html b/simulator/tests/ui_smoke.html
new file mode 100644
index 0000000..09cddf1
--- /dev/null
+++ b/simulator/tests/ui_smoke.html
@@ -0,0 +1,134 @@
+
+
+
+UI-Rauchtest
+
+
+
+
+

+
+
+
diff --git a/simulator/tools/build_bank.py b/simulator/tools/build_bank.py
new file mode 100644
index 0000000..d54726f
--- /dev/null
+++ b/simulator/tools/build_bank.py
@@ -0,0 +1,352 @@
+#!/usr/bin/env python3
+"""
+@file     build_bank.py
+@brief    Prüft alle Fragendateien unter data/, erzeugt die verschlüsselte js/bank.js und optional ein Export-Verzeichnis
+@author   Björn Runden 
+@owner    Björn Runden 
+@assist   KI-unterstützt (Claude Opus 5.5), geprüft von Björn Runden 
+@version  0.3.0 (29.10.2026)
+@usage    build_bank.py [-d] [-q] [-n] [-c] [--approved-only] [-o js/bank.js] [-e [DIR]] [-b [FILE]]
+
+Aufbau von data/: je Prüfung ein Ordner mit exam.json und beliebig vielen questions_*.json (Quelltext, Klartext).
+js/bank.js enthält die Fragen nur ChaCha20-verschlüsselt (RFC 8439). Der Schlüssel wird aus einem PSK abgeleitet
+(Umgebung LPIC_SIM_PSK, sonst tools/.psk, sonst zufällig erzeugt) und steht als „build“-Kennung in bank.js –
+das verhindert Klartext auf der Platte, ist aber kein Schutz gegen gezielte Analyse (der Browser braucht den Schlüssel).
+Mit -n/--dry-run bzw. -c/--check wird nur geprüft und die Abdeckung je Objective ausgegeben.
+"""
+
+from __future__ import annotations
+
+import argparse
+import base64
+import hashlib
+import json
+import logging
+import os
+import re
+import secrets
+import shutil
+import struct
+import sys
+from datetime import datetime, timezone
+from pathlib import Path
+
+BASE = Path(__file__).resolve().parent.parent
+DATA = BASE / "data"
+OUT_DEFAULT = BASE / "js" / "bank.js"
+PSK_FILE = BASE / "tools" / ".psk"
+EXPORT_DEFAULT = BASE / "dist"
+EXPORT_MARKER = ".lpic-sim-export"
+EXPORT_ITEMS = ["index.html", "css", "js", "vendor"]
+
+OPTION_IDS = ["a", "b", "c", "d", "e"]
+QID_RE = re.compile(r"^(\d{3}\.\d+)-\d{3}$")
+QUESTION_KEYS = {"id", "objective", "type", "lang", "difficulty", "question", "code", "options",
+                 "answers", "case_sensitive", "explanation", "references", "review"}
+REVIEW_STATES = {"pending", "approved", "rejected"}
+
+log = logging.getLogger("build_bank")
+
+
+# ------------------------------------------------------------------ ChaCha20 (RFC 8439), nur Standardbibliothek
+
+def _chacha20_block(key_words: tuple, counter: int, nonce_words: tuple) -> bytes:
+    """Ein 64-Byte-Keystream-Block nach RFC 8439, Abschnitt 2.3."""
+    state = [0x61707865, 0x3320646E, 0x79622D32, 0x6B206574, *key_words, counter & 0xFFFFFFFF, *nonce_words]
+    x = state[:]
+
+    def qr(a: int, b: int, c: int, d: int) -> None:
+        x[a] = (x[a] + x[b]) & 0xFFFFFFFF; x[d] ^= x[a]; x[d] = ((x[d] << 16) | (x[d] >> 16)) & 0xFFFFFFFF
+        x[c] = (x[c] + x[d]) & 0xFFFFFFFF; x[b] ^= x[c]; x[b] = ((x[b] << 12) | (x[b] >> 20)) & 0xFFFFFFFF
+        x[a] = (x[a] + x[b]) & 0xFFFFFFFF; x[d] ^= x[a]; x[d] = ((x[d] << 8) | (x[d] >> 24)) & 0xFFFFFFFF
+        x[c] = (x[c] + x[d]) & 0xFFFFFFFF; x[b] ^= x[c]; x[b] = ((x[b] << 7) | (x[b] >> 25)) & 0xFFFFFFFF
+
+    for _ in range(10):
+        qr(0, 4, 8, 12); qr(1, 5, 9, 13); qr(2, 6, 10, 14); qr(3, 7, 11, 15)
+        qr(0, 5, 10, 15); qr(1, 6, 11, 12); qr(2, 7, 8, 13); qr(3, 4, 9, 14)
+    return struct.pack("<16L", *((x[i] + state[i]) & 0xFFFFFFFF for i in range(16)))
+
+
+def chacha20(key: bytes, nonce: bytes, data: bytes, counter: int = 1) -> bytes:
+    """Ver-/Entschlüsselt data mit ChaCha20 (32-Byte-Schlüssel, 12-Byte-Nonce). Returns: Ergebnis gleicher Länge."""
+    kw, nw = struct.unpack("<8L", key), struct.unpack("<3L", nonce)
+    out = bytearray(len(data))
+    for off in range(0, len(data), 64):
+        block = _chacha20_block(kw, counter + off // 64, nw)
+        chunk = data[off:off + 64]
+        out[off:off + len(chunk)] = bytes(a ^ b for a, b in zip(chunk, block))
+    return bytes(out)
+
+
+def load_psk() -> str:
+    """PSK aus LPIC_SIM_PSK oder tools/.psk; fehlt beides, wird einer erzeugt und in tools/.psk abgelegt."""
+    env = os.environ.get("LPIC_SIM_PSK", "").strip()
+    if env:
+        return env
+    if PSK_FILE.is_file():
+        psk = PSK_FILE.read_text(encoding="utf-8").strip()
+        if psk:
+            return psk
+    psk = secrets.token_urlsafe(24)
+    PSK_FILE.write_text(psk + "\n", encoding="utf-8")
+    PSK_FILE.chmod(0o600)
+    log.info("neuer PSK erzeugt: %s (nicht weitergeben)", PSK_FILE.relative_to(BASE))
+    return psk
+
+
+def derive_key(psk: str) -> bytes:
+    """Schlüssel = SHA-256 über den PSK mit festem Kontext; so taucht der PSK selbst nirgends auf."""
+    return hashlib.sha256(b"lpic-sim/bank/v1:" + psk.encode("utf-8")).digest()
+
+
+# ------------------------------------------------------------------ Prüfung der Fragen
+
+def load_json(path: Path) -> dict:
+    """Liest eine JSON-Datei; Fehler werden mit Dateiname gemeldet."""
+    try:
+        return json.loads(path.read_text(encoding="utf-8"))
+    except json.JSONDecodeError as exc:
+        raise ValueError(f"{path.relative_to(BASE)}: ungültiges JSON ({exc})") from exc
+
+
+def review_state(q: dict) -> str:
+    """Prüfstatus einer Frage; ohne Eintrag 'pending'."""
+    return (q.get("review") or {}).get("status", "pending")
+
+
+def check_question(q: dict, objectives: set[str], where: str) -> list[str]:
+    """Prüft eine Frage gegen die Erstellungsregeln. Returns: Liste der Fehlermeldungen."""
+    err: list[str] = []
+    qid = q.get("id", "?")
+    p = f"{where} [{qid}]"
+    unknown = set(q) - QUESTION_KEYS
+    if unknown:
+        err.append(f"{p}: unbekannte Schlüssel {sorted(unknown)}")
+    m = QID_RE.match(qid)
+    if not m:
+        err.append(f"{p}: id muss - sein")
+    elif m.group(1) != q.get("objective"):
+        err.append(f"{p}: id passt nicht zu objective {q.get('objective')}")
+    if q.get("objective") not in objectives:
+        err.append(f"{p}: objective {q.get('objective')} gibt es in der Prüfung nicht")
+    for key in ("question", "explanation"):
+        if not str(q.get(key, "")).strip():
+            err.append(f"{p}: '{key}' fehlt oder ist leer")
+    if review_state(q) not in REVIEW_STATES:
+        err.append(f"{p}: review.status muss pending, approved oder rejected sein")
+    qtype = q.get("type")
+    if qtype in ("single", "multi"):
+        opts = q.get("options") or []
+        if [o.get("id") for o in opts] != OPTION_IDS:
+            err.append(f"{p}: genau 5 Optionen mit ids a–e in dieser Reihenfolge erforderlich")
+        texts = [o.get("text", "").strip() for o in opts]
+        if len(set(texts)) != len(texts):
+            err.append(f"{p}: doppelte Optionstexte")
+        for o in opts:
+            if not o.get("text", "").strip() or not o.get("explanation", "").strip():
+                err.append(f"{p}: Option {o.get('id')} ohne Text oder Erläuterung")
+            if not isinstance(o.get("correct"), bool):
+                err.append(f"{p}: Option {o.get('id')}: 'correct' muss true/false sein")
+        n_ok = sum(1 for o in opts if o.get("correct") is True)
+        if qtype == "single" and n_ok != 1:
+            err.append(f"{p}: single braucht genau 1 richtige Option (hat {n_ok})")
+        if qtype == "multi" and not 2 <= n_ok <= 4:
+            err.append(f"{p}: multi braucht 2–4 richtige Optionen (hat {n_ok})")
+        if "answers" in q:
+            err.append(f"{p}: 'answers' nur bei type fill")
+    elif qtype == "fill":
+        if not q.get("answers") or not all(str(a).strip() for a in q["answers"]):
+            err.append(f"{p}: fill braucht nicht leere 'answers'")
+        if "options" in q:
+            err.append(f"{p}: 'options' nicht bei type fill")
+    else:
+        err.append(f"{p}: type muss single, multi oder fill sein")
+    return err
+
+
+def load_exam(exam_dir: Path, approved_only: bool) -> tuple[dict, list[str]]:
+    """Lädt exam.json und alle questions_*.json eines Prüfungsordners. Returns: (Prüfung, Fehler)."""
+    exam_doc = load_json(exam_dir / "exam.json")
+    exam = dict(exam_doc["exam"])
+    exam["topics"] = exam_doc["topics"]
+    objectives = {o["id"] for t in exam["topics"] for o in t["objectives"]}
+    errors: list[str] = []
+    questions: list[dict] = []
+    seen: set[str] = set()
+    states = {s: 0 for s in sorted(REVIEW_STATES)}
+    for qfile in sorted(exam_dir.glob("questions_*.json")):
+        doc = load_json(qfile)
+        where = str(qfile.relative_to(BASE))
+        if doc.get("format") != "lpic-sim-questions":
+            errors.append(f"{where}: format muss 'lpic-sim-questions' sein")
+        if doc.get("exam") != exam["id"]:
+            errors.append(f"{where}: exam '{doc.get('exam')}' passt nicht zu '{exam['id']}'")
+        for q in doc.get("questions", []):
+            errors += check_question(q, objectives, where)
+            if q.get("id") in seen:
+                errors.append(f"{where}: doppelte id {q.get('id')}")
+            seen.add(q.get("id"))
+            state = review_state(q)
+            states[state] = states.get(state, 0) + 1
+            if state == "rejected" or (approved_only and state != "approved"):
+                continue
+            q = {k: v for k, v in q.items() if k != "review"}   # Prüfvermerke gehören nicht in die Bank
+            q.setdefault("lang", exam.get("lang", "de"))
+            questions.append(q)
+    questions.sort(key=lambda q: (tuple(int(x) for x in q["objective"].split(".")), q["id"]))
+    exam["questions_bank"] = questions
+    exam["review_states"] = states
+    return exam, errors
+
+
+def coverage(exam: dict) -> None:
+    """Gibt Prüfstatus und die Anzahl der Fragen je Objective im Verhältnis zur Gewichtung aus."""
+    counts: dict[str, int] = {}
+    for q in exam["questions_bank"]:
+        counts[q["objective"]] = counts.get(q["objective"], 0) + 1
+    st = exam["review_states"]
+    log.info("%s: %d Fragen in der Bank (Prüfstatus: %d approved, %d pending, %d rejected)", exam["id"],
+             len(exam["questions_bank"]), st.get("approved", 0), st.get("pending", 0), st.get("rejected", 0))
+    for t in exam["topics"]:
+        for o in t["objectives"]:
+            n = counts.get(o["id"], 0)
+            flag = "" if n >= o["weight"] else "  <- weniger Fragen als Gewicht (Prüfungsmodus füllt auf)"
+            log.info("  %-6s Gewicht %d  Fragen %3d%s", o["id"], o["weight"], n, flag)
+
+
+# ------------------------------------------------------------------ Ausgabe
+
+def write_bank(exams: list[dict], output: Path) -> None:
+    """Schreibt bank.js: Metadaten im Klartext, Prüfungen und Fragen ChaCha20-verschlüsselt (Base64)."""
+    generated = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
+    # exam["questions"] bleibt die Fragenzahl der Prüfung, die Fragen selbst stehen unter "bank"
+    plain = json.dumps({"exams": [{**{k: v for k, v in e.items() if k not in ("questions_bank", "review_states")},
+                                   "bank": e["questions_bank"]} for e in exams]},
+                       ensure_ascii=False, separators=(",", ":")).encode("utf-8")
+    key, nonce = derive_key(load_psk()), secrets.token_bytes(12)
+    bank = {
+        "generated": generated,
+        "build": key.hex(),       # Schlüssel, getarnt als Build-Kennung
+        "rev": nonce.hex(),       # Nonce
+        "payload": base64.b64encode(chacha20(key, nonce, plain)).decode("ascii"),
+    }
+    header = ("/**\n * @file     bank.js\n * @brief    Fragenbank (verschlüsselt) – ERZEUGT von tools/build_bank.py, nicht von Hand bearbeiten\n"
+              " * @author   Björn Runden \n * @owner    Björn Runden \n"
+              f" * @version  {generated}\n */\n")
+    output.write_text(header + "window.LPIC_BANK = " + json.dumps(bank, indent=1) + ";\n", encoding="utf-8")
+
+
+def export_site(target: Path, dry_run: bool) -> None:
+    """Kopiert nur die Laufzeitdateien (ohne data/, tools/, tests/) nach target.
+    Ein vorhandenes Ziel wird nur ersetzt, wenn es von hier stammt (Markierungsdatei)."""
+    target = target.resolve()
+    if target == BASE or BASE in target.parents and target.name in EXPORT_ITEMS + ["data", "tools", "tests"]:
+        raise ValueError(f"Export-Ziel {target} liegt im Quellbaum")
+    if target.exists() and any(target.iterdir()) and not (target / EXPORT_MARKER).exists():
+        raise ValueError(f"Export-Ziel {target} ist nicht leer und kein früherer Export – bitte prüfen")
+    if dry_run:
+        log.info("Trockenlauf: würde %s nach %s exportieren", ", ".join(EXPORT_ITEMS), target)
+        return
+    if target.exists():
+        shutil.rmtree(target)
+    target.mkdir(parents=True)
+    for item in EXPORT_ITEMS:
+        src = BASE / item
+        (shutil.copytree if src.is_dir() else shutil.copy2)(src, target / item)
+    (target / EXPORT_MARKER).write_text("Export von simulator/tools/build_bank.py – Verzeichnis wird beim nächsten Export ersetzt\n",
+                                        encoding="utf-8")
+    log.info("Export nach %s geschrieben (Start: python3 -m http.server 8080 -d %s)", target, target)
+
+
+def bundle_excluded(rel: Path) -> bool:
+    """Nicht ins Prüferpaket: PSK, Erzeugtes (Export, Pakete), Caches, Sicherungen."""
+    parts = rel.parts
+    return (rel.as_posix() == "tools/.psk" or parts[0] in ("dist", "release")
+            or "__pycache__" in parts or rel.name.endswith(".orig"))
+
+
+def write_bundle(target: Path, dry_run: bool) -> None:
+    """Packt den kompletten Quellstand (Fragen, Doku, Compiler, Tests, Laufzeit) als tar.gz mit Wurzel lpic-sim/."""
+    import tarfile
+    files = sorted(p for p in BASE.rglob("*") if p.is_file() and not bundle_excluded(p.relative_to(BASE)))
+    if dry_run:
+        log.info("Trockenlauf: würde %d Dateien nach %s packen", len(files), target)
+        return
+    target.parent.mkdir(parents=True, exist_ok=True)
+    with tarfile.open(target, "w:gz") as tar:
+        for p in files:
+            tar.add(p, arcname=f"lpic-sim/{p.relative_to(BASE).as_posix()}", recursive=False)
+    log.info("Prüferpaket %s geschrieben (%d Dateien, %d KiB)", target, len(files), target.stat().st_size // 1024)
+
+
+def main() -> int:
+    ap = argparse.ArgumentParser(description="Fragenbank prüfen, verschlüsselte js/bank.js erzeugen, optional exportieren")
+    ap.add_argument("-d", "--debug", action="store_true", help="Debug-Ausgaben")
+    ap.add_argument("-q", "--quiet", action="store_true", help="nur Fehler ausgeben")
+    ap.add_argument("-n", "--dry-run", action="store_true", help="nur prüfen, nichts schreiben")
+    ap.add_argument("-c", "--check", action="store_true", help="wie --dry-run, mit Abdeckungsbericht")
+    ap.add_argument("--approved-only", action="store_true", help="nur Fragen mit review.status approved übernehmen")
+    ap.add_argument("-o", "--output", type=Path, default=OUT_DEFAULT, help="Zieldatei (Default js/bank.js)")
+    ap.add_argument("-e", "--export", type=Path, nargs="?", const=EXPORT_DEFAULT, metavar="DIR",
+                    help=f"Laufzeitdateien nach DIR exportieren (Default {EXPORT_DEFAULT.relative_to(BASE)})")
+    ap.add_argument("-b", "--bundle", type=Path, nargs="?", metavar="FILE",
+                    const=BASE / "release" / f"lpic-sim_{datetime.now():%Y-%m-%d}.tar.gz",
+                    help="Prüferpaket (tar.gz, ohne PSK und Erzeugtes) schreiben; Default release/lpic-sim_.tar.gz")
+    args = ap.parse_args()
+    level = logging.DEBUG if args.debug else logging.ERROR if args.quiet else logging.INFO
+    logging.basicConfig(level=level, format="%(levelname)s %(message)s")
+
+    exams: list[dict] = []
+    errors: list[str] = []
+    try:
+        for exam_file in sorted(DATA.glob("*/exam.json")):
+            exam, errs = load_exam(exam_file.parent, args.approved_only)
+            exams.append(exam)
+            errors += errs
+    except (ValueError, KeyError) as exc:
+        log.error("%s", exc)
+        return 1
+    for e in errors:
+        log.error("%s", e)
+    if errors:
+        log.error("%d Fehler – bank.js nicht geschrieben", len(errors))
+        return 1
+    exams.sort(key=lambda e: (e.get("level", ""), e.get("order", 0)))
+    total = sum(len(e["questions_bank"]) for e in exams)
+    if args.check or args.debug:
+        for exam in exams:
+            coverage(exam)
+    if args.dry_run or args.check:
+        log.info("Prüfung ok: %d Prüfungen, %d Fragen", len(exams), total)
+        if args.export:
+            try:
+                export_site(args.export, True)
+            except ValueError as exc:
+                log.error("%s", exc)
+                return 1
+        if args.bundle:
+            write_bundle(args.bundle, True)
+        return 0
+    if total == 0:
+        log.error("keine Fragen für die Bank (bei --approved-only: noch nichts freigegeben?)")
+        return 1
+
+    write_bank(exams, args.output)
+    log.info("%s geschrieben (verschlüsselt): %d Prüfungen, %d Fragen", args.output, len(exams), total)
+    if args.export:
+        try:
+            export_site(args.export, False)
+        except (ValueError, OSError) as exc:
+            log.error("Export fehlgeschlagen: %s", exc)
+            return 1
+    if args.bundle:
+        try:
+            write_bundle(args.bundle, False)
+        except OSError as exc:
+            log.error("Prüferpaket fehlgeschlagen: %s", exc)
+            return 1
+    return 0
+
+
+if __name__ == "__main__":
+    sys.exit(main())
diff --git a/simulator/vendor/reveal/LICENSE b/simulator/vendor/reveal/LICENSE
new file mode 100644
index 0000000..38ff0eb
--- /dev/null
+++ b/simulator/vendor/reveal/LICENSE
@@ -0,0 +1,19 @@
+Copyright (C) 2011-2024 Hakim El Hattab, http://hakim.se, and reveal.js contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
\ No newline at end of file
diff --git a/simulator/vendor/reveal/VERSION.txt b/simulator/vendor/reveal/VERSION.txt
new file mode 100644
index 0000000..d13e31a
--- /dev/null
+++ b/simulator/vendor/reveal/VERSION.txt
@@ -0,0 +1,3 @@
+reveal.js 5.1.0 (dist), Quelle: https://github.com/hakimel/reveal.js/archive/refs/tags/5.1.0.tar.gz
+Abgerufen: 2026-10-29, sha256 (tar.gz): ddc83539ec50583eac9a972e88f892971b37c44e70dd0c08be069e2688684b71
+Unverändert übernommen: reveal.js, reveal.css, reset.css, theme/dracula.css, LICENSE (MIT)
diff --git a/simulator/vendor/reveal/reset.css b/simulator/vendor/reveal/reset.css
new file mode 100644
index 0000000..e238539
--- /dev/null
+++ b/simulator/vendor/reveal/reset.css
@@ -0,0 +1,30 @@
+/* http://meyerweb.com/eric/tools/css/reset/
+   v4.0 | 20180602
+   License: none (public domain)
+*/
+
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+b, u, i, center,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td,
+article, aside, canvas, details, embed,
+figure, figcaption, footer, header, hgroup,
+main, menu, nav, output, ruby, section, summary,
+time, mark, audio, video {
+  margin: 0;
+  padding: 0;
+  border: 0;
+  font-size: 100%;
+  font: inherit;
+  vertical-align: baseline;
+}
+/* HTML5 display-role reset for older browsers */
+article, aside, details, figcaption, figure,
+footer, header, hgroup, main, menu, nav, section {
+  display: block;
+}
\ No newline at end of file
diff --git a/simulator/vendor/reveal/reveal.css b/simulator/vendor/reveal/reveal.css
new file mode 100644
index 0000000..869289e
--- /dev/null
+++ b/simulator/vendor/reveal/reveal.css
@@ -0,0 +1,8 @@
+/*!
+* reveal.js 5.1.0
+* https://revealjs.com
+* MIT licensed
+*
+* Copyright (C) 2011-2024 Hakim El Hattab, https://hakim.se
+*/
+.reveal .r-stretch,.reveal .stretch{max-width:none;max-height:none}.reveal pre.r-stretch code,.reveal pre.stretch code{height:100%;max-height:100%;box-sizing:border-box}.reveal .r-fit-text{display:inline-block;white-space:nowrap}.reveal .r-stack{display:grid;grid-template-rows:100%}.reveal .r-stack>*{grid-area:1/1;margin:auto}.reveal .r-hstack,.reveal .r-vstack{display:flex}.reveal .r-hstack img,.reveal .r-hstack video,.reveal .r-vstack img,.reveal .r-vstack video{min-width:0;min-height:0;object-fit:contain}.reveal .r-vstack{flex-direction:column;align-items:center;justify-content:center}.reveal .r-hstack{flex-direction:row;align-items:center;justify-content:center}.reveal .items-stretch{align-items:stretch}.reveal .items-start{align-items:flex-start}.reveal .items-center{align-items:center}.reveal .items-end{align-items:flex-end}.reveal .justify-between{justify-content:space-between}.reveal .justify-around{justify-content:space-around}.reveal .justify-start{justify-content:flex-start}.reveal .justify-center{justify-content:center}.reveal .justify-end{justify-content:flex-end}html.reveal-full-page{width:100%;height:100%;height:100vh;height:calc(var(--vh,1vh) * 100);height:100svh;overflow:hidden}.reveal-viewport{height:100%;overflow:hidden;position:relative;line-height:1;margin:0;background-color:#fff;color:#000;--r-controls-spacing:12px}.reveal-viewport:fullscreen{top:0!important;left:0!important;width:100%!important;height:100%!important;transform:none!important}.reveal .fragment{transition:all .2s ease}.reveal .fragment:not(.custom){opacity:0;visibility:hidden;will-change:opacity}.reveal .fragment.visible{opacity:1;visibility:inherit}.reveal .fragment.disabled{transition:none}.reveal .fragment.grow{opacity:1;visibility:inherit}.reveal .fragment.grow.visible{transform:scale(1.3)}.reveal .fragment.shrink{opacity:1;visibility:inherit}.reveal .fragment.shrink.visible{transform:scale(.7)}.reveal .fragment.zoom-in{transform:scale(.1)}.reveal .fragment.zoom-in.visible{transform:none}.reveal .fragment.fade-out{opacity:1;visibility:inherit}.reveal .fragment.fade-out.visible{opacity:0;visibility:hidden}.reveal .fragment.semi-fade-out{opacity:1;visibility:inherit}.reveal .fragment.semi-fade-out.visible{opacity:.5;visibility:inherit}.reveal .fragment.strike{opacity:1;visibility:inherit}.reveal .fragment.strike.visible{text-decoration:line-through}.reveal .fragment.fade-up{transform:translate(0,40px)}.reveal .fragment.fade-up.visible{transform:translate(0,0)}.reveal .fragment.fade-down{transform:translate(0,-40px)}.reveal .fragment.fade-down.visible{transform:translate(0,0)}.reveal .fragment.fade-right{transform:translate(-40px,0)}.reveal .fragment.fade-right.visible{transform:translate(0,0)}.reveal .fragment.fade-left{transform:translate(40px,0)}.reveal .fragment.fade-left.visible{transform:translate(0,0)}.reveal .fragment.current-visible,.reveal .fragment.fade-in-then-out{opacity:0;visibility:hidden}.reveal .fragment.current-visible.current-fragment,.reveal .fragment.fade-in-then-out.current-fragment{opacity:1;visibility:inherit}.reveal .fragment.fade-in-then-semi-out{opacity:0;visibility:hidden}.reveal .fragment.fade-in-then-semi-out.visible{opacity:.5;visibility:inherit}.reveal .fragment.fade-in-then-semi-out.current-fragment{opacity:1;visibility:inherit}.reveal .fragment.highlight-blue,.reveal .fragment.highlight-current-blue,.reveal .fragment.highlight-current-green,.reveal .fragment.highlight-current-red,.reveal .fragment.highlight-green,.reveal .fragment.highlight-red{opacity:1;visibility:inherit}.reveal .fragment.highlight-red.visible{color:#ff2c2d}.reveal .fragment.highlight-green.visible{color:#17ff2e}.reveal .fragment.highlight-blue.visible{color:#1b91ff}.reveal .fragment.highlight-current-red.current-fragment{color:#ff2c2d}.reveal .fragment.highlight-current-green.current-fragment{color:#17ff2e}.reveal .fragment.highlight-current-blue.current-fragment{color:#1b91ff}.reveal:after{content:"";font-style:italic}.reveal iframe{z-index:1}.reveal a{position:relative}@keyframes bounce-right{0%,10%,25%,40%,50%{transform:translateX(0)}20%{transform:translateX(10px)}30%{transform:translateX(-5px)}}@keyframes bounce-left{0%,10%,25%,40%,50%{transform:translateX(0)}20%{transform:translateX(-10px)}30%{transform:translateX(5px)}}@keyframes bounce-down{0%,10%,25%,40%,50%{transform:translateY(0)}20%{transform:translateY(10px)}30%{transform:translateY(-5px)}}.reveal .controls{display:none;position:absolute;top:auto;bottom:var(--r-controls-spacing);right:var(--r-controls-spacing);left:auto;z-index:11;color:#000;pointer-events:none;font-size:10px}.reveal .controls button{position:absolute;padding:0;background-color:transparent;border:0;outline:0;cursor:pointer;color:currentColor;transform:scale(.9999);transition:color .2s ease,opacity .2s ease,transform .2s ease;z-index:2;pointer-events:auto;font-size:inherit;visibility:hidden;opacity:0;-webkit-appearance:none;-webkit-tap-highlight-color:transparent}.reveal .controls .controls-arrow:after,.reveal .controls .controls-arrow:before{content:"";position:absolute;top:0;left:0;width:2.6em;height:.5em;border-radius:.25em;background-color:currentColor;transition:all .15s ease,background-color .8s ease;transform-origin:.2em 50%;will-change:transform}.reveal .controls .controls-arrow{position:relative;width:3.6em;height:3.6em}.reveal .controls .controls-arrow:before{transform:translateX(.5em) translateY(1.55em) rotate(45deg)}.reveal .controls .controls-arrow:after{transform:translateX(.5em) translateY(1.55em) rotate(-45deg)}.reveal .controls .controls-arrow:hover:before{transform:translateX(.5em) translateY(1.55em) rotate(40deg)}.reveal .controls .controls-arrow:hover:after{transform:translateX(.5em) translateY(1.55em) rotate(-40deg)}.reveal .controls .controls-arrow:active:before{transform:translateX(.5em) translateY(1.55em) rotate(36deg)}.reveal .controls .controls-arrow:active:after{transform:translateX(.5em) translateY(1.55em) rotate(-36deg)}.reveal .controls .navigate-left{right:6.4em;bottom:3.2em;transform:translateX(-10px)}.reveal .controls .navigate-left.highlight{animation:bounce-left 2s 50 both ease-out}.reveal .controls .navigate-right{right:0;bottom:3.2em;transform:translateX(10px)}.reveal .controls .navigate-right .controls-arrow{transform:rotate(180deg)}.reveal .controls .navigate-right.highlight{animation:bounce-right 2s 50 both ease-out}.reveal .controls .navigate-up{right:3.2em;bottom:6.4em;transform:translateY(-10px)}.reveal .controls .navigate-up .controls-arrow{transform:rotate(90deg)}.reveal .controls .navigate-down{right:3.2em;bottom:-1.4em;padding-bottom:1.4em;transform:translateY(10px)}.reveal .controls .navigate-down .controls-arrow{transform:rotate(-90deg)}.reveal .controls .navigate-down.highlight{animation:bounce-down 2s 50 both ease-out}.reveal .controls[data-controls-back-arrows=faded] .navigate-up.enabled{opacity:.3}.reveal .controls[data-controls-back-arrows=faded] .navigate-up.enabled:hover{opacity:1}.reveal .controls[data-controls-back-arrows=hidden] .navigate-up.enabled{opacity:0;visibility:hidden}.reveal .controls .enabled{visibility:visible;opacity:.9;cursor:pointer;transform:none}.reveal .controls .enabled.fragmented{opacity:.5}.reveal .controls .enabled.fragmented:hover,.reveal .controls .enabled:hover{opacity:1}.reveal:not(.rtl) .controls[data-controls-back-arrows=faded] .navigate-left.enabled{opacity:.3}.reveal:not(.rtl) .controls[data-controls-back-arrows=faded] .navigate-left.enabled:hover{opacity:1}.reveal:not(.rtl) .controls[data-controls-back-arrows=hidden] .navigate-left.enabled{opacity:0;visibility:hidden}.reveal.rtl .controls[data-controls-back-arrows=faded] .navigate-right.enabled{opacity:.3}.reveal.rtl .controls[data-controls-back-arrows=faded] .navigate-right.enabled:hover{opacity:1}.reveal.rtl .controls[data-controls-back-arrows=hidden] .navigate-right.enabled{opacity:0;visibility:hidden}.reveal[data-navigation-mode=linear].has-horizontal-slides .navigate-down,.reveal[data-navigation-mode=linear].has-horizontal-slides .navigate-up{display:none}.reveal:not(.has-vertical-slides) .controls .navigate-left,.reveal[data-navigation-mode=linear].has-horizontal-slides .navigate-left{bottom:1.4em;right:5.5em}.reveal:not(.has-vertical-slides) .controls .navigate-right,.reveal[data-navigation-mode=linear].has-horizontal-slides .navigate-right{bottom:1.4em;right:.5em}.reveal:not(.has-horizontal-slides) .controls .navigate-up{right:1.4em;bottom:5em}.reveal:not(.has-horizontal-slides) .controls .navigate-down{right:1.4em;bottom:.5em}.reveal.has-dark-background .controls{color:#fff}.reveal.has-light-background .controls{color:#000}.reveal.no-hover .controls .controls-arrow:active:before,.reveal.no-hover .controls .controls-arrow:hover:before{transform:translateX(.5em) translateY(1.55em) rotate(45deg)}.reveal.no-hover .controls .controls-arrow:active:after,.reveal.no-hover .controls .controls-arrow:hover:after{transform:translateX(.5em) translateY(1.55em) rotate(-45deg)}@media screen and (min-width:500px){.reveal-viewport{--r-controls-spacing:0.8em}.reveal .controls[data-controls-layout=edges]{top:0;right:0;bottom:0;left:0}.reveal .controls[data-controls-layout=edges] .navigate-down,.reveal .controls[data-controls-layout=edges] .navigate-left,.reveal .controls[data-controls-layout=edges] .navigate-right,.reveal .controls[data-controls-layout=edges] .navigate-up{bottom:auto;right:auto}.reveal .controls[data-controls-layout=edges] .navigate-left{top:50%;left:var(--r-controls-spacing);margin-top:-1.8em}.reveal .controls[data-controls-layout=edges] .navigate-right{top:50%;right:var(--r-controls-spacing);margin-top:-1.8em}.reveal .controls[data-controls-layout=edges] .navigate-up{top:var(--r-controls-spacing);left:50%;margin-left:-1.8em}.reveal .controls[data-controls-layout=edges] .navigate-down{bottom:calc(var(--r-controls-spacing) - 1.4em + .3em);left:50%;margin-left:-1.8em}}.reveal .progress{position:absolute;display:none;height:3px;width:100%;bottom:0;left:0;z-index:10;background-color:rgba(0,0,0,.2);color:#fff}.reveal .progress:after{content:"";display:block;position:absolute;height:10px;width:100%;top:-10px}.reveal .progress span{display:block;height:100%;width:100%;background-color:currentColor;transition:transform .8s cubic-bezier(.26,.86,.44,.985);transform-origin:0 0;transform:scaleX(0)}.reveal .slide-number{position:absolute;display:block;right:8px;bottom:8px;z-index:31;font-family:Helvetica,sans-serif;font-size:12px;line-height:1;color:#fff;background-color:rgba(0,0,0,.4);padding:5px}.reveal .slide-number a{color:currentColor}.reveal .slide-number-delimiter{margin:0 3px}.reveal{position:relative;width:100%;height:100%;overflow:hidden;touch-action:pinch-zoom}.reveal.embedded{touch-action:pan-y}.reveal.embedded.is-vertical-slide{touch-action:none}.reveal .slides{position:absolute;width:100%;height:100%;top:0;right:0;bottom:0;left:0;margin:auto;pointer-events:none;overflow:visible;z-index:1;text-align:center;perspective:600px;perspective-origin:50% 40%}.reveal .slides>section{perspective:600px}.reveal .slides>section,.reveal .slides>section>section{display:none;position:absolute;width:100%;pointer-events:auto;z-index:10;transform-style:flat;transition:transform-origin .8s cubic-bezier(.26,.86,.44,.985),transform .8s cubic-bezier(.26,.86,.44,.985),visibility .8s cubic-bezier(.26,.86,.44,.985),opacity .8s cubic-bezier(.26,.86,.44,.985)}.reveal[data-transition-speed=fast] .slides section{transition-duration:.4s}.reveal[data-transition-speed=slow] .slides section{transition-duration:1.2s}.reveal .slides section[data-transition-speed=fast]{transition-duration:.4s}.reveal .slides section[data-transition-speed=slow]{transition-duration:1.2s}.reveal .slides>section.stack{padding-top:0;padding-bottom:0;pointer-events:none;height:100%}.reveal .slides>section.present,.reveal .slides>section>section.present{display:block;z-index:11;opacity:1}.reveal .slides>section:empty,.reveal .slides>section>section:empty,.reveal .slides>section>section[data-background-interactive],.reveal .slides>section[data-background-interactive]{pointer-events:none}.reveal.center,.reveal.center .slides,.reveal.center .slides section{min-height:0!important}.reveal .slides>section:not(.present),.reveal .slides>section>section:not(.present){pointer-events:none}.reveal.overview .slides>section,.reveal.overview .slides>section>section{pointer-events:auto}.reveal .slides>section.future,.reveal .slides>section.future>section,.reveal .slides>section.past,.reveal .slides>section.past>section,.reveal .slides>section>section.future,.reveal .slides>section>section.past{opacity:0}.reveal .slides>section[data-transition=slide].past,.reveal .slides>section[data-transition~=slide-out].past,.reveal.slide .slides>section:not([data-transition]).past{transform:translate(-150%,0)}.reveal .slides>section[data-transition=slide].future,.reveal .slides>section[data-transition~=slide-in].future,.reveal.slide .slides>section:not([data-transition]).future{transform:translate(150%,0)}.reveal .slides>section>section[data-transition=slide].past,.reveal .slides>section>section[data-transition~=slide-out].past,.reveal.slide .slides>section>section:not([data-transition]).past{transform:translate(0,-150%)}.reveal .slides>section>section[data-transition=slide].future,.reveal .slides>section>section[data-transition~=slide-in].future,.reveal.slide .slides>section>section:not([data-transition]).future{transform:translate(0,150%)}.reveal .slides>section[data-transition=linear].past,.reveal .slides>section[data-transition~=linear-out].past,.reveal.linear .slides>section:not([data-transition]).past{transform:translate(-150%,0)}.reveal .slides>section[data-transition=linear].future,.reveal .slides>section[data-transition~=linear-in].future,.reveal.linear .slides>section:not([data-transition]).future{transform:translate(150%,0)}.reveal .slides>section>section[data-transition=linear].past,.reveal .slides>section>section[data-transition~=linear-out].past,.reveal.linear .slides>section>section:not([data-transition]).past{transform:translate(0,-150%)}.reveal .slides>section>section[data-transition=linear].future,.reveal .slides>section>section[data-transition~=linear-in].future,.reveal.linear .slides>section>section:not([data-transition]).future{transform:translate(0,150%)}.reveal .slides section[data-transition=default].stack,.reveal.default .slides section.stack{transform-style:preserve-3d}.reveal .slides>section[data-transition=default].past,.reveal .slides>section[data-transition~=default-out].past,.reveal.default .slides>section:not([data-transition]).past{transform:translate3d(-100%,0,0) rotateY(-90deg) translate3d(-100%,0,0)}.reveal .slides>section[data-transition=default].future,.reveal .slides>section[data-transition~=default-in].future,.reveal.default .slides>section:not([data-transition]).future{transform:translate3d(100%,0,0) rotateY(90deg) translate3d(100%,0,0)}.reveal .slides>section>section[data-transition=default].past,.reveal .slides>section>section[data-transition~=default-out].past,.reveal.default .slides>section>section:not([data-transition]).past{transform:translate3d(0,-300px,0) rotateX(70deg) translate3d(0,-300px,0)}.reveal .slides>section>section[data-transition=default].future,.reveal .slides>section>section[data-transition~=default-in].future,.reveal.default .slides>section>section:not([data-transition]).future{transform:translate3d(0,300px,0) rotateX(-70deg) translate3d(0,300px,0)}.reveal .slides section[data-transition=convex].stack,.reveal.convex .slides section.stack{transform-style:preserve-3d}.reveal .slides>section[data-transition=convex].past,.reveal .slides>section[data-transition~=convex-out].past,.reveal.convex .slides>section:not([data-transition]).past{transform:translate3d(-100%,0,0) rotateY(-90deg) translate3d(-100%,0,0)}.reveal .slides>section[data-transition=convex].future,.reveal .slides>section[data-transition~=convex-in].future,.reveal.convex .slides>section:not([data-transition]).future{transform:translate3d(100%,0,0) rotateY(90deg) translate3d(100%,0,0)}.reveal .slides>section>section[data-transition=convex].past,.reveal .slides>section>section[data-transition~=convex-out].past,.reveal.convex .slides>section>section:not([data-transition]).past{transform:translate3d(0,-300px,0) rotateX(70deg) translate3d(0,-300px,0)}.reveal .slides>section>section[data-transition=convex].future,.reveal .slides>section>section[data-transition~=convex-in].future,.reveal.convex .slides>section>section:not([data-transition]).future{transform:translate3d(0,300px,0) rotateX(-70deg) translate3d(0,300px,0)}.reveal .slides section[data-transition=concave].stack,.reveal.concave .slides section.stack{transform-style:preserve-3d}.reveal .slides>section[data-transition=concave].past,.reveal .slides>section[data-transition~=concave-out].past,.reveal.concave .slides>section:not([data-transition]).past{transform:translate3d(-100%,0,0) rotateY(90deg) translate3d(-100%,0,0)}.reveal .slides>section[data-transition=concave].future,.reveal .slides>section[data-transition~=concave-in].future,.reveal.concave .slides>section:not([data-transition]).future{transform:translate3d(100%,0,0) rotateY(-90deg) translate3d(100%,0,0)}.reveal .slides>section>section[data-transition=concave].past,.reveal .slides>section>section[data-transition~=concave-out].past,.reveal.concave .slides>section>section:not([data-transition]).past{transform:translate3d(0,-80%,0) rotateX(-70deg) translate3d(0,-80%,0)}.reveal .slides>section>section[data-transition=concave].future,.reveal .slides>section>section[data-transition~=concave-in].future,.reveal.concave .slides>section>section:not([data-transition]).future{transform:translate3d(0,80%,0) rotateX(70deg) translate3d(0,80%,0)}.reveal .slides section[data-transition=zoom],.reveal.zoom .slides section:not([data-transition]){transition-timing-function:ease}.reveal .slides>section[data-transition=zoom].past,.reveal .slides>section[data-transition~=zoom-out].past,.reveal.zoom .slides>section:not([data-transition]).past{visibility:hidden;transform:scale(16)}.reveal .slides>section[data-transition=zoom].future,.reveal .slides>section[data-transition~=zoom-in].future,.reveal.zoom .slides>section:not([data-transition]).future{visibility:hidden;transform:scale(.2)}.reveal .slides>section>section[data-transition=zoom].past,.reveal .slides>section>section[data-transition~=zoom-out].past,.reveal.zoom .slides>section>section:not([data-transition]).past{transform:scale(16)}.reveal .slides>section>section[data-transition=zoom].future,.reveal .slides>section>section[data-transition~=zoom-in].future,.reveal.zoom .slides>section>section:not([data-transition]).future{transform:scale(.2)}.reveal.cube .slides{perspective:1300px}.reveal.cube .slides section{padding:30px;min-height:700px;backface-visibility:hidden;box-sizing:border-box;transform-style:preserve-3d}.reveal.center.cube .slides section{min-height:0}.reveal.cube .slides section:not(.stack):before{content:"";position:absolute;display:block;width:100%;height:100%;left:0;top:0;background:rgba(0,0,0,.1);border-radius:4px;transform:translateZ(-20px)}.reveal.cube .slides section:not(.stack):after{content:"";position:absolute;display:block;width:90%;height:30px;left:5%;bottom:0;background:0 0;z-index:1;border-radius:4px;box-shadow:0 95px 25px rgba(0,0,0,.2);transform:translateZ(-90px) rotateX(65deg)}.reveal.cube .slides>section.stack{padding:0;background:0 0}.reveal.cube .slides>section.past{transform-origin:100% 0;transform:translate3d(-100%,0,0) rotateY(-90deg)}.reveal.cube .slides>section.future{transform-origin:0 0;transform:translate3d(100%,0,0) rotateY(90deg)}.reveal.cube .slides>section>section.past{transform-origin:0 100%;transform:translate3d(0,-100%,0) rotateX(90deg)}.reveal.cube .slides>section>section.future{transform-origin:0 0;transform:translate3d(0,100%,0) rotateX(-90deg)}.reveal.page .slides{perspective-origin:0 50%;perspective:3000px}.reveal.page .slides section{padding:30px;min-height:700px;box-sizing:border-box;transform-style:preserve-3d}.reveal.page .slides section.past{z-index:12}.reveal.page .slides section:not(.stack):before{content:"";position:absolute;display:block;width:100%;height:100%;left:0;top:0;background:rgba(0,0,0,.1);transform:translateZ(-20px)}.reveal.page .slides section:not(.stack):after{content:"";position:absolute;display:block;width:90%;height:30px;left:5%;bottom:0;background:0 0;z-index:1;border-radius:4px;box-shadow:0 95px 25px rgba(0,0,0,.2);-webkit-transform:translateZ(-90px) rotateX(65deg)}.reveal.page .slides>section.stack{padding:0;background:0 0}.reveal.page .slides>section.past{transform-origin:0 0;transform:translate3d(-40%,0,0) rotateY(-80deg)}.reveal.page .slides>section.future{transform-origin:100% 0;transform:translate3d(0,0,0)}.reveal.page .slides>section>section.past{transform-origin:0 0;transform:translate3d(0,-40%,0) rotateX(80deg)}.reveal.page .slides>section>section.future{transform-origin:0 100%;transform:translate3d(0,0,0)}.reveal .slides section[data-transition=fade],.reveal.fade .slides section:not([data-transition]),.reveal.fade .slides>section>section:not([data-transition]){transform:none;transition:opacity .5s}.reveal.fade.overview .slides section,.reveal.fade.overview .slides>section>section{transition:none}.reveal .slides section[data-transition=none],.reveal.none .slides section:not([data-transition]){transform:none;transition:none}.reveal .pause-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background:#000;visibility:hidden;opacity:0;z-index:100;transition:all 1s ease}.reveal .pause-overlay .resume-button{position:absolute;bottom:20px;right:20px;color:#ccc;border-radius:2px;padding:6px 14px;border:2px solid #ccc;font-size:16px;background:0 0;cursor:pointer}.reveal .pause-overlay .resume-button:hover{color:#fff;border-color:#fff}.reveal.paused .pause-overlay{visibility:visible;opacity:1}.reveal .no-transition,.reveal .no-transition *,.reveal .slides.disable-slide-transitions section{transition:none!important}.reveal .slides.disable-slide-transitions section{transform:none!important}.reveal .backgrounds{position:absolute;width:100%;height:100%;top:0;left:0;perspective:600px}.reveal .slide-background{display:none;position:absolute;width:100%;height:100%;opacity:0;visibility:hidden;overflow:hidden;background-color:rgba(0,0,0,0);transition:all .8s cubic-bezier(.26,.86,.44,.985)}.reveal .slide-background-content{position:absolute;width:100%;height:100%;background-position:50% 50%;background-repeat:no-repeat;background-size:cover}.reveal .slide-background.stack{display:block}.reveal .slide-background.present{opacity:1;visibility:visible;z-index:2}.print-pdf .reveal .slide-background{opacity:1!important;visibility:visible!important}.reveal .slide-background video{position:absolute;width:100%;height:100%;max-width:none;max-height:none;top:0;left:0;object-fit:cover}.reveal .slide-background[data-background-size=contain] video{object-fit:contain}.reveal>.backgrounds .slide-background[data-background-transition=none],.reveal[data-background-transition=none]>.backgrounds .slide-background:not([data-background-transition]){transition:none}.reveal>.backgrounds .slide-background[data-background-transition=slide],.reveal[data-background-transition=slide]>.backgrounds .slide-background:not([data-background-transition]){opacity:1}.reveal>.backgrounds .slide-background.past[data-background-transition=slide],.reveal[data-background-transition=slide]>.backgrounds .slide-background.past:not([data-background-transition]){transform:translate(-100%,0)}.reveal>.backgrounds .slide-background.future[data-background-transition=slide],.reveal[data-background-transition=slide]>.backgrounds .slide-background.future:not([data-background-transition]){transform:translate(100%,0)}.reveal>.backgrounds .slide-background>.slide-background.past[data-background-transition=slide],.reveal[data-background-transition=slide]>.backgrounds .slide-background>.slide-background.past:not([data-background-transition]){transform:translate(0,-100%)}.reveal>.backgrounds .slide-background>.slide-background.future[data-background-transition=slide],.reveal[data-background-transition=slide]>.backgrounds .slide-background>.slide-background.future:not([data-background-transition]){transform:translate(0,100%)}.reveal>.backgrounds .slide-background.past[data-background-transition=convex],.reveal[data-background-transition=convex]>.backgrounds .slide-background.past:not([data-background-transition]){opacity:0;transform:translate3d(-100%,0,0) rotateY(-90deg) translate3d(-100%,0,0)}.reveal>.backgrounds .slide-background.future[data-background-transition=convex],.reveal[data-background-transition=convex]>.backgrounds .slide-background.future:not([data-background-transition]){opacity:0;transform:translate3d(100%,0,0) rotateY(90deg) translate3d(100%,0,0)}.reveal>.backgrounds .slide-background>.slide-background.past[data-background-transition=convex],.reveal[data-background-transition=convex]>.backgrounds .slide-background>.slide-background.past:not([data-background-transition]){opacity:0;transform:translate3d(0,-100%,0) rotateX(90deg) translate3d(0,-100%,0)}.reveal>.backgrounds .slide-background>.slide-background.future[data-background-transition=convex],.reveal[data-background-transition=convex]>.backgrounds .slide-background>.slide-background.future:not([data-background-transition]){opacity:0;transform:translate3d(0,100%,0) rotateX(-90deg) translate3d(0,100%,0)}.reveal>.backgrounds .slide-background.past[data-background-transition=concave],.reveal[data-background-transition=concave]>.backgrounds .slide-background.past:not([data-background-transition]){opacity:0;transform:translate3d(-100%,0,0) rotateY(90deg) translate3d(-100%,0,0)}.reveal>.backgrounds .slide-background.future[data-background-transition=concave],.reveal[data-background-transition=concave]>.backgrounds .slide-background.future:not([data-background-transition]){opacity:0;transform:translate3d(100%,0,0) rotateY(-90deg) translate3d(100%,0,0)}.reveal>.backgrounds .slide-background>.slide-background.past[data-background-transition=concave],.reveal[data-background-transition=concave]>.backgrounds .slide-background>.slide-background.past:not([data-background-transition]){opacity:0;transform:translate3d(0,-100%,0) rotateX(-90deg) translate3d(0,-100%,0)}.reveal>.backgrounds .slide-background>.slide-background.future[data-background-transition=concave],.reveal[data-background-transition=concave]>.backgrounds .slide-background>.slide-background.future:not([data-background-transition]){opacity:0;transform:translate3d(0,100%,0) rotateX(90deg) translate3d(0,100%,0)}.reveal>.backgrounds .slide-background[data-background-transition=zoom],.reveal[data-background-transition=zoom]>.backgrounds .slide-background:not([data-background-transition]){transition-timing-function:ease}.reveal>.backgrounds .slide-background.past[data-background-transition=zoom],.reveal[data-background-transition=zoom]>.backgrounds .slide-background.past:not([data-background-transition]){opacity:0;visibility:hidden;transform:scale(16)}.reveal>.backgrounds .slide-background.future[data-background-transition=zoom],.reveal[data-background-transition=zoom]>.backgrounds .slide-background.future:not([data-background-transition]){opacity:0;visibility:hidden;transform:scale(.2)}.reveal>.backgrounds .slide-background>.slide-background.past[data-background-transition=zoom],.reveal[data-background-transition=zoom]>.backgrounds .slide-background>.slide-background.past:not([data-background-transition]){opacity:0;visibility:hidden;transform:scale(16)}.reveal>.backgrounds .slide-background>.slide-background.future[data-background-transition=zoom],.reveal[data-background-transition=zoom]>.backgrounds .slide-background>.slide-background.future:not([data-background-transition]){opacity:0;visibility:hidden;transform:scale(.2)}.reveal[data-transition-speed=fast]>.backgrounds .slide-background{transition-duration:.4s}.reveal[data-transition-speed=slow]>.backgrounds .slide-background{transition-duration:1.2s}.reveal [data-auto-animate-target^=unmatched]{will-change:opacity}.reveal section[data-auto-animate]:not(.stack):not([data-auto-animate=running]) [data-auto-animate-target^=unmatched]{opacity:0}.reveal.overview{perspective-origin:50% 50%;perspective:700px}.reveal.overview .slides{-moz-transform-style:preserve-3d}.reveal.overview .slides section{height:100%;top:0!important;opacity:1!important;overflow:hidden;visibility:visible!important;cursor:pointer;box-sizing:border-box}.reveal.overview .slides section.present,.reveal.overview .slides section:hover{outline:10px solid rgba(150,150,150,.4);outline-offset:10px}.reveal.overview .slides section .fragment{opacity:1;transition:none}.reveal.overview .slides section:after,.reveal.overview .slides section:before{display:none!important}.reveal.overview .slides>section.stack{padding:0;top:0!important;background:0 0;outline:0;overflow:visible}.reveal.overview .backgrounds{perspective:inherit;-moz-transform-style:preserve-3d}.reveal.overview .backgrounds .slide-background{opacity:1;visibility:visible;outline:10px solid rgba(150,150,150,.1);outline-offset:10px}.reveal.overview .backgrounds .slide-background.stack{overflow:visible}.reveal.overview .slides section,.reveal.overview-deactivating .slides section{transition:none}.reveal.overview .backgrounds .slide-background,.reveal.overview-deactivating .backgrounds .slide-background{transition:none}.reveal.rtl .slides,.reveal.rtl .slides h1,.reveal.rtl .slides h2,.reveal.rtl .slides h3,.reveal.rtl .slides h4,.reveal.rtl .slides h5,.reveal.rtl .slides h6{direction:rtl;font-family:sans-serif}.reveal.rtl code,.reveal.rtl pre{direction:ltr}.reveal.rtl ol,.reveal.rtl ul{text-align:right}.reveal.rtl .progress span{transform-origin:100% 0}.reveal.has-parallax-background .backgrounds{transition:all .8s ease}.reveal.has-parallax-background[data-transition-speed=fast] .backgrounds{transition-duration:.4s}.reveal.has-parallax-background[data-transition-speed=slow] .backgrounds{transition-duration:1.2s}.reveal>.overlay{position:absolute;top:0;left:0;width:100%;height:100%;z-index:1000;background:rgba(0,0,0,.95);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);transition:all .3s ease}.reveal>.overlay .spinner{position:absolute;display:block;top:50%;left:50%;width:32px;height:32px;margin:-16px 0 0 -16px;z-index:10;background-image:url(data:image/gif;base64,R0lGODlhIAAgAPMAAJmZmf%2F%2F%2F6%2Bvr8nJybW1tcDAwOjo6Nvb26ioqKOjo7Ozs%2FLy8vz8%2FAAAAAAAAAAAACH%2FC05FVFNDQVBFMi4wAwEAAAAh%2FhpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh%2BQQJCgAAACwAAAAAIAAgAAAE5xDISWlhperN52JLhSSdRgwVo1ICQZRUsiwHpTJT4iowNS8vyW2icCF6k8HMMBkCEDskxTBDAZwuAkkqIfxIQyhBQBFvAQSDITM5VDW6XNE4KagNh6Bgwe60smQUB3d4Rz1ZBApnFASDd0hihh12BkE9kjAJVlycXIg7CQIFA6SlnJ87paqbSKiKoqusnbMdmDC2tXQlkUhziYtyWTxIfy6BE8WJt5YJvpJivxNaGmLHT0VnOgSYf0dZXS7APdpB309RnHOG5gDqXGLDaC457D1zZ%2FV%2FnmOM82XiHRLYKhKP1oZmADdEAAAh%2BQQJCgAAACwAAAAAIAAgAAAE6hDISWlZpOrNp1lGNRSdRpDUolIGw5RUYhhHukqFu8DsrEyqnWThGvAmhVlteBvojpTDDBUEIFwMFBRAmBkSgOrBFZogCASwBDEY%2FCZSg7GSE0gSCjQBMVG023xWBhklAnoEdhQEfyNqMIcKjhRsjEdnezB%2BA4k8gTwJhFuiW4dokXiloUepBAp5qaKpp6%2BHo7aWW54wl7obvEe0kRuoplCGepwSx2jJvqHEmGt6whJpGpfJCHmOoNHKaHx61WiSR92E4lbFoq%2BB6QDtuetcaBPnW6%2BO7wDHpIiK9SaVK5GgV543tzjgGcghAgAh%2BQQJCgAAACwAAAAAIAAgAAAE7hDISSkxpOrN5zFHNWRdhSiVoVLHspRUMoyUakyEe8PTPCATW9A14E0UvuAKMNAZKYUZCiBMuBakSQKG8G2FzUWox2AUtAQFcBKlVQoLgQReZhQlCIJesQXI5B0CBnUMOxMCenoCfTCEWBsJColTMANldx15BGs8B5wlCZ9Po6OJkwmRpnqkqnuSrayqfKmqpLajoiW5HJq7FL1Gr2mMMcKUMIiJgIemy7xZtJsTmsM4xHiKv5KMCXqfyUCJEonXPN2rAOIAmsfB3uPoAK%2B%2BG%2Bw48edZPK%2BM6hLJpQg484enXIdQFSS1u6UhksENEQAAIfkECQoAAAAsAAAAACAAIAAABOcQyEmpGKLqzWcZRVUQnZYg1aBSh2GUVEIQ2aQOE%2BG%2BcD4ntpWkZQj1JIiZIogDFFyHI0UxQwFugMSOFIPJftfVAEoZLBbcLEFhlQiqGp1Vd140AUklUN3eCA51C1EWMzMCezCBBmkxVIVHBWd3HHl9JQOIJSdSnJ0TDKChCwUJjoWMPaGqDKannasMo6WnM562R5YluZRwur0wpgqZE7NKUm%2BFNRPIhjBJxKZteWuIBMN4zRMIVIhffcgojwCF117i4nlLnY5ztRLsnOk%2BaV%2BoJY7V7m76PdkS4trKcdg0Zc0tTcKkRAAAIfkECQoAAAAsAAAAACAAIAAABO4QyEkpKqjqzScpRaVkXZWQEximw1BSCUEIlDohrft6cpKCk5xid5MNJTaAIkekKGQkWyKHkvhKsR7ARmitkAYDYRIbUQRQjWBwJRzChi9CRlBcY1UN4g0%2FVNB0AlcvcAYHRyZPdEQFYV8ccwR5HWxEJ02YmRMLnJ1xCYp0Y5idpQuhopmmC2KgojKasUQDk5BNAwwMOh2RtRq5uQuPZKGIJQIGwAwGf6I0JXMpC8C7kXWDBINFMxS4DKMAWVWAGYsAdNqW5uaRxkSKJOZKaU3tPOBZ4DuK2LATgJhkPJMgTwKCdFjyPHEnKxFCDhEAACH5BAkKAAAALAAAAAAgACAAAATzEMhJaVKp6s2nIkolIJ2WkBShpkVRWqqQrhLSEu9MZJKK9y1ZrqYK9WiClmvoUaF8gIQSNeF1Er4MNFn4SRSDARWroAIETg1iVwuHjYB1kYc1mwruwXKC9gmsJXliGxc%2BXiUCby9ydh1sOSdMkpMTBpaXBzsfhoc5l58Gm5yToAaZhaOUqjkDgCWNHAULCwOLaTmzswadEqggQwgHuQsHIoZCHQMMQgQGubVEcxOPFAcMDAYUA85eWARmfSRQCdcMe0zeP1AAygwLlJtPNAAL19DARdPzBOWSm1brJBi45soRAWQAAkrQIykShQ9wVhHCwCQCACH5BAkKAAAALAAAAAAgACAAAATrEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiRMDjI0Fd30%2FiI2UA5GSS5UDj2l6NoqgOgN4gksEBgYFf0FDqKgHnyZ9OX8HrgYHdHpcHQULXAS2qKpENRg7eAMLC7kTBaixUYFkKAzWAAnLC7FLVxLWDBLKCwaKTULgEwbLA4hJtOkSBNqITT3xEgfLpBtzE%2FjiuL04RGEBgwWhShRgQExHBAAh%2BQQJCgAAACwAAAAAIAAgAAAE7xDISWlSqerNpyJKhWRdlSAVoVLCWk6JKlAqAavhO9UkUHsqlE6CwO1cRdCQ8iEIfzFVTzLdRAmZX3I2SfZiCqGk5dTESJeaOAlClzsJsqwiJwiqnFrb2nS9kmIcgEsjQydLiIlHehhpejaIjzh9eomSjZR%2BipslWIRLAgMDOR2DOqKogTB9pCUJBagDBXR6XB0EBkIIsaRsGGMMAxoDBgYHTKJiUYEGDAzHC9EACcUGkIgFzgwZ0QsSBcXHiQvOwgDdEwfFs0sDzt4S6BK4xYjkDOzn0unFeBzOBijIm1Dgmg5YFQwsCMjp1oJ8LyIAACH5BAkKAAAALAAAAAAgACAAAATwEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiUd6GGl6NoiPOH16iZKNlH6KmyWFOggHhEEvAwwMA0N9GBsEC6amhnVcEwavDAazGwIDaH1ipaYLBUTCGgQDA8NdHz0FpqgTBwsLqAbWAAnIA4FWKdMLGdYGEgraigbT0OITBcg5QwPT4xLrROZL6AuQAPUS7bxLpoWidY0JtxLHKhwwMJBTHgPKdEQAACH5BAkKAAAALAAAAAAgACAAAATrEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiUd6GAULDJCRiXo1CpGXDJOUjY%2BYip9DhToJA4RBLwMLCwVDfRgbBAaqqoZ1XBMHswsHtxtFaH1iqaoGNgAIxRpbFAgfPQSqpbgGBqUD1wBXeCYp1AYZ19JJOYgH1KwA4UBvQwXUBxPqVD9L3sbp2BNk2xvvFPJd%2BMFCN6HAAIKgNggY0KtEBAAh%2BQQJCgAAACwAAAAAIAAgAAAE6BDISWlSqerNpyJKhWRdlSAVoVLCWk6JKlAqAavhO9UkUHsqlE6CwO1cRdCQ8iEIfzFVTzLdRAmZX3I2SfYIDMaAFdTESJeaEDAIMxYFqrOUaNW4E4ObYcCXaiBVEgULe0NJaxxtYksjh2NLkZISgDgJhHthkpU4mW6blRiYmZOlh4JWkDqILwUGBnE6TYEbCgevr0N1gH4At7gHiRpFaLNrrq8HNgAJA70AWxQIH1%2BvsYMDAzZQPC9VCNkDWUhGkuE5PxJNwiUK4UfLzOlD4WvzAHaoG9nxPi5d%2BjYUqfAhhykOFwJWiAAAIfkECQoAAAAsAAAAACAAIAAABPAQyElpUqnqzaciSoVkXVUMFaFSwlpOCcMYlErAavhOMnNLNo8KsZsMZItJEIDIFSkLGQoQTNhIsFehRww2CQLKF0tYGKYSg%2BygsZIuNqJksKgbfgIGepNo2cIUB3V1B3IvNiBYNQaDSTtfhhx0CwVPI0UJe0%2Bbm4g5VgcGoqOcnjmjqDSdnhgEoamcsZuXO1aWQy8KAwOAuTYYGwi7w5h%2BKr0SJ8MFihpNbx%2B4Erq7BYBuzsdiH1jCAzoSfl0rVirNbRXlBBlLX%2BBP0XJLAPGzTkAuAOqb0WT5AH7OcdCm5B8TgRwSRKIHQtaLCwg1RAAAOwAAAAAAAAAAAA%3D%3D);visibility:visible;opacity:.6;transition:all .3s ease}.reveal>.overlay header{position:absolute;left:0;top:0;width:100%;padding:5px;z-index:2;box-sizing:border-box}.reveal>.overlay header a{display:inline-block;width:40px;height:40px;line-height:36px;padding:0 10px;float:right;opacity:.6;box-sizing:border-box}.reveal>.overlay header a:hover{opacity:1}.reveal>.overlay header a .icon{display:inline-block;width:20px;height:20px;background-position:50% 50%;background-size:100%;background-repeat:no-repeat}.reveal>.overlay header a.close .icon{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABkklEQVRYR8WX4VHDMAxG6wnoJrABZQPYBCaBTWAD2g1gE5gg6OOsXuxIlr40d81dfrSJ9V4c2VLK7spHuTJ/5wpM07QXuXc5X0opX2tEJcadjHuV80li/FgxTIEK/5QBCICBD6xEhSMGHgQPgBgLiYVAB1dpSqKDawxTohFw4JSEA3clzgIBPCURwE2JucBR7rhPJJv5OpJwDX+SfDjgx1wACQeJG1aChP9K/IMmdZ8DtESV1WyP3Bt4MwM6sj4NMxMYiqUWHQu4KYA/SYkIjOsm3BXYWMKFDwU2khjCQ4ELJUJ4SmClRArOCmSXGuKma0fYD5CbzHxFpCSGAhfAVSSUGDUk2BWZaff2g6GE15BsBQ9nwmpIGDiyHQddwNTMKkbZaf9fajXQca1EX44puJZUsnY0ObGmITE3GVLCbEhQUjGVt146j6oasWN+49Vph2w1pZ5EansNZqKBm1txbU57iRRcZ86RWMDdWtBJUHBHwoQPi1GV+JCbntmvok7iTX4/Up9mgyTc/FJYDTcndgH/AA5A/CHsyEkVAAAAAElFTkSuQmCC)}.reveal>.overlay header a.external .icon{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAcElEQVRYR+2WSQoAIQwEzf8f7XiOMkUQxUPlGkM3hVmiQfQR9GYnH1SsAQlI4DiBqkCMoNb9y2e90IAEJPAcgdznU9+engMaeJ7Azh5Y1U67gAho4DqBqmB1buAf0MB1AlVBek83ZPkmJMGc1wAR+AAqod/B97TRpQAAAABJRU5ErkJggg==)}.reveal>.overlay .viewport{position:absolute;display:flex;top:50px;right:0;bottom:0;left:0}.reveal>.overlay.overlay-preview .viewport iframe{width:100%;height:100%;max-width:100%;max-height:100%;border:0;opacity:0;visibility:hidden;transition:all .3s ease}.reveal>.overlay.overlay-preview.loaded .viewport iframe{opacity:1;visibility:visible}.reveal>.overlay.overlay-preview.loaded .viewport-inner{position:absolute;z-index:-1;left:0;top:45%;width:100%;text-align:center;letter-spacing:normal}.reveal>.overlay.overlay-preview .x-frame-error{opacity:0;transition:opacity .3s ease .3s}.reveal>.overlay.overlay-preview.loaded .x-frame-error{opacity:1}.reveal>.overlay.overlay-preview.loaded .spinner{opacity:0;visibility:hidden;transform:scale(.2)}.reveal>.overlay.overlay-help .viewport{overflow:auto;color:#fff}.reveal>.overlay.overlay-help .viewport .viewport-inner{width:600px;margin:auto;padding:20px 20px 80px 20px;text-align:center;letter-spacing:normal}.reveal>.overlay.overlay-help .viewport .viewport-inner .title{font-size:20px}.reveal>.overlay.overlay-help .viewport .viewport-inner table{border:1px solid #fff;border-collapse:collapse;font-size:16px}.reveal>.overlay.overlay-help .viewport .viewport-inner table td,.reveal>.overlay.overlay-help .viewport .viewport-inner table th{width:200px;padding:14px;border:1px solid #fff;vertical-align:middle}.reveal>.overlay.overlay-help .viewport .viewport-inner table th{padding-top:20px;padding-bottom:20px}.reveal .playback{position:absolute;left:15px;bottom:20px;z-index:30;cursor:pointer;transition:all .4s ease;-webkit-tap-highlight-color:transparent}.reveal.overview .playback{opacity:0;visibility:hidden}.reveal .hljs{min-height:100%}.reveal .hljs table{margin:initial}.reveal .hljs-ln-code,.reveal .hljs-ln-numbers{padding:0;border:0}.reveal .hljs-ln-numbers{opacity:.6;padding-right:.75em;text-align:right;vertical-align:top}.reveal .hljs.has-highlights tr:not(.highlight-line){opacity:.4}.reveal .hljs.has-highlights.fragment{transition:all .2s ease}.reveal .hljs:not(:first-child).fragment{position:absolute;top:0;left:0;width:100%;box-sizing:border-box}.reveal pre[data-auto-animate-target]{overflow:hidden}.reveal pre[data-auto-animate-target] code{height:100%}.reveal .roll{display:inline-block;line-height:1.2;overflow:hidden;vertical-align:top;perspective:400px;perspective-origin:50% 50%}.reveal .roll:hover{background:0 0;text-shadow:none}.reveal .roll span{display:block;position:relative;padding:0 2px;pointer-events:none;transition:all .4s ease;transform-origin:50% 0;transform-style:preserve-3d;backface-visibility:hidden}.reveal .roll:hover span{background:rgba(0,0,0,.5);transform:translate3d(0,0,-45px) rotateX(90deg)}.reveal .roll span:after{content:attr(data-title);display:block;position:absolute;left:0;top:0;padding:0 2px;backface-visibility:hidden;transform-origin:50% 0;transform:translate3d(0,110%,0) rotateX(-90deg)}.reveal aside.notes{display:none}.reveal .speaker-notes{display:none;position:absolute;width:33.3333333333%;height:100%;top:0;left:100%;padding:14px 18px 14px 18px;z-index:1;font-size:18px;line-height:1.4;border:1px solid rgba(0,0,0,.05);color:#222;background-color:#f5f5f5;overflow:auto;box-sizing:border-box;text-align:left;font-family:Helvetica,sans-serif;-webkit-overflow-scrolling:touch}.reveal .speaker-notes .notes-placeholder{color:#ccc;font-style:italic}.reveal .speaker-notes:focus{outline:0}.reveal .speaker-notes:before{content:"Speaker notes";display:block;margin-bottom:10px;opacity:.5}.reveal.show-notes{max-width:75%;overflow:visible}.reveal.show-notes .speaker-notes{display:block}@media screen and (min-width:1600px){.reveal .speaker-notes{font-size:20px}}@media screen and (max-width:1024px){.reveal.show-notes{border-left:0;max-width:none;max-height:70%;max-height:70vh;overflow:visible}.reveal.show-notes .speaker-notes{top:100%;left:0;width:100%;height:30vh;border:0}}@media screen and (max-width:600px){.reveal.show-notes{max-height:60%;max-height:60vh}.reveal.show-notes .speaker-notes{top:100%;height:40vh}.reveal .speaker-notes{font-size:14px}}.reveal .jump-to-slide{position:absolute;top:15px;left:15px;z-index:30;font-size:32px;-webkit-tap-highlight-color:transparent}.reveal .jump-to-slide-input{background:0 0;padding:8px;font-size:inherit;color:currentColor;border:0}.reveal .jump-to-slide-input::placeholder{color:currentColor;opacity:.5}.reveal.has-dark-background .jump-to-slide-input{color:#fff}.reveal.has-light-background .jump-to-slide-input{color:#222}.reveal .jump-to-slide-input:focus{outline:0}.zoomed .reveal *,.zoomed .reveal :after,.zoomed .reveal :before{backface-visibility:visible!important}.zoomed .reveal .controls,.zoomed .reveal .progress{opacity:0}.zoomed .reveal .roll span{background:0 0}.zoomed .reveal .roll span:after{visibility:hidden}.reveal-viewport.loading-scroll-mode{visibility:hidden}.reveal-viewport.reveal-scroll{margin:0 auto;overflow:auto;overflow-x:hidden;overflow-y:auto;z-index:1;--r-scrollbar-width:7px;--r-scrollbar-trigger-size:5px;--r-controls-spacing:8px}@media screen and (max-width:500px){.reveal-viewport.reveal-scroll{--r-scrollbar-width:3px;--r-scrollbar-trigger-size:3px}}.reveal-viewport.reveal-scroll .backgrounds,.reveal-viewport.reveal-scroll .controls,.reveal-viewport.reveal-scroll .playback,.reveal-viewport.reveal-scroll .progress,.reveal-viewport.reveal-scroll .slide-number,.reveal-viewport.reveal-scroll .speaker-notes{display:none!important}.reveal-viewport.reveal-scroll .overlay,.reveal-viewport.reveal-scroll .pause-overlay{position:fixed}.reveal-viewport.reveal-scroll .reveal{overflow:visible;touch-action:manipulation}.reveal-viewport.reveal-scroll .slides{position:static;pointer-events:initial;left:auto;top:auto;width:100%!important;margin:0;padding:0;overflow:visible;display:block;perspective:none;perspective-origin:50% 50%}.reveal-viewport.reveal-scroll .scroll-page{position:relative;width:100%;height:calc(var(--page-height) + var(--page-scroll-padding));z-index:1;overflow:visible}.reveal-viewport.reveal-scroll .scroll-page-sticky{position:sticky;height:var(--page-height);top:0}.reveal-viewport.reveal-scroll .scroll-page-content{position:absolute;top:0;left:0;width:100%;height:100%;overflow:hidden}.reveal-viewport.reveal-scroll .scroll-page section{visibility:visible!important;display:block!important;position:absolute!important;width:var(--slide-width)!important;height:var(--slide-height)!important;top:50%!important;left:50%!important;opacity:1!important;transform:scale(var(--slide-scale)) translate(-50%,-50%)!important;transform-style:flat!important;transform-origin:0 0!important}.reveal-viewport.reveal-scroll .slide-background{display:block!important;position:absolute;top:0;left:0;width:100%;height:100%;z-index:auto!important;visibility:visible;opacity:1;touch-action:manipulation}.reveal-viewport.reveal-scroll[data-scrollbar=auto]::-webkit-scrollbar,.reveal-viewport.reveal-scroll[data-scrollbar=true]::-webkit-scrollbar{display:none}.reveal-viewport.reveal-scroll[data-scrollbar=auto],.reveal-viewport.reveal-scroll[data-scrollbar=true]{scrollbar-width:none}.reveal-viewport.has-dark-background,.reveal.has-dark-background{--r-overlay-element-bg-color:240,240,240;--r-overlay-element-fg-color:0,0,0}.reveal-viewport.has-light-background,.reveal.has-light-background{--r-overlay-element-bg-color:0,0,0;--r-overlay-element-fg-color:240,240,240}.reveal-viewport.reveal-scroll .scrollbar{position:sticky;top:50%;z-index:20;opacity:0;transition:all .3s ease}.reveal-viewport.reveal-scroll .scrollbar.visible,.reveal-viewport.reveal-scroll .scrollbar:hover{opacity:1}.reveal-viewport.reveal-scroll .scrollbar .scrollbar-inner{position:absolute;width:var(--r-scrollbar-width);height:calc(var(--viewport-height) - var(--r-controls-spacing) * 2);right:var(--r-controls-spacing);top:0;transform:translateY(-50%);border-radius:var(--r-scrollbar-width);z-index:10}.reveal-viewport.reveal-scroll .scrollbar .scrollbar-playhead{position:absolute;width:var(--r-scrollbar-width);height:var(--r-scrollbar-width);top:0;left:0;border-radius:var(--r-scrollbar-width);background-color:rgba(var(--r-overlay-element-bg-color),1);z-index:11;transition:background-color .2s ease}.reveal-viewport.reveal-scroll .scrollbar .scrollbar-slide{position:absolute;width:100%;background-color:rgba(var(--r-overlay-element-bg-color),.2);box-shadow:0 0 0 1px rgba(var(--r-overlay-element-fg-color),.1);border-radius:var(--r-scrollbar-width);transition:background-color .2s ease}.reveal-viewport.reveal-scroll .scrollbar .scrollbar-slide:after{content:"";position:absolute;width:200%;height:100%;top:0;left:-50%;background:rgba(0,0,0,0);z-index:-1}.reveal-viewport.reveal-scroll .scrollbar .scrollbar-slide.active,.reveal-viewport.reveal-scroll .scrollbar .scrollbar-slide:hover{background-color:rgba(var(--r-overlay-element-bg-color),.4)}.reveal-viewport.reveal-scroll .scrollbar .scrollbar-trigger{position:absolute;width:100%;transition:background-color .2s ease}.reveal-viewport.reveal-scroll .scrollbar .scrollbar-slide.active.has-triggers{background-color:rgba(var(--r-overlay-element-bg-color),.4);z-index:10}.reveal-viewport.reveal-scroll .scrollbar .scrollbar-slide.active .scrollbar-trigger:after{content:"";position:absolute;width:var(--r-scrollbar-trigger-size);height:var(--r-scrollbar-trigger-size);border-radius:20px;top:50%;left:50%;transform:translate(-50%,-50%);background-color:rgba(var(--r-overlay-element-bg-color),1);transition:transform .2s ease,opacity .2s ease;opacity:.4}.reveal-viewport.reveal-scroll .scrollbar .scrollbar-slide.active .scrollbar-trigger.active:after,.reveal-viewport.reveal-scroll .scrollbar .scrollbar-slide.active .scrollbar-trigger.active~.scrollbar-trigger:after{opacity:1}.reveal-viewport.reveal-scroll .scrollbar .scrollbar-slide.active .scrollbar-trigger~.scrollbar-trigger.active:after{transform:translate(calc(var(--r-scrollbar-width) * -2),0);background-color:rgba(var(--r-overlay-element-bg-color),1)}html.reveal-print *{-webkit-print-color-adjust:exact}html.reveal-print{width:100%;height:100%;overflow:visible}html.reveal-print body{margin:0 auto!important;border:0;padding:0;float:none!important;overflow:visible}html.reveal-print .nestedarrow,html.reveal-print .reveal .controls,html.reveal-print .reveal .playback,html.reveal-print .reveal .progress,html.reveal-print .reveal.overview,html.reveal-print .state-background{display:none!important}html.reveal-print .reveal pre code{overflow:hidden!important}html.reveal-print .reveal{width:auto!important;height:auto!important;overflow:hidden!important}html.reveal-print .reveal .slides{position:static;width:100%!important;height:auto!important;zoom:1!important;pointer-events:initial;left:auto;top:auto;margin:0!important;padding:0!important;overflow:visible;display:block;perspective:none;perspective-origin:50% 50%}html.reveal-print .reveal .slides .pdf-page{position:relative;overflow:hidden;z-index:1;page-break-after:always}html.reveal-print .reveal .slides .pdf-page:last-of-type{page-break-after:avoid}html.reveal-print .reveal .slides section{visibility:visible!important;display:block!important;position:absolute!important;margin:0!important;padding:0!important;box-sizing:border-box!important;min-height:1px;opacity:1!important;transform-style:flat!important;transform:none!important}html.reveal-print .reveal section.stack{position:relative!important;margin:0!important;padding:0!important;page-break-after:avoid!important;height:auto!important;min-height:auto!important}html.reveal-print .reveal img{box-shadow:none}html.reveal-print .reveal .backgrounds{display:none}html.reveal-print .reveal .slide-background{display:block!important;position:absolute;top:0;left:0;width:100%;height:100%;z-index:auto!important}html.reveal-print .reveal.show-notes{max-width:none;max-height:none}html.reveal-print .reveal .speaker-notes-pdf{display:block;width:100%;height:auto;max-height:none;top:auto;right:auto;bottom:auto;left:auto;z-index:100}html.reveal-print .reveal .speaker-notes-pdf[data-layout=separate-page]{position:relative;color:inherit;background-color:transparent;padding:20px;page-break-after:always;border:0}html.reveal-print .reveal .slide-number-pdf{display:block;position:absolute;font-size:14px;visibility:visible}html.reveal-print .aria-status{display:none}@media print{html:not(.print-pdf){overflow:visible;width:auto;height:auto}html:not(.print-pdf) body{margin:0;padding:0;overflow:visible}html:not(.print-pdf) .reveal{background:#fff;font-size:20pt}html:not(.print-pdf) .reveal .backgrounds,html:not(.print-pdf) .reveal .controls,html:not(.print-pdf) .reveal .progress,html:not(.print-pdf) .reveal .slide-number,html:not(.print-pdf) .reveal .state-background{display:none!important}html:not(.print-pdf) .reveal li,html:not(.print-pdf) .reveal p,html:not(.print-pdf) .reveal td{font-size:20pt!important;color:#000}html:not(.print-pdf) .reveal h1,html:not(.print-pdf) .reveal h2,html:not(.print-pdf) .reveal h3,html:not(.print-pdf) .reveal h4,html:not(.print-pdf) .reveal h5,html:not(.print-pdf) .reveal h6{color:#000!important;height:auto;line-height:normal;text-align:left;letter-spacing:normal}html:not(.print-pdf) .reveal h1{font-size:28pt!important}html:not(.print-pdf) .reveal h2{font-size:24pt!important}html:not(.print-pdf) .reveal h3{font-size:22pt!important}html:not(.print-pdf) .reveal h4{font-size:22pt!important;font-variant:small-caps}html:not(.print-pdf) .reveal h5{font-size:21pt!important}html:not(.print-pdf) .reveal h6{font-size:20pt!important;font-style:italic}html:not(.print-pdf) .reveal a:link,html:not(.print-pdf) .reveal a:visited{color:#000!important;font-weight:700;text-decoration:underline}html:not(.print-pdf) .reveal div,html:not(.print-pdf) .reveal ol,html:not(.print-pdf) .reveal p,html:not(.print-pdf) .reveal ul{visibility:visible;position:static;width:auto;height:auto;display:block;overflow:visible;margin:0;text-align:left!important}html:not(.print-pdf) .reveal pre,html:not(.print-pdf) .reveal table{margin-left:0;margin-right:0}html:not(.print-pdf) .reveal pre code{padding:20px}html:not(.print-pdf) .reveal blockquote{margin:20px 0}html:not(.print-pdf) .reveal .slides{position:static!important;width:auto!important;height:auto!important;left:0!important;top:0!important;margin-left:0!important;margin-top:0!important;padding:0!important;zoom:1!important;transform:none!important;overflow:visible!important;display:block!important;text-align:left!important;perspective:none;perspective-origin:50% 50%}html:not(.print-pdf) .reveal .slides section{visibility:visible!important;position:static!important;width:auto!important;height:auto!important;display:block!important;overflow:visible!important;left:0!important;top:0!important;margin-left:0!important;margin-top:0!important;padding:60px 20px!important;z-index:auto!important;opacity:1!important;page-break-after:always!important;transform-style:flat!important;transform:none!important;transition:none!important}html:not(.print-pdf) .reveal .slides section.stack{padding:0!important}html:not(.print-pdf) .reveal .slides section:last-of-type{page-break-after:avoid!important}html:not(.print-pdf) .reveal .slides section .fragment{opacity:1!important;visibility:visible!important;transform:none!important}html:not(.print-pdf) .reveal .r-fit-text{white-space:normal!important}html:not(.print-pdf) .reveal section img{display:block;margin:15px 0;background:#fff;border:1px solid #666;box-shadow:none}html:not(.print-pdf) .reveal section small{font-size:.8em}html:not(.print-pdf) .reveal .hljs{max-height:100%;white-space:pre-wrap;word-wrap:break-word;word-break:break-word;font-size:15pt}html:not(.print-pdf) .reveal .hljs .hljs-ln-numbers{white-space:nowrap}html:not(.print-pdf) .reveal .hljs td{font-size:inherit!important;color:inherit!important}}
\ No newline at end of file
diff --git a/simulator/vendor/reveal/reveal.js b/simulator/vendor/reveal/reveal.js
new file mode 100644
index 0000000..2812b62
--- /dev/null
+++ b/simulator/vendor/reveal/reveal.js
@@ -0,0 +1,9 @@
+/*!
+* reveal.js 5.1.0
+* https://revealjs.com
+* MIT licensed
+*
+* Copyright (C) 2011-2024 Hakim El Hattab, https://hakim.se
+*/
+!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).Reveal=t()}(this,(function(){"use strict";const e=(e,t)=>{for(let i in t)e[i]=t[i];return e},t=(e,t)=>Array.from(e.querySelectorAll(t)),i=(e,t,i)=>{i?e.classList.add(t):e.classList.remove(t)},s=e=>{if("string"==typeof e){if("null"===e)return null;if("true"===e)return!0;if("false"===e)return!1;if(e.match(/^-?[\d\.]+$/))return parseFloat(e)}return e},a=(e,t)=>{e.style.transform=t},n=(e,t)=>{let i=e.matches||e.matchesSelector||e.msMatchesSelector;return!(!i||!i.call(e,t))},r=(e,t)=>{if("function"==typeof e.closest)return e.closest(t);for(;e;){if(n(e,t))return e;e=e.parentNode}return null},o=e=>{let t=(e=e||document.documentElement).requestFullscreen||e.webkitRequestFullscreen||e.webkitRequestFullScreen||e.mozRequestFullScreen||e.msRequestFullscreen;t&&t.apply(e)},l=e=>{let t=document.createElement("style");return t.type="text/css",e&&e.length>0&&(t.styleSheet?t.styleSheet.cssText=e:t.appendChild(document.createTextNode(e))),document.head.appendChild(t),t},d=()=>{let e={};location.search.replace(/[A-Z0-9]+?=([\w\.%-]*)/gi,(t=>{e[t.split("=").shift()]=t.split("=").pop()}));for(let t in e){let i=e[t];e[t]=s(unescape(i))}return void 0!==e.dependencies&&delete e.dependencies,e},c={mp4:"video/mp4",m4a:"video/mp4",ogv:"video/ogg",mpeg:"video/mpeg",webm:"video/webm"},h=navigator.userAgent,u=/(iphone|ipod|ipad|android)/gi.test(h)||"MacIntel"===navigator.platform&&navigator.maxTouchPoints>1,g=/android/gi.test(h);var p=function(e){if(e){var t=function(e){return[].slice.call(e)},i=3,s=[],a=null,n="requestAnimationFrame"in e?function(){e.cancelAnimationFrame(a),a=e.requestAnimationFrame((function(){return o(s.filter((function(e){return e.dirty&&e.active})))}))}:function(){},r=function(e){return function(){s.forEach((function(t){return t.dirty=e})),n()}},o=function(e){e.filter((function(e){return!e.styleComputed})).forEach((function(e){e.styleComputed=h(e)})),e.filter(u).forEach(g);var t=e.filter(c);t.forEach(d),t.forEach((function(e){g(e),l(e)})),t.forEach(p)},l=function(e){return e.dirty=0},d=function(e){e.availableWidth=e.element.parentNode.clientWidth,e.currentWidth=e.element.scrollWidth,e.previousFontSize=e.currentFontSize,e.currentFontSize=Math.min(Math.max(e.minSize,e.availableWidth/e.currentWidth*e.previousFontSize),e.maxSize),e.whiteSpace=e.multiLine&&e.currentFontSize===e.minSize?"normal":"nowrap"},c=function(e){return 2!==e.dirty||2===e.dirty&&e.element.parentNode.clientWidth!==e.availableWidth},h=function(t){var i=e.getComputedStyle(t.element,null);return t.currentFontSize=parseFloat(i.getPropertyValue("font-size")),t.display=i.getPropertyValue("display"),t.whiteSpace=i.getPropertyValue("white-space"),!0},u=function(e){var t=!1;return!e.preStyleTestCompleted&&(/inline-/.test(e.display)||(t=!0,e.display="inline-block"),"nowrap"!==e.whiteSpace&&(t=!0,e.whiteSpace="nowrap"),e.preStyleTestCompleted=!0,t)},g=function(e){e.element.style.whiteSpace=e.whiteSpace,e.element.style.display=e.display,e.element.style.fontSize=e.currentFontSize+"px"},p=function(e){e.element.dispatchEvent(new CustomEvent("fit",{detail:{oldValue:e.previousFontSize,newValue:e.currentFontSize,scaleFactor:e.currentFontSize/e.previousFontSize}}))},v=function(e,t){return function(){e.dirty=t,e.active&&n()}},m=function(e){return function(){s=s.filter((function(t){return t.element!==e.element})),e.observeMutations&&e.observer.disconnect(),e.element.style.whiteSpace=e.originalStyle.whiteSpace,e.element.style.display=e.originalStyle.display,e.element.style.fontSize=e.originalStyle.fontSize}},f=function(e){return function(){e.active||(e.active=!0,n())}},y=function(e){return function(){return e.active=!1}},b=function(e){e.observeMutations&&(e.observer=new MutationObserver(v(e,1)),e.observer.observe(e.element,e.observeMutations))},w={minSize:16,maxSize:512,multiLine:!0,observeMutations:"MutationObserver"in e&&{subtree:!0,childList:!0,characterData:!0}},E=null,S=function(){e.clearTimeout(E),E=e.setTimeout(r(2),k.observeWindowDelay)},A=["resize","orientationchange"];return Object.defineProperty(k,"observeWindow",{set:function(t){var i="".concat(t?"add":"remove","EventListener");A.forEach((function(t){e[i](t,S)}))}}),k.observeWindow=!0,k.observeWindowDelay=100,k.fitAll=r(i),k}function R(e,t){var a=Object.assign({},w,t),r=e.map((function(e){var t=Object.assign({},a,{element:e,active:!0});return function(e){e.originalStyle={whiteSpace:e.element.style.whiteSpace,display:e.element.style.display,fontSize:e.element.style.fontSize},b(e),e.newbie=!0,e.dirty=!0,s.push(e)}(t),{element:e,fit:v(t,i),unfreeze:f(t),freeze:y(t),unsubscribe:m(t)}}));return n(),r}function k(e){var i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return"string"==typeof e?R(t(document.querySelectorAll(e)),i):R([e],i)[0]}}("undefined"==typeof window?null:window);class v{constructor(e){this.Reveal=e,this.startEmbeddedIframe=this.startEmbeddedIframe.bind(this)}shouldPreload(e){if(this.Reveal.isScrollView())return!0;let t=this.Reveal.getConfig().preloadIframes;return"boolean"!=typeof t&&(t=e.hasAttribute("data-preload")),t}load(e,i={}){e.style.display=this.Reveal.getConfig().display,t(e,"img[data-src], video[data-src], audio[data-src], iframe[data-src]").forEach((e=>{("IFRAME"!==e.tagName||this.shouldPreload(e))&&(e.setAttribute("src",e.getAttribute("data-src")),e.setAttribute("data-lazy-loaded",""),e.removeAttribute("data-src"))})),t(e,"video, audio").forEach((e=>{let i=0;t(e,"source[data-src]").forEach((e=>{e.setAttribute("src",e.getAttribute("data-src")),e.removeAttribute("data-src"),e.setAttribute("data-lazy-loaded",""),i+=1})),u&&"VIDEO"===e.tagName&&e.setAttribute("playsinline",""),i>0&&e.load()}));let s=e.slideBackgroundElement;if(s){s.style.display="block";let t=e.slideBackgroundContentElement,a=e.getAttribute("data-background-iframe");if(!1===s.hasAttribute("data-loaded")){s.setAttribute("data-loaded","true");let n=e.getAttribute("data-background-image"),r=e.getAttribute("data-background-video"),o=e.hasAttribute("data-background-video-loop"),l=e.hasAttribute("data-background-video-muted");if(n)/^data:/.test(n.trim())?t.style.backgroundImage=`url(${n.trim()})`:t.style.backgroundImage=n.split(",").map((e=>`url(${((e="")=>encodeURI(e).replace(/%5B/g,"[").replace(/%5D/g,"]").replace(/[!'()*]/g,(e=>`%${e.charCodeAt(0).toString(16).toUpperCase()}`)))(decodeURI(e.trim()))})`)).join(",");else if(r&&!this.Reveal.isSpeakerNotes()){let e=document.createElement("video");o&&e.setAttribute("loop",""),l&&(e.muted=!0),u&&(e.muted=!0,e.setAttribute("playsinline","")),r.split(",").forEach((t=>{const i=document.createElement("source");i.setAttribute("src",t);let s=((e="")=>c[e.split(".").pop()])(t);s&&i.setAttribute("type",s),e.appendChild(i)})),t.appendChild(e)}else if(a&&!0!==i.excludeIframes){let e=document.createElement("iframe");e.setAttribute("allowfullscreen",""),e.setAttribute("mozallowfullscreen",""),e.setAttribute("webkitallowfullscreen",""),e.setAttribute("allow","autoplay"),e.setAttribute("data-src",a),e.style.width="100%",e.style.height="100%",e.style.maxHeight="100%",e.style.maxWidth="100%",t.appendChild(e)}}let n=t.querySelector("iframe[data-src]");n&&this.shouldPreload(s)&&!/autoplay=(1|true|yes)/gi.test(a)&&n.getAttribute("src")!==a&&n.setAttribute("src",a)}this.layout(e)}layout(e){Array.from(e.querySelectorAll(".r-fit-text")).forEach((e=>{p(e,{minSize:24,maxSize:.8*this.Reveal.getConfig().height,observeMutations:!1,observeWindow:!1})}))}unload(e){e.style.display="none";let i=this.Reveal.getSlideBackground(e);i&&(i.style.display="none",t(i,"iframe[src]").forEach((e=>{e.removeAttribute("src")}))),t(e,"video[data-lazy-loaded][src], audio[data-lazy-loaded][src], iframe[data-lazy-loaded][src]").forEach((e=>{e.setAttribute("data-src",e.getAttribute("src")),e.removeAttribute("src")})),t(e,"video[data-lazy-loaded] source[src], audio source[src]").forEach((e=>{e.setAttribute("data-src",e.getAttribute("src")),e.removeAttribute("src")}))}formatEmbeddedContent(){let e=(e,i,s)=>{t(this.Reveal.getSlidesElement(),"iframe["+e+'*="'+i+'"]').forEach((t=>{let i=t.getAttribute(e);i&&-1===i.indexOf(s)&&t.setAttribute(e,i+(/\?/.test(i)?"&":"?")+s)}))};e("src","youtube.com/embed/","enablejsapi=1"),e("data-src","youtube.com/embed/","enablejsapi=1"),e("src","player.vimeo.com/","api=1"),e("data-src","player.vimeo.com/","api=1")}startEmbeddedContent(e){e&&!this.Reveal.isSpeakerNotes()&&(t(e,'img[src$=".gif"]').forEach((e=>{e.setAttribute("src",e.getAttribute("src"))})),t(e,"video, audio").forEach((e=>{if(r(e,".fragment")&&!r(e,".fragment.visible"))return;let t=this.Reveal.getConfig().autoPlayMedia;if("boolean"!=typeof t&&(t=e.hasAttribute("data-autoplay")||!!r(e,".slide-background")),t&&"function"==typeof e.play)if(e.readyState>1)this.startEmbeddedMedia({target:e});else if(u){let t=e.play();t&&"function"==typeof t.catch&&!1===e.controls&&t.catch((()=>{e.controls=!0,e.addEventListener("play",(()=>{e.controls=!1}))}))}else e.removeEventListener("loadeddata",this.startEmbeddedMedia),e.addEventListener("loadeddata",this.startEmbeddedMedia)})),t(e,"iframe[src]").forEach((e=>{r(e,".fragment")&&!r(e,".fragment.visible")||this.startEmbeddedIframe({target:e})})),t(e,"iframe[data-src]").forEach((e=>{r(e,".fragment")&&!r(e,".fragment.visible")||e.getAttribute("src")!==e.getAttribute("data-src")&&(e.removeEventListener("load",this.startEmbeddedIframe),e.addEventListener("load",this.startEmbeddedIframe),e.setAttribute("src",e.getAttribute("data-src")))})))}startEmbeddedMedia(e){let t=!!r(e.target,"html"),i=!!r(e.target,".present");t&&i&&(e.target.paused||e.target.ended)&&(e.target.currentTime=0,e.target.play()),e.target.removeEventListener("loadeddata",this.startEmbeddedMedia)}startEmbeddedIframe(e){let t=e.target;if(t&&t.contentWindow){let i=!!r(e.target,"html"),s=!!r(e.target,".present");if(i&&s){let e=this.Reveal.getConfig().autoPlayMedia;"boolean"!=typeof e&&(e=t.hasAttribute("data-autoplay")||!!r(t,".slide-background")),/youtube\.com\/embed\//.test(t.getAttribute("src"))&&e?t.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}',"*"):/player\.vimeo\.com\//.test(t.getAttribute("src"))&&e?t.contentWindow.postMessage('{"method":"play"}',"*"):t.contentWindow.postMessage("slide:start","*")}}}stopEmbeddedContent(i,s={}){s=e({unloadIframes:!0},s),i&&i.parentNode&&(t(i,"video, audio").forEach((e=>{e.hasAttribute("data-ignore")||"function"!=typeof e.pause||(e.setAttribute("data-paused-by-reveal",""),e.pause())})),t(i,"iframe").forEach((e=>{e.contentWindow&&e.contentWindow.postMessage("slide:stop","*"),e.removeEventListener("load",this.startEmbeddedIframe)})),t(i,'iframe[src*="youtube.com/embed/"]').forEach((e=>{!e.hasAttribute("data-ignore")&&e.contentWindow&&"function"==typeof e.contentWindow.postMessage&&e.contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}',"*")})),t(i,'iframe[src*="player.vimeo.com/"]').forEach((e=>{!e.hasAttribute("data-ignore")&&e.contentWindow&&"function"==typeof e.contentWindow.postMessage&&e.contentWindow.postMessage('{"method":"pause"}',"*")})),!0===s.unloadIframes&&t(i,"iframe[data-src]").forEach((e=>{e.setAttribute("src","about:blank"),e.removeAttribute("src")})))}}const m=".slides section",f=".slides>section",y=".slides>section.present>section",b=/registerPlugin|registerKeyboardShortcut|addKeyBinding|addEventListener|showPreview/,w=/fade-(down|up|right|left|out|in-then-out|in-then-semi-out)|semi-fade-out|current-visible|shrink|grow/;class E{constructor(e){this.Reveal=e}render(){this.element=document.createElement("div"),this.element.className="slide-number",this.Reveal.getRevealElement().appendChild(this.element)}configure(e,t){let i="none";e.slideNumber&&!this.Reveal.isPrintView()&&("all"===e.showSlideNumber||"speaker"===e.showSlideNumber&&this.Reveal.isSpeakerNotes())&&(i="block"),this.element.style.display=i}update(){this.Reveal.getConfig().slideNumber&&this.element&&(this.element.innerHTML=this.getSlideNumber())}getSlideNumber(e=this.Reveal.getCurrentSlide()){let t,i=this.Reveal.getConfig(),s="h.v";if("function"==typeof i.slideNumber)t=i.slideNumber(e);else{"string"==typeof i.slideNumber&&(s=i.slideNumber),/c/.test(s)||1!==this.Reveal.getHorizontalSlides().length||(s="c");let a=e&&"uncounted"===e.dataset.visibility?0:1;switch(t=[],s){case"c":t.push(this.Reveal.getSlidePastCount(e)+a);break;case"c/t":t.push(this.Reveal.getSlidePastCount(e)+a,"/",this.Reveal.getTotalSlides());break;default:let i=this.Reveal.getIndices(e);t.push(i.h+a);let n="h/v"===s?"/":".";this.Reveal.isVerticalSlide(e)&&t.push(n,i.v+1)}}let a="#"+this.Reveal.location.getHash(e);return this.formatNumber(t[0],t[1],t[2],a)}formatNumber(e,t,i,s="#"+this.Reveal.location.getHash()){return"number"!=typeof i||isNaN(i)?`\n\t\t\t\t\t${e}\n\t\t\t\t\t`:`\n\t\t\t\t\t${e}\n\t\t\t\t\t${t}\n\t\t\t\t\t${i}\n\t\t\t\t\t`}destroy(){this.element.remove()}}class S{constructor(e){this.Reveal=e,this.onInput=this.onInput.bind(this),this.onBlur=this.onBlur.bind(this),this.onKeyDown=this.onKeyDown.bind(this)}render(){this.element=document.createElement("div"),this.element.className="jump-to-slide",this.jumpInput=document.createElement("input"),this.jumpInput.type="text",this.jumpInput.className="jump-to-slide-input",this.jumpInput.placeholder="Jump to slide",this.jumpInput.addEventListener("input",this.onInput),this.jumpInput.addEventListener("keydown",this.onKeyDown),this.jumpInput.addEventListener("blur",this.onBlur),this.element.appendChild(this.jumpInput)}show(){this.indicesOnShow=this.Reveal.getIndices(),this.Reveal.getRevealElement().appendChild(this.element),this.jumpInput.focus()}hide(){this.isVisible()&&(this.element.remove(),this.jumpInput.value="",clearTimeout(this.jumpTimeout),delete this.jumpTimeout)}isVisible(){return!!this.element.parentNode}jump(){clearTimeout(this.jumpTimeout),delete this.jumpTimeout;let e,t=this.jumpInput.value.trim("");if(/^\d+$/.test(t)){const i=this.Reveal.getConfig().slideNumber;if("c"===i||"c/t"===i){const i=this.Reveal.getSlides()[parseInt(t,10)-1];i&&(e=this.Reveal.getIndices(i))}}return e||(/^\d+\.\d+$/.test(t)&&(t=t.replace(".","/")),e=this.Reveal.location.getIndicesFromHash(t,{oneBasedIndex:!0})),!e&&/\S+/i.test(t)&&t.length>1&&(e=this.search(t)),e&&""!==t?(this.Reveal.slide(e.h,e.v,e.f),!0):(this.Reveal.slide(this.indicesOnShow.h,this.indicesOnShow.v,this.indicesOnShow.f),!1)}jumpAfter(e){clearTimeout(this.jumpTimeout),this.jumpTimeout=setTimeout((()=>this.jump()),e)}search(e){const t=new RegExp("\\b"+e.trim()+"\\b","i"),i=this.Reveal.getSlides().find((e=>t.test(e.innerText)));return i?this.Reveal.getIndices(i):null}cancel(){this.Reveal.slide(this.indicesOnShow.h,this.indicesOnShow.v,this.indicesOnShow.f),this.hide()}confirm(){this.jump(),this.hide()}destroy(){this.jumpInput.removeEventListener("input",this.onInput),this.jumpInput.removeEventListener("keydown",this.onKeyDown),this.jumpInput.removeEventListener("blur",this.onBlur),this.element.remove()}onKeyDown(e){13===e.keyCode?this.confirm():27===e.keyCode&&(this.cancel(),e.stopImmediatePropagation())}onInput(e){this.jumpAfter(200)}onBlur(){setTimeout((()=>this.hide()),1)}}const A=e=>{let t=e.match(/^#([0-9a-f]{3})$/i);if(t&&t[1])return t=t[1],{r:17*parseInt(t.charAt(0),16),g:17*parseInt(t.charAt(1),16),b:17*parseInt(t.charAt(2),16)};let i=e.match(/^#([0-9a-f]{6})$/i);if(i&&i[1])return i=i[1],{r:parseInt(i.slice(0,2),16),g:parseInt(i.slice(2,4),16),b:parseInt(i.slice(4,6),16)};let s=e.match(/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i);if(s)return{r:parseInt(s[1],10),g:parseInt(s[2],10),b:parseInt(s[3],10)};let a=e.match(/^rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\,\s*([\d]+|[\d]*.[\d]+)\s*\)$/i);return a?{r:parseInt(a[1],10),g:parseInt(a[2],10),b:parseInt(a[3],10),a:parseFloat(a[4])}:null};class R{constructor(e){this.Reveal=e}render(){this.element=document.createElement("div"),this.element.className="backgrounds",this.Reveal.getRevealElement().appendChild(this.element)}create(){this.element.innerHTML="",this.element.classList.add("no-transition"),this.Reveal.getHorizontalSlides().forEach((e=>{let i=this.createBackground(e,this.element);t(e,"section").forEach((e=>{this.createBackground(e,i),i.classList.add("stack")}))})),this.Reveal.getConfig().parallaxBackgroundImage?(this.element.style.backgroundImage='url("'+this.Reveal.getConfig().parallaxBackgroundImage+'")',this.element.style.backgroundSize=this.Reveal.getConfig().parallaxBackgroundSize,this.element.style.backgroundRepeat=this.Reveal.getConfig().parallaxBackgroundRepeat,this.element.style.backgroundPosition=this.Reveal.getConfig().parallaxBackgroundPosition,setTimeout((()=>{this.Reveal.getRevealElement().classList.add("has-parallax-background")}),1)):(this.element.style.backgroundImage="",this.Reveal.getRevealElement().classList.remove("has-parallax-background"))}createBackground(e,t){let i=document.createElement("div");i.className="slide-background "+e.className.replace(/present|past|future/,"");let s=document.createElement("div");return s.className="slide-background-content",i.appendChild(s),t.appendChild(i),e.slideBackgroundElement=i,e.slideBackgroundContentElement=s,this.sync(e),i}sync(e){const t=e.slideBackgroundElement,i=e.slideBackgroundContentElement,s={background:e.getAttribute("data-background"),backgroundSize:e.getAttribute("data-background-size"),backgroundImage:e.getAttribute("data-background-image"),backgroundVideo:e.getAttribute("data-background-video"),backgroundIframe:e.getAttribute("data-background-iframe"),backgroundColor:e.getAttribute("data-background-color"),backgroundGradient:e.getAttribute("data-background-gradient"),backgroundRepeat:e.getAttribute("data-background-repeat"),backgroundPosition:e.getAttribute("data-background-position"),backgroundTransition:e.getAttribute("data-background-transition"),backgroundOpacity:e.getAttribute("data-background-opacity")},a=e.hasAttribute("data-preload");e.classList.remove("has-dark-background"),e.classList.remove("has-light-background"),t.removeAttribute("data-loaded"),t.removeAttribute("data-background-hash"),t.removeAttribute("data-background-size"),t.removeAttribute("data-background-transition"),t.style.backgroundColor="",i.style.backgroundSize="",i.style.backgroundRepeat="",i.style.backgroundPosition="",i.style.backgroundImage="",i.style.opacity="",i.innerHTML="",s.background&&(/^(http|file|\/\/)/gi.test(s.background)||/\.(svg|png|jpg|jpeg|gif|bmp|webp)([?#\s]|$)/gi.test(s.background)?e.setAttribute("data-background-image",s.background):t.style.background=s.background),(s.background||s.backgroundColor||s.backgroundGradient||s.backgroundImage||s.backgroundVideo||s.backgroundIframe)&&t.setAttribute("data-background-hash",s.background+s.backgroundSize+s.backgroundImage+s.backgroundVideo+s.backgroundIframe+s.backgroundColor+s.backgroundGradient+s.backgroundRepeat+s.backgroundPosition+s.backgroundTransition+s.backgroundOpacity),s.backgroundSize&&t.setAttribute("data-background-size",s.backgroundSize),s.backgroundColor&&(t.style.backgroundColor=s.backgroundColor),s.backgroundGradient&&(t.style.backgroundImage=s.backgroundGradient),s.backgroundTransition&&t.setAttribute("data-background-transition",s.backgroundTransition),a&&t.setAttribute("data-preload",""),s.backgroundSize&&(i.style.backgroundSize=s.backgroundSize),s.backgroundRepeat&&(i.style.backgroundRepeat=s.backgroundRepeat),s.backgroundPosition&&(i.style.backgroundPosition=s.backgroundPosition),s.backgroundOpacity&&(i.style.opacity=s.backgroundOpacity);const n=this.getContrastClass(e);"string"==typeof n&&e.classList.add(n)}getContrastClass(e){const t=e.slideBackgroundElement;let i=e.getAttribute("data-background-color");if(!i||!A(i)){let e=window.getComputedStyle(t);e&&e.backgroundColor&&(i=e.backgroundColor)}if(i){const e=A(i);if(e&&0!==e.a)return"string"==typeof(s=i)&&(s=A(s)),(s?(299*s.r+587*s.g+114*s.b)/1e3:null)<128?"has-dark-background":"has-light-background"}var s;return null}bubbleSlideContrastClassToElement(e,t){["has-light-background","has-dark-background"].forEach((i=>{e.classList.contains(i)?t.classList.add(i):t.classList.remove(i)}),this)}update(e=!1){let i=this.Reveal.getConfig(),s=this.Reveal.getCurrentSlide(),a=this.Reveal.getIndices(),n=null,r=i.rtl?"future":"past",o=i.rtl?"past":"future";if(Array.from(this.element.childNodes).forEach(((i,s)=>{i.classList.remove("past","present","future"),sa.h?i.classList.add(o):(i.classList.add("present"),n=i),(e||s===a.h)&&t(i,".slide-background").forEach(((e,t)=>{e.classList.remove("past","present","future");const i="number"==typeof a.v?a.v:0;ti?e.classList.add("future"):(e.classList.add("present"),s===a.h&&(n=e))}))})),this.previousBackground&&!this.previousBackground.closest("body")&&(this.previousBackground=null),n&&this.previousBackground){let e=this.previousBackground.getAttribute("data-background-hash"),t=n.getAttribute("data-background-hash");if(t&&t===e&&n!==this.previousBackground){this.element.classList.add("no-transition");const e=n.querySelector("video"),t=this.previousBackground.querySelector("video");if(e&&t){const i=e.parentNode;t.parentNode.appendChild(e),i.appendChild(t)}}}if(this.previousBackground&&this.Reveal.slideContent.stopEmbeddedContent(this.previousBackground,{unloadIframes:!this.Reveal.slideContent.shouldPreload(this.previousBackground)}),n){this.Reveal.slideContent.startEmbeddedContent(n);let e=n.querySelector(".slide-background-content");if(e){let t=e.style.backgroundImage||"";/\.gif/i.test(t)&&(e.style.backgroundImage="",window.getComputedStyle(e).opacity,e.style.backgroundImage=t)}this.previousBackground=n}s&&this.bubbleSlideContrastClassToElement(s,this.Reveal.getRevealElement()),setTimeout((()=>{this.element.classList.remove("no-transition")}),10)}updateParallax(){let e=this.Reveal.getIndices();if(this.Reveal.getConfig().parallaxBackgroundImage){let t,i,s=this.Reveal.getHorizontalSlides(),a=this.Reveal.getVerticalSlides(),n=this.element.style.backgroundSize.split(" ");1===n.length?t=i=parseInt(n[0],10):(t=parseInt(n[0],10),i=parseInt(n[1],10));let r,o,l=this.element.offsetWidth,d=s.length;r="number"==typeof this.Reveal.getConfig().parallaxBackgroundHorizontal?this.Reveal.getConfig().parallaxBackgroundHorizontal:d>1?(t-l)/(d-1):0,o=r*e.h*-1;let c,h,u=this.element.offsetHeight,g=a.length;c="number"==typeof this.Reveal.getConfig().parallaxBackgroundVertical?this.Reveal.getConfig().parallaxBackgroundVertical:(i-u)/(g-1),h=g>0?c*e.v:0,this.element.style.backgroundPosition=o+"px "+-h+"px"}}destroy(){this.element.remove()}}let k=0;class L{constructor(e){this.Reveal=e}run(e,t){this.reset();let i=this.Reveal.getSlides(),s=i.indexOf(t),a=i.indexOf(e);if(e&&t&&e.hasAttribute("data-auto-animate")&&t.hasAttribute("data-auto-animate")&&e.getAttribute("data-auto-animate-id")===t.getAttribute("data-auto-animate-id")&&!(s>a?t:e).hasAttribute("data-auto-animate-restart")){this.autoAnimateStyleSheet=this.autoAnimateStyleSheet||l();let i=this.getAutoAnimateOptions(t);e.dataset.autoAnimate="pending",t.dataset.autoAnimate="pending",i.slideDirection=s>a?"forward":"backward";let n="none"===e.style.display;n&&(e.style.display=this.Reveal.getConfig().display);let r=this.getAutoAnimatableElements(e,t).map((e=>this.autoAnimateElements(e.from,e.to,e.options||{},i,k++)));if(n&&(e.style.display="none"),"false"!==t.dataset.autoAnimateUnmatched&&!0===this.Reveal.getConfig().autoAnimateUnmatched){let e=.8*i.duration,s=.2*i.duration;this.getUnmatchedAutoAnimateElements(t).forEach((e=>{let t=this.getAutoAnimateOptions(e,i),s="unmatched";t.duration===i.duration&&t.delay===i.delay||(s="unmatched-"+k++,r.push(`[data-auto-animate="running"] [data-auto-animate-target="${s}"] { transition: opacity ${t.duration}s ease ${t.delay}s; }`)),e.dataset.autoAnimateTarget=s}),this),r.push(`[data-auto-animate="running"] [data-auto-animate-target="unmatched"] { transition: opacity ${e}s ease ${s}s; }`)}this.autoAnimateStyleSheet.innerHTML=r.join(""),requestAnimationFrame((()=>{this.autoAnimateStyleSheet&&(getComputedStyle(this.autoAnimateStyleSheet).fontWeight,t.dataset.autoAnimate="running")})),this.Reveal.dispatchEvent({type:"autoanimate",data:{fromSlide:e,toSlide:t,sheet:this.autoAnimateStyleSheet}})}}reset(){t(this.Reveal.getRevealElement(),'[data-auto-animate]:not([data-auto-animate=""])').forEach((e=>{e.dataset.autoAnimate=""})),t(this.Reveal.getRevealElement(),"[data-auto-animate-target]").forEach((e=>{delete e.dataset.autoAnimateTarget})),this.autoAnimateStyleSheet&&this.autoAnimateStyleSheet.parentNode&&(this.autoAnimateStyleSheet.parentNode.removeChild(this.autoAnimateStyleSheet),this.autoAnimateStyleSheet=null)}autoAnimateElements(e,t,i,s,a){e.dataset.autoAnimateTarget="",t.dataset.autoAnimateTarget=a;let n=this.getAutoAnimateOptions(t,s);void 0!==i.delay&&(n.delay=i.delay),void 0!==i.duration&&(n.duration=i.duration),void 0!==i.easing&&(n.easing=i.easing);let r=this.getAutoAnimatableProperties("from",e,i),o=this.getAutoAnimatableProperties("to",t,i);if(t.classList.contains("fragment")&&(delete o.styles.opacity,e.classList.contains("fragment"))){(e.className.match(w)||[""])[0]===(t.className.match(w)||[""])[0]&&"forward"===s.slideDirection&&t.classList.add("visible","disabled")}if(!1!==i.translate||!1!==i.scale){let e=this.Reveal.getScale(),t={x:(r.x-o.x)/e,y:(r.y-o.y)/e,scaleX:r.width/o.width,scaleY:r.height/o.height};t.x=Math.round(1e3*t.x)/1e3,t.y=Math.round(1e3*t.y)/1e3,t.scaleX=Math.round(1e3*t.scaleX)/1e3,t.scaleX=Math.round(1e3*t.scaleX)/1e3;let s=!1!==i.translate&&(0!==t.x||0!==t.y),a=!1!==i.scale&&(0!==t.scaleX||0!==t.scaleY);if(s||a){let e=[];s&&e.push(`translate(${t.x}px, ${t.y}px)`),a&&e.push(`scale(${t.scaleX}, ${t.scaleY})`),r.styles.transform=e.join(" "),r.styles["transform-origin"]="top left",o.styles.transform="none"}}for(let e in o.styles){const t=o.styles[e],i=r.styles[e];t===i?delete o.styles[e]:(!0===t.explicitValue&&(o.styles[e]=t.value),!0===i.explicitValue&&(r.styles[e]=i.value))}let l="",d=Object.keys(o.styles);if(d.length>0){r.styles.transition="none",o.styles.transition=`all ${n.duration}s ${n.easing} ${n.delay}s`,o.styles["transition-property"]=d.join(", "),o.styles["will-change"]=d.join(", "),l='[data-auto-animate-target="'+a+'"] {'+Object.keys(r.styles).map((e=>e+": "+r.styles[e]+" !important;")).join("")+'}[data-auto-animate="running"] [data-auto-animate-target="'+a+'"] {'+Object.keys(o.styles).map((e=>e+": "+o.styles[e]+" !important;")).join("")+"}"}return l}getAutoAnimateOptions(t,i){let s={easing:this.Reveal.getConfig().autoAnimateEasing,duration:this.Reveal.getConfig().autoAnimateDuration,delay:0};if(s=e(s,i),t.parentNode){let e=r(t.parentNode,"[data-auto-animate-target]");e&&(s=this.getAutoAnimateOptions(e,s))}return t.dataset.autoAnimateEasing&&(s.easing=t.dataset.autoAnimateEasing),t.dataset.autoAnimateDuration&&(s.duration=parseFloat(t.dataset.autoAnimateDuration)),t.dataset.autoAnimateDelay&&(s.delay=parseFloat(t.dataset.autoAnimateDelay)),s}getAutoAnimatableProperties(e,t,i){let s=this.Reveal.getConfig(),a={styles:[]};if(!1!==i.translate||!1!==i.scale){let e;if("function"==typeof i.measure)e=i.measure(t);else if(s.center)e=t.getBoundingClientRect();else{let i=this.Reveal.getScale();e={x:t.offsetLeft*i,y:t.offsetTop*i,width:t.offsetWidth*i,height:t.offsetHeight*i}}a.x=e.x,a.y=e.y,a.width=e.width,a.height=e.height}const n=getComputedStyle(t);return(i.styles||s.autoAnimateStyles).forEach((t=>{let i;"string"==typeof t&&(t={property:t}),void 0!==t.from&&"from"===e?i={value:t.from,explicitValue:!0}:void 0!==t.to&&"to"===e?i={value:t.to,explicitValue:!0}:("line-height"===t.property&&(i=parseFloat(n["line-height"])/parseFloat(n["font-size"])),isNaN(i)&&(i=n[t.property])),""!==i&&(a.styles[t.property]=i)})),a}getAutoAnimatableElements(e,t){let i=("function"==typeof this.Reveal.getConfig().autoAnimateMatcher?this.Reveal.getConfig().autoAnimateMatcher:this.getAutoAnimatePairs).call(this,e,t),s=[];return i.filter(((e,t)=>{if(-1===s.indexOf(e.to))return s.push(e.to),!0}))}getAutoAnimatePairs(e,t){let i=[];const s="h1, h2, h3, h4, h5, h6, p, li";return this.findAutoAnimateMatches(i,e,t,"[data-id]",(e=>e.nodeName+":::"+e.getAttribute("data-id"))),this.findAutoAnimateMatches(i,e,t,s,(e=>e.nodeName+":::"+e.innerText)),this.findAutoAnimateMatches(i,e,t,"img, video, iframe",(e=>e.nodeName+":::"+(e.getAttribute("src")||e.getAttribute("data-src")))),this.findAutoAnimateMatches(i,e,t,"pre",(e=>e.nodeName+":::"+e.innerText)),i.forEach((e=>{n(e.from,s)?e.options={scale:!1}:n(e.from,"pre")&&(e.options={scale:!1,styles:["width","height"]},this.findAutoAnimateMatches(i,e.from,e.to,".hljs .hljs-ln-code",(e=>e.textContent),{scale:!1,styles:[],measure:this.getLocalBoundingBox.bind(this)}),this.findAutoAnimateMatches(i,e.from,e.to,".hljs .hljs-ln-numbers[data-line-number]",(e=>e.getAttribute("data-line-number")),{scale:!1,styles:["width"],measure:this.getLocalBoundingBox.bind(this)}))}),this),i}getLocalBoundingBox(e){const t=this.Reveal.getScale();return{x:Math.round(e.offsetLeft*t*100)/100,y:Math.round(e.offsetTop*t*100)/100,width:Math.round(e.offsetWidth*t*100)/100,height:Math.round(e.offsetHeight*t*100)/100}}findAutoAnimateMatches(e,t,i,s,a,n){let r={},o={};[].slice.call(t.querySelectorAll(s)).forEach(((e,t)=>{const i=a(e);"string"==typeof i&&i.length&&(r[i]=r[i]||[],r[i].push(e))})),[].slice.call(i.querySelectorAll(s)).forEach(((t,i)=>{const s=a(t);let l;if(o[s]=o[s]||[],o[s].push(t),r[s]){const e=o[s].length-1,t=r[s].length-1;r[s][e]?(l=r[s][e],r[s][e]=null):r[s][t]&&(l=r[s][t],r[s][t]=null)}l&&e.push({from:l,to:t,options:n})}))}getUnmatchedAutoAnimateElements(e){return[].slice.call(e.children).reduce(((e,t)=>{const i=t.querySelector("[data-auto-animate-target]");return t.hasAttribute("data-auto-animate-target")||i||e.push(t),t.querySelector("[data-auto-animate-target]")&&(e=e.concat(this.getUnmatchedAutoAnimateElements(t))),e}),[])}}class C{constructor(e){this.Reveal=e,this.active=!1,this.activatedCallbacks=[],this.onScroll=this.onScroll.bind(this)}activate(){if(this.active)return;const e=this.Reveal.getState();this.active=!0,this.slideHTMLBeforeActivation=this.Reveal.getSlidesElement().innerHTML;const i=t(this.Reveal.getRevealElement(),f),s=t(this.Reveal.getRevealElement(),".backgrounds>.slide-background");let a;this.viewportElement.classList.add("loading-scroll-mode","reveal-scroll");const n=window.getComputedStyle(this.viewportElement);n&&n.background&&(a=n.background);const r=[],o=i[0].parentNode;let l;const d=(e,t,i,n)=>{let o;if(l&&this.Reveal.shouldAutoAnimateBetween(l,e))o=document.createElement("div"),o.className="scroll-page-content scroll-auto-animate-page",o.style.display="none",l.closest(".scroll-page-content").parentNode.appendChild(o);else{const e=document.createElement("div");if(e.className="scroll-page",r.push(e),n&&s.length>t){const i=s[t],n=window.getComputedStyle(i);n&&n.background?e.style.background=n.background:a&&(e.style.background=a)}else a&&(e.style.background=a);const i=document.createElement("div");i.className="scroll-page-sticky",e.appendChild(i),o=document.createElement("div"),o.className="scroll-page-content",i.appendChild(o)}o.appendChild(e),e.classList.remove("past","future"),e.setAttribute("data-index-h",t),e.setAttribute("data-index-v",i),e.slideBackgroundElement&&(e.slideBackgroundElement.remove("past","future"),o.insertBefore(e.slideBackgroundElement,e)),l=e};i.forEach(((e,t)=>{this.Reveal.isVerticalStack(e)?e.querySelectorAll("section").forEach(((e,i)=>{d(e,t,i,!0)})):d(e,t,0)}),this),this.createProgressBar(),t(this.Reveal.getRevealElement(),".stack").forEach((e=>e.remove())),r.forEach((e=>o.appendChild(e))),this.Reveal.slideContent.layout(this.Reveal.getSlidesElement()),this.Reveal.layout(),this.Reveal.setState(e),this.activatedCallbacks.forEach((e=>e())),this.activatedCallbacks=[],this.restoreScrollPosition(),this.viewportElement.classList.remove("loading-scroll-mode"),this.viewportElement.addEventListener("scroll",this.onScroll,{passive:!0})}deactivate(){if(!this.active)return;const e=this.Reveal.getState();this.active=!1,this.viewportElement.removeEventListener("scroll",this.onScroll),this.viewportElement.classList.remove("reveal-scroll"),this.removeProgressBar(),this.Reveal.getSlidesElement().innerHTML=this.slideHTMLBeforeActivation,this.Reveal.sync(),this.Reveal.setState(e),this.slideHTMLBeforeActivation=null}toggle(e){"boolean"==typeof e?e?this.activate():this.deactivate():this.isActive()?this.deactivate():this.activate()}isActive(){return this.active}createProgressBar(){this.progressBar=document.createElement("div"),this.progressBar.className="scrollbar",this.progressBarInner=document.createElement("div"),this.progressBarInner.className="scrollbar-inner",this.progressBar.appendChild(this.progressBarInner),this.progressBarPlayhead=document.createElement("div"),this.progressBarPlayhead.className="scrollbar-playhead",this.progressBarInner.appendChild(this.progressBarPlayhead),this.viewportElement.insertBefore(this.progressBar,this.viewportElement.firstChild);const e=e=>{let t=(e.clientY-this.progressBarInner.getBoundingClientRect().top)/this.progressBarHeight;t=Math.max(Math.min(t,1),0),this.viewportElement.scrollTop=t*(this.viewportElement.scrollHeight-this.viewportElement.offsetHeight)},t=i=>{this.draggingProgressBar=!1,this.showProgressBar(),document.removeEventListener("mousemove",e),document.removeEventListener("mouseup",t)};this.progressBarInner.addEventListener("mousedown",(i=>{i.preventDefault(),this.draggingProgressBar=!0,document.addEventListener("mousemove",e),document.addEventListener("mouseup",t),e(i)}))}removeProgressBar(){this.progressBar&&(this.progressBar.remove(),this.progressBar=null)}layout(){this.isActive()&&(this.syncPages(),this.syncScrollPosition())}syncPages(){const e=this.Reveal.getConfig(),t=this.Reveal.getComputedSlideSize(window.innerWidth,window.innerHeight),i=this.Reveal.getScale(),s="compact"===e.scrollLayout,a=this.viewportElement.offsetHeight,n=t.height*i,r=s?n:a;this.scrollTriggerHeight=s?n:a,this.viewportElement.style.setProperty("--page-height",r+"px"),this.viewportElement.style.scrollSnapType="string"==typeof e.scrollSnap?`y ${e.scrollSnap}`:"",this.slideTriggers=[];const o=Array.from(this.Reveal.getRevealElement().querySelectorAll(".scroll-page"));this.pages=o.map((i=>{const n=this.createPage({pageElement:i,slideElement:i.querySelector("section"),stickyElement:i.querySelector(".scroll-page-sticky"),contentElement:i.querySelector(".scroll-page-content"),backgroundElement:i.querySelector(".slide-background"),autoAnimateElements:i.querySelectorAll(".scroll-auto-animate-page"),autoAnimatePages:[]});n.pageElement.style.setProperty("--slide-height",!0===e.center?"auto":t.height+"px"),this.slideTriggers.push({page:n,activate:()=>this.activatePage(n),deactivate:()=>this.deactivatePage(n)}),this.createFragmentTriggersForPage(n),n.autoAnimateElements.length>0&&this.createAutoAnimateTriggersForPage(n);let o=Math.max(n.scrollTriggers.length-1,0);o+=n.autoAnimatePages.reduce(((e,t)=>e+Math.max(t.scrollTriggers.length-1,0)),n.autoAnimatePages.length),n.pageElement.querySelectorAll(".scroll-snap-point").forEach((e=>e.remove()));for(let e=0;e0?(n.pageHeight=a,n.pageElement.style.setProperty("--page-height",a+"px")):(n.pageHeight=r,n.pageElement.style.removeProperty("--page-height")),n.scrollPadding=this.scrollTriggerHeight*o,n.totalHeight=n.pageHeight+n.scrollPadding,n.pageElement.style.setProperty("--page-scroll-padding",n.scrollPadding+"px"),o>0?(n.stickyElement.style.position="sticky",n.stickyElement.style.top=Math.max((a-n.pageHeight)/2,0)+"px"):(n.stickyElement.style.position="relative",n.pageElement.style.scrollSnapAlign=n.pageHeight1?(this.progressBar||this.createProgressBar(),this.syncProgressBar()):this.removeProgressBar()}setTriggerRanges(){this.totalScrollTriggerCount=this.slideTriggers.reduce(((e,t)=>e+Math.max(t.page.scrollTriggers.length,1)),0);let e=0;this.slideTriggers.forEach(((t,i)=>{t.range=[e,e+Math.max(t.page.scrollTriggers.length,1)/this.totalScrollTriggerCount];const s=(t.range[1]-t.range[0])/t.page.scrollTriggers.length;t.page.scrollTriggers.forEach(((t,i)=>{t.range=[e+i*s,e+(i+1)*s]})),e=t.range[1]}))}createFragmentTriggersForPage(e,t){t=t||e.slideElement;const i=this.Reveal.fragments.sort(t.querySelectorAll(".fragment"),!0);return i.length&&(e.fragments=this.Reveal.fragments.sort(t.querySelectorAll(".fragment:not(.disabled)")),e.scrollTriggers.push({activate:()=>{this.Reveal.fragments.update(-1,e.fragments,t)}}),i.forEach(((i,s)=>{e.scrollTriggers.push({activate:()=>{this.Reveal.fragments.update(s,e.fragments,t)}})}))),e.scrollTriggers.length}createAutoAnimateTriggersForPage(e){e.autoAnimateElements.length>0&&this.slideTriggers.push(...Array.from(e.autoAnimateElements).map(((t,i)=>{let s=this.createPage({slideElement:t.querySelector("section"),contentElement:t,backgroundElement:t.querySelector(".slide-background")});return this.createFragmentTriggersForPage(s,s.slideElement),e.autoAnimatePages.push(s),{page:s,activate:()=>this.activatePage(s),deactivate:()=>this.deactivatePage(s)}})))}createPage(e){return e.scrollTriggers=[],e.indexh=parseInt(e.slideElement.getAttribute("data-index-h"),10),e.indexv=parseInt(e.slideElement.getAttribute("data-index-v"),10),e}syncProgressBar(){this.progressBarInner.querySelectorAll(".scrollbar-slide").forEach((e=>e.remove()));const e=this.viewportElement.scrollHeight,t=this.viewportElement.offsetHeight,i=t/e;this.progressBarHeight=this.progressBarInner.offsetHeight,this.playheadHeight=Math.max(i*this.progressBarHeight,8),this.progressBarScrollableHeight=this.progressBarHeight-this.playheadHeight;const s=t/e*this.progressBarHeight,a=Math.min(s/8,4);this.progressBarPlayhead.style.height=this.playheadHeight-a+"px",s>6?this.slideTriggers.forEach((e=>{const{page:t}=e;t.progressBarSlide=document.createElement("div"),t.progressBarSlide.className="scrollbar-slide",t.progressBarSlide.style.top=e.range[0]*this.progressBarHeight+"px",t.progressBarSlide.style.height=(e.range[1]-e.range[0])*this.progressBarHeight-a+"px",t.progressBarSlide.classList.toggle("has-triggers",t.scrollTriggers.length>0),this.progressBarInner.appendChild(t.progressBarSlide),t.scrollTriggerElements=t.scrollTriggers.map(((i,s)=>{const n=document.createElement("div");return n.className="scrollbar-trigger",n.style.top=(i.range[0]-e.range[0])*this.progressBarHeight+"px",n.style.height=(i.range[1]-i.range[0])*this.progressBarHeight-a+"px",t.progressBarSlide.appendChild(n),0===s&&(n.style.display="none"),n}))})):this.pages.forEach((e=>e.progressBarSlide=null))}syncScrollPosition(){const e=this.viewportElement.offsetHeight,t=e/this.viewportElement.scrollHeight,i=this.viewportElement.scrollTop,s=this.viewportElement.scrollHeight-e,a=Math.max(Math.min(i/s,1),0),n=Math.max(Math.min((i+e/2)/this.viewportElement.scrollHeight,1),0);let r;this.slideTriggers.forEach((e=>{const{page:i}=e;a>=e.range[0]-2*t&&a<=e.range[1]+2*t&&!i.loaded?(i.loaded=!0,this.Reveal.slideContent.load(i.slideElement)):i.loaded&&(i.loaded=!1,this.Reveal.slideContent.unload(i.slideElement)),a>=e.range[0]&&a<=e.range[1]?(this.activateTrigger(e),r=e.page):e.active&&this.deactivateTrigger(e)})),r&&r.scrollTriggers.forEach((e=>{n>=e.range[0]&&n<=e.range[1]?this.activateTrigger(e):e.active&&this.deactivateTrigger(e)})),this.setProgressBarValue(i/(this.viewportElement.scrollHeight-e))}setProgressBarValue(e){this.progressBar&&(this.progressBarPlayhead.style.transform=`translateY(${e*this.progressBarScrollableHeight}px)`,this.getAllPages().filter((e=>e.progressBarSlide)).forEach((e=>{e.progressBarSlide.classList.toggle("active",!0===e.active),e.scrollTriggers.forEach(((t,i)=>{e.scrollTriggerElements[i].classList.toggle("active",!0===e.active&&!0===t.active)}))})),this.showProgressBar())}showProgressBar(){this.progressBar.classList.add("visible"),clearTimeout(this.hideProgressBarTimeout),"auto"!==this.Reveal.getConfig().scrollProgress||this.draggingProgressBar||(this.hideProgressBarTimeout=setTimeout((()=>{this.progressBar&&this.progressBar.classList.remove("visible")}),500))}prev(){this.viewportElement.scrollTop-=this.scrollTriggerHeight}next(){this.viewportElement.scrollTop+=this.scrollTriggerHeight}scrollToSlide(e){if(this.active){const t=this.getScrollTriggerBySlide(e);t&&(this.viewportElement.scrollTop=t.range[0]*(this.viewportElement.scrollHeight-this.viewportElement.offsetHeight))}else this.activatedCallbacks.push((()=>this.scrollToSlide(e)))}storeScrollPosition(){clearTimeout(this.storeScrollPositionTimeout),this.storeScrollPositionTimeout=setTimeout((()=>{sessionStorage.setItem("reveal-scroll-top",this.viewportElement.scrollTop),sessionStorage.setItem("reveal-scroll-origin",location.origin+location.pathname),this.storeScrollPositionTimeout=null}),50)}restoreScrollPosition(){const e=sessionStorage.getItem("reveal-scroll-top"),t=sessionStorage.getItem("reveal-scroll-origin");e&&t===location.origin+location.pathname&&(this.viewportElement.scrollTop=parseInt(e,10))}activatePage(e){if(!e.active){e.active=!0;const{slideElement:t,backgroundElement:i,contentElement:s,indexh:a,indexv:n}=e;s.style.display="block",t.classList.add("present"),i&&i.classList.add("present"),this.Reveal.setCurrentScrollPage(t,a,n),this.Reveal.backgrounds.bubbleSlideContrastClassToElement(t,this.viewportElement),Array.from(s.parentNode.querySelectorAll(".scroll-page-content")).forEach((e=>{e!==s&&(e.style.display="none")}))}}deactivatePage(e){e.active&&(e.active=!1,e.slideElement&&e.slideElement.classList.remove("present"),e.backgroundElement&&e.backgroundElement.classList.remove("present"))}activateTrigger(e){e.active||(e.active=!0,e.activate())}deactivateTrigger(e){e.active&&(e.active=!1,e.deactivate&&e.deactivate())}getSlideByIndices(e,t){const i=this.getAllPages().find((i=>i.indexh===e&&i.indexv===t));return i?i.slideElement:null}getScrollTriggerBySlide(e){return this.slideTriggers.find((t=>t.page.slideElement===e))}getAllPages(){return this.pages.flatMap((e=>[e,...e.autoAnimatePages||[]]))}onScroll(){this.syncScrollPosition(),this.storeScrollPosition()}get viewportElement(){return this.Reveal.getViewportElement()}}class x{constructor(e){this.Reveal=e}async activate(){const e=this.Reveal.getConfig(),i=t(this.Reveal.getRevealElement(),m),s=e.slideNumber&&/all|print/i.test(e.showSlideNumber),a=this.Reveal.getComputedSlideSize(window.innerWidth,window.innerHeight),n=Math.floor(a.width*(1+e.margin)),r=Math.floor(a.height*(1+e.margin)),o=a.width,d=a.height;await new Promise(requestAnimationFrame),l("@page{size:"+n+"px "+r+"px; margin: 0px;}"),l(".reveal section>img, .reveal section>video, .reveal section>iframe{max-width: "+o+"px; max-height:"+d+"px}"),document.documentElement.classList.add("reveal-print","print-pdf"),document.body.style.width=n+"px",document.body.style.height=r+"px";const c=this.Reveal.getViewportElement();let h;if(c){const e=window.getComputedStyle(c);e&&e.background&&(h=e.background)}await new Promise(requestAnimationFrame),this.Reveal.layoutSlideContents(o,d),await new Promise(requestAnimationFrame);const u=i.map((e=>e.scrollHeight)),g=[],p=i[0].parentNode;let v=1;i.forEach((function(i,a){if(!1===i.classList.contains("stack")){let l=(n-o)/2,c=(r-d)/2;const p=u[a];let m=Math.max(Math.ceil(p/r),1);m=Math.min(m,e.pdfMaxPagesPerSlide),(1===m&&e.center||i.classList.contains("center"))&&(c=Math.max((r-p)/2,0));const f=document.createElement("div");if(g.push(f),f.className="pdf-page",f.style.height=(r+e.pdfPageHeightOffset)*m+"px",h&&(f.style.background=h),f.appendChild(i),i.style.left=l+"px",i.style.top=c+"px",i.style.width=o+"px",this.Reveal.slideContent.layout(i),i.slideBackgroundElement&&f.insertBefore(i.slideBackgroundElement,i),e.showNotes){const t=this.Reveal.getSlideNotes(i);if(t){const i=8,s="string"==typeof e.showNotes?e.showNotes:"inline",a=document.createElement("div");a.classList.add("speaker-notes"),a.classList.add("speaker-notes-pdf"),a.setAttribute("data-layout",s),a.innerHTML=t,"separate-page"===s?g.push(a):(a.style.left=i+"px",a.style.bottom=i+"px",a.style.width=n-2*i+"px",f.appendChild(a))}}if(s){const e=document.createElement("div");e.classList.add("slide-number"),e.classList.add("slide-number-pdf"),e.innerHTML=v++,f.appendChild(e)}if(e.pdfSeparateFragments){const e=this.Reveal.fragments.sort(f.querySelectorAll(".fragment"),!0);let t;e.forEach((function(e,i){t&&t.forEach((function(e){e.classList.remove("current-fragment")})),e.forEach((function(e){e.classList.add("visible","current-fragment")}),this);const a=f.cloneNode(!0);if(s){const e=i+1;a.querySelector(".slide-number-pdf").innerHTML+="."+e}g.push(a),t=e}),this),e.forEach((function(e){e.forEach((function(e){e.classList.remove("visible","current-fragment")}))}))}else t(f,".fragment:not(.fade-out)").forEach((function(e){e.classList.add("visible")}))}}),this),await new Promise(requestAnimationFrame),g.forEach((e=>p.appendChild(e))),this.Reveal.slideContent.layout(this.Reveal.getSlidesElement()),this.Reveal.dispatchEvent({type:"pdf-ready"}),c.classList.remove("loading-scroll-mode")}isActive(){return"print"===this.Reveal.getConfig().view}}class P{constructor(e){this.Reveal=e}configure(e,t){!1===e.fragments?this.disable():!1===t.fragments&&this.enable()}disable(){t(this.Reveal.getSlidesElement(),".fragment").forEach((e=>{e.classList.add("visible"),e.classList.remove("current-fragment")}))}enable(){t(this.Reveal.getSlidesElement(),".fragment").forEach((e=>{e.classList.remove("visible"),e.classList.remove("current-fragment")}))}availableRoutes(){let e=this.Reveal.getCurrentSlide();if(e&&this.Reveal.getConfig().fragments){let t=e.querySelectorAll(".fragment:not(.disabled)"),i=e.querySelectorAll(".fragment:not(.disabled):not(.visible)");return{prev:t.length-i.length>0,next:!!i.length}}return{prev:!1,next:!1}}sort(e,t=!1){e=Array.from(e);let i=[],s=[],a=[];e.forEach((e=>{if(e.hasAttribute("data-fragment-index")){let t=parseInt(e.getAttribute("data-fragment-index"),10);i[t]||(i[t]=[]),i[t].push(e)}else s.push([e])})),i=i.concat(s);let n=0;return i.forEach((e=>{e.forEach((e=>{a.push(e),e.setAttribute("data-fragment-index",n)})),n++})),!0===t?i:a}sortAll(){this.Reveal.getHorizontalSlides().forEach((e=>{let i=t(e,"section");i.forEach(((e,t)=>{this.sort(e.querySelectorAll(".fragment"))}),this),0===i.length&&this.sort(e.querySelectorAll(".fragment"))}))}update(e,t,i=this.Reveal.getCurrentSlide()){let s={shown:[],hidden:[]};if(i&&this.Reveal.getConfig().fragments&&(t=t||this.sort(i.querySelectorAll(".fragment"))).length){let a=0;if("number"!=typeof e){let t=this.sort(i.querySelectorAll(".fragment.visible")).pop();t&&(e=parseInt(t.getAttribute("data-fragment-index")||0,10))}Array.from(t).forEach(((t,i)=>{if(t.hasAttribute("data-fragment-index")&&(i=parseInt(t.getAttribute("data-fragment-index"),10)),a=Math.max(a,i),i<=e){let a=t.classList.contains("visible");t.classList.add("visible"),t.classList.remove("current-fragment"),i===e&&(this.Reveal.announceStatus(this.Reveal.getStatusText(t)),t.classList.add("current-fragment"),this.Reveal.slideContent.startEmbeddedContent(t)),a||(s.shown.push(t),this.Reveal.dispatchEvent({target:t,type:"visible",bubbles:!1}))}else{let e=t.classList.contains("visible");t.classList.remove("visible"),t.classList.remove("current-fragment"),e&&(this.Reveal.slideContent.stopEmbeddedContent(t),s.hidden.push(t),this.Reveal.dispatchEvent({target:t,type:"hidden",bubbles:!1}))}})),e="number"==typeof e?e:-1,e=Math.max(Math.min(e,a),-1),i.setAttribute("data-fragment",e)}return s.hidden.length&&this.Reveal.dispatchEvent({type:"fragmenthidden",data:{fragment:s.hidden[0],fragments:s.hidden}}),s.shown.length&&this.Reveal.dispatchEvent({type:"fragmentshown",data:{fragment:s.shown[0],fragments:s.shown}}),s}sync(e=this.Reveal.getCurrentSlide()){return this.sort(e.querySelectorAll(".fragment"))}goto(e,t=0){let i=this.Reveal.getCurrentSlide();if(i&&this.Reveal.getConfig().fragments){let s=this.sort(i.querySelectorAll(".fragment:not(.disabled)"));if(s.length){if("number"!=typeof e){let t=this.sort(i.querySelectorAll(".fragment:not(.disabled).visible")).pop();e=t?parseInt(t.getAttribute("data-fragment-index")||0,10):-1}e+=t;let a=this.update(e,s);return this.Reveal.controls.update(),this.Reveal.progress.update(),this.Reveal.getConfig().fragmentInURL&&this.Reveal.location.writeURL(),!(!a.shown.length&&!a.hidden.length)}}return!1}next(){return this.goto(null,1)}prev(){return this.goto(null,-1)}}class T{constructor(e){this.Reveal=e,this.active=!1,this.onSlideClicked=this.onSlideClicked.bind(this)}activate(){if(this.Reveal.getConfig().overview&&!this.Reveal.isScrollView()&&!this.isActive()){this.active=!0,this.Reveal.getRevealElement().classList.add("overview"),this.Reveal.cancelAutoSlide(),this.Reveal.getSlidesElement().appendChild(this.Reveal.getBackgroundsElement()),t(this.Reveal.getRevealElement(),m).forEach((e=>{e.classList.contains("stack")||e.addEventListener("click",this.onSlideClicked,!0)}));const e=70,i=this.Reveal.getComputedSlideSize();this.overviewSlideWidth=i.width+e,this.overviewSlideHeight=i.height+e,this.Reveal.getConfig().rtl&&(this.overviewSlideWidth=-this.overviewSlideWidth),this.Reveal.updateSlidesVisibility(),this.layout(),this.update(),this.Reveal.layout();const s=this.Reveal.getIndices();this.Reveal.dispatchEvent({type:"overviewshown",data:{indexh:s.h,indexv:s.v,currentSlide:this.Reveal.getCurrentSlide()}})}}layout(){this.Reveal.getHorizontalSlides().forEach(((e,i)=>{e.setAttribute("data-index-h",i),a(e,"translate3d("+i*this.overviewSlideWidth+"px, 0, 0)"),e.classList.contains("stack")&&t(e,"section").forEach(((e,t)=>{e.setAttribute("data-index-h",i),e.setAttribute("data-index-v",t),a(e,"translate3d(0, "+t*this.overviewSlideHeight+"px, 0)")}))})),Array.from(this.Reveal.getBackgroundsElement().childNodes).forEach(((e,i)=>{a(e,"translate3d("+i*this.overviewSlideWidth+"px, 0, 0)"),t(e,".slide-background").forEach(((e,t)=>{a(e,"translate3d(0, "+t*this.overviewSlideHeight+"px, 0)")}))}))}update(){const e=Math.min(window.innerWidth,window.innerHeight),t=Math.max(e/5,150)/e,i=this.Reveal.getIndices();this.Reveal.transformSlides({overview:["scale("+t+")","translateX("+-i.h*this.overviewSlideWidth+"px)","translateY("+-i.v*this.overviewSlideHeight+"px)"].join(" ")})}deactivate(){if(this.Reveal.getConfig().overview){this.active=!1,this.Reveal.getRevealElement().classList.remove("overview"),this.Reveal.getRevealElement().classList.add("overview-deactivating"),setTimeout((()=>{this.Reveal.getRevealElement().classList.remove("overview-deactivating")}),1),this.Reveal.getRevealElement().appendChild(this.Reveal.getBackgroundsElement()),t(this.Reveal.getRevealElement(),m).forEach((e=>{a(e,""),e.removeEventListener("click",this.onSlideClicked,!0)})),t(this.Reveal.getBackgroundsElement(),".slide-background").forEach((e=>{a(e,"")})),this.Reveal.transformSlides({overview:""});const e=this.Reveal.getIndices();this.Reveal.slide(e.h,e.v),this.Reveal.layout(),this.Reveal.cueAutoSlide(),this.Reveal.dispatchEvent({type:"overviewhidden",data:{indexh:e.h,indexv:e.v,currentSlide:this.Reveal.getCurrentSlide()}})}}toggle(e){"boolean"==typeof e?e?this.activate():this.deactivate():this.isActive()?this.deactivate():this.activate()}isActive(){return this.active}onSlideClicked(e){if(this.isActive()){e.preventDefault();let t=e.target;for(;t&&!t.nodeName.match(/section/gi);)t=t.parentNode;if(t&&!t.classList.contains("disabled")&&(this.deactivate(),t.nodeName.match(/section/gi))){let e=parseInt(t.getAttribute("data-index-h"),10),i=parseInt(t.getAttribute("data-index-v"),10);this.Reveal.slide(e,i)}}}}class N{constructor(e){this.Reveal=e,this.shortcuts={},this.bindings={},this.onDocumentKeyDown=this.onDocumentKeyDown.bind(this)}configure(e,t){"linear"===e.navigationMode?(this.shortcuts["→  ,  ↓  ,  SPACE  ,  N  ,  L  ,  J"]="Next slide",this.shortcuts["←  ,  ↑  ,  P  ,  H  ,  K"]="Previous slide"):(this.shortcuts["N  ,  SPACE"]="Next slide",this.shortcuts["P  ,  Shift SPACE"]="Previous slide",this.shortcuts["←  ,  H"]="Navigate left",this.shortcuts["→  ,  L"]="Navigate right",this.shortcuts["↑  ,  K"]="Navigate up",this.shortcuts["↓  ,  J"]="Navigate down"),this.shortcuts["Alt + ←/↑/→/↓"]="Navigate without fragments",this.shortcuts["Shift + ←/↑/→/↓"]="Jump to first/last slide",this.shortcuts["B  ,  ."]="Pause",this.shortcuts.F="Fullscreen",this.shortcuts.G="Jump to slide",this.shortcuts["ESC, O"]="Slide overview"}bind(){document.addEventListener("keydown",this.onDocumentKeyDown,!1)}unbind(){document.removeEventListener("keydown",this.onDocumentKeyDown,!1)}addKeyBinding(e,t){"object"==typeof e&&e.keyCode?this.bindings[e.keyCode]={callback:t,key:e.key,description:e.description}:this.bindings[e]={callback:t,key:null,description:null}}removeKeyBinding(e){delete this.bindings[e]}triggerKey(e){this.onDocumentKeyDown({keyCode:e})}registerKeyboardShortcut(e,t){this.shortcuts[e]=t}getShortcuts(){return this.shortcuts}getBindings(){return this.bindings}onDocumentKeyDown(e){let t=this.Reveal.getConfig();if("function"==typeof t.keyboardCondition&&!1===t.keyboardCondition(e))return!0;if("focused"===t.keyboardCondition&&!this.Reveal.isFocused())return!0;let i=e.keyCode,s=!this.Reveal.isAutoSliding();this.Reveal.onUserInput(e);let a=document.activeElement&&!0===document.activeElement.isContentEditable,n=document.activeElement&&document.activeElement.tagName&&/input|textarea/i.test(document.activeElement.tagName),r=document.activeElement&&document.activeElement.className&&/speaker-notes/i.test(document.activeElement.className),l=!(-1!==[32,37,38,39,40,63,78,80,191].indexOf(e.keyCode)&&e.shiftKey||e.altKey)&&(e.shiftKey||e.altKey||e.ctrlKey||e.metaKey);if(a||n||r||l)return;let d,c=[66,86,190,191,112];if("object"==typeof t.keyboard)for(d in t.keyboard)"togglePause"===t.keyboard[d]&&c.push(parseInt(d,10));if(this.Reveal.isPaused()&&-1===c.indexOf(i))return!1;let h="linear"===t.navigationMode||!this.Reveal.hasHorizontalSlides()||!this.Reveal.hasVerticalSlides(),u=!1;if("object"==typeof t.keyboard)for(d in t.keyboard)if(parseInt(d,10)===i){let i=t.keyboard[d];"function"==typeof i?i.apply(null,[e]):"string"==typeof i&&"function"==typeof this.Reveal[i]&&this.Reveal[i].call(),u=!0}if(!1===u)for(d in this.bindings)if(parseInt(d,10)===i){let t=this.bindings[d].callback;"function"==typeof t?t.apply(null,[e]):"string"==typeof t&&"function"==typeof this.Reveal[t]&&this.Reveal[t].call(),u=!0}!1===u&&(u=!0,80===i||33===i?this.Reveal.prev({skipFragments:e.altKey}):78===i||34===i?this.Reveal.next({skipFragments:e.altKey}):72===i||37===i?e.shiftKey?this.Reveal.slide(0):!this.Reveal.overview.isActive()&&h?t.rtl?this.Reveal.next({skipFragments:e.altKey}):this.Reveal.prev({skipFragments:e.altKey}):this.Reveal.left({skipFragments:e.altKey}):76===i||39===i?e.shiftKey?this.Reveal.slide(this.Reveal.getHorizontalSlides().length-1):!this.Reveal.overview.isActive()&&h?t.rtl?this.Reveal.prev({skipFragments:e.altKey}):this.Reveal.next({skipFragments:e.altKey}):this.Reveal.right({skipFragments:e.altKey}):75===i||38===i?e.shiftKey?this.Reveal.slide(void 0,0):!this.Reveal.overview.isActive()&&h?this.Reveal.prev({skipFragments:e.altKey}):this.Reveal.up({skipFragments:e.altKey}):74===i||40===i?e.shiftKey?this.Reveal.slide(void 0,Number.MAX_VALUE):!this.Reveal.overview.isActive()&&h?this.Reveal.next({skipFragments:e.altKey}):this.Reveal.down({skipFragments:e.altKey}):36===i?this.Reveal.slide(0):35===i?this.Reveal.slide(this.Reveal.getHorizontalSlides().length-1):32===i?(this.Reveal.overview.isActive()&&this.Reveal.overview.deactivate(),e.shiftKey?this.Reveal.prev({skipFragments:e.altKey}):this.Reveal.next({skipFragments:e.altKey})):[58,59,66,86,190].includes(i)||191===i&&!e.shiftKey?this.Reveal.togglePause():70===i?o(t.embedded?this.Reveal.getViewportElement():document.documentElement):65===i?t.autoSlideStoppable&&this.Reveal.toggleAutoSlide(s):71===i?t.jumpToSlide&&this.Reveal.toggleJumpToSlide():63!==i&&191!==i||!e.shiftKey?112===i?this.Reveal.toggleHelp():u=!1:this.Reveal.toggleHelp()),u?e.preventDefault&&e.preventDefault():27!==i&&79!==i||(!1===this.Reveal.closeOverlay()&&this.Reveal.overview.toggle(),e.preventDefault&&e.preventDefault()),this.Reveal.cueAutoSlide()}}class M{MAX_REPLACE_STATE_FREQUENCY=1e3;constructor(e){this.Reveal=e,this.writeURLTimeout=0,this.replaceStateTimestamp=0,this.onWindowHashChange=this.onWindowHashChange.bind(this)}bind(){window.addEventListener("hashchange",this.onWindowHashChange,!1)}unbind(){window.removeEventListener("hashchange",this.onWindowHashChange,!1)}getIndicesFromHash(e=window.location.hash,t={}){let i=e.replace(/^#\/?/,""),s=i.split("/");if(/^[0-9]*$/.test(s[0])||!i.length){const e=this.Reveal.getConfig();let i,a=e.hashOneBasedIndex||t.oneBasedIndex?1:0,n=parseInt(s[0],10)-a||0,r=parseInt(s[1],10)-a||0;return e.fragmentInURL&&(i=parseInt(s[2],10),isNaN(i)&&(i=void 0)),{h:n,v:r,f:i}}{let e,t;/\/[-\d]+$/g.test(i)&&(t=parseInt(i.split("/").pop(),10),t=isNaN(t)?void 0:t,i=i.split("/").shift());try{e=document.getElementById(decodeURIComponent(i)).closest(".slides section")}catch(e){}if(e)return{...this.Reveal.getIndices(e),f:t}}return null}readURL(){const e=this.Reveal.getIndices(),t=this.getIndicesFromHash();t?t.h===e.h&&t.v===e.v&&void 0===t.f||this.Reveal.slide(t.h,t.v,t.f):this.Reveal.slide(e.h||0,e.v||0)}writeURL(e){let t=this.Reveal.getConfig(),i=this.Reveal.getCurrentSlide();if(clearTimeout(this.writeURLTimeout),"number"==typeof e)this.writeURLTimeout=setTimeout(this.writeURL,e);else if(i){let e=this.getHash();t.history?window.location.hash=e:t.hash&&("/"===e?this.debouncedReplaceState(window.location.pathname+window.location.search):this.debouncedReplaceState("#"+e))}}replaceState(e){window.history.replaceState(null,null,e),this.replaceStateTimestamp=Date.now()}debouncedReplaceState(e){clearTimeout(this.replaceStateTimeout),Date.now()-this.replaceStateTimestamp>this.MAX_REPLACE_STATE_FREQUENCY?this.replaceState(e):this.replaceStateTimeout=setTimeout((()=>this.replaceState(e)),this.MAX_REPLACE_STATE_FREQUENCY)}getHash(e){let t="/",i=e||this.Reveal.getCurrentSlide(),s=i?i.getAttribute("id"):null;s&&(s=encodeURIComponent(s));let a=this.Reveal.getIndices(e);if(this.Reveal.getConfig().fragmentInURL||(a.f=void 0),"string"==typeof s&&s.length)t="/"+s,a.f>=0&&(t+="/"+a.f);else{let e=this.Reveal.getConfig().hashOneBasedIndex?1:0;(a.h>0||a.v>0||a.f>=0)&&(t+=a.h+e),(a.v>0||a.f>=0)&&(t+="/"+(a.v+e)),a.f>=0&&(t+="/"+a.f)}return t}onWindowHashChange(e){this.readURL()}}class I{constructor(e){this.Reveal=e,this.onNavigateLeftClicked=this.onNavigateLeftClicked.bind(this),this.onNavigateRightClicked=this.onNavigateRightClicked.bind(this),this.onNavigateUpClicked=this.onNavigateUpClicked.bind(this),this.onNavigateDownClicked=this.onNavigateDownClicked.bind(this),this.onNavigatePrevClicked=this.onNavigatePrevClicked.bind(this),this.onNavigateNextClicked=this.onNavigateNextClicked.bind(this),this.onEnterFullscreen=this.onEnterFullscreen.bind(this)}render(){const e=this.Reveal.getConfig().rtl,i=this.Reveal.getRevealElement();this.element=document.createElement("aside"),this.element.className="controls",this.element.innerHTML=`\n\t\t\t\n\t\t\t\n\t\t\t`,this.Reveal.getRevealElement().appendChild(this.element),this.controlsLeft=t(i,".navigate-left"),this.controlsRight=t(i,".navigate-right"),this.controlsUp=t(i,".navigate-up"),this.controlsDown=t(i,".navigate-down"),this.controlsPrev=t(i,".navigate-prev"),this.controlsNext=t(i,".navigate-next"),this.controlsFullscreen=t(i,".enter-fullscreen"),this.controlsRightArrow=this.element.querySelector(".navigate-right"),this.controlsLeftArrow=this.element.querySelector(".navigate-left"),this.controlsDownArrow=this.element.querySelector(".navigate-down")}configure(e,t){this.element.style.display=e.controls?"block":"none",this.element.setAttribute("data-controls-layout",e.controlsLayout),this.element.setAttribute("data-controls-back-arrows",e.controlsBackArrows)}bind(){let e=["touchstart","click"];g&&(e=["touchstart"]),e.forEach((e=>{this.controlsLeft.forEach((t=>t.addEventListener(e,this.onNavigateLeftClicked,!1))),this.controlsRight.forEach((t=>t.addEventListener(e,this.onNavigateRightClicked,!1))),this.controlsUp.forEach((t=>t.addEventListener(e,this.onNavigateUpClicked,!1))),this.controlsDown.forEach((t=>t.addEventListener(e,this.onNavigateDownClicked,!1))),this.controlsPrev.forEach((t=>t.addEventListener(e,this.onNavigatePrevClicked,!1))),this.controlsNext.forEach((t=>t.addEventListener(e,this.onNavigateNextClicked,!1))),this.controlsFullscreen.forEach((t=>t.addEventListener(e,this.onEnterFullscreen,!1)))}))}unbind(){["touchstart","click"].forEach((e=>{this.controlsLeft.forEach((t=>t.removeEventListener(e,this.onNavigateLeftClicked,!1))),this.controlsRight.forEach((t=>t.removeEventListener(e,this.onNavigateRightClicked,!1))),this.controlsUp.forEach((t=>t.removeEventListener(e,this.onNavigateUpClicked,!1))),this.controlsDown.forEach((t=>t.removeEventListener(e,this.onNavigateDownClicked,!1))),this.controlsPrev.forEach((t=>t.removeEventListener(e,this.onNavigatePrevClicked,!1))),this.controlsNext.forEach((t=>t.removeEventListener(e,this.onNavigateNextClicked,!1))),this.controlsFullscreen.forEach((t=>t.removeEventListener(e,this.onEnterFullscreen,!1)))}))}update(){let e=this.Reveal.availableRoutes();[...this.controlsLeft,...this.controlsRight,...this.controlsUp,...this.controlsDown,...this.controlsPrev,...this.controlsNext].forEach((e=>{e.classList.remove("enabled","fragmented"),e.setAttribute("disabled","disabled")})),e.left&&this.controlsLeft.forEach((e=>{e.classList.add("enabled"),e.removeAttribute("disabled")})),e.right&&this.controlsRight.forEach((e=>{e.classList.add("enabled"),e.removeAttribute("disabled")})),e.up&&this.controlsUp.forEach((e=>{e.classList.add("enabled"),e.removeAttribute("disabled")})),e.down&&this.controlsDown.forEach((e=>{e.classList.add("enabled"),e.removeAttribute("disabled")})),(e.left||e.up)&&this.controlsPrev.forEach((e=>{e.classList.add("enabled"),e.removeAttribute("disabled")})),(e.right||e.down)&&this.controlsNext.forEach((e=>{e.classList.add("enabled"),e.removeAttribute("disabled")}));let t=this.Reveal.getCurrentSlide();if(t){let e=this.Reveal.fragments.availableRoutes();e.prev&&this.controlsPrev.forEach((e=>{e.classList.add("fragmented","enabled"),e.removeAttribute("disabled")})),e.next&&this.controlsNext.forEach((e=>{e.classList.add("fragmented","enabled"),e.removeAttribute("disabled")})),this.Reveal.isVerticalSlide(t)?(e.prev&&this.controlsUp.forEach((e=>{e.classList.add("fragmented","enabled"),e.removeAttribute("disabled")})),e.next&&this.controlsDown.forEach((e=>{e.classList.add("fragmented","enabled"),e.removeAttribute("disabled")}))):(e.prev&&this.controlsLeft.forEach((e=>{e.classList.add("fragmented","enabled"),e.removeAttribute("disabled")})),e.next&&this.controlsRight.forEach((e=>{e.classList.add("fragmented","enabled"),e.removeAttribute("disabled")})))}if(this.Reveal.getConfig().controlsTutorial){let t=this.Reveal.getIndices();!this.Reveal.hasNavigatedVertically()&&e.down?this.controlsDownArrow.classList.add("highlight"):(this.controlsDownArrow.classList.remove("highlight"),this.Reveal.getConfig().rtl?!this.Reveal.hasNavigatedHorizontally()&&e.left&&0===t.v?this.controlsLeftArrow.classList.add("highlight"):this.controlsLeftArrow.classList.remove("highlight"):!this.Reveal.hasNavigatedHorizontally()&&e.right&&0===t.v?this.controlsRightArrow.classList.add("highlight"):this.controlsRightArrow.classList.remove("highlight"))}}destroy(){this.unbind(),this.element.remove()}onNavigateLeftClicked(e){e.preventDefault(),this.Reveal.onUserInput(),"linear"===this.Reveal.getConfig().navigationMode?this.Reveal.prev():this.Reveal.left()}onNavigateRightClicked(e){e.preventDefault(),this.Reveal.onUserInput(),"linear"===this.Reveal.getConfig().navigationMode?this.Reveal.next():this.Reveal.right()}onNavigateUpClicked(e){e.preventDefault(),this.Reveal.onUserInput(),this.Reveal.up()}onNavigateDownClicked(e){e.preventDefault(),this.Reveal.onUserInput(),this.Reveal.down()}onNavigatePrevClicked(e){e.preventDefault(),this.Reveal.onUserInput(),this.Reveal.prev()}onNavigateNextClicked(e){e.preventDefault(),this.Reveal.onUserInput(),this.Reveal.next()}onEnterFullscreen(e){const t=this.Reveal.getConfig(),i=this.Reveal.getViewportElement();o(t.embedded?i:i.parentElement)}}class B{constructor(e){this.Reveal=e,this.onProgressClicked=this.onProgressClicked.bind(this)}render(){this.element=document.createElement("div"),this.element.className="progress",this.Reveal.getRevealElement().appendChild(this.element),this.bar=document.createElement("span"),this.element.appendChild(this.bar)}configure(e,t){this.element.style.display=e.progress?"block":"none"}bind(){this.Reveal.getConfig().progress&&this.element&&this.element.addEventListener("click",this.onProgressClicked,!1)}unbind(){this.Reveal.getConfig().progress&&this.element&&this.element.removeEventListener("click",this.onProgressClicked,!1)}update(){if(this.Reveal.getConfig().progress&&this.bar){let e=this.Reveal.getProgress();this.Reveal.getTotalSlides()<2&&(e=0),this.bar.style.transform="scaleX("+e+")"}}getMaxWidth(){return this.Reveal.getRevealElement().offsetWidth}onProgressClicked(e){this.Reveal.onUserInput(e),e.preventDefault();let t=this.Reveal.getSlides(),i=t.length,s=Math.floor(e.clientX/this.getMaxWidth()*i);this.Reveal.getConfig().rtl&&(s=i-s);let a=this.Reveal.getIndices(t[s]);this.Reveal.slide(a.h,a.v)}destroy(){this.element.remove()}}class H{constructor(e){this.Reveal=e,this.lastMouseWheelStep=0,this.cursorHidden=!1,this.cursorInactiveTimeout=0,this.onDocumentCursorActive=this.onDocumentCursorActive.bind(this),this.onDocumentMouseScroll=this.onDocumentMouseScroll.bind(this)}configure(e,t){e.mouseWheel?document.addEventListener("wheel",this.onDocumentMouseScroll,!1):document.removeEventListener("wheel",this.onDocumentMouseScroll,!1),e.hideInactiveCursor?(document.addEventListener("mousemove",this.onDocumentCursorActive,!1),document.addEventListener("mousedown",this.onDocumentCursorActive,!1)):(this.showCursor(),document.removeEventListener("mousemove",this.onDocumentCursorActive,!1),document.removeEventListener("mousedown",this.onDocumentCursorActive,!1))}showCursor(){this.cursorHidden&&(this.cursorHidden=!1,this.Reveal.getRevealElement().style.cursor="")}hideCursor(){!1===this.cursorHidden&&(this.cursorHidden=!0,this.Reveal.getRevealElement().style.cursor="none")}destroy(){this.showCursor(),document.removeEventListener("wheel",this.onDocumentMouseScroll,!1),document.removeEventListener("mousemove",this.onDocumentCursorActive,!1),document.removeEventListener("mousedown",this.onDocumentCursorActive,!1)}onDocumentCursorActive(e){this.showCursor(),clearTimeout(this.cursorInactiveTimeout),this.cursorInactiveTimeout=setTimeout(this.hideCursor.bind(this),this.Reveal.getConfig().hideCursorTime)}onDocumentMouseScroll(e){if(Date.now()-this.lastMouseWheelStep>1e3){this.lastMouseWheelStep=Date.now();let t=e.detail||-e.wheelDelta;t>0?this.Reveal.next():t<0&&this.Reveal.prev()}}}const D=(e,t)=>{const i=document.createElement("script");i.type="text/javascript",i.async=!1,i.defer=!1,i.src=e,"function"==typeof t&&(i.onload=i.onreadystatechange=e=>{("load"===e.type||/loaded|complete/.test(i.readyState))&&(i.onload=i.onreadystatechange=i.onerror=null,t())},i.onerror=e=>{i.onload=i.onreadystatechange=i.onerror=null,t(new Error("Failed loading script: "+i.src+"\n"+e))});const s=document.querySelector("head");s.insertBefore(i,s.lastChild)};class F{constructor(e){this.Reveal=e,this.state="idle",this.registeredPlugins={},this.asyncDependencies=[]}load(e,t){return this.state="loading",e.forEach(this.registerPlugin.bind(this)),new Promise((e=>{let i=[],s=0;if(t.forEach((e=>{e.condition&&!e.condition()||(e.async?this.asyncDependencies.push(e):i.push(e))})),i.length){s=i.length;const t=t=>{t&&"function"==typeof t.callback&&t.callback(),0==--s&&this.initPlugins().then(e)};i.forEach((e=>{"string"==typeof e.id?(this.registerPlugin(e),t(e)):"string"==typeof e.src?D(e.src,(()=>t(e))):(console.warn("Unrecognized plugin format",e),t())}))}else this.initPlugins().then(e)}))}initPlugins(){return new Promise((e=>{let t=Object.values(this.registeredPlugins),i=t.length;if(0===i)this.loadAsync().then(e);else{let s,a=()=>{0==--i?this.loadAsync().then(e):s()},n=0;s=()=>{let e=t[n++];if("function"==typeof e.init){let t=e.init(this.Reveal);t&&"function"==typeof t.then?t.then(a):a()}else a()},s()}}))}loadAsync(){return this.state="loaded",this.asyncDependencies.length&&this.asyncDependencies.forEach((e=>{D(e.src,e.callback)})),Promise.resolve()}registerPlugin(e){2===arguments.length&&"string"==typeof arguments[0]?(e=arguments[1]).id=arguments[0]:"function"==typeof e&&(e=e());let t=e.id;"string"!=typeof t?console.warn("Unrecognized plugin format; can't find plugin.id",e):void 0===this.registeredPlugins[t]?(this.registeredPlugins[t]=e,"loaded"===this.state&&"function"==typeof e.init&&e.init(this.Reveal)):console.warn('reveal.js: "'+t+'" plugin has already been registered')}hasPlugin(e){return!!this.registeredPlugins[e]}getPlugin(e){return this.registeredPlugins[e]}getRegisteredPlugins(){return this.registeredPlugins}destroy(){Object.values(this.registeredPlugins).forEach((e=>{"function"==typeof e.destroy&&e.destroy()})),this.registeredPlugins={},this.asyncDependencies=[]}}class z{constructor(e){this.Reveal=e,this.touchStartX=0,this.touchStartY=0,this.touchStartCount=0,this.touchCaptured=!1,this.onPointerDown=this.onPointerDown.bind(this),this.onPointerMove=this.onPointerMove.bind(this),this.onPointerUp=this.onPointerUp.bind(this),this.onTouchStart=this.onTouchStart.bind(this),this.onTouchMove=this.onTouchMove.bind(this),this.onTouchEnd=this.onTouchEnd.bind(this)}bind(){let e=this.Reveal.getRevealElement();"onpointerdown"in window?(e.addEventListener("pointerdown",this.onPointerDown,!1),e.addEventListener("pointermove",this.onPointerMove,!1),e.addEventListener("pointerup",this.onPointerUp,!1)):window.navigator.msPointerEnabled?(e.addEventListener("MSPointerDown",this.onPointerDown,!1),e.addEventListener("MSPointerMove",this.onPointerMove,!1),e.addEventListener("MSPointerUp",this.onPointerUp,!1)):(e.addEventListener("touchstart",this.onTouchStart,!1),e.addEventListener("touchmove",this.onTouchMove,!1),e.addEventListener("touchend",this.onTouchEnd,!1))}unbind(){let e=this.Reveal.getRevealElement();e.removeEventListener("pointerdown",this.onPointerDown,!1),e.removeEventListener("pointermove",this.onPointerMove,!1),e.removeEventListener("pointerup",this.onPointerUp,!1),e.removeEventListener("MSPointerDown",this.onPointerDown,!1),e.removeEventListener("MSPointerMove",this.onPointerMove,!1),e.removeEventListener("MSPointerUp",this.onPointerUp,!1),e.removeEventListener("touchstart",this.onTouchStart,!1),e.removeEventListener("touchmove",this.onTouchMove,!1),e.removeEventListener("touchend",this.onTouchEnd,!1)}isSwipePrevented(e){if(n(e,"video[controls], audio[controls]"))return!0;for(;e&&"function"==typeof e.hasAttribute;){if(e.hasAttribute("data-prevent-swipe"))return!0;e=e.parentNode}return!1}onTouchStart(e){if(this.touchCaptured=!1,this.isSwipePrevented(e.target))return!0;this.touchStartX=e.touches[0].clientX,this.touchStartY=e.touches[0].clientY,this.touchStartCount=e.touches.length}onTouchMove(e){if(this.isSwipePrevented(e.target))return!0;let t=this.Reveal.getConfig();if(this.touchCaptured)g&&e.preventDefault();else{this.Reveal.onUserInput(e);let i=e.touches[0].clientX,s=e.touches[0].clientY;if(1===e.touches.length&&2!==this.touchStartCount){let a=this.Reveal.availableRoutes({includeFragments:!0}),n=i-this.touchStartX,r=s-this.touchStartY;n>40&&Math.abs(n)>Math.abs(r)?(this.touchCaptured=!0,"linear"===t.navigationMode?t.rtl?this.Reveal.next():this.Reveal.prev():this.Reveal.left()):n<-40&&Math.abs(n)>Math.abs(r)?(this.touchCaptured=!0,"linear"===t.navigationMode?t.rtl?this.Reveal.prev():this.Reveal.next():this.Reveal.right()):r>40&&a.up?(this.touchCaptured=!0,"linear"===t.navigationMode?this.Reveal.prev():this.Reveal.up()):r<-40&&a.down&&(this.touchCaptured=!0,"linear"===t.navigationMode?this.Reveal.next():this.Reveal.down()),t.embedded?(this.touchCaptured||this.Reveal.isVerticalSlide())&&e.preventDefault():e.preventDefault()}}}onTouchEnd(e){this.touchCaptured=!1}onPointerDown(e){e.pointerType!==e.MSPOINTER_TYPE_TOUCH&&"touch"!==e.pointerType||(e.touches=[{clientX:e.clientX,clientY:e.clientY}],this.onTouchStart(e))}onPointerMove(e){e.pointerType!==e.MSPOINTER_TYPE_TOUCH&&"touch"!==e.pointerType||(e.touches=[{clientX:e.clientX,clientY:e.clientY}],this.onTouchMove(e))}onPointerUp(e){e.pointerType!==e.MSPOINTER_TYPE_TOUCH&&"touch"!==e.pointerType||(e.touches=[{clientX:e.clientX,clientY:e.clientY}],this.onTouchEnd(e))}}const q="focus",O="blur";class W{constructor(e){this.Reveal=e,this.onRevealPointerDown=this.onRevealPointerDown.bind(this),this.onDocumentPointerDown=this.onDocumentPointerDown.bind(this)}configure(e,t){e.embedded?this.blur():(this.focus(),this.unbind())}bind(){this.Reveal.getConfig().embedded&&this.Reveal.getRevealElement().addEventListener("pointerdown",this.onRevealPointerDown,!1)}unbind(){this.Reveal.getRevealElement().removeEventListener("pointerdown",this.onRevealPointerDown,!1),document.removeEventListener("pointerdown",this.onDocumentPointerDown,!1)}focus(){this.state!==q&&(this.Reveal.getRevealElement().classList.add("focused"),document.addEventListener("pointerdown",this.onDocumentPointerDown,!1)),this.state=q}blur(){this.state!==O&&(this.Reveal.getRevealElement().classList.remove("focused"),document.removeEventListener("pointerdown",this.onDocumentPointerDown,!1)),this.state=O}isFocused(){return this.state===q}destroy(){this.Reveal.getRevealElement().classList.remove("focused")}onRevealPointerDown(e){this.focus()}onDocumentPointerDown(e){let t=r(e.target,".reveal");t&&t===this.Reveal.getRevealElement()||this.blur()}}class U{constructor(e){this.Reveal=e}render(){this.element=document.createElement("div"),this.element.className="speaker-notes",this.element.setAttribute("data-prevent-swipe",""),this.element.setAttribute("tabindex","0"),this.Reveal.getRevealElement().appendChild(this.element)}configure(e,t){e.showNotes&&this.element.setAttribute("data-layout","string"==typeof e.showNotes?e.showNotes:"inline")}update(){this.Reveal.getConfig().showNotes&&this.element&&this.Reveal.getCurrentSlide()&&!this.Reveal.isScrollView()&&!this.Reveal.isPrintView()&&(this.element.innerHTML=this.getSlideNotes()||'No notes on this slide.')}updateVisibility(){this.Reveal.getConfig().showNotes&&this.hasNotes()&&!this.Reveal.isScrollView()&&!this.Reveal.isPrintView()?this.Reveal.getRevealElement().classList.add("show-notes"):this.Reveal.getRevealElement().classList.remove("show-notes")}hasNotes(){return this.Reveal.getSlidesElement().querySelectorAll("[data-notes], aside.notes").length>0}isSpeakerNotesWindow(){return!!window.location.search.match(/receiver/gi)}getSlideNotes(e=this.Reveal.getCurrentSlide()){if(e.hasAttribute("data-notes"))return e.getAttribute("data-notes");let t=e.querySelectorAll("aside.notes");return t?Array.from(t).map((e=>e.innerHTML)).join("\n"):null}destroy(){this.element.remove()}}class V{constructor(e,t){this.diameter=100,this.diameter2=this.diameter/2,this.thickness=6,this.playing=!1,this.progress=0,this.progressOffset=1,this.container=e,this.progressCheck=t,this.canvas=document.createElement("canvas"),this.canvas.className="playback",this.canvas.width=this.diameter,this.canvas.height=this.diameter,this.canvas.style.width=this.diameter2+"px",this.canvas.style.height=this.diameter2+"px",this.context=this.canvas.getContext("2d"),this.container.appendChild(this.canvas),this.render()}setPlaying(e){const t=this.playing;this.playing=e,!t&&this.playing?this.animate():this.render()}animate(){const e=this.progress;this.progress=this.progressCheck(),e>.8&&this.progress<.2&&(this.progressOffset=this.progress),this.render(),this.playing&&requestAnimationFrame(this.animate.bind(this))}render(){let e=this.playing?this.progress:0,t=this.diameter2-this.thickness,i=this.diameter2,s=this.diameter2,a=28;this.progressOffset+=.1*(1-this.progressOffset);const n=-Math.PI/2+e*(2*Math.PI),r=-Math.PI/2+this.progressOffset*(2*Math.PI);this.context.save(),this.context.clearRect(0,0,this.diameter,this.diameter),this.context.beginPath(),this.context.arc(i,s,t+4,0,2*Math.PI,!1),this.context.fillStyle="rgba( 0, 0, 0, 0.4 )",this.context.fill(),this.context.beginPath(),this.context.arc(i,s,t,0,2*Math.PI,!1),this.context.lineWidth=this.thickness,this.context.strokeStyle="rgba( 255, 255, 255, 0.2 )",this.context.stroke(),this.playing&&(this.context.beginPath(),this.context.arc(i,s,t,r,n,!1),this.context.lineWidth=this.thickness,this.context.strokeStyle="#fff",this.context.stroke()),this.context.translate(i-14,s-14),this.playing?(this.context.fillStyle="#fff",this.context.fillRect(0,0,10,a),this.context.fillRect(18,0,10,a)):(this.context.beginPath(),this.context.translate(4,0),this.context.moveTo(0,0),this.context.lineTo(24,14),this.context.lineTo(0,a),this.context.fillStyle="#fff",this.context.fill()),this.context.restore()}on(e,t){this.canvas.addEventListener(e,t,!1)}off(e,t){this.canvas.removeEventListener(e,t,!1)}destroy(){this.playing=!1,this.canvas.parentNode&&this.container.removeChild(this.canvas)}}var j={width:960,height:700,margin:.04,minScale:.2,maxScale:2,controls:!0,controlsTutorial:!0,controlsLayout:"bottom-right",controlsBackArrows:"faded",progress:!0,slideNumber:!1,showSlideNumber:"all",hashOneBasedIndex:!1,hash:!1,respondToHashChanges:!0,jumpToSlide:!0,history:!1,keyboard:!0,keyboardCondition:null,disableLayout:!1,overview:!0,center:!0,touch:!0,loop:!1,rtl:!1,navigationMode:"default",shuffle:!1,fragments:!0,fragmentInURL:!0,embedded:!1,help:!0,pause:!0,showNotes:!1,showHiddenSlides:!1,autoPlayMedia:null,preloadIframes:null,autoAnimate:!0,autoAnimateMatcher:null,autoAnimateEasing:"ease",autoAnimateDuration:1,autoAnimateUnmatched:!0,autoAnimateStyles:["opacity","color","background-color","padding","font-size","line-height","letter-spacing","border-width","border-color","border-radius","outline","outline-offset"],autoSlide:0,autoSlideStoppable:!0,autoSlideMethod:null,defaultTiming:null,mouseWheel:!1,previewLinks:!1,postMessage:!0,postMessageEvents:!1,focusBodyOnPageVisibilityChange:!0,transition:"slide",transitionSpeed:"default",backgroundTransition:"fade",parallaxBackgroundImage:"",parallaxBackgroundSize:"",parallaxBackgroundRepeat:"",parallaxBackgroundPosition:"",parallaxBackgroundHorizontal:null,parallaxBackgroundVertical:null,view:null,scrollLayout:"full",scrollSnap:"mandatory",scrollProgress:"auto",scrollActivationWidth:435,pdfMaxPagesPerSlide:Number.POSITIVE_INFINITY,pdfSeparateFragments:!0,pdfPageHeightOffset:-1,viewDistance:3,mobileViewDistance:2,display:"block",hideInactiveCursor:!0,hideCursorTime:5e3,sortFragmentsOnSync:!0,dependencies:[],plugins:[]};const K="5.1.0";function $(n,o){arguments.length<2&&(o=arguments[0],n=document.querySelector(".reveal"));const l={};let c,h,g,p,w,A={},k=!1,D=!1,q={hasNavigatedHorizontally:!1,hasNavigatedVertically:!1},O=[],$=1,X={layout:"",overview:""},Y={},_="idle",J=0,G=0,Q=-1,Z=!1,ee=new v(l),te=new E(l),ie=new S(l),se=new L(l),ae=new R(l),ne=new C(l),re=new x(l),oe=new P(l),le=new T(l),de=new N(l),ce=new M(l),he=new I(l),ue=new B(l),ge=new H(l),pe=new F(l),ve=new W(l),me=new z(l),fe=new U(l);function ye(){D=!0,A.showHiddenSlides||t(Y.wrapper,'section[data-visibility="hidden"]').forEach((e=>{const t=e.parentNode;1===t.childElementCount&&/section/i.test(t.nodeName)?t.remove():e.remove()})),function(){Y.slides.classList.add("no-transition"),u?Y.wrapper.classList.add("no-hover"):Y.wrapper.classList.remove("no-hover");ae.render(),te.render(),ie.render(),he.render(),ue.render(),fe.render(),Y.pauseOverlay=((e,t,i,s="")=>{let a=e.querySelectorAll("."+i);for(let t=0;tResume presentation':null),Y.statusElement=function(){let e=Y.wrapper.querySelector(".aria-status");e||(e=document.createElement("div"),e.style.position="absolute",e.style.height="1px",e.style.width="1px",e.style.overflow="hidden",e.style.clip="rect( 1px, 1px, 1px, 1px )",e.classList.add("aria-status"),e.setAttribute("aria-live","polite"),e.setAttribute("aria-atomic","true"),Y.wrapper.appendChild(e));return e}(),Y.wrapper.setAttribute("role","application")}(),A.postMessage&&window.addEventListener("message",At,!1),setInterval((()=>{(!ne.isActive()&&0!==Y.wrapper.scrollTop||0!==Y.wrapper.scrollLeft)&&(Y.wrapper.scrollTop=0,Y.wrapper.scrollLeft=0)}),1e3),document.addEventListener("fullscreenchange",xt),document.addEventListener("webkitfullscreenchange",xt),rt().forEach((e=>{t(e,"section").forEach(((e,t)=>{t>0&&(e.classList.remove("present"),e.classList.remove("past"),e.classList.add("future"),e.setAttribute("aria-hidden","true"))}))})),Ee(),ae.update(!0),function(){const e="print"===A.view,t="scroll"===A.view||"reader"===A.view;(e||t)&&(e?Ae():me.unbind(),Y.viewport.classList.add("loading-scroll-mode"),e?"complete"===document.readyState?re.activate():window.addEventListener("load",(()=>re.activate())):ne.activate())}(),ce.readURL(),setTimeout((()=>{Y.slides.classList.remove("no-transition"),Y.wrapper.classList.add("ready"),Ce({type:"ready",data:{indexh:c,indexv:h,currentSlide:p}})}),1)}function be(e){Y.statusElement.textContent=e}function we(e){let t="";if(3===e.nodeType)t+=e.textContent;else if(1===e.nodeType){let i=e.getAttribute("aria-hidden"),s="none"===window.getComputedStyle(e).display;"true"===i||s||Array.from(e.childNodes).forEach((e=>{t+=we(e)}))}return t=t.trim(),""===t?"":t+" "}function Ee(t){const s={...A};if("object"==typeof t&&e(A,t),!1===l.isReady())return;const a=Y.wrapper.querySelectorAll(m).length;Y.wrapper.classList.remove(s.transition),Y.wrapper.classList.add(A.transition),Y.wrapper.setAttribute("data-transition-speed",A.transitionSpeed),Y.wrapper.setAttribute("data-background-transition",A.backgroundTransition),Y.viewport.style.setProperty("--slide-width","string"==typeof A.width?A.width:A.width+"px"),Y.viewport.style.setProperty("--slide-height","string"==typeof A.height?A.height:A.height+"px"),A.shuffle&&Ge(),i(Y.wrapper,"embedded",A.embedded),i(Y.wrapper,"rtl",A.rtl),i(Y.wrapper,"center",A.center),!1===A.pause&&Ke(),A.previewLinks?(Te(),Ne("[data-preview-link=false]")):(Ne(),Te("[data-preview-link]:not([data-preview-link=false])")),se.reset(),w&&(w.destroy(),w=null),a>1&&A.autoSlide&&A.autoSlideStoppable&&(w=new V(Y.wrapper,(()=>Math.min(Math.max((Date.now()-Q)/J,0),1))),w.on("click",Tt),Z=!1),"default"!==A.navigationMode?Y.wrapper.setAttribute("data-navigation-mode",A.navigationMode):Y.wrapper.removeAttribute("data-navigation-mode"),fe.configure(A,s),ve.configure(A,s),ge.configure(A,s),he.configure(A,s),ue.configure(A,s),de.configure(A,s),oe.configure(A,s),te.configure(A,s),Je()}function Se(){window.addEventListener("resize",Lt,!1),A.touch&&me.bind(),A.keyboard&&de.bind(),A.progress&&ue.bind(),A.respondToHashChanges&&ce.bind(),he.bind(),ve.bind(),Y.slides.addEventListener("click",kt,!1),Y.slides.addEventListener("transitionend",Rt,!1),Y.pauseOverlay.addEventListener("click",Ke,!1),A.focusBodyOnPageVisibilityChange&&document.addEventListener("visibilitychange",Ct,!1)}function Ae(){me.unbind(),ve.unbind(),de.unbind(),he.unbind(),ue.unbind(),ce.unbind(),window.removeEventListener("resize",Lt,!1),Y.slides.removeEventListener("click",kt,!1),Y.slides.removeEventListener("transitionend",Rt,!1),Y.pauseOverlay.removeEventListener("click",Ke,!1)}function Re(e,t,i){n.addEventListener(e,t,i)}function ke(e,t,i){n.removeEventListener(e,t,i)}function Le(e){"string"==typeof e.layout&&(X.layout=e.layout),"string"==typeof e.overview&&(X.overview=e.overview),X.layout?a(Y.slides,X.layout+" "+X.overview):a(Y.slides,X.overview)}function Ce({target:t=Y.wrapper,type:i,data:s,bubbles:a=!0}){let n=document.createEvent("HTMLEvents",1,2);return n.initEvent(i,a,!0),e(n,s),t.dispatchEvent(n),t===Y.wrapper&&Pe(i),n}function xe(e){Ce({type:"slidechanged",data:{indexh:c,indexv:h,previousSlide:g,currentSlide:p,origin:e}})}function Pe(t,i){if(A.postMessageEvents&&window.parent!==window.self){let s={namespace:"reveal",eventName:t,state:ut()};e(s,i),window.parent.postMessage(JSON.stringify(s),"*")}}function Te(e="a"){Array.from(Y.wrapper.querySelectorAll(e)).forEach((e=>{/^(http|www)/gi.test(e.getAttribute("href"))&&e.addEventListener("click",Pt,!1)}))}function Ne(e="a"){Array.from(Y.wrapper.querySelectorAll(e)).forEach((e=>{/^(http|www)/gi.test(e.getAttribute("href"))&&e.removeEventListener("click",Pt,!1)}))}function Me(e){Be(),Y.overlay=document.createElement("div"),Y.overlay.classList.add("overlay"),Y.overlay.classList.add("overlay-preview"),Y.wrapper.appendChild(Y.overlay),Y.overlay.innerHTML=`
\n\t\t\t\t\n\t\t\t\t\n\t\t\t
\n\t\t\t
\n\t\t\t
\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\tUnable to load iframe. This is likely due to the site's policy (x-frame-options).\n\t\t\t\t\n\t\t\t
`,Y.overlay.querySelector("iframe").addEventListener("load",(e=>{Y.overlay.classList.add("loaded")}),!1),Y.overlay.querySelector(".close").addEventListener("click",(e=>{Be(),e.preventDefault()}),!1),Y.overlay.querySelector(".external").addEventListener("click",(e=>{Be()}),!1)}function Ie(){if(A.help){Be(),Y.overlay=document.createElement("div"),Y.overlay.classList.add("overlay"),Y.overlay.classList.add("overlay-help"),Y.wrapper.appendChild(Y.overlay);let e='

Keyboard Shortcuts


',t=de.getShortcuts(),i=de.getBindings();e+="";for(let i in t)e+=``;for(let t in i)i[t].key&&i[t].description&&(e+=``);e+="
KEYACTION
${i}${t[i]}
${i[t].key}${i[t].description}
",Y.overlay.innerHTML=`\n\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t
${e}
\n\t\t\t\t
\n\t\t\t`,Y.overlay.querySelector(".close").addEventListener("click",(e=>{Be(),e.preventDefault()}),!1)}}function Be(){return!!Y.overlay&&(Y.overlay.parentNode.removeChild(Y.overlay),Y.overlay=null,!0)}function He(){if(Y.wrapper&&!re.isActive()){const e=Y.viewport.offsetWidth,t=Y.viewport.offsetHeight;if(!A.disableLayout){u&&!A.embedded&&document.documentElement.style.setProperty("--vh",.01*window.innerHeight+"px");const i=ne.isActive()?Fe(e,t):Fe(),s=$;De(A.width,A.height),Y.slides.style.width=i.width+"px",Y.slides.style.height=i.height+"px",$=Math.min(i.presentationWidth/i.width,i.presentationHeight/i.height),$=Math.max($,A.minScale),$=Math.min($,A.maxScale),1===$||ne.isActive()?(Y.slides.style.zoom="",Y.slides.style.left="",Y.slides.style.top="",Y.slides.style.bottom="",Y.slides.style.right="",Le({layout:""})):(Y.slides.style.zoom="",Y.slides.style.left="50%",Y.slides.style.top="50%",Y.slides.style.bottom="auto",Y.slides.style.right="auto",Le({layout:"translate(-50%, -50%) scale("+$+")"}));const a=Array.from(Y.wrapper.querySelectorAll(m));for(let e=0,t=a.length;e0&&e.presentationWidth<=A.scrollActivationWidth?ne.isActive()||(ae.create(),ne.activate()):ne.isActive()&&ne.deactivate()}}(),Y.viewport.style.setProperty("--slide-scale",$),Y.viewport.style.setProperty("--viewport-width",e+"px"),Y.viewport.style.setProperty("--viewport-height",t+"px"),ne.layout(),ue.update(),ae.updateParallax(),le.isActive()&&le.update()}}function De(e,i){t(Y.slides,"section > .stretch, section > .r-stretch").forEach((t=>{let s=((e,t=0)=>{if(e){let i,s=e.style.height;return e.style.height="0px",e.parentNode.style.height="auto",i=t-e.parentNode.offsetHeight,e.style.height=s+"px",e.parentNode.style.removeProperty("height"),i}return t})(t,i);if(/(img|video)/gi.test(t.nodeName)){const i=t.naturalWidth||t.videoWidth,a=t.naturalHeight||t.videoHeight,n=Math.min(e/i,s/a);t.style.width=i*n+"px",t.style.height=a*n+"px"}else t.style.width=e+"px",t.style.height=s+"px"}))}function Fe(e,t){let i=A.width,s=A.height;A.disableLayout&&(i=Y.slides.offsetWidth,s=Y.slides.offsetHeight);const a={width:i,height:s,presentationWidth:e||Y.wrapper.offsetWidth,presentationHeight:t||Y.wrapper.offsetHeight};return a.presentationWidth-=a.presentationWidth*A.margin,a.presentationHeight-=a.presentationHeight*A.margin,"string"==typeof a.width&&/%$/.test(a.width)&&(a.width=parseInt(a.width,10)/100*a.presentationWidth),"string"==typeof a.height&&/%$/.test(a.height)&&(a.height=parseInt(a.height,10)/100*a.presentationHeight),a}function ze(e,t){"object"==typeof e&&"function"==typeof e.setAttribute&&e.setAttribute("data-previous-indexv",t||0)}function qe(e){if("object"==typeof e&&"function"==typeof e.setAttribute&&e.classList.contains("stack")){const t=e.hasAttribute("data-start-indexv")?"data-start-indexv":"data-previous-indexv";return parseInt(e.getAttribute(t)||0,10)}return 0}function Oe(e=p){return e&&e.parentNode&&!!e.parentNode.nodeName.match(/section/i)}function We(){return!(!p||!Oe(p))&&!p.nextElementSibling}function Ue(){return 0===c&&0===h}function Ve(){return!!p&&(!p.nextElementSibling&&(!Oe(p)||!p.parentNode.nextElementSibling))}function je(){if(A.pause){const e=Y.wrapper.classList.contains("paused");pt(),Y.wrapper.classList.add("paused"),!1===e&&Ce({type:"paused"})}}function Ke(){const e=Y.wrapper.classList.contains("paused");Y.wrapper.classList.remove("paused"),gt(),e&&Ce({type:"resumed"})}function $e(e){"boolean"==typeof e?e?je():Ke():Xe()?Ke():je()}function Xe(){return Y.wrapper.classList.contains("paused")}function Ye(e,i,s,a){if(Ce({type:"beforeslidechange",data:{indexh:void 0===e?c:e,indexv:void 0===i?h:i,origin:a}}).defaultPrevented)return;g=p;const r=Y.wrapper.querySelectorAll(f);if(ne.isActive()){const t=ne.getSlideByIndices(e,i);return void(t&&ne.scrollToSlide(t))}if(0===r.length)return;void 0!==i||le.isActive()||(i=qe(r[e])),g&&g.parentNode&&g.parentNode.classList.contains("stack")&&ze(g.parentNode,h);const o=O.concat();O.length=0;let l=c||0,d=h||0;c=Qe(f,void 0===e?c:e),h=Qe(y,void 0===i?h:i);let u=c!==l||h!==d;u||(g=null);let v=r[c],m=v.querySelectorAll("section");n.classList.toggle("is-vertical-slide",m.length>1),p=m[h]||v;let b=!1;u&&g&&p&&!le.isActive()&&(_="running",b=_e(g,p,l,d),b&&Y.slides.classList.add("disable-slide-transitions")),tt(),He(),le.isActive()&&le.update(),void 0!==s&&oe.goto(s),g&&g!==p&&(g.classList.remove("present"),g.setAttribute("aria-hidden","true"),Ue()&&setTimeout((()=>{t(Y.wrapper,f+".stack").forEach((e=>{ze(e,0)}))}),0));e:for(let e=0,t=O.length;e{be(we(p))})),ue.update(),he.update(),fe.update(),ae.update(),ae.updateParallax(),te.update(),oe.update(),ce.writeURL(),gt(),b&&(setTimeout((()=>{Y.slides.classList.remove("disable-slide-transitions")}),0),A.autoAnimate&&se.run(g,p))}function _e(e,t,i,s){return e.hasAttribute("data-auto-animate")&&t.hasAttribute("data-auto-animate")&&e.getAttribute("data-auto-animate-id")===t.getAttribute("data-auto-animate-id")&&!(c>i||h>s?t:e).hasAttribute("data-auto-animate-restart")}function Je(){Ae(),Se(),He(),J=A.autoSlide,gt(),ae.create(),ce.writeURL(),!0===A.sortFragmentsOnSync&&oe.sortAll(),he.update(),ue.update(),tt(),fe.update(),fe.updateVisibility(),ae.update(!0),te.update(),ee.formatEmbeddedContent(),!1===A.autoPlayMedia?ee.stopEmbeddedContent(p,{unloadIframes:!1}):ee.startEmbeddedContent(p),le.isActive()&&le.layout()}function Ge(e=rt()){e.forEach(((t,i)=>{let s=e[Math.floor(Math.random()*e.length)];s.parentNode===t.parentNode&&t.parentNode.insertBefore(t,s);let a=t.querySelectorAll("section");a.length&&Ge(a)}))}function Qe(e,i){let s=t(Y.wrapper,e),a=s.length,n=ne.isActive()||re.isActive(),r=!1,o=!1;if(a){A.loop&&(i>=a&&(r=!0),(i%=a)<0&&(i=a+i,o=!0)),i=Math.max(Math.min(i,a-1),0);for(let e=0;ei?(t.classList.add(a?"past":"future"),A.fragments&&et(t)):e===i&&A.fragments&&(r?et(t):o&&Ze(t))}let e=s[i],t=e.classList.contains("present");e.classList.add("present"),e.removeAttribute("hidden"),e.removeAttribute("aria-hidden"),t||Ce({target:e,type:"visible",bubbles:!1});let l=e.getAttribute("data-state");l&&(O=O.concat(l.split(" ")))}else i=0;return i}function Ze(e){t(e,".fragment").forEach((e=>{e.classList.add("visible"),e.classList.remove("current-fragment")}))}function et(e){t(e,".fragment.visible").forEach((e=>{e.classList.remove("visible","current-fragment")}))}function tt(){let e,i,s=rt(),a=s.length;if(a&&void 0!==c){let n=le.isActive()?10:A.viewDistance;u&&(n=le.isActive()?6:A.mobileViewDistance),re.isActive()&&(n=Number.MAX_VALUE);for(let r=0;r0,right:c0,down:h1&&(s.left=!0,s.right=!0),i.length>1&&(s.up=!0,s.down=!0)),t.length>1&&"linear"===A.navigationMode&&(s.right=s.right||s.down,s.left=s.left||s.up),!0===e){let e=oe.availableRoutes();s.left=s.left||e.prev,s.up=s.up||e.prev,s.down=s.down||e.next,s.right=s.right||e.next}if(A.rtl){let e=s.left;s.left=s.right,s.right=e}return s}function st(e=p){let t=rt(),i=0;e:for(let s=0;s0){let e=p.querySelector(".current-fragment");i=e&&e.hasAttribute("data-fragment-index")?parseInt(e.getAttribute("data-fragment-index"),10):p.querySelectorAll(".fragment.visible").length-1}}return{h:s,v:a,f:i}}function nt(){return t(Y.wrapper,m+':not(.stack):not([data-visibility="uncounted"])')}function rt(){return t(Y.wrapper,f)}function ot(){return t(Y.wrapper,".slides>section>section")}function lt(){return rt().length>1}function dt(){return ot().length>1}function ct(){return nt().length}function ht(e,t){let i=rt()[e],s=i&&i.querySelectorAll("section");return s&&s.length&&"number"==typeof t?s?s[t]:void 0:i}function ut(){let e=at();return{indexh:e.h,indexv:e.v,indexf:e.f,paused:Xe(),overview:le.isActive()}}function gt(){if(pt(),p&&!1!==A.autoSlide){let e=p.querySelector(".current-fragment[data-autoslide]"),i=e?e.getAttribute("data-autoslide"):null,s=p.parentNode?p.parentNode.getAttribute("data-autoslide"):null,a=p.getAttribute("data-autoslide");i?J=parseInt(i,10):a?J=parseInt(a,10):s?J=parseInt(s,10):(J=A.autoSlide,0===p.querySelectorAll(".fragment").length&&t(p,"video, audio").forEach((e=>{e.hasAttribute("data-autoplay")&&J&&1e3*e.duration/e.playbackRate>J&&(J=1e3*e.duration/e.playbackRate+1e3)}))),!J||Z||Xe()||le.isActive()||Ve()&&!oe.availableRoutes().next&&!0!==A.loop||(G=setTimeout((()=>{"function"==typeof A.autoSlideMethod?A.autoSlideMethod():St(),gt()}),J),Q=Date.now()),w&&w.setPlaying(-1!==G)}}function pt(){clearTimeout(G),G=-1}function vt(){J&&!Z&&(Z=!0,Ce({type:"autoslidepaused"}),clearTimeout(G),w&&w.setPlaying(!1))}function mt(){J&&Z&&(Z=!1,Ce({type:"autoslideresumed"}),gt())}function ft({skipFragments:e=!1}={}){if(q.hasNavigatedHorizontally=!0,ne.isActive())return ne.prev();A.rtl?(le.isActive()||e||!1===oe.next())&&it().left&&Ye(c+1,"grid"===A.navigationMode?h:void 0):(le.isActive()||e||!1===oe.prev())&&it().left&&Ye(c-1,"grid"===A.navigationMode?h:void 0)}function yt({skipFragments:e=!1}={}){if(q.hasNavigatedHorizontally=!0,ne.isActive())return ne.next();A.rtl?(le.isActive()||e||!1===oe.prev())&&it().right&&Ye(c-1,"grid"===A.navigationMode?h:void 0):(le.isActive()||e||!1===oe.next())&&it().right&&Ye(c+1,"grid"===A.navigationMode?h:void 0)}function bt({skipFragments:e=!1}={}){if(ne.isActive())return ne.prev();(le.isActive()||e||!1===oe.prev())&&it().up&&Ye(c,h-1)}function wt({skipFragments:e=!1}={}){if(q.hasNavigatedVertically=!0,ne.isActive())return ne.next();(le.isActive()||e||!1===oe.next())&&it().down&&Ye(c,h+1)}function Et({skipFragments:e=!1}={}){if(ne.isActive())return ne.prev();if(e||!1===oe.prev())if(it().up)bt({skipFragments:e});else{let i;if(i=A.rtl?t(Y.wrapper,f+".future").pop():t(Y.wrapper,f+".past").pop(),i&&i.classList.contains("stack")){let e=i.querySelectorAll("section").length-1||void 0;Ye(c-1,e)}else A.rtl?yt({skipFragments:e}):ft({skipFragments:e})}}function St({skipFragments:e=!1}={}){if(q.hasNavigatedHorizontally=!0,q.hasNavigatedVertically=!0,ne.isActive())return ne.next();if(e||!1===oe.next()){let t=it();t.down&&t.right&&A.loop&&We()&&(t.down=!1),t.down?wt({skipFragments:e}):A.rtl?ft({skipFragments:e}):yt({skipFragments:e})}}function At(e){let t=e.data;if("string"==typeof t&&"{"===t.charAt(0)&&"}"===t.charAt(t.length-1)&&(t=JSON.parse(t),t.method&&"function"==typeof l[t.method]))if(!1===b.test(t.method)){const e=l[t.method].apply(l,t.args);Pe("callback",{method:t.method,result:e})}else console.warn('reveal.js: "'+t.method+'" is is blacklisted from the postMessage API')}function Rt(e){"running"===_&&/section/gi.test(e.target.nodeName)&&(_="idle",Ce({type:"slidetransitionend",data:{indexh:c,indexv:h,previousSlide:g,currentSlide:p}}))}function kt(e){const t=r(e.target,'a[href^="#"]');if(t){const i=t.getAttribute("href"),s=ce.getIndicesFromHash(i);s&&(l.slide(s.h,s.v,s.f),e.preventDefault())}}function Lt(e){He()}function Ct(e){!1===document.hidden&&document.activeElement!==document.body&&("function"==typeof document.activeElement.blur&&document.activeElement.blur(),document.body.focus())}function xt(e){(document.fullscreenElement||document.webkitFullscreenElement)===Y.wrapper&&(e.stopImmediatePropagation(),setTimeout((()=>{l.layout(),l.focus.focus()}),1))}function Pt(e){if(e.currentTarget&&e.currentTarget.hasAttribute("href")){let t=e.currentTarget.getAttribute("href");t&&(Me(t),e.preventDefault())}}function Tt(e){Ve()&&!1===A.loop?(Ye(0,0),mt()):Z?mt():vt()}const Nt={VERSION:K,initialize:function(e){if(!n)throw'Unable to find presentation root (
).';if(k=!0,Y.wrapper=n,Y.slides=n.querySelector(".slides"),!Y.slides)throw'Unable to find slides container (
).';return A={...j,...A,...o,...e,...d()},/print-pdf/gi.test(window.location.search)&&(A.view="print"),function(){!0===A.embedded?Y.viewport=r(n,".reveal-viewport")||n:(Y.viewport=document.body,document.documentElement.classList.add("reveal-full-page"));Y.viewport.classList.add("reveal-viewport")}(),window.addEventListener("load",He,!1),pe.load(A.plugins,A.dependencies).then(ye),new Promise((e=>l.on("ready",e)))},configure:Ee,destroy:function(){!1!==k&&(Ae(),pt(),Ne(),fe.destroy(),ve.destroy(),pe.destroy(),ge.destroy(),he.destroy(),ue.destroy(),ae.destroy(),te.destroy(),ie.destroy(),document.removeEventListener("fullscreenchange",xt),document.removeEventListener("webkitfullscreenchange",xt),document.removeEventListener("visibilitychange",Ct,!1),window.removeEventListener("message",At,!1),window.removeEventListener("load",He,!1),Y.pauseOverlay&&Y.pauseOverlay.remove(),Y.statusElement&&Y.statusElement.remove(),document.documentElement.classList.remove("reveal-full-page"),Y.wrapper.classList.remove("ready","center","has-horizontal-slides","has-vertical-slides"),Y.wrapper.removeAttribute("data-transition-speed"),Y.wrapper.removeAttribute("data-background-transition"),Y.viewport.classList.remove("reveal-viewport"),Y.viewport.style.removeProperty("--slide-width"),Y.viewport.style.removeProperty("--slide-height"),Y.slides.style.removeProperty("width"),Y.slides.style.removeProperty("height"),Y.slides.style.removeProperty("zoom"),Y.slides.style.removeProperty("left"),Y.slides.style.removeProperty("top"),Y.slides.style.removeProperty("bottom"),Y.slides.style.removeProperty("right"),Y.slides.style.removeProperty("transform"),Array.from(Y.wrapper.querySelectorAll(m)).forEach((e=>{e.style.removeProperty("display"),e.style.removeProperty("top"),e.removeAttribute("hidden"),e.removeAttribute("aria-hidden")})))},sync:Je,syncSlide:function(e=p){ae.sync(e),oe.sync(e),ee.load(e),ae.update(),fe.update()},syncFragments:oe.sync.bind(oe),slide:Ye,left:ft,right:yt,up:bt,down:wt,prev:Et,next:St,navigateLeft:ft,navigateRight:yt,navigateUp:bt,navigateDown:wt,navigatePrev:Et,navigateNext:St,navigateFragment:oe.goto.bind(oe),prevFragment:oe.prev.bind(oe),nextFragment:oe.next.bind(oe),on:Re,off:ke,addEventListener:Re,removeEventListener:ke,layout:He,shuffle:Ge,availableRoutes:it,availableFragments:oe.availableRoutes.bind(oe),toggleHelp:function(e){"boolean"==typeof e?e?Ie():Be():Y.overlay?Be():Ie()},toggleOverview:le.toggle.bind(le),toggleScrollView:ne.toggle.bind(ne),togglePause:$e,toggleAutoSlide:function(e){"boolean"==typeof e?e?mt():vt():Z?mt():vt()},toggleJumpToSlide:function(e){"boolean"==typeof e?e?ie.show():ie.hide():ie.isVisible()?ie.hide():ie.show()},isFirstSlide:Ue,isLastSlide:Ve,isLastVerticalSlide:We,isVerticalSlide:Oe,isVerticalStack:function(e=p){return e.classList.contains(".stack")||null!==e.querySelector("section")},isPaused:Xe,isAutoSliding:function(){return!(!J||Z)},isSpeakerNotes:fe.isSpeakerNotesWindow.bind(fe),isOverview:le.isActive.bind(le),isFocused:ve.isFocused.bind(ve),isScrollView:ne.isActive.bind(ne),isPrintView:re.isActive.bind(re),isReady:()=>D,loadSlide:ee.load.bind(ee),unloadSlide:ee.unload.bind(ee),startEmbeddedContent:()=>ee.startEmbeddedContent(p),stopEmbeddedContent:()=>ee.stopEmbeddedContent(p,{unloadIframes:!1}),showPreview:Me,hidePreview:Be,addEventListeners:Se,removeEventListeners:Ae,dispatchEvent:Ce,getState:ut,setState:function(e){if("object"==typeof e){Ye(s(e.indexh),s(e.indexv),s(e.indexf));let t=s(e.paused),i=s(e.overview);"boolean"==typeof t&&t!==Xe()&&$e(t),"boolean"==typeof i&&i!==le.isActive()&&le.toggle(i)}},getProgress:function(){let e=ct(),t=st();if(p){let e=p.querySelectorAll(".fragment");if(e.length>0){let i=.9;t+=p.querySelectorAll(".fragment.visible").length/e.length*i}}return Math.min(t/(e-1),1)},getIndices:at,getSlidesAttributes:function(){return nt().map((e=>{let t={};for(let i=0;ig,getCurrentSlide:()=>p,getSlideBackground:function(e,t){let i="number"==typeof e?ht(e,t):e;if(i)return i.slideBackgroundElement},getSlideNotes:fe.getSlideNotes.bind(fe),getSlides:nt,getHorizontalSlides:rt,getVerticalSlides:ot,hasHorizontalSlides:lt,hasVerticalSlides:dt,hasNavigatedHorizontally:()=>q.hasNavigatedHorizontally,hasNavigatedVertically:()=>q.hasNavigatedVertically,shouldAutoAnimateBetween:_e,addKeyBinding:de.addKeyBinding.bind(de),removeKeyBinding:de.removeKeyBinding.bind(de),triggerKey:de.triggerKey.bind(de),registerKeyboardShortcut:de.registerKeyboardShortcut.bind(de),getComputedSlideSize:Fe,setCurrentScrollPage:function(e,t,i){let s=c||0;c=t,h=i;const a=p!==e;g=p,p=e,p&&g&&A.autoAnimate&&_e(g,p,s,h)&&se.run(g,p),a&&(g&&(ee.stopEmbeddedContent(g),ee.stopEmbeddedContent(g.slideBackgroundElement)),ee.startEmbeddedContent(p),ee.startEmbeddedContent(p.slideBackgroundElement)),requestAnimationFrame((()=>{be(we(p))})),xe()},getScale:()=>$,getConfig:()=>A,getQueryHash:d,getSlidePath:ce.getHash.bind(ce),getRevealElement:()=>n,getSlidesElement:()=>Y.slides,getViewportElement:()=>Y.viewport,getBackgroundsElement:()=>ae.element,registerPlugin:pe.registerPlugin.bind(pe),hasPlugin:pe.hasPlugin.bind(pe),getPlugin:pe.getPlugin.bind(pe),getPlugins:pe.getRegisteredPlugins.bind(pe)};return e(l,{...Nt,announceStatus:be,getStatusText:we,focus:ve,scroll:ne,progress:ue,controls:he,location:ce,overview:le,fragments:oe,backgrounds:ae,slideContent:ee,slideNumber:te,onUserInput:function(e){A.autoSlideStoppable&&vt()},closeOverlay:Be,updateSlidesVisibility:tt,layoutSlideContents:De,transformSlides:Le,cueAutoSlide:gt,cancelAutoSlide:pt}),Nt}let X=$,Y=[];return X.initialize=e=>(Object.assign(X,new $(document.querySelector(".reveal"),e)),Y.map((e=>e(X))),X.initialize()),["configure","on","off","addEventListener","removeEventListener","registerPlugin"].forEach((e=>{X[e]=(...t)=>{Y.push((i=>i[e].call(null,...t)))}})),X.isReady=()=>!1,X.VERSION=K,X})); +//# sourceMappingURL=reveal.js.map diff --git a/simulator/vendor/reveal/theme/dracula.css b/simulator/vendor/reveal/theme/dracula.css new file mode 100644 index 0000000..60d20bf --- /dev/null +++ b/simulator/vendor/reveal/theme/dracula.css @@ -0,0 +1,385 @@ +/** + * Dracula Dark theme for reveal.js. + * Based on https://draculatheme.com + */ +/** + * Dracula colors by Zeno Rocha + * https://draculatheme.com/contribute + */ +html * { + color-profile: sRGB; + rendering-intent: auto; +} + +section.has-light-background, section.has-light-background h1, section.has-light-background h2, section.has-light-background h3, section.has-light-background h4, section.has-light-background h5, section.has-light-background h6 { + color: #282A36; +} + +/********************************************* + * GLOBAL STYLES + *********************************************/ +:root { + --r-background-color: #282A36; + --r-main-font: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif; + --r-main-font-size: 40px; + --r-main-color: #F8F8F2; + --r-block-margin: 20px; + --r-heading-margin: 0 0 20px 0; + --r-heading-font: League Gothic, Impact, sans-serif; + --r-heading-color: #BD93F9; + --r-heading-line-height: 1.2; + --r-heading-letter-spacing: normal; + --r-heading-text-transform: none; + --r-heading-text-shadow: none; + --r-heading-font-weight: normal; + --r-heading1-text-shadow: none; + --r-heading1-size: 3.77em; + --r-heading2-size: 2.11em; + --r-heading3-size: 1.55em; + --r-heading4-size: 1em; + --r-code-font: Fira Code, Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace; + --r-link-color: #FF79C6; + --r-link-color-dark: #ff2da5; + --r-link-color-hover: #8BE9FD; + --r-selection-background-color: #44475A; + --r-selection-color: #fff; + --r-overlay-element-bg-color: 240, 240, 240; + --r-overlay-element-fg-color: 0, 0, 0; +} + +.reveal-viewport { + background: #282A36; + background-color: var(--r-background-color); +} + +.reveal { + font-family: var(--r-main-font); + font-size: var(--r-main-font-size); + font-weight: normal; + color: var(--r-main-color); +} + +.reveal ::selection { + color: var(--r-selection-color); + background: var(--r-selection-background-color); + text-shadow: none; +} + +.reveal ::-moz-selection { + color: var(--r-selection-color); + background: var(--r-selection-background-color); + text-shadow: none; +} + +.reveal .slides section, +.reveal .slides section > section { + line-height: 1.3; + font-weight: inherit; +} + +/********************************************* + * HEADERS + *********************************************/ +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + margin: var(--r-heading-margin); + color: var(--r-heading-color); + font-family: var(--r-heading-font); + font-weight: var(--r-heading-font-weight); + line-height: var(--r-heading-line-height); + letter-spacing: var(--r-heading-letter-spacing); + text-transform: var(--r-heading-text-transform); + text-shadow: var(--r-heading-text-shadow); + word-wrap: break-word; +} + +.reveal h1 { + font-size: var(--r-heading1-size); +} + +.reveal h2 { + font-size: var(--r-heading2-size); +} + +.reveal h3 { + font-size: var(--r-heading3-size); +} + +.reveal h4 { + font-size: var(--r-heading4-size); +} + +.reveal h1 { + text-shadow: var(--r-heading1-text-shadow); +} + +/********************************************* + * OTHER + *********************************************/ +.reveal p { + margin: var(--r-block-margin) 0; + line-height: 1.3; +} + +/* Remove trailing margins after titles */ +.reveal h1:last-child, +.reveal h2:last-child, +.reveal h3:last-child, +.reveal h4:last-child, +.reveal h5:last-child, +.reveal h6:last-child { + margin-bottom: 0; +} + +/* Ensure certain elements are never larger than the slide itself */ +.reveal img, +.reveal video, +.reveal iframe { + max-width: 95%; + max-height: 95%; +} + +.reveal strong, +.reveal b { + font-weight: bold; +} + +.reveal em { + font-style: italic; +} + +.reveal ol, +.reveal dl, +.reveal ul { + display: inline-block; + text-align: left; + margin: 0 0 0 1em; +} + +.reveal ol { + list-style-type: decimal; +} + +.reveal ul { + list-style-type: disc; +} + +.reveal ul ul { + list-style-type: square; +} + +.reveal ul ul ul { + list-style-type: circle; +} + +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { + display: block; + margin-left: 40px; +} + +.reveal dt { + font-weight: bold; +} + +.reveal dd { + margin-left: 40px; +} + +.reveal blockquote { + display: block; + position: relative; + width: 70%; + margin: var(--r-block-margin) auto; + padding: 5px; + font-style: italic; + background: rgba(255, 255, 255, 0.05); + box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); +} + +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { + display: inline-block; +} + +.reveal q { + font-style: italic; +} + +.reveal pre { + display: block; + position: relative; + width: 90%; + margin: var(--r-block-margin) auto; + text-align: left; + font-size: 0.55em; + font-family: var(--r-code-font); + line-height: 1.2em; + word-wrap: break-word; + box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); +} + +.reveal code { + font-family: var(--r-code-font); + text-transform: none; + tab-size: 2; +} + +.reveal pre code { + display: block; + padding: 5px; + overflow: auto; + max-height: 400px; + word-wrap: normal; +} + +.reveal .code-wrapper { + white-space: normal; +} + +.reveal .code-wrapper code { + white-space: pre; +} + +.reveal table { + margin: auto; + border-collapse: collapse; + border-spacing: 0; +} + +.reveal table th { + font-weight: bold; +} + +.reveal table th, +.reveal table td { + text-align: left; + padding: 0.2em 0.5em 0.2em 0.5em; + border-bottom: 1px solid; +} + +.reveal table th[align=center], +.reveal table td[align=center] { + text-align: center; +} + +.reveal table th[align=right], +.reveal table td[align=right] { + text-align: right; +} + +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { + border-bottom: none; +} + +.reveal sup { + vertical-align: super; + font-size: smaller; +} + +.reveal sub { + vertical-align: sub; + font-size: smaller; +} + +.reveal small { + display: inline-block; + font-size: 0.6em; + line-height: 1.2em; + vertical-align: top; +} + +.reveal small * { + vertical-align: top; +} + +.reveal img { + margin: var(--r-block-margin) 0; +} + +/********************************************* + * LINKS + *********************************************/ +.reveal a { + color: var(--r-link-color); + text-decoration: none; + transition: color 0.15s ease; +} + +.reveal a:hover { + color: var(--r-link-color-hover); + text-shadow: none; + border: none; +} + +.reveal .roll span:after { + color: #fff; + background: var(--r-link-color-dark); +} + +/********************************************* + * Frame helper + *********************************************/ +.reveal .r-frame { + border: 4px solid var(--r-main-color); + box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); +} + +.reveal a .r-frame { + transition: all 0.15s linear; +} + +.reveal a:hover .r-frame { + border-color: var(--r-link-color); + box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); +} + +/********************************************* + * NAVIGATION CONTROLS + *********************************************/ +.reveal .controls { + color: var(--r-link-color); +} + +/********************************************* + * PROGRESS BAR + *********************************************/ +.reveal .progress { + background: rgba(0, 0, 0, 0.2); + color: var(--r-link-color); +} + +/********************************************* + * PRINT BACKGROUND + *********************************************/ +@media print { + .backgrounds { + background-color: var(--r-background-color); + } +} +:root { + --r-bold-color: #FFB86C; + --r-italic-color: #F1FA8C; + --r-inline-code-color: #50FA7B; + --r-list-bullet-color: #8BE9FD; +} + +.reveal strong, .reveal b { + color: var(--r-bold-color); +} +.reveal em, .reveal i, .reveal blockquote { + color: var(--r-italic-color); +} +.reveal code { + color: var(--r-inline-code-color); +} +.reveal ul li::marker, .reveal ol li::marker { + color: var(--r-list-bullet-color); +} \ No newline at end of file