From f7470d333ce98642520d4de8982a15340e86a358 Mon Sep 17 00:00:00 2001 From: FBukovina Date: Thu, 17 Sep 2026 16:06:15 +0200 Subject: [PATCH] Add the Next.js web app and shared lesson content. Move lessons out of the C sources into JSON so the web client can use the same material as the desktop app, and point release builds at desktop/. Co-authored-by: Cursor --- .github/workflows/release.yml | 9 +- .gitignore | 13 + README.md | 84 +- content/README.md | 80 + content/i18n/content.json | 1248 ++++++++ content/i18n/ui.json | 541 ++++ .../lessons/czech/fuks-spalovac-mrtvol.json | 539 ++++ content/lessons/czech/mluvnice.json | 1657 ++++++++++ content/lessons/czech/orwell-1984.json | 481 +++ content/lessons/deutsch/unit-01.json | 2200 +++++++++++++ content/lessons/deutsch/unit-02.json | 2788 +++++++++++++++++ content/lessons/deutsch/unit-03.json | 2731 ++++++++++++++++ content/lessons/hardware/unit-01.json | 125 + content/lessons/hardware/unit-02.json | 177 ++ content/lessons/hardware/unit-03.json | 86 + content/lessons/networks/unit-01.json | 178 ++ content/lessons/networks/unit-02.json | 173 + content/lessons/networks/unit-03.json | 161 + content/lessons/networks/unit-04.json | 156 + content/lessons/networks/unit-05.json | 156 + content/lessons/networks/unit-06.json | 139 + content/lessons/networks/unit-07.json | 152 + content/lessons/networks/unit-08.json | 153 + content/lessons/networks/unit-09.json | 151 + content/lessons/networks/unit-10.json | 120 + content/lessons/networks/unit-11.json | 181 ++ content/lessons/networks/unit-12.json | 172 + content/lessons/networks/unit-13.json | 130 + content/lessons/networks/unit-14.json | 140 + content/lessons/networks/unit-15.json | 118 + content/lessons/networks/unit-16.json | 129 + content/lessons/networks/unit-17.json | 162 + content/lessons/networks/unit-18.json | 139 + content/lessons/networks/unit-19.json | 173 + content/lessons/networks/unit-20.json | 172 + content/lessons/networks/unit-21.json | 180 ++ content/lessons/networks/unit-22.json | 198 ++ content/lessons/networks/unit-23.json | 139 + content/lessons/networks/unit-24.json | 138 + content/lessons/networks/unit-25.json | 164 + content/lessons/networks/unit-26.json | 185 ++ content/lessons/networks/unit-27.json | 196 ++ content/manifest.json | 63 + content/paths.json | 389 +++ content/schema.ts | 337 ++ content/subjects.json | 93 + content/themes.json | 562 ++++ package.json | 14 + tools/build-content.mjs | 239 ++ tools/extract/cetba.mjs | 114 + tools/extract/deutsch-helpers.mjs | 196 ++ tools/extract/deutsch-u2.mjs | 159 + tools/extract/deutsch-u3.mjs | 174 + tools/extract/deutsch.mjs | 249 ++ tools/extract/hardware.mjs | 73 + tools/extract/i18n.mjs | 35 + tools/extract/mluvnice.mjs | 145 + tools/extract/networks.mjs | 97 + tools/extract/themes.mjs | 48 + tools/lib/cparse.mjs | 354 +++ web/next-env.d.ts | 7 + web/next.config.ts | 10 + web/package-lock.json | 1076 +++++++ web/package.json | 24 + web/src/app/ThemeScript.tsx | 38 + web/src/app/czech/mluvnice/page.tsx | 12 + web/src/app/czech/page.tsx | 28 + web/src/app/czech/reading/[book]/page.tsx | 21 + web/src/app/czech/reading/page.tsx | 24 + web/src/app/deutsch/[lesson]/page.tsx | 30 + .../deutsch/[lesson]/vocab/VocabTrainer.tsx | 142 + web/src/app/deutsch/[lesson]/vocab/page.tsx | 21 + web/src/app/deutsch/page.tsx | 24 + web/src/app/globals.css | 1005 ++++++ web/src/app/hardware/[lesson]/page.tsx | 23 + web/src/app/hardware/page.tsx | 24 + web/src/app/layout.tsx | 36 + web/src/app/networks/NetworkYearsScreen.tsx | 53 + web/src/app/networks/page.tsx | 6 + web/src/app/networks/year-1/[lesson]/page.tsx | 23 + web/src/app/networks/year-1/page.tsx | 23 + web/src/app/page.tsx | 20 + web/src/app/providers.tsx | 150 + web/src/app/settings/page.tsx | 74 + web/src/app/stats/StatsScreen.tsx | 155 + web/src/app/stats/page.tsx | 29 + web/src/app/subjects/SubjectsScreen.tsx | 58 + web/src/app/subjects/page.tsx | 6 + web/src/components/LessonScreen.tsx | 127 + web/src/components/PathMap.tsx | 151 + web/src/components/PathScreen.tsx | 71 + web/src/components/Slides.tsx | 61 + web/src/components/TopBar.tsx | 52 + web/src/components/exercises/AssemblyTask.tsx | 117 + web/src/components/exercises/AssignTask.tsx | 117 + web/src/components/exercises/ChoiceTask.tsx | 73 + web/src/components/exercises/DialogueTask.tsx | 96 + web/src/components/exercises/FieldsTask.tsx | 84 + web/src/components/exercises/FillTask.tsx | 212 ++ web/src/components/exercises/FreeTask.tsx | 81 + web/src/components/exercises/HangmanTask.tsx | 104 + web/src/components/exercises/ProfileTask.tsx | 64 + web/src/components/exercises/RevealTask.tsx | 71 + web/src/components/exercises/SubnetTask.tsx | 146 + web/src/components/exercises/TableTask.tsx | 102 + web/src/components/exercises/TaskRenderer.tsx | 99 + web/src/components/exercises/TaskShell.tsx | 69 + web/src/components/exercises/TypedTask.tsx | 76 + web/src/components/icons.tsx | 88 + web/src/content/index.ts | 84 + web/src/lib/answers.ts | 58 + web/src/lib/progress.ts | 82 + web/tsconfig.json | 44 + 113 files changed, 25817 insertions(+), 9 deletions(-) create mode 100644 content/README.md create mode 100644 content/i18n/content.json create mode 100644 content/i18n/ui.json create mode 100644 content/lessons/czech/fuks-spalovac-mrtvol.json create mode 100644 content/lessons/czech/mluvnice.json create mode 100644 content/lessons/czech/orwell-1984.json create mode 100644 content/lessons/deutsch/unit-01.json create mode 100644 content/lessons/deutsch/unit-02.json create mode 100644 content/lessons/deutsch/unit-03.json create mode 100644 content/lessons/hardware/unit-01.json create mode 100644 content/lessons/hardware/unit-02.json create mode 100644 content/lessons/hardware/unit-03.json create mode 100644 content/lessons/networks/unit-01.json create mode 100644 content/lessons/networks/unit-02.json create mode 100644 content/lessons/networks/unit-03.json create mode 100644 content/lessons/networks/unit-04.json create mode 100644 content/lessons/networks/unit-05.json create mode 100644 content/lessons/networks/unit-06.json create mode 100644 content/lessons/networks/unit-07.json create mode 100644 content/lessons/networks/unit-08.json create mode 100644 content/lessons/networks/unit-09.json create mode 100644 content/lessons/networks/unit-10.json create mode 100644 content/lessons/networks/unit-11.json create mode 100644 content/lessons/networks/unit-12.json create mode 100644 content/lessons/networks/unit-13.json create mode 100644 content/lessons/networks/unit-14.json create mode 100644 content/lessons/networks/unit-15.json create mode 100644 content/lessons/networks/unit-16.json create mode 100644 content/lessons/networks/unit-17.json create mode 100644 content/lessons/networks/unit-18.json create mode 100644 content/lessons/networks/unit-19.json create mode 100644 content/lessons/networks/unit-20.json create mode 100644 content/lessons/networks/unit-21.json create mode 100644 content/lessons/networks/unit-22.json create mode 100644 content/lessons/networks/unit-23.json create mode 100644 content/lessons/networks/unit-24.json create mode 100644 content/lessons/networks/unit-25.json create mode 100644 content/lessons/networks/unit-26.json create mode 100644 content/lessons/networks/unit-27.json create mode 100644 content/manifest.json create mode 100644 content/paths.json create mode 100644 content/schema.ts create mode 100644 content/subjects.json create mode 100644 content/themes.json create mode 100644 package.json create mode 100644 tools/build-content.mjs create mode 100644 tools/extract/cetba.mjs create mode 100644 tools/extract/deutsch-helpers.mjs create mode 100644 tools/extract/deutsch-u2.mjs create mode 100644 tools/extract/deutsch-u3.mjs create mode 100644 tools/extract/deutsch.mjs create mode 100644 tools/extract/hardware.mjs create mode 100644 tools/extract/i18n.mjs create mode 100644 tools/extract/mluvnice.mjs create mode 100644 tools/extract/networks.mjs create mode 100644 tools/extract/themes.mjs create mode 100644 tools/lib/cparse.mjs create mode 100644 web/next-env.d.ts create mode 100644 web/next.config.ts create mode 100644 web/package-lock.json create mode 100644 web/package.json create mode 100644 web/src/app/ThemeScript.tsx create mode 100644 web/src/app/czech/mluvnice/page.tsx create mode 100644 web/src/app/czech/page.tsx create mode 100644 web/src/app/czech/reading/[book]/page.tsx create mode 100644 web/src/app/czech/reading/page.tsx create mode 100644 web/src/app/deutsch/[lesson]/page.tsx create mode 100644 web/src/app/deutsch/[lesson]/vocab/VocabTrainer.tsx create mode 100644 web/src/app/deutsch/[lesson]/vocab/page.tsx create mode 100644 web/src/app/deutsch/page.tsx create mode 100644 web/src/app/globals.css create mode 100644 web/src/app/hardware/[lesson]/page.tsx create mode 100644 web/src/app/hardware/page.tsx create mode 100644 web/src/app/layout.tsx create mode 100644 web/src/app/networks/NetworkYearsScreen.tsx create mode 100644 web/src/app/networks/page.tsx create mode 100644 web/src/app/networks/year-1/[lesson]/page.tsx create mode 100644 web/src/app/networks/year-1/page.tsx create mode 100644 web/src/app/page.tsx create mode 100644 web/src/app/providers.tsx create mode 100644 web/src/app/settings/page.tsx create mode 100644 web/src/app/stats/StatsScreen.tsx create mode 100644 web/src/app/stats/page.tsx create mode 100644 web/src/app/subjects/SubjectsScreen.tsx create mode 100644 web/src/app/subjects/page.tsx create mode 100644 web/src/components/LessonScreen.tsx create mode 100644 web/src/components/PathMap.tsx create mode 100644 web/src/components/PathScreen.tsx create mode 100644 web/src/components/Slides.tsx create mode 100644 web/src/components/TopBar.tsx create mode 100644 web/src/components/exercises/AssemblyTask.tsx create mode 100644 web/src/components/exercises/AssignTask.tsx create mode 100644 web/src/components/exercises/ChoiceTask.tsx create mode 100644 web/src/components/exercises/DialogueTask.tsx create mode 100644 web/src/components/exercises/FieldsTask.tsx create mode 100644 web/src/components/exercises/FillTask.tsx create mode 100644 web/src/components/exercises/FreeTask.tsx create mode 100644 web/src/components/exercises/HangmanTask.tsx create mode 100644 web/src/components/exercises/ProfileTask.tsx create mode 100644 web/src/components/exercises/RevealTask.tsx create mode 100644 web/src/components/exercises/SubnetTask.tsx create mode 100644 web/src/components/exercises/TableTask.tsx create mode 100644 web/src/components/exercises/TaskRenderer.tsx create mode 100644 web/src/components/exercises/TaskShell.tsx create mode 100644 web/src/components/exercises/TypedTask.tsx create mode 100644 web/src/components/icons.tsx create mode 100644 web/src/content/index.ts create mode 100644 web/src/lib/answers.ts create mode 100644 web/src/lib/progress.ts create mode 100644 web/tsconfig.json diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 22b1b37..46cede3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,6 +27,7 @@ jobs: - name: Build AppImage env: VERSION: ${{ github.ref_name }} + working-directory: desktop run: | chmod +x scripts/bundle-linux.sh ./scripts/bundle-linux.sh @@ -35,7 +36,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: maturita-linux - path: dist/maturita-linux-*.AppImage + path: desktop/dist/maturita-linux-*.AppImage windows: name: Windows zip @@ -59,6 +60,7 @@ jobs: mingw-w64-ucrt-x86_64-make - name: Build and bundle + working-directory: desktop run: | make bundle cd dist @@ -71,7 +73,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: maturita-windows - path: dist-out/maturita-windows-x64.zip + path: desktop/dist-out/maturita-windows-x64.zip macos: name: macOS app @@ -86,6 +88,7 @@ jobs: - name: Build .app zip env: VERSION: ${{ github.ref_name }} + working-directory: desktop run: | chmod +x scripts/bundle-macos.sh ./scripts/bundle-macos.sh @@ -94,7 +97,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: maturita-macos - path: dist/maturita-macos-*.zip + path: desktop/dist/maturita-macos-*.zip publish: name: Publish GitHub Release diff --git a/.gitignore b/.gitignore index 7e776a5..06f734c 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,19 @@ build/ # Generated from assets/app-icon.png (Makefile / CMake POST_BUILD) assets/icons/ +desktop/assets/icons/ +desktop/maturita + +# ---> Node / Next.js (web/) +node_modules/ +.next/ +out/ +.turbo/ +*.tsbuildinfo +.env*.local +.vercel +# Generated by `next dev` for AI agents (same reason CLAUDE.md is ignored above) +web/AGENTS.md # Object files *.o diff --git a/README.md b/README.md index 3ebafd2..4e4d132 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ GTK 4 interface. | Welcome screen | Subjects ("Předměty") | German learning roadmap | | --------------------------------------- | ---------------------------------------- | --------------------------------------- | -| ![Welcome screen](assets/welcomescreen.png) | ![Subjects screen](assets/subjectsscreen.png) | ![German roadmap](assets/germanlection.png) | +| ![Welcome screen](desktop/assets/welcomescreen.png) | ![Subjects screen](desktop/assets/subjectsscreen.png) | ![German roadmap](desktop/assets/germanlection.png) | ### Features @@ -218,10 +218,30 @@ sudo pacman -S base-devel pkgconf Windows – `gcc`, GTK 4 and `pkg-config` are installed in step 1 of the Windows guide below. Visual Studio is not required. -#### Building the application +#### Running the web app + +The web client needs Node.js 20 or newer and no GTK at all: + +```bash +npm run web:install # installs web/ dependencies +npm run web # dev server on http://localhost:3000 +npm run web:build # production build +``` + +It reads its lessons from `content/`, which is exported from the C sources by +`npm run content`. Themes, translations, exercises and progress tracking all +mirror the desktop app; progress is kept in the browser's localStorage instead of +`progress/*.conf`. + +Coverage matches the desktop client: German units 1–3 with their vocabulary +trainers, all 27 network lessons, the three hardware lessons, the 20 Czech +grammar exercises and both reading-list books. + +#### Building the desktop application 1. Clone or download this repository -2. Navigate to the project directory +2. Navigate to the `desktop/` directory — every command in this section runs + there, since the C sources and the Makefile live inside it 3. Build with the Makefile: ```bash @@ -378,6 +398,22 @@ Completed network units are saved to `progress/net.conf`; hardware units to ### Project structure +The repository holds three pieces: the GTK desktop app, a Next.js web app, and +the shared lesson content both read from. + +``` +desktop/ GTK 4 desktop app (C) +web/ Next.js web app (TypeScript / React) +content/ shared lesson content as JSON — see content/README.md +tools/ exports content/ from the desktop C sources +``` + +Run `npm run content` from the repo root to regenerate `content/` after editing +lesson data in `desktop/`. Run `npm run web` for the web app (after +`npm run web:install`) and `npm run desktop` for the GTK client. + +#### desktop/ + ``` maturita.h shared types, macros, globals and prototypes globals.c shared global state (window, stack, units, theme, …) @@ -494,7 +530,7 @@ moderním GTK 4 rozhraním stylovaným přes CSS. | Úvodní obrazovka | Předměty | Německá učební cesta | | --------------------------------------- | ---------------------------------------- | --------------------------------------- | -| ![Welcome screen](assets/welcomescreen.png) | ![Subjects screen](assets/subjectsscreen.png) | ![German roadmap](assets/germanlection.png) | +| ![Welcome screen](desktop/assets/welcomescreen.png) | ![Subjects screen](desktop/assets/subjectsscreen.png) | ![German roadmap](desktop/assets/germanlection.png) | ### Funkce @@ -680,10 +716,30 @@ sudo pacman -S base-devel pkgconf Windows – `gcc`, GTK 4 i `pkg-config` se nainstalují v kroku 1 návodu níže. Visual Studio není potřeba. -#### Sestavení aplikace +#### Spuštění webové aplikace + +Webový klient potřebuje Node.js 20 nebo novější a žádné GTK: + +```bash +npm run web:install # instalace závislostí ve web/ +npm run web # vývojový server na http://localhost:3000 +npm run web:build # produkční build +``` + +Lekce čte z `content/`, který se z C zdrojů exportuje příkazem +`npm run content`. Témata, překlady, cvičení i sledování postupu odpovídají +desktopové aplikaci; postup se ukládá do localStorage prohlížeče místo do +`progress/*.conf`. + +Obsah odpovídá desktopovému klientovi: německé jednotky 1–3 včetně slovníkového +tréninku, všech 27 lekcí sítí, tři lekce technického vybavení, 20 cvičení +mluvnice a obě knihy maturitní četby. + +#### Sestavení desktopové aplikace 1. Naklonujte nebo stáhněte tento repozitář -2. Přejděte do složky projektu +2. Přejděte do složky `desktop/` — všechny příkazy v této části se spouštějí + tam, protože C zdroje i Makefile jsou uvnitř 3. Sestavte pomocí Makefile: ```bash @@ -836,6 +892,22 @@ ukládají do `progress/net.conf`, hardwarové do `progress/hw.conf`. ### Struktura projektu +Repozitář obsahuje tři části: desktopovou aplikaci v GTK, webovou aplikaci +v Next.js a společný obsah lekcí, který obě čtou. + +``` +desktop/ desktopová aplikace GTK 4 (C) +web/ webová aplikace Next.js (TypeScript / React) +content/ společný obsah lekcí v JSON — viz content/README.md +tools/ export content/ z C zdrojů desktopové aplikace +``` + +Po úpravě obsahu lekcí v `desktop/` spusťte v hlavní složce repozitáře +`npm run content` a `content/` se přegeneruje. Webovou aplikaci spustíte přes +`npm run web` (po `npm run web:install`), desktopovou přes `npm run desktop`. + +#### desktop/ + ``` maturita.h sdílené typy, makra, globální proměnné a prototypy globals.c sdílený globální stav (okno, stack, jednotky, téma, …) diff --git a/content/README.md b/content/README.md new file mode 100644 index 0000000..77430d3 --- /dev/null +++ b/content/README.md @@ -0,0 +1,80 @@ +# content/ + +Shared lesson content for the whole project. One folder, one file per lesson — +instead of lesson text being buried inside each unit's C source file. + +`schema.ts` is the single description of every shape here. Both the extractor in +`tools/` and the web app in `web/` type against it, so a change there shows up as +a type error on both sides. + +## Layout + +``` +content/ + schema.ts TypeScript types for everything below + themes.json 10 palettes, dark + light (24 colors each) + subjects.json the 13 subjects, their i18n keys and routes + paths.json serpentine unit paths per subject + manifest.json subject and lesson ids + i18n/ + ui.json UI chrome strings, keyed by identifier + content.json lesson strings, keyed by the Czech text + lessons/ + deutsch/unit-01.json … unit-03.json + networks/unit-01.json … unit-27.json + hardware/unit-01.json … unit-03.json + czech/mluvnice.json, orwell-1984.json, fuks-spalovac-mrtvol.json +``` + +`paths.json` holds one entry per path. A subject usually has exactly one, but +Czech has two: the top-level area picker and the `reading` branch listing the +books, distinguished by the `branch` field. + +## Lesson shape + +A lesson holds theory `slides` and a list of `tasks`. Each task is one bubble on +the unit map and contains `items` of a single `kind`: + +| kind | what it is | +| ---- | ---------- | +| `choice` | multiple choice, `correct` indexes `options` | +| `fill` | sentence split into `segments` with a gap between each; `input` picks dropdown or text | +| `dialogue` | dialogue lines with one missing word each | +| `assembly` | build a sentence from scrambled words | +| `assign` | sort labelled cards into named groups | +| `free` | open question with a model answer | +| `typed` | type the answer, `answers` lists accepted spellings | +| `fields` | one prompt, several labelled fields (Czech grammatical categories) | +| `reveal` | self-assessed: write an answer, then compare it with the model | +| `hangman` | guess the word letter by letter | +| `profile` | "Steckbrief" line with a model answer | +| `table` | editable grid, some cells prefilled | +| `subnet` | VLSM subnetting worksheet | + +`fill` absorbs every gap variant in the desktop app. A few flags steer it: +`letters` marks gaps holding missing letters inside a word rather than whole +words, `gapPool` picks the task's `pool` or `altPool` per gap (the "Ordne zu" +question-word and answer columns), and `heading` starts a labelled group of rows. + +Two conventions carried over from the desktop app: + +- **Pipe-separated answers.** `"bin|heiße"` means either spelling is accepted. +- **Lenient comparison.** Answers are matched after lowercasing, expanding + `ä ö ü ß` to `ae oe ue ss`, dropping accents and ignoring punctuation, so Czech + diacritics and German umlauts are optional. See `web/src/lib/answers.ts`. + +Titles come either as a literal `title` or as a `titleKey` to look up in the +i18n tables, because German unit names are identical in both languages while +network lesson names are translated. + +## Regenerating + +The C sources in `desktop/` are still where content is authored, so this folder +is a generated one-way export: + +```bash +npm run content # from the repo root, or: node tools/build-content.mjs +``` + +The extractor parses the C initializers directly and throws on any shape it does +not recognise, so a bad export fails loudly rather than emitting empty lessons. diff --git a/content/i18n/content.json b/content/i18n/content.json new file mode 100644 index 0000000..df50e5a --- /dev/null +++ b/content/i18n/content.json @@ -0,0 +1,1248 @@ +{ + "cs": { + "Ahoj! Jmenuji se Anna.": "Ahoj! Jmenuji se Anna.", + "Ahoj! Jmenuji se Petr.": "Ahoj! Jmenuji se Petr.", + "Jmenuji se Anna.": "Jmenuji se Anna.", + "Jmenuji se Petr.": "Jmenuji se Petr.", + "Odkud jsi?": "Odkud jsi?", + "Odkud pocházíš?": "Odkud pocházíš?", + "Pocházím z Česka.": "Pocházím z Česka.", + "Dobré ráno!": "Dobré ráno!", + "Jak se máš?": "Jak se máš?", + "Mám se dobře, děkuji.": "Mám se dobře, děkuji.", + "Musím jít. Na shledanou!": "Musím jít. Na shledanou!", + "Brzy na viděnou!": "Brzy na viděnou!", + "Čau!": "Čau!", + "Jak se jmenuješ?": "Jak se jmenuješ?", + "Kde bydlíš?": "Kde bydlíš?", + "Kdo to je?": "Kdo to je?", + "Kolik je ti let?": "Kolik je ti let?", + "Je mi šestnáct let.": "Je mi šestnáct let.", + "Bydlím v Praze.": "Bydlím v Praze.", + "Hraji fotbal.": "Hraji fotbal.", + "Co rád/a děláš?": "Co rád/a děláš?", + "Kolik je hodin?": "Kolik je hodin?", + "Na shledanou.": "Na shledanou.", + "Moc děkuji.": "Moc děkuji.", + "„vierzehn“ = čtrnáct (14)": "„vierzehn“ = čtrnáct (14)", + "„siebzehn“ = sedmnáct (17)": "„siebzehn“ = sedmnáct (17)", + "„zwanzig“ = dvacet (20)": "„zwanzig“ = dvacet (20)", + "„sechs“ = šest (6)": "„sechs“ = šest (6)", + "1 B = 8 b": "1 B = 8 b", + "2⁸ = 256 hodnot (0–255)": "2⁸ = 256 hodnot (0–255)", + "Kabely – síť zůstává připojená i po přenosu": "Kabely – síť zůstává připojená i po přenosu", + "WAN = Wide Area Network, např. internet": "WAN = Wide Area Network, např. internet", + "Např. hvězda, kruh, sběrnice": "Např. hvězda, kruh, sběrnice", + "Architektura = topologie + standard": "Architektura = topologie + standard", + "Bez centrálního serveru – stanice si sdílejí data a tiskárny": "Bez centrálního serveru – stanice si sdílejí data a tiskárny", + "Server řídí a poskytuje služby, má vyšší výkon": "Server řídí a poskytuje služby, má vyšší výkon", + "Ověřují uživatele a povolují přístup ke službám": "Ověřují uživatele a povolují přístup ke službám", + "Fileserver = souborový server": "Fileserver = souborový server", + "Jeden server – při výpadku je služba nedostupná": "Jeden server – při výpadku je služba nedostupná", + "Více serverů, každý obsluhuje část – vyšší spolehlivost": "Více serverů, každý obsluhuje část – vyšší spolehlivost", + "Slouží zároveň i jako pracovní stanice": "Slouží zároveň i jako pracovní stanice", + "Jen síťové služby – vysoký výkon a bezpečnost, často v racku": "Jen síťové služby – vysoký výkon a bezpečnost, často v racku", + "Obří sálové počítače (IBM, Siemens) pro banky a státní správu": "Obří sálové počítače (IBM, Siemens) pro banky a státní správu", + "SaaS = software jako služba, přístup online z libovolného zařízení": "SaaS = software jako služba, přístup online z libovolného zařízení", + "Více bitů najednou po více vodičích; problém jsou přeslechy": "Více bitů najednou po více vodičích; problém jsou přeslechy", + "Přeslechy vznikají při delších kabelech a vysokých frekvencích": "Přeslechy vznikají při delších kabelech a vysokých frekvencích", + "Bit po bitu po jednom vodiči – vyšší frekvence i délky": "Bit po bitu po jednom vodiči – vyšší frekvence i délky", + "Start-bit (0) synchronizuje, Stop-bit (1) ukončuje znak": "Start-bit (0) synchronizuje, Stop-bit (1) ukončuje znak", + "Řízeno společným hodinovým signálem a přesným časováním": "Řízeno společným hodinovým signálem a přesným časováním", + "Nejslabší – přidá bit pro sudý/lichý počet jedniček": "Nejslabší – přidá bit pro sudý/lichý počet jedniček", + "Součet znaků jako dvojkových čísel": "Součet znaků jako dvojkových čísel", + "Nejbezpečnější – počítá se z jednotlivých bitů v bloku": "Nejbezpečnější – počítá se z jednotlivých bitů v bloku", + "Analogový je spojitý, digitální má diskrétní hodnoty 0 a 1": "Analogový je spojitý, digitální má diskrétní hodnoty 0 a 1", + "Frekvence f = 1/T, kde T je perioda": "Frekvence f = 1/T, kde T je perioda", + "AM mění amplitudu, FM frekvenci, PM fázi": "AM mění amplitudu, FM frekvenci, PM fázi", + "QPSK nese 2 bity v prvku, 256-QAM nese 8 bitů": "QPSK nese 2 bity v prvku, 256-QAM nese 8 bitů", + "Modulační rychlost = počet změn signálu za sekundu [Bd/s]": "Modulační rychlost = počet změn signálu za sekundu [Bd/s]", + "Přenosová rychlost = množství informace za sekundu [bit/s]": "Přenosová rychlost = množství informace za sekundu [bit/s]", + "Šířka pásma určuje maximální možnou přenosovou rychlost": "Šířka pásma určuje maximální možnou přenosovou rychlost", + "Datový spoj umožňuje výměnu informací mezi uzly": "Datový spoj umožňuje výměnu informací mezi uzly", + "Fyzické médium: kabely, mikrovlny nebo družice": "Fyzické médium: kabely, mikrovlny nebo družice", + "Kanál je jednosměrný souhrn prostředků pro spojení": "Kanál je jednosměrný souhrn prostředků pro spojení", + "Okruh tvoří dva kanály pro obousměrný přenos": "Okruh tvoří dva kanály pro obousměrný přenos", + "Trunking spojuje více cest do jednoho okruhu": "Trunking spojuje více cest do jednoho okruhu", + "Trunking zvyšuje šířku pásma spojením cest": "Trunking zvyšuje šířku pásma spojením cest", + "Multiplex dělí jeden kanál na více logických podkanálů": "Multiplex dělí jeden kanál na více logických podkanálů", + "FDM: každému kanálu část frekvenčního pásma": "FDM: každému kanálu část frekvenčního pásma", + "TDM: každému kanálu vyhrazený časový slot": "TDM: každému kanálu vyhrazený časový slot", + "STDM přiděluje kapacitu dle potřeby, negarantuje 100 %": "STDM přiděluje kapacitu dle potřeby, negarantuje 100 %", + "Simplex = jen jeden směr přenosu": "Simplex = jen jeden směr přenosu", + "Half-duplex = oběma směry, ale ne současně": "Half-duplex = oběma směry, ale ne současně", + "Full-duplex = oběma směry současně": "Full-duplex = oběma směry současně", + "Agregace = sdílení kapacity kanálu více uživateli": "Agregace = sdílení kapacity kanálu více uživateli", + "Cesta se vytýčí předem, kapacita je garantována": "Cesta se vytýčí předem, kapacita je garantována", + "Data se dělí na pakety, každý může jít jinou cestou": "Data se dělí na pakety, každý může jít jinou cestou", + "Výhody: reakce na zátěž a lepší využití kapacity": "Výhody: reakce na zátěž a lepší využití kapacity", + "Negarantuje pořadí ani plynulost – nevhodné pro živé video": "Negarantuje pořadí ani plynulost – nevhodné pro živé video", + "Cesta je předem, prostředky se použijí jen při průchodu paketu": "Cesta je předem, prostředky se použijí jen při průchodu paketu", + "Virtuální spoje zrychlují přenos datagramů": "Virtuální spoje zrychlují přenos datagramů", + "Standardizace zajišťuje kompatibilitu mezi výrobci": "Standardizace zajišťuje kompatibilitu mezi výrobci", + "Dekompozice rozkládá přenos na jednotlivé vrstvy": "Dekompozice rozkládá přenos na jednotlivé vrstvy", + "Vrstvy komunikují jen se sousedy přes rozhraní SAP": "Vrstvy komunikují jen se sousedy přes rozhraní SAP", + "Protokol = pravidla mezi stejnými vrstvami na různých uzlech": "Protokol = pravidla mezi stejnými vrstvami na různých uzlech", + "Každá vrstva přidává k datům hlavičku (header)": "Každá vrstva přidává k datům hlavičku (header)", + "Rámec = linková, paket = síťová, segment = transportní": "Rámec = linková, paket = síťová, segment = transportní", + "ISO/OSI má 7 vrstev a je univerzální model": "ISO/OSI má 7 vrstev a je univerzální model", + "V praxi je ISO/OSI pomalejší – spolehlivost řeší každá vrstva": "V praxi je ISO/OSI pomalejší – spolehlivost řeší každá vrstva", + "TCP/IP zvítězil, protože vycházel ze skutečných potřeb": "TCP/IP zvítězil, protože vycházel ze skutečných potřeb", + "V TCP/IP řeší spolehlivost až vyšší vrstvy": "V TCP/IP řeší spolehlivost až vyšší vrstvy", + "Fyzická vrstva přenáší bity a řeší médium": "Fyzická vrstva přenáší bity a řeší médium", + "Spojová vrstva má podvrstvy MAC a LLC": "Spojová vrstva má podvrstvy MAC a LLC", + "Síťová vrstva směruje pakety i bez přímého spojení": "Síťová vrstva směruje pakety i bez přímého spojení", + "Transportní vrstva je jen v koncových uzlech, ne v routerech": "Transportní vrstva je jen v koncových uzlech, ne v routerech", + "Relační vrstva řídí relace, dialog a synchronizaci": "Relační vrstva řídí relace, dialog a synchronizaci", + "Prezentační vrstva formátuje data, komprimuje a šifruje": "Prezentační vrstva formátuje data, komprimuje a šifruje", + "Aplikační vrstva je rozhraní pro programy a služby": "Aplikační vrstva je rozhraní pro programy a služby", + "Aplikační TCP/IP = aplikační + prezentační + relační ISO/OSI": "Aplikační TCP/IP = aplikační + prezentační + relační ISO/OSI", + "Síťové rozhraní TCP/IP = linková + fyzická ISO/OSI": "Síťové rozhraní TCP/IP = linková + fyzická ISO/OSI", + "U TCP/IP vznikly nejdřív protokoly, až pak model": "U TCP/IP vznikly nejdřív protokoly, až pak model", + "TCP je spolehlivý a spojovaný": "TCP je spolehlivý a spojovaný", + "UDP je nespolehlivý a rychlý": "UDP je nespolehlivý a rychlý", + "HTTP, DNS a SMTP jsou aplikační protokoly": "HTTP, DNS a SMTP jsou aplikační protokoly", + "IP, ICMP a OSPF patří na síťovou (internetovou) vrstvu": "IP, ICMP a OSPF patří na síťovou (internetovou) vrstvu", + "Ethernet a PPP patří na vrstvu síťového rozhraní": "Ethernet a PPP patří na vrstvu síťového rozhraní", + "Sběrnice: médium sdílí všichni": "Sběrnice: médium sdílí všichni", + "Sběrnice: nízká bezpečnost a porucha kabelu vyřadí síť": "Sběrnice: nízká bezpečnost a porucha kabelu vyřadí síť", + "Hvězda: uzly jdou přes hub nebo switch": "Hvězda: uzly jdou přes hub nebo switch", + "Hvězda: porucha kabelu k uzlu nevyřadí celou síť": "Hvězda: porucha kabelu k uzlu nevyřadí celou síť", + "Hvězda používá kroucenou dvoulinku nebo optiku": "Hvězda používá kroucenou dvoulinku nebo optiku", + "V kruhu zprávy obíhají, dokud nenajdou adresáta": "V kruhu zprávy obíhají, dokud nenajdou adresáta", + "Optika: el. impulsy → světlo (LED/laser) → fotodioda": "Optika: el. impulsy → světlo (LED/laser) → fotodioda", + "Jedno vlákno = jednosměrný přenos; obousměrně dvě vlákna": "Jedno vlákno = jednosměrný přenos; obousměrně dvě vlákna", + "Nevýhody: náročná montáž a cena prvků/konektorů": "Nevýhody: náročná montáž a cena prvků/konektorů", + "MM: jádro 50/62,5 µm a více vidů": "MM: jádro 50/62,5 µm a více vidů", + "SM: jádro 7–10 µm, jeden paprsek, laser": "SM: jádro 7–10 µm, jeden paprsek, laser", + "MM typicky používá levnější LED zdroje": "MM typicky používá levnější LED zdroje", + "Primární ochrana: 250 µm": "Primární ochrana: 250 µm", + "Sekundární ochrana: 900 µm": "Sekundární ochrana: 900 µm", + "Těsná sekundární ochrana: svislé instalace": "Těsná sekundární ochrana: svislé instalace", + "Volná sekundární ochrana: vodorovné instalace": "Volná sekundární ochrana: vodorovné instalace", + "Montáž: lámačka a svářečka optických vláken": "Montáž: lámačka a svářečka optických vláken", + "Lámání vyžaduje kolmost asi 0,5°": "Lámání vyžaduje kolmost asi 0,5°", + "Kolize = více uzlů vysílá na sdíleném médiu najednou": "Kolize = více uzlů vysílá na sdíleném médiu najednou", + "Aloha: vysílej kdykoliv, při chybě znovu": "Aloha: vysílej kdykoliv, při chybě znovu", + "CSMA/CD patří k Ethernetu": "CSMA/CD patří k Ethernetu", + "CSMA/CD nejdřív poslouchá nosnou (Carrier Sense)": "CSMA/CD nejdřív poslouchá nosnou (Carrier Sense)", + "Po kolizi CSMA/CD čeká náhodný čas a zkusí znovu": "Po kolizi CSMA/CD čeká náhodný čas a zkusí znovu", + "CSMA/CA rezervuje médium přes RTS/CTS": "CSMA/CA rezervuje médium přes RTS/CTS", + "Repeater zesiluje signál na fyzické vrstvě": "Repeater zesiluje signál na fyzické vrstvě", + "Transceiver převádí mezi médii (např. metalika ↔ optika)": "Transceiver převádí mezi médii (např. metalika ↔ optika)", + "Hub rozešle přijatá data do všech ostatních portů": "Hub rozešle přijatá data do všech ostatních portů", + "Bridge/switch = linková vrstva, rámce a MAC": "Bridge/switch = linková vrstva, rámce a MAC", + "Switch dělí síť na kolizní domény": "Switch dělí síť na kolizní domény", + "Router = síťová vrstva, pakety a IP, propojuje sítě": "Router = síťová vrstva, pakety a IP, propojuje sítě", + "Gateway převádí mezi odlišnými architekturami/protokoly": "Gateway převádí mezi odlišnými architekturami/protokoly", + "MAC adresy switch ukládá do CAM tabulky": "MAC adresy switch ukládá do CAM tabulky", + "Podle CAM tabulky posílá rámec jen na cílový port": "Podle CAM tabulky posílá rámec jen na cílový port", + "Cut-through čte adresu příjemce a hned přeposílá": "Cut-through čte adresu příjemce a hned přeposílá", + "Cut-through je rychlý, ale propustí i chyby": "Cut-through je rychlý, ale propustí i chyby", + "Store-and-forward kontroluje celý rámec včetně CRC": "Store-and-forward kontroluje celý rámec včetně CRC", + "Fragment-free čte prvních 64 bytů kvůli kolizím": "Fragment-free čte prvních 64 bytů kvůli kolizím", + "Směrování běží na síťové (3.) vrstvě ISO/OSI": "Směrování běží na síťové (3.) vrstvě ISO/OSI", + "Adaptivní algoritmy reagují na změny a sdílí stav sítě": "Adaptivní algoritmy reagují na změny a sdílí stav sítě", + "Statické cesty nastaví správce a samy se nemění": "Statické cesty nastaví správce a samy se nemění", + "Centralizované směrování padá s výpadkem centra": "Centralizované směrování padá s výpadkem centra", + "Distribuované: výměna informací a vlastní tabulky": "Distribuované: výměna informací a vlastní tabulky", + "Nižší metrika = lepší / rychlejší trasa": "Nižší metrika = lepší / rychlejší trasa", + "Distance Vector: výměna tabulek se sousedy (např. každých 30 s)": "Distance Vector: výměna tabulek se sousedy (např. každých 30 s)", + "Router pracuje na síťové (3.) vrstvě": "Router pracuje na síťové (3.) vrstvě", + "Router segmentuje podsítě a zajišťuje WAN přístup": "Router segmentuje podsítě a zajišťuje WAN přístup", + "Firewall filtruje pakety a služby": "Firewall filtruje pakety a služby", + "Multiprotokolový router spojuje různé protokoly/standardy": "Multiprotokolový router spojuje různé protokoly/standardy", + "Router dělí síť na broadcastové domény": "Router dělí síť na broadcastové domény", + "Gateway připojuje LAN na odlišné prostředí": "Gateway připojuje LAN na odlišné prostředí", + "Pojem brána někdy označuje router nebo LAN–WAN připojení": "Pojem brána někdy označuje router nebo LAN–WAN připojení", + "MAC adresa Ethernetu má 48 bitů a je unikátní": "MAC adresa Ethernetu má 48 bitů a je unikátní", + "IEEE přidělí výrobci první 3 byty adresy": "IEEE přidělí výrobci první 3 byty adresy", + "Ethernet II: EtherType > 1500 (IP = 0800h)": "Ethernet II: EtherType > 1500 (IP = 0800h)", + "IEEE 802.3: délka ≤ 1500 a rámec 802.2": "IEEE 802.3: délka ≤ 1500 a rámec 802.2", + "Raw 802.3: Novell/IPX, začíná FFFFh": "Raw 802.3: Novell/IPX, začíná FFFFh", + "Max. Ethernet II = 1518 B": "Max. Ethernet II = 1518 B", + "Min. rámec 64 B kvůli koliznímu okénku": "Min. rámec 64 B kvůli koliznímu okénku", + "IP je nespojovaný a nespolehlivý": "IP je nespojovaný a nespolehlivý", + "Routing = rozhodnutí o směru datagramu": "Routing = rozhodnutí o směru datagramu", + "Forwarding = vložení do rámce a odeslání": "Forwarding = vložení do rámce a odeslání", + "HLEN 5 = 5 × 4 B = 20 B hlavičky": "HLEN 5 = 5 × 4 B = 20 B hlavičky", + "TTL snižují směrovače proti zacyklení": "TTL snižují směrovače proti zacyklení", + "PROTOCOL 6 = TCP": "PROTOCOL 6 = TCP", + "PROTOCOL 17 = UDP": "PROTOCOL 17 = UDP", + "Ethernet MTU = 1500 B": "Ethernet MTU = 1500 B", + "ICMP posílá informace o chybách a stavu přenosu": "ICMP posílá informace o chybách a stavu přenosu", + "ICMP jede uvnitř IP datagramu": "ICMP jede uvnitř IP datagramu", + "Source Quench = zpomal odesílání kvůli zahlcení": "Source Quench = zpomal odesílání kvůli zahlcení", + "Time Exceeded = TTL kleslo na 0": "Time Exceeded = TTL kleslo na 0", + "Echo Request/Reply = ping": "Echo Request/Reply = ping", + "Traceroute zvyšuje TTL a čte Time Exceeded": "Traceroute zvyšuje TTL a čte Time Exceeded", + "ARP: IP → MAC": "ARP: IP → MAC", + "RARP: MAC → IP": "RARP: MAC → IP", + "Nejčastější je dynamický dotaz a odpověď": "Nejčastější je dynamický dotaz a odpověď", + "ARP dotaz jde broadcastem": "ARP dotaz jde broadcastem", + "ARP odpověď je unicast s MAC": "ARP odpověď je unicast s MAC", + "ARP cache ukládá výsledky dočasně (arp -a)": "ARP cache ukládá výsledky dočasně (arp -a)", + "TCP = spolehlivý a spojovaný": "TCP = spolehlivý a spojovaný", + "UDP = nespolehlivý, nespojovaný, malá režie": "UDP = nespolehlivý, nespojovaný, malá režie", + "Porty rozlišují aplikace na uzlu": "Porty rozlišují aplikace na uzlu", + "TCP se navazuje three-way handshake": "TCP se navazuje three-way handshake", + "TCP hlavička 20 B, UDP 8 B": "TCP hlavička 20 B, UDP 8 B", + "TCP čeká na znovudoručení – špatné pro real-time": "TCP čeká na znovudoručení – špatné pro real-time", + "SCTP: multihoming a multistreaming": "SCTP: multihoming a multistreaming", + "Aplikace posílají data přes TCP/UDP": "Aplikace posílají data přes TCP/UDP", + "Dva procesy nesmí sdílet stejný port": "Dva procesy nesmí sdílet stejný port", + "Well-known: 0–1023 (IANA)": "Well-known: 0–1023 (IANA)", + "Dynamické porty: 49152–65535": "Dynamické porty: 49152–65535", + "Spojení = pětice hodnot": "Spojení = pětice hodnot", + "HTTP 80, HTTPS 443": "HTTP 80, HTTPS 443", + "SSH 22, DNS 53": "SSH 22, DNS 53", + "MySQL 3306, RDP 3389": "MySQL 3306, RDP 3389", + "Geostacionární družice ~36 000 km": "Geostacionární družice ~36 000 km", + "Družice: zpoždění stovky ms": "Družice: zpoždění stovky ms", + "VSAT: jen terminál ↔ hub": "VSAT: jen terminál ↔ hub", + "Mikrovlny: přímá viditelnost ~50 km": "Mikrovlny: přímá viditelnost ~50 km", + "STA komunikují přes AP": "STA komunikují přes AP", + "Wi-Fi 6 (ax): OFDMA": "Wi-Fi 6 (ax): OFDMA", + "WEP prolomen – nepoužívat": "WEP prolomen – nepoužívat", + "Používej WPA2/WPA3 + AES": "Používej WPA2/WPA3 + AES", + "čtrnáct": "čtrnáct", + "sedmnáct": "sedmnáct", + "dvacet": "dvacet", + "šest": "šest", + "třináct": "třináct", + "dvě jablka": "dvě jablka", + "pět hvězd": "pět hvězd", + "sedm koček": "sedm koček", + "devět květin": "devět květin", + "tři auta": "tři auta", + "jedenáct knih": "jedenáct knih", + "čtyři svíčky": "čtyři svíčky", + "osm míčů": "osm míčů", + "šest ptáků": "šest ptáků", + "šest, sedm, osm, devět": "šest, sedm, osm, devět", + "dvanáct, třináct, čtrnáct, patnáct": "dvanáct, třináct, čtrnáct, patnáct", + "osmnáct, devatenáct, dvacet, dvacet jedna": "osmnáct, devatenáct, dvacet, dvacet jedna", + "čtyři, pět, šest, sedm": "čtyři, pět, šest, sedm", + "deset, jedenáct, dvanáct, třináct": "deset, jedenáct, dvanáct, třináct", + "Plave v jezeře.": "Plave v jezeře.", + "Zpívá píseň.": "Zpívá píseň.", + "Vaří polévku.": "Vaří polévku.", + "Čte knihu.": "Čte knihu.", + "Řídí auto.": "Řídí auto.", + "Maluje obraz.": "Maluje obraz.", + "Hraje fotbal.": "Hraje fotbal.", + "Spí.": "Spí.", + "Ahoj": "Ahoj", + "Dobré ráno": "Dobré ráno", + "Dobrý den": "Dobrý den", + "Dobrý večer": "Dobrý večer", + "Dobrý den (Bavorsko, Rakousko)": "Dobrý den (Bavorsko, Rakousko)", + "Ahoj / Čau": "Ahoj / Čau", + "Čau": "Čau", + "Na shledanou": "Na shledanou", + "Brzy na viděnou": "Brzy na viděnou", + "Do zítřka": "Do zítřka", + "Dobrou noc": "Dobrou noc", + "Zatím / Na viděnou": "Zatím / Na viděnou", + "Preclík": "Preclík", + "Klobása": "Klobása", + "Braniborská brána": "Braniborská brána", + "Značka aut": "Značka aut", + "Rakouský skladatel": "Rakouský skladatel", + "Čokoládový dort (Vídeň)": "Čokoládový dort (Vídeň)", + "Vídeňský řízek": "Vídeňský řízek", + "Sýr": "Sýr", + "Švýcarská hora": "Švýcarská hora", + "Čokoláda": "Čokoláda", + "Pochází z Rakouska.": "Pochází z Rakouska.", + "Bydlí ve Štýrském Hradci (Graz).": "Bydlí ve Štýrském Hradci (Graz).", + "Rád hraje golf.": "Rád hraje golf.", + "Mluví německy, anglicky a italsky.": "Mluví německy, anglicky a italsky.", + "Pocházejí ze Slovenska.": "Pocházejí ze Slovenska.", + "Bydlí v Bratislavě (ona).": "Bydlí v Bratislavě (ona).", + "Ona ráda tancuje.": "Ona ráda tancuje.", + "On rád cestuje.": "On rád cestuje.", + "Jsou dobří přátelé.": "Jsou dobří přátelé.", + "Pocházím z Atén.": "Pocházím z Atén.", + "Petr bydlí v Salcburku.": "Petr bydlí v Salcburku.", + "Berlín leží v Německu.": "Berlín leží v Německu.", + "Bydlíme v Paříži.": "Bydlíme v Paříži.", + "Pocházejí z Řecka.": "Pocházejí z Řecka.", + "Odkud je? – Z Londýna.": "Odkud je? – Z Londýna.", + "Jak se jmenuje? – Andrea.": "Jak se jmenuje? – Andrea.", + "Kdo pochází z Ruska? – Alexandr.": "Kdo pochází z Ruska? – Alexandr.", + "Kde leží Praha? – V Česku.": "Kde leží Praha? – V Česku.", + "Kde bydlí? – V Bratislavě.": "Kde bydlí? – V Bratislavě.", + "Co děláte? – Studujeme germanistiku.": "Co děláte? – Studujeme germanistiku.", + "Mluvím německy. A ty?": "Mluvím německy. A ty?", + "Kterými jazyky mluvíte?": "Kterými jazyky mluvíte?", + "Mluvíš francouzsky? – Ano, trochu.": "Mluvíš francouzsky? – Ano, trochu.", + "My mluvíme polsky a vy?": "My mluvíme polsky a vy?", + "Mluvíte anglicky? – Ano, velmi dobře.": "Mluvíte anglicky? – Ano, velmi dobře.", + "Nemluví ani slovo turecky.": "Nemluví ani slovo turecky.", + "Čech": "Čech", + "Španělka": "Španělka", + "Turek": "Turek", + "Chorvatka": "Chorvatka", + "Němka": "Němka", + "Rakušanka": "Rakušanka", + "Slovák": "Slovák", + "Švýcarka": "Švýcarka", + "Němec": "Němec", + "Německo": "Německo", + "Deutschland – Německo": "Deutschland – Německo", + "Slowakei – Slovensko": "Slowakei – Slovensko", + "Österreich – Rakousko": "Österreich – Rakousko", + "Spanien – Španělsko": "Spanien – Španělsko", + "England – Anglie": "England – Anglie", + "Polen – Polsko": "Polen – Polsko", + "Slovensko": "Slovensko", + "Rakousko": "Rakousko", + "Španělsko": "Španělsko", + "Anglie": "Anglie", + "Polsko": "Polsko", + "Rusko": "Rusko", + "Russland – Rusko": "Russland – Rusko", + "Türkei – Turecko": "Türkei – Turecko", + "Kroatien – Chorvatsko": "Kroatien – Chorvatsko", + "Griechenland – Řecko": "Griechenland – Řecko", + "Italien – Itálie": "Italien – Itálie", + "Turecko": "Turecko", + "Chorvatsko": "Chorvatsko", + "Řecko": "Řecko", + "Itálie": "Itálie", + "otec": "otec", + "rodiče": "rodiče", + "Češka": "Češka", + "student": "student", + "Co čte? – Knihu.": "Co čte? – Knihu.", + "Co studuje? – Medicínu.": "Co studuje? – Medicínu.", + "Čím Jan rád jezdí? – Autem.": "Čím Jan rád jezdí? – Autem.", + "Kde bydlíte? – Ve Vídni.": "Kde bydlíte? – Ve Vídni.", + "Kdo pracuje u Siemensu? – Moje kamarádka Věra.": "Kdo pracuje u Siemensu? – Moje kamarádka Věra.", + "Kam jedeš?": "Kam jedeš?", + "Co rád/a čteš?": "Co rád/a čteš?", + "Co rád/a hraješ?": "Co rád/a hraješ?", + "Jmenuji se Lukáš.": "Jmenuji se Lukáš.", + "Jedu do Německa.": "Jedu do Německa.", + "Rád/a čtu detektivky.": "Rád/a čtu detektivky.", + "Rád/a hraju golf.": "Rád/a hraju golf.", + "šedesát tři eur": "šedesát tři eur", + "třicet osm eur": "třicet osm eur", + "čtyřicet pět eur": "čtyřicet pět eur", + "padesát sedm eur": "padesát sedm eur", + "devadesát devět eur": "devadesát devět eur", + "Agnieszka Kowalski pochází z Polska, z Krakova.": "Agnieszka Kowalski pochází z Polska, z Krakova.", + "Je jí 18 let a letos dělá maturitu.": "Je jí 18 let a letos dělá maturitu.", + "Ráda chatuje se svým německým přítelem.": "Ráda chatuje se svým německým přítelem.", + "Jmenuje se Stefan Böhmermann a bydlí v Drážďanech.": "Jmenuje se Stefan Böhmermann a bydlí v Drážďanech.", + "Agnieszce přijde ten jazyk super.": "Agnieszce přijde ten jazyk super.", + "Už mluví velmi dobře německy.": "Už mluví velmi dobře německy.", + "potřebovat mobil": "potřebovat mobil", + "pracovat ve BMW": "pracovat ve BMW", + "řídit auto": "řídit auto", + "navštěvovat gymnázium": "navštěvovat gymnázium", + "mluvit španělsky": "mluvit španělsky", + "číst detektivky": "číst detektivky", + "padesát čtyři": "padesát čtyři", + "čtyřicet pět": "čtyřicet pět", + "tři sta šedesát devět": "tři sta šedesát devět", + "sto dvanáct": "sto dvanáct", + "sto dvacet dva": "sto dvacet dva", + "šedesát osm": "šedesát osm", + "Petr rád čte knihy.": "Petr rád čte knihy.", + "Filip pracuje v Salcburku.": "Filip pracuje v Salcburku.", + "Magda dobře mluví anglicky.": "Magda dobře mluví anglicky.", + "Marek navštěvuje gymnázium.": "Marek navštěvuje gymnázium.", + "Dominice je 15 let.": "Dominice je 15 let.", + "Moje sestra se jmenuje Marta.": "Moje sestra se jmenuje Marta.", + "Jak se jmenují? – Jana a Michael.": "Jak se jmenují? – Jana a Michael.", + "Kdo mluví polsky? – Jacek.": "Kdo mluví polsky? – Jacek.", + "Kde bydlí Eva? – V Plzni.": "Kde bydlí Eva? – V Plzni.", + "Odkud pochází Markus? – Z Německa.": "Odkud pochází Markus? – Z Německa.", + "Jakým jazykem mluví Jana? – Slovensky.": "Jakým jazykem mluví Jana? – Slovensky.", + "vaří v restauraci": "vaří v restauraci", + "léčí nemocné lidi": "léčí nemocné lidi", + "učí ve škole": "učí ve škole", + "pracuje u policie": "pracuje u policie", + "prodává v obchodě": "prodává v obchodě", + "z": "z", + "dělá": "dělá", + "kamarád": "kamarád", + "žije": "žije", + "jazyk": "jazyk", + "dobře": "dobře", + "potřebovat": "potřebovat", + "pracovat": "pracovat", + "řídit": "řídit", + "navštěvovat": "navštěvovat", + "mluvit": "mluvit", + "číst": "číst", + "bratranec / sestřenice": "bratranec / sestřenice", + "strýc / teta": "strýc / teta", + "dědeček / babička": "dědeček / babička", + "sestra / bratr": "sestra / bratr", + "kamarád / kamarádka": "kamarád / kamarádka", + "dcera / syn": "dcera / syn", + "Je to tvoje matka? – Ne, to není moje matka. To je jeho teta.": "Je to tvoje matka? – Ne, to není moje matka. To je jeho teta.", + "tvůj": "tvůj", + "tvoje": "tvoje", + "můj": "můj", + "moje": "moje", + "jeho": "jeho", + "Je to tvůj bratr? – Ne, to není můj bratr. To je jeho bratranec.": "Je to tvůj bratr? – Ne, to není můj bratr. To je jeho bratranec.", + "Jsou to tvoji rodiče? – Ne, to nejsou moji rodiče. To jsou rodiče Markuse.": "Jsou to tvoji rodiče? – Ne, to nejsou moji rodiče. To jsou rodiče Markuse.", + "Máš křečka? – Ne, nemám křečka. Mám želvu.": "Máš křečka? – Ne, nemám křečka. Mám želvu.", + "Máš koně? – Ne, nemám koně. Mám králíka.": "Máš koně? – Ne, nemám koně. Mám králíka.", + "Máš rybu? – Ne, nemám rybu. Mám ptáka.": "Máš rybu? – Ne, nemám rybu. Mám ptáka.", + "Máš morče? – Ne, nemám morče. Mám andulku.": "Máš morče? – Ne, nemám morče. Mám andulku.", + "Máme přátele v Rakousku. Bydlí ve Vídni.": "Máme přátele v Rakousku. Bydlí ve Vídni.", + "Jmenují se Elfriede a Jiří. Mají také děti.": "Jmenují se Elfriede a Jiří. Mají také děti.", + "Jejich syn se jmenuje Philipp a jejich dcera Sabine.": "Jejich syn se jmenuje Philipp a jejich dcera Sabine.", + "Rodina ráda cestuje.": "Rodina ráda cestuje.", + "Často je u nás na návštěvě v Česku.": "Často je u nás na návštěvě v Česku.", + "Rodina ráda cestuje. Často je u nás na návštěvě v Česku.": "Rodina ráda cestuje. Často je u nás na návštěvě v Česku.", + "Děti se učí také česky.": "Děti se učí také česky.", + "mít": "mít", + "přátelé": "přátelé", + "bydlet": "bydlet", + "jmenovat se": "jmenovat se", + "děti": "děti", + "syn": "syn", + "jejich": "jejich", + "rodina": "rodina", + "cestuje": "cestuje", + "často": "často", + "návštěva": "návštěva", + "Česko": "Česko", + "učit se": "učit se", + "čeština": "čeština", + "Máme mužskou domácnost: Můj otec Johann (50), Ivo (16) a já.": "Máme mužskou domácnost: Můj otec Johann (50), Ivo (16) a já.", + "Ivo a já jsme stejně staří – jsme totiž dvojčata.": "Ivo a já jsme stejně staří – jsme totiž dvojčata.", + "Náš otec tu má novou práci.": "Náš otec tu má novou práci.", + "Naši rodiče jsou rozvedení.": "Naši rodiče jsou rozvedení.", + "Naše matka Maja (50) žije ve Vídni, ale pochází z Chorvatska.": "Naše matka Maja (50) žije ve Vídni, ale pochází z Chorvatska.", + "Máme v Chorvatsku hodně strýců, tet, sestřenic a bratranců.": "Máme v Chorvatsku hodně strýců, tet, sestřenic a bratranců.", + "Vídáme je někdy o prázdninách.": "Vídáme je někdy o prázdninách.", + "křeček": "křeček", + "babička": "babička", + "kůň": "kůň", + "bratr": "bratr", + "kočka": "kočka", + "dědeček": "dědeček", + "dcera": "dcera", + "pes": "pes", + "teta": "teta", + "andulka": "andulka", + "Potřebuješ svůj mobil.": "Potřebuješ svůj mobil.", + "Má svého koně.": "Má svého koně.", + "Dělá svou párty.": "Dělá svou párty.", + "Ptá se svého učitele.": "Ptá se svého učitele.", + "Navštěvujeme náš víkendový dům.": "Navštěvujeme náš víkendový dům.", + "Vy vidíte svého psa.": "Vy vidíte svého psa.", + "Mají své nástroje.": "Mají své nástroje.", + "u3g_dein": "(tvůj)", + "u3g_sein": "(jeho)", + "u3g_ihr_sie": "(její)", + "u3g_sein_es": "(jeho)", + "u3g_unser": "(náš)", + "u3g_euer": "(váš)", + "u3g_ihr_sie_pl": "(jejich)", + "Mluvíš španělsky? – Ne, nemluvím španělsky.": "Mluvíš španělsky? – Ne, nemluvím španělsky.", + "Máš bratra? – Ne, nemám bratra.": "Máš bratra? – Ne, nemám bratra.", + "Je v Opavě zoo? – Ne, v Opavě žádná zoo není.": "Je v Opavě zoo? – Ne, v Opavě žádná zoo není.", + "Jdeš do bazénu? – Ne, do bazénu nejdu.": "Jdeš do bazénu? – Ne, do bazénu nejdu.", + "Rád chodí na túry? – Ne, nerad chodí na túry.": "Rád chodí na túry? – Ne, nerad chodí na túry.", + "Navštívíš dnes zámek? – Ne, dnes nenavštívím žádný zámek.": "Navštívíš dnes zámek? – Ne, dnes nenavštívím žádný zámek.", + "Mají želvu.": "Mají želvu.", + "Co dělá tvoje kamarádka o víkendu?": "Co dělá tvoje kamarádka o víkendu?", + "Můj otec je povoláním učitel.": "Můj otec je povoláním učitel.", + "Je vás doma hodně?": "Je vás doma hodně?", + "Julie představuje svého psa Trixiho.": "Julie představuje svého psa Trixiho.", + "Vidím hrad / zámek.": "Vidím hrad / zámek.", + "Vidím jezero.": "Vidím jezero.", + "Vidím rodinu.": "Vidím rodinu.", + "To je jeho mobil.": "To je jeho mobil.", + "To je její králík.": "To je její králík.", + "To jsou jejich brusle.": "To jsou jejich brusle.", + "To je její dort.": "To je její dort.", + "To je jeho dům.": "To je jeho dům.", + "To jsou jejich děti.": "To jsou jejich děti.", + "Je tu koncert.": "Je tu koncert.", + "Je tu výstava.": "Je tu výstava.", + "Je tu sportovní slavnost.": "Je tu sportovní slavnost.", + "Je tu rodinné setkání.": "Je tu rodinné setkání.", + "Je tu divadelní představení.": "Je tu divadelní představení.", + "Je tu bleší trh.": "Je tu bleší trh.", + "Vidím ženu.": "Vidím ženu.", + "Jezdí na kole.": "Jezdí na kole.", + "Vidím muže.": "Vidím muže.", + "Chodí po lese.": "Chodí po lese.", + "Vidím dvě děti.": "Vidím dvě děti.", + "Hrají fotbal.": "Hrají fotbal.", + "Moji prarodiče jedou o víkendu do víkendového domu.": "Moji prarodiče jedou o víkendu do víkendového domu.", + "Můj otec a moje matka navštíví koncert.": "Můj otec a moje matka navštíví koncert.", + "Moje sestra jde do kina.": "Moje sestra jde do kina.", + "Můj bratr jede k jezeru.": "Můj bratr jede k jezeru.", + "A já? Navštívím obchodní centrum.": "A já? Navštívím obchodní centrum.", + "Strana 10": "Strana 10", + "Strana 11": "Strana 11", + "Strana 12": "Strana 12", + "Strana 13": "Strana 13", + "Strana 14": "Strana 14", + "Strana 15": "Strana 15", + "večer": "večer", + "Dobrý večer!": "Dobrý večer!", + "ty": "ty", + "Těší mě.": "Těší mě.", + "dobrý": "dobrý", + "Ahoj!": "Ahoj!", + "Jmenuji se Jens.": "Jmenuji se Jens.", + "Ahoj! (neformálně)": "Ahoj! (neformálně)", + "já": "já", + "vy": "vy", + "ano": "ano", + "ráno": "ráno", + "jméno": "jméno", + "ne": "ne", + "je": "je", + "den": "den", + "Dobrý den!": "Dobrý den!", + "a": "a", + "kdo": "kdo", + "Kdo jsi?": "Kdo jsi?", + "jak": "jak", + "my": "my", + "v": "v", + "poblíž, v blízkosti": "poblíž, v blízkosti", + "hra": "hra", + "kde": "kde", + "nula": "nula", + "jedna": "jedna", + "dvě": "dvě", + "tři": "tři", + "čtyři": "čtyři", + "pět": "pět", + "sedm": "sedm", + "osm": "osm", + "devět": "devět", + "deset": "deset", + "jedenáct": "jedenáct", + "dvanáct": "dvanáct", + "patnáct": "patnáct", + "šestnáct": "šestnáct", + "osmnáct": "osmnáct", + "devatenáct": "devatenáct", + "starý": "starý", + "on": "on", + "měsíc": "měsíc", + "ona": "ona", + "oni": "oni", + "ale": "ale", + "věk": "věk", + "také": "také", + "(hudební) skupina": "(hudební) skupina", + "chatovat": "chatovat", + "počítačová hra": "počítačová hra", + "e-mail": "e-mail", + "angličtina, anglicky": "angličtina, anglicky", + "fanoušek": "fanoušek", + "francouzština, francouzsky": "francouzština, francouzsky", + "kamarádka": "kamarádka", + "nejlepší kamarádka": "nejlepší kamarádka", + "fotbal": "fotbal", + "Je fotbalový fanatik.": "Je fotbalový fanatik.", + "jít": "jít", + "Rád(a) chodím na koncerty.": "Rád(a) chodím na koncerty.", + "rád/a": "rád/a", + "kytara": "kytara", + "mobil": "mobil", + "koníček": "koníček", + "poslouchat": "poslouchat", + "Rád poslouchá hudbu.": "Rád poslouchá hudbu.", + "surfovat na internetu": "surfovat na internetu", + "pořád, neustále": "pořád, neustále", + "rok": "rok", + "žádný/žádná/žádné": "žádný/žádná/žádné", + "klavír": "klavír", + "přicházet, pocházet (z)": "přicházet, pocházet (z)", + "Pochází z Vídně.": "Pochází z Vídně.", + "koncert": "koncert", + "ležet": "ležet", + "příjmení": "příjmení", + "nedaleko od": "nedaleko od", + "cestovat": "cestovat", + "psát": "psát", + "škola": "škola", + "hrát": "hrát", + "Hraje na kytaru.": "Hraje na kytaru.", + "tancovat": "tancovat", + "křestní jméno": "křestní jméno", + "bydliště": "bydliště", + "nesprávně, chybně": "nesprávně, chybně", + "flétna": "flétna", + "(hudební) nástroj": "(hudební) nástroj", + "teď": "teď", + "dělat": "dělat", + "správně": "správně", + "sport": "sport", + "sportovat": "sportovat", + "squash": "squash", + "jóga": "jóga", + "brzy": "brzy", + "Brzy na shledanou!": "Brzy na shledanou!", + "do": "do", + "Do příštího setkání!": "Do příštího setkání!", + "paní": "paní", + "pan": "pan", + "Měj se hezky!": "Měj se hezky!", + "muzeum": "muzeum", + "Jdou do muzea.": "Jdou do muzea.", + "hezký": "hezký", + "Hezký zbytek dne!": "Hezký zbytek dne!", + "Ahoj! (servus)": "Ahoj! (servus)", + "Ahoj! (při loučení)": "Ahoj! (při loučení)", + "shledání": "shledání", + "Na shledanou!": "Na shledanou!", + "John von Neumann – americký matematik": "John von Neumann – americký matematik", + "Americký matematik s objevy v digitálních počítačích": "Americký matematik s objevy v digitálních počítačích", + "ALU = aritmeticko-logická jednotka": "ALU = aritmeticko-logická jednotka", + "Řadič řídí činnost ostatních částí": "Řadič řídí činnost ostatních částí", + "Operační paměť uchovává program i data": "Operační paměť uchovává program i data", + "Byl tvůrcem teorie her": "Byl tvůrcem teorie her", + "Nultá generace: 1938–1944": "Nultá generace: 1938–1944", + "Jen několik počítačů, většinou vojenský účel": "Jen několik počítačů, většinou vojenský účel", + "1. generace – objev elektronky": "1. generace – objev elektronky", + "1. generace – děrné štítky": "1. generace – děrné štítky", + "2. generace – objev tranzistoru": "2. generace – objev tranzistoru", + "3. generace – integrovaný obvod": "3. generace – integrovaný obvod", + "4. generace – programovatelné mikroprocesory": "4. generace – programovatelné mikroprocesory", + "1972 – první počítačová hra": "1972 – první počítačová hra", + "Bit = dvojková číslice, nejmenší jednotka informace": "Bit = dvojková číslice, nejmenší jednotka informace", + "Bit nabývá hodnoty 0 nebo 1": "Bit nabývá hodnoty 0 nebo 1", + "Byte = nejmenší adresovatelná jednotka paměti": "Byte = nejmenší adresovatelná jednotka paměti" + }, + "en": { + "Ahoj! Jmenuji se Anna.": "Hi! My name is Anna.", + "Ahoj! Jmenuji se Petr.": "Hi! My name is Petr.", + "Jmenuji se Anna.": "My name is Anna.", + "Jmenuji se Petr.": "My name is Petr.", + "Odkud jsi?": "Where are you from?", + "Odkud pocházíš?": "Where do you come from?", + "Pocházím z Česka.": "I come from Czechia.", + "Dobré ráno!": "Good morning!", + "Jak se máš?": "How are you?", + "Mám se dobře, děkuji.": "I am fine, thank you.", + "Musím jít. Na shledanou!": "I have to go. Goodbye!", + "Brzy na viděnou!": "See you soon!", + "Čau!": "Bye!", + "Jak se jmenuješ?": "What is your name?", + "Kde bydlíš?": "Where do you live?", + "Kdo to je?": "Who is that?", + "Kolik je ti let?": "How old are you?", + "Je mi šestnáct let.": "I am sixteen years old.", + "Bydlím v Praze.": "I live in Prague.", + "Hraji fotbal.": "I play football.", + "Co rád/a děláš?": "What do you like to do?", + "Kolik je hodin?": "What time is it?", + "Na shledanou.": "Goodbye.", + "Moc děkuji.": "Thank you very much.", + "„vierzehn“ = čtrnáct (14)": "“vierzehn” = fourteen (14)", + "„siebzehn“ = sedmnáct (17)": "“siebzehn” = seventeen (17)", + "„zwanzig“ = dvacet (20)": "“zwanzig” = twenty (20)", + "„sechs“ = šest (6)": "“sechs” = six (6)", + "1 B = 8 b": "1 B = 8 b", + "2⁸ = 256 hodnot (0–255)": "2⁸ = 256 values (0–255)", + "Kabely – síť zůstává připojená i po přenosu": "Cables – the network stays connected after transfer", + "WAN = Wide Area Network, např. internet": "WAN = Wide Area Network, e.g. the internet", + "Např. hvězda, kruh, sběrnice": "E.g. star, ring, bus", + "Architektura = topologie + standard": "Architecture = topology + standard", + "Bez centrálního serveru – stanice si sdílejí data a tiskárny": "No central server – stations share data and printers", + "Server řídí a poskytuje služby, má vyšší výkon": "A server controls and provides services; higher performance", + "Ověřují uživatele a povolují přístup ke službám": "They authenticate users and grant access to services", + "Fileserver = souborový server": "Fileserver = file server", + "Jeden server – při výpadku je služba nedostupná": "One server – if it fails, the service is unavailable", + "Více serverů, každý obsluhuje část – vyšší spolehlivost": "Multiple servers, each handles a part – higher reliability", + "Slouží zároveň i jako pracovní stanice": "It also works as a workstation", + "Jen síťové služby – vysoký výkon a bezpečnost, často v racku": "Network services only – high performance and security, often in a rack", + "Obří sálové počítače (IBM, Siemens) pro banky a státní správu": "Huge mainframe computers (IBM, Siemens) for banks and government", + "SaaS = software jako služba, přístup online z libovolného zařízení": "SaaS = software as a service, online access from any device", + "Více bitů najednou po více vodičích; problém jsou přeslechy": "Multiple bits at once over multiple wires; crosstalk is the problem", + "Přeslechy vznikají při delších kabelech a vysokých frekvencích": "Crosstalk occurs on longer cables and at high frequencies", + "Bit po bitu po jednom vodiči – vyšší frekvence i délky": "Bit by bit over one wire – higher frequencies and longer distances", + "Start-bit (0) synchronizuje, Stop-bit (1) ukončuje znak": "Start bit (0) synchronizes, stop bit (1) ends the character", + "Řízeno společným hodinovým signálem a přesným časováním": "Controlled by a shared clock signal and precise timing", + "Nejslabší – přidá bit pro sudý/lichý počet jedniček": "Weakest – adds a bit for even/odd number of ones", + "Součet znaků jako dvojkových čísel": "Sum of characters treated as binary numbers", + "Nejbezpečnější – počítá se z jednotlivých bitů v bloku": "Most secure – computed from individual bits in the block", + "Analogový je spojitý, digitální má diskrétní hodnoty 0 a 1": "Analog is continuous; digital has discrete 0 and 1 values", + "Frekvence f = 1/T, kde T je perioda": "Frequency f = 1/T, where T is the period", + "AM mění amplitudu, FM frekvenci, PM fázi": "AM changes amplitude, FM frequency, PM phase", + "QPSK nese 2 bity v prvku, 256-QAM nese 8 bitů": "QPSK carries 2 bits per symbol, 256-QAM carries 8 bits", + "Modulační rychlost = počet změn signálu za sekundu [Bd/s]": "Modulation rate = number of signal changes per second [Bd/s]", + "Přenosová rychlost = množství informace za sekundu [bit/s]": "Bit rate = amount of information per second [bit/s]", + "Šířka pásma určuje maximální možnou přenosovou rychlost": "Bandwidth determines the maximum possible bit rate", + "Datový spoj umožňuje výměnu informací mezi uzly": "A data link enables information exchange between nodes", + "Fyzické médium: kabely, mikrovlny nebo družice": "Physical medium: cables, microwaves or satellites", + "Kanál je jednosměrný souhrn prostředků pro spojení": "A channel is a one-way set of means for a connection", + "Okruh tvoří dva kanály pro obousměrný přenos": "A circuit is made of two channels for two-way transfer", + "Trunking spojuje více cest do jednoho okruhu": "Trunking joins multiple paths into one circuit", + "Trunking zvyšuje šířku pásma spojením cest": "Trunking increases bandwidth by combining paths", + "Multiplex dělí jeden kanál na více logických podkanálů": "Multiplexing splits one channel into multiple logical subchannels", + "FDM: každému kanálu část frekvenčního pásma": "FDM: each channel gets part of the frequency band", + "TDM: každému kanálu vyhrazený časový slot": "TDM: each channel gets a reserved time slot", + "STDM přiděluje kapacitu dle potřeby, negarantuje 100 %": "STDM allocates capacity on demand and does not guarantee 100%", + "Simplex = jen jeden směr přenosu": "Simplex = only one transmission direction", + "Half-duplex = oběma směry, ale ne současně": "Half-duplex = both directions, but not at the same time", + "Full-duplex = oběma směry současně": "Full-duplex = both directions at the same time", + "Agregace = sdílení kapacity kanálu více uživateli": "Aggregation = sharing channel capacity among multiple users", + "Cesta se vytýčí předem, kapacita je garantována": "The path is set up in advance and capacity is guaranteed", + "Data se dělí na pakety, každý může jít jinou cestou": "Data are split into packets; each may take a different path", + "Výhody: reakce na zátěž a lepší využití kapacity": "Advantages: reaction to load and better capacity use", + "Negarantuje pořadí ani plynulost – nevhodné pro živé video": "Does not guarantee order or smoothness – unsuitable for live video", + "Cesta je předem, prostředky se použijí jen při průchodu paketu": "Path is preset; resources are used only when a packet passes", + "Virtuální spoje zrychlují přenos datagramů": "Virtual circuits speed up datagram transfer", + "Standardizace zajišťuje kompatibilitu mezi výrobci": "Standardization ensures compatibility between vendors", + "Dekompozice rozkládá přenos na jednotlivé vrstvy": "Decomposition splits transmission into individual layers", + "Vrstvy komunikují jen se sousedy přes rozhraní SAP": "Layers communicate only with neighbors through SAP interfaces", + "Protokol = pravidla mezi stejnými vrstvami na různých uzlech": "A protocol is rules between the same layers on different nodes", + "Každá vrstva přidává k datům hlavičku (header)": "Each layer adds a header to the data", + "Rámec = linková, paket = síťová, segment = transportní": "Frame = link, packet = network, segment = transport", + "ISO/OSI má 7 vrstev a je univerzální model": "ISO/OSI has 7 layers and is a universal model", + "V praxi je ISO/OSI pomalejší – spolehlivost řeší každá vrstva": "In practice ISO/OSI is slower – each layer handles reliability", + "TCP/IP zvítězil, protože vycházel ze skutečných potřeb": "TCP/IP won because it came from real-world needs", + "V TCP/IP řeší spolehlivost až vyšší vrstvy": "In TCP/IP, reliability is handled by higher layers", + "Fyzická vrstva přenáší bity a řeší médium": "The physical layer transmits bits and handles the medium", + "Spojová vrstva má podvrstvy MAC a LLC": "The data-link layer has MAC and LLC sublayers", + "Síťová vrstva směruje pakety i bez přímého spojení": "The network layer routes packets even without a direct link", + "Transportní vrstva je jen v koncových uzlech, ne v routerech": "The transport layer exists only in end nodes, not in routers", + "Relační vrstva řídí relace, dialog a synchronizaci": "The session layer manages sessions, dialogue and synchronization", + "Prezentační vrstva formátuje data, komprimuje a šifruje": "The presentation layer formats, compresses and encrypts data", + "Aplikační vrstva je rozhraní pro programy a služby": "The application layer is the interface for programs and services", + "Aplikační TCP/IP = aplikační + prezentační + relační ISO/OSI": "TCP/IP application = ISO/OSI application + presentation + session", + "Síťové rozhraní TCP/IP = linková + fyzická ISO/OSI": "TCP/IP network interface = ISO/OSI data-link + physical", + "U TCP/IP vznikly nejdřív protokoly, až pak model": "With TCP/IP, protocols came first and the model later", + "TCP je spolehlivý a spojovaný": "TCP is reliable and connection-oriented", + "UDP je nespolehlivý a rychlý": "UDP is unreliable and fast", + "HTTP, DNS a SMTP jsou aplikační protokoly": "HTTP, DNS and SMTP are application protocols", + "IP, ICMP a OSPF patří na síťovou (internetovou) vrstvu": "IP, ICMP and OSPF belong to the network (internet) layer", + "Ethernet a PPP patří na vrstvu síťového rozhraní": "Ethernet and PPP belong to the network interface layer", + "Sběrnice: médium sdílí všichni": "Bus: the medium is shared by everyone", + "Sběrnice: nízká bezpečnost a porucha kabelu vyřadí síť": "Bus: low security and a cable fault takes down the network", + "Hvězda: uzly jdou přes hub nebo switch": "Star: nodes connect through a hub or switch", + "Hvězda: porucha kabelu k uzlu nevyřadí celou síť": "Star: a cable fault to one node does not take down the whole network", + "Hvězda používá kroucenou dvoulinku nebo optiku": "Star uses twisted pair or fiber", + "V kruhu zprávy obíhají, dokud nenajdou adresáta": "In a ring, messages circulate until they find the recipient", + "Optika: el. impulsy → světlo (LED/laser) → fotodioda": "Optics: electrical pulses → light (LED/laser) → photodiode", + "Jedno vlákno = jednosměrný přenos; obousměrně dvě vlákna": "One fiber = one-way; two fibers for bidirectional use", + "Nevýhody: náročná montáž a cena prvků/konektorů": "Drawbacks: difficult installation and costly parts/connectors", + "MM: jádro 50/62,5 µm a více vidů": "MM: 50/62.5 µm core and multiple modes", + "SM: jádro 7–10 µm, jeden paprsek, laser": "SM: 7–10 µm core, one beam, laser", + "MM typicky používá levnější LED zdroje": "MM typically uses cheaper LED sources", + "Primární ochrana: 250 µm": "Primary protection: 250 µm", + "Sekundární ochrana: 900 µm": "Secondary protection: 900 µm", + "Těsná sekundární ochrana: svislé instalace": "Tight secondary protection: vertical installs", + "Volná sekundární ochrana: vodorovné instalace": "Loose secondary protection: horizontal installs", + "Montáž: lámačka a svářečka optických vláken": "Installation: cleaver and optical fiber splicer", + "Lámání vyžaduje kolmost asi 0,5°": "Cleaving requires roughly 0.5° squareness", + "Kolize = více uzlů vysílá na sdíleném médiu najednou": "A collision is multiple nodes transmitting on a shared medium at once", + "Aloha: vysílej kdykoliv, při chybě znovu": "Aloha: transmit anytime; retry if there is no acknowledgment", + "CSMA/CD patří k Ethernetu": "CSMA/CD belongs to Ethernet", + "CSMA/CD nejdřív poslouchá nosnou (Carrier Sense)": "CSMA/CD first listens for the carrier (Carrier Sense)", + "Po kolizi CSMA/CD čeká náhodný čas a zkusí znovu": "After a collision, CSMA/CD waits a random time and retries", + "CSMA/CA rezervuje médium přes RTS/CTS": "CSMA/CA reserves the medium with RTS/CTS", + "Repeater zesiluje signál na fyzické vrstvě": "A repeater amplifies the signal at the physical layer", + "Transceiver převádí mezi médii (např. metalika ↔ optika)": "A transceiver converts between media (e.g. copper ↔ fiber)", + "Hub rozešle přijatá data do všech ostatních portů": "A hub floods received data to all other ports", + "Bridge/switch = linková vrstva, rámce a MAC": "Bridge/switch = data-link layer, frames and MAC", + "Switch dělí síť na kolizní domény": "A switch splits the network into collision domains", + "Router = síťová vrstva, pakety a IP, propojuje sítě": "A router = network layer, packets and IP, connects networks", + "Gateway převádí mezi odlišnými architekturami/protokoly": "A gateway converts between different architectures/protocols", + "MAC adresy switch ukládá do CAM tabulky": "A switch stores MAC addresses in the CAM table", + "Podle CAM tabulky posílá rámec jen na cílový port": "Using the CAM table, it forwards a frame only to the target port", + "Cut-through čte adresu příjemce a hned přeposílá": "Cut-through reads the destination address and forwards immediately", + "Cut-through je rychlý, ale propustí i chyby": "Cut-through is fast but also forwards errors", + "Store-and-forward kontroluje celý rámec včetně CRC": "Store-and-forward checks the whole frame including CRC", + "Fragment-free čte prvních 64 bytů kvůli kolizím": "Fragment-free reads the first 64 bytes for collision detection", + "Směrování běží na síťové (3.) vrstvě ISO/OSI": "Routing runs on the network (3rd) ISO/OSI layer", + "Adaptivní algoritmy reagují na změny a sdílí stav sítě": "Adaptive algorithms react to changes and share network state", + "Statické cesty nastaví správce a samy se nemění": "Static routes are set by an admin and do not change themselves", + "Centralizované směrování padá s výpadkem centra": "Centralized routing fails if the center fails", + "Distribuované: výměna informací a vlastní tabulky": "Distributed: information exchange and local tables", + "Nižší metrika = lepší / rychlejší trasa": "Lower metric = better / faster route", + "Distance Vector: výměna tabulek se sousedy (např. každých 30 s)": "Distance Vector: exchange tables with neighbors (e.g. every 30 s)", + "Router pracuje na síťové (3.) vrstvě": "A router works at the network (3rd) layer", + "Router segmentuje podsítě a zajišťuje WAN přístup": "A router segments subnets and provides WAN access", + "Firewall filtruje pakety a služby": "A firewall filters packets and services", + "Multiprotokolový router spojuje různé protokoly/standardy": "A multiprotocol router joins different protocols/standards", + "Router dělí síť na broadcastové domény": "A router splits the network into broadcast domains", + "Gateway připojuje LAN na odlišné prostředí": "A gateway connects a LAN to a different environment", + "Pojem brána někdy označuje router nebo LAN–WAN připojení": "Gateway sometimes means a router or LAN–WAN connection", + "MAC adresa Ethernetu má 48 bitů a je unikátní": "An Ethernet MAC address is 48 bits and unique", + "IEEE přidělí výrobci první 3 byty adresy": "IEEE assigns the manufacturer the first 3 address bytes", + "Ethernet II: EtherType > 1500 (IP = 0800h)": "Ethernet II: EtherType > 1500 (IP = 0800h)", + "IEEE 802.3: délka ≤ 1500 a rámec 802.2": "IEEE 802.3: length ≤ 1500 and an 802.2 frame", + "Raw 802.3: Novell/IPX, začíná FFFFh": "Raw 802.3: Novell/IPX, starts with FFFFh", + "Max. Ethernet II = 1518 B": "Max Ethernet II frame = 1518 B", + "Min. rámec 64 B kvůli koliznímu okénku": "Min frame is 64 B due to the collision window", + "IP je nespojovaný a nespolehlivý": "IP is connectionless and unreliable", + "Routing = rozhodnutí o směru datagramu": "Routing = deciding the next direction of a datagram", + "Forwarding = vložení do rámce a odeslání": "Forwarding = placing into a frame and sending", + "HLEN 5 = 5 × 4 B = 20 B hlavičky": "HLEN 5 = 5 × 4 B = 20 B header", + "TTL snižují směrovače proti zacyklení": "Routers decrease TTL to prevent loops", + "PROTOCOL 6 = TCP": "PROTOCOL 6 = TCP", + "PROTOCOL 17 = UDP": "PROTOCOL 17 = UDP", + "Ethernet MTU = 1500 B": "Ethernet MTU = 1500 B", + "ICMP posílá informace o chybách a stavu přenosu": "ICMP sends information about errors and transfer status", + "ICMP jede uvnitř IP datagramu": "ICMP is carried inside an IP datagram", + "Source Quench = zpomal odesílání kvůli zahlcení": "Source Quench = slow down sending due to congestion", + "Time Exceeded = TTL kleslo na 0": "Time Exceeded = TTL dropped to 0", + "Echo Request/Reply = ping": "Echo Request/Reply = ping", + "Traceroute zvyšuje TTL a čte Time Exceeded": "Traceroute raises TTL and reads Time Exceeded", + "ARP: IP → MAC": "ARP: IP → MAC", + "RARP: MAC → IP": "RARP: MAC → IP", + "Nejčastější je dynamický dotaz a odpověď": "The most common way is a dynamic query and reply", + "ARP dotaz jde broadcastem": "An ARP request goes out as a broadcast", + "ARP odpověď je unicast s MAC": "An ARP reply is a unicast with the MAC", + "ARP cache ukládá výsledky dočasně (arp -a)": "ARP cache stores results temporarily (arp -a)", + "TCP = spolehlivý a spojovaný": "TCP = reliable and connection-oriented", + "UDP = nespolehlivý, nespojovaný, malá režie": "UDP = unreliable, connectionless, low overhead", + "Porty rozlišují aplikace na uzlu": "Ports distinguish applications on a node", + "TCP se navazuje three-way handshake": "TCP is established with a three-way handshake", + "TCP hlavička 20 B, UDP 8 B": "TCP header is 20 B, UDP is 8 B", + "TCP čeká na znovudoručení – špatné pro real-time": "TCP waits for retransmission – bad for real-time", + "SCTP: multihoming a multistreaming": "SCTP: multihoming and multistreaming", + "Aplikace posílají data přes TCP/UDP": "Applications send data over TCP/UDP", + "Dva procesy nesmí sdílet stejný port": "Two processes must not share the same port", + "Well-known: 0–1023 (IANA)": "Well-known: 0–1023 (IANA)", + "Dynamické porty: 49152–65535": "Dynamic ports: 49152–65535", + "Spojení = pětice hodnot": "A connection is a 5-tuple", + "HTTP 80, HTTPS 443": "HTTP 80, HTTPS 443", + "SSH 22, DNS 53": "SSH 22, DNS 53", + "MySQL 3306, RDP 3389": "MySQL 3306, RDP 3389", + "Geostacionární družice ~36 000 km": "Geostationary satellites ~36,000 km", + "Družice: zpoždění stovky ms": "Satellites: hundreds of ms delay", + "VSAT: jen terminál ↔ hub": "VSAT: only terminal ↔ hub", + "Mikrovlny: přímá viditelnost ~50 km": "Microwaves: line of sight ~50 km", + "STA komunikují přes AP": "STAs communicate via an AP", + "Wi-Fi 6 (ax): OFDMA": "Wi-Fi 6 (ax): OFDMA", + "WEP prolomen – nepoužívat": "WEP is broken – do not use", + "Používej WPA2/WPA3 + AES": "Use WPA2/WPA3 + AES", + "čtrnáct": "fourteen", + "sedmnáct": "seventeen", + "dvacet": "twenty", + "šest": "six", + "třináct": "thirteen", + "dvě jablka": "two apples", + "pět hvězd": "five stars", + "sedm koček": "seven cats", + "devět květin": "nine flowers", + "tři auta": "three cars", + "jedenáct knih": "eleven books", + "čtyři svíčky": "four candles", + "osm míčů": "eight balls", + "šest ptáků": "six birds", + "šest, sedm, osm, devět": "six, seven, eight, nine", + "dvanáct, třináct, čtrnáct, patnáct": "twelve, thirteen, fourteen, fifteen", + "osmnáct, devatenáct, dvacet, dvacet jedna": "eighteen, nineteen, twenty, twenty-one", + "čtyři, pět, šest, sedm": "four, five, six, seven", + "deset, jedenáct, dvanáct, třináct": "ten, eleven, twelve, thirteen", + "Plave v jezeře.": "He/She is swimming in the lake.", + "Zpívá píseň.": "He/She is singing a song.", + "Vaří polévku.": "He/She is cooking soup.", + "Čte knihu.": "He/She is reading a book.", + "Řídí auto.": "He/She is driving a car.", + "Maluje obraz.": "He/She is painting a picture.", + "Hraje fotbal.": "He/She is playing football.", + "Spí.": "He/She is sleeping.", + "Ahoj": "Hi", + "Dobré ráno": "Good morning", + "Dobrý den": "Good day", + "Dobrý večer": "Good evening", + "Dobrý den (Bavorsko, Rakousko)": "Good day (Bavaria, Austria)", + "Ahoj / Čau": "Hi / Hey", + "Čau": "Bye", + "Na shledanou": "Goodbye", + "Brzy na viděnou": "See you soon", + "Do zítřka": "See you tomorrow", + "Dobrou noc": "Good night", + "Zatím / Na viděnou": "See you later", + "Preclík": "Pretzel", + "Klobása": "Sausage", + "Braniborská brána": "Brandenburg Gate", + "Značka aut": "Car brand", + "Rakouský skladatel": "Austrian composer", + "Čokoládový dort (Vídeň)": "Chocolate cake (Vienna)", + "Vídeňský řízek": "Viennese schnitzel", + "Sýr": "Cheese", + "Švýcarská hora": "Swiss mountain", + "Čokoláda": "Chocolate", + "Pochází z Rakouska.": "He is from Austria.", + "Bydlí ve Štýrském Hradci (Graz).": "He lives in Graz.", + "Rád hraje golf.": "He likes playing golf.", + "Mluví německy, anglicky a italsky.": "He speaks German, English and Italian.", + "Pocházejí ze Slovenska.": "They are from Slovakia.", + "Bydlí v Bratislavě (ona).": "She lives in Bratislava.", + "Ona ráda tancuje.": "She likes dancing.", + "On rád cestuje.": "He likes travelling.", + "Jsou dobří přátelé.": "They are good friends.", + "Pocházím z Atén.": "I am from Athens.", + "Petr bydlí v Salcburku.": "Peter lives in Salzburg.", + "Berlín leží v Německu.": "Berlin is in Germany.", + "Bydlíme v Paříži.": "We live in Paris.", + "Pocházejí z Řecka.": "They are from Greece.", + "Odkud je? – Z Londýna.": "Where is he from? – From London.", + "Jak se jmenuje? – Andrea.": "What is her name? – Andrea.", + "Kdo pochází z Ruska? – Alexandr.": "Who comes from Russia? – Alexander.", + "Kde leží Praha? – V Česku.": "Where is Prague? – In Czechia.", + "Kde bydlí? – V Bratislavě.": "Where do they live? – In Bratislava.", + "Co děláte? – Studujeme germanistiku.": "What are you doing? – We're studying German studies.", + "Mluvím německy. A ty?": "I speak German. And you?", + "Kterými jazyky mluvíte?": "Which languages do you speak?", + "Mluvíš francouzsky? – Ano, trochu.": "Do you speak French? – Yes, a little.", + "My mluvíme polsky a vy?": "We speak Polish and you?", + "Mluvíte anglicky? – Ano, velmi dobře.": "Do you speak English? – Yes, very well.", + "Nemluví ani slovo turecky.": "He doesn't speak a word of Turkish.", + "Čech": "Czech man", + "Španělka": "Spanish woman", + "Turek": "Turk (man)", + "Chorvatka": "Croatian woman", + "Němka": "German woman", + "Rakušanka": "Austrian woman", + "Slovák": "Slovak man", + "Švýcarka": "Swiss woman", + "Němec": "German man", + "Německo": "Germany", + "Deutschland – Německo": "Deutschland – Germany", + "Slowakei – Slovensko": "Slowakei – Slovakia", + "Österreich – Rakousko": "Österreich – Austria", + "Spanien – Španělsko": "Spanien – Spain", + "England – Anglie": "England – England", + "Polen – Polsko": "Polen – Poland", + "Slovensko": "Slovakia", + "Rakousko": "Austria", + "Španělsko": "Spain", + "Anglie": "England", + "Polsko": "Poland", + "Rusko": "Russia", + "Russland – Rusko": "Russland – Russia", + "Türkei – Turecko": "Türkei – Turkey", + "Kroatien – Chorvatsko": "Kroatien – Croatia", + "Griechenland – Řecko": "Griechenland – Greece", + "Italien – Itálie": "Italien – Italy", + "Turecko": "Turkey", + "Chorvatsko": "Croatia", + "Řecko": "Greece", + "Itálie": "Italy", + "otec": "father", + "rodiče": "parents", + "Češka": "Czech woman", + "student": "student", + "Co čte? – Knihu.": "What is he reading? – A book.", + "Co studuje? – Medicínu.": "What is she studying? – Medicine.", + "Čím Jan rád jezdí? – Autem.": "What does Jan like to drive? – A car.", + "Kde bydlíte? – Ve Vídni.": "Where do you live? – In Vienna.", + "Kdo pracuje u Siemensu? – Moje kamarádka Věra.": "Who works at Siemens? – My friend Vera.", + "Kam jedeš?": "Where are you going?", + "Co rád/a čteš?": "What do you like to read?", + "Co rád/a hraješ?": "What do you like to play?", + "Jmenuji se Lukáš.": "My name is Lukáš.", + "Jedu do Německa.": "I'm going to Germany.", + "Rád/a čtu detektivky.": "I like reading crime novels.", + "Rád/a hraju golf.": "I like playing golf.", + "šedesát tři eur": "sixty-three euros", + "třicet osm eur": "thirty-eight euros", + "čtyřicet pět eur": "forty-five euros", + "padesát sedm eur": "fifty-seven euros", + "devadesát devět eur": "ninety-nine euros", + "Agnieszka Kowalski pochází z Polska, z Krakova.": "Agnieszka Kowalski is from Kraków, Poland.", + "Je jí 18 let a letos dělá maturitu.": "She is 18 years old and is taking her A-levels this year.", + "Ráda chatuje se svým německým přítelem.": "She likes chatting with her German friend.", + "Jmenuje se Stefan Böhmermann a bydlí v Drážďanech.": "His name is Stefan Böhmermann and he lives in Dresden.", + "Agnieszce přijde ten jazyk super.": "Agnieszka thinks the language is cool.", + "Už mluví velmi dobře německy.": "She already speaks German very well.", + "potřebovat mobil": "to need a mobile phone", + "pracovat ve BMW": "to work at BMW", + "řídit auto": "to drive a car", + "navštěvovat gymnázium": "to attend a grammar school", + "mluvit španělsky": "to speak Spanish", + "číst detektivky": "to read crime novels", + "padesát čtyři": "fifty-four", + "čtyřicet pět": "forty-five", + "tři sta šedesát devět": "three hundred and sixty-nine", + "sto dvanáct": "one hundred and twelve", + "sto dvacet dva": "one hundred and twenty-two", + "šedesát osm": "sixty-eight", + "Petr rád čte knihy.": "Peter likes reading books.", + "Filip pracuje v Salcburku.": "Filip works in Salzburg.", + "Magda dobře mluví anglicky.": "Magda speaks English well.", + "Marek navštěvuje gymnázium.": "Marek attends the grammar school.", + "Dominice je 15 let.": "Dominika is 15 years old.", + "Moje sestra se jmenuje Marta.": "My sister is called Marta.", + "Jak se jmenují? – Jana a Michael.": "What are their names? – Jana and Michael.", + "Kdo mluví polsky? – Jacek.": "Who speaks Polish? – Jacek.", + "Kde bydlí Eva? – V Plzni.": "Where does Eva live? – In Plzeň.", + "Odkud pochází Markus? – Z Německa.": "Where is Markus from? – From Germany.", + "Jakým jazykem mluví Jana? – Slovensky.": "What language does Jana speak? – Slovak.", + "vaří v restauraci": "he cooks in a restaurant", + "léčí nemocné lidi": "he treats sick people", + "učí ve škole": "he teaches at school", + "pracuje u policie": "he works for the police", + "prodává v obchodě": "he sells in a shop", + "z": "from", + "dělá": "does", + "kamarád": "friend", + "žije": "lives", + "jazyk": "language", + "dobře": "well", + "potřebovat": "to need", + "pracovat": "to work", + "řídit": "to drive", + "navštěvovat": "to attend", + "mluvit": "to speak", + "číst": "to read", + "bratranec / sestřenice": "male cousin / female cousin", + "strýc / teta": "uncle / aunt", + "dědeček / babička": "grandfather / grandmother", + "sestra / bratr": "sister / brother", + "kamarád / kamarádka": "friend (m) / friend (f)", + "dcera / syn": "daughter / son", + "Je to tvoje matka? – Ne, to není moje matka. To je jeho teta.": "Is that your mother? – No, that is not my mother. That is his aunt.", + "tvůj": "yours (m.)", + "tvoje": "yours (f.)", + "můj": "mine (m.)", + "moje": "mine (f.)", + "jeho": "his", + "Je to tvůj bratr? – Ne, to není můj bratr. To je jeho bratranec.": "Is that your brother? – No, that is not my brother. That is his cousin.", + "Jsou to tvoji rodiče? – Ne, to nejsou moji rodiče. To jsou rodiče Markuse.": "Are those your parents? – No, those are not my parents. Those are Markus's parents.", + "Máš křečka? – Ne, nemám křečka. Mám želvu.": "Have you got a hamster? – No, I haven't got a hamster. I have a tortoise.", + "Máš koně? – Ne, nemám koně. Mám králíka.": "Have you got a horse? – No, I haven't got a horse. I have a rabbit.", + "Máš rybu? – Ne, nemám rybu. Mám ptáka.": "Have you got a fish? – No, I haven't got a fish. I have a bird.", + "Máš morče? – Ne, nemám morče. Mám andulku.": "Have you got a guinea pig? – No, I haven't got a guinea pig. I have a budgie.", + "Máme přátele v Rakousku. Bydlí ve Vídni.": "We have friends in Austria. They live in Vienna.", + "Jmenují se Elfriede a Jiří. Mají také děti.": "They are called Elfriede and Jiri. They also have children.", + "Jejich syn se jmenuje Philipp a jejich dcera Sabine.": "Their son is called Philipp and their daughter Sabine.", + "Rodina ráda cestuje.": "The family likes travelling.", + "Často je u nás na návštěvě v Česku.": "They often visit us in Czechia.", + "Rodina ráda cestuje. Často je u nás na návštěvě v Česku.": "The family likes travelling. They often visit us in Czechia.", + "Děti se učí také česky.": "The children are also learning Czech.", + "mít": "to have", + "přátelé": "friends", + "bydlet": "to live", + "jmenovat se": "to be called", + "děti": "children", + "syn": "son", + "jejich": "their", + "rodina": "family", + "cestuje": "travels", + "často": "often", + "návštěva": "visit", + "Česko": "Czechia", + "učit se": "to learn", + "čeština": "Czech", + "Máme mužskou domácnost: Můj otec Johann (50), Ivo (16) a já.": "We live in an all-male household: my father Johann (50), Ivo (16) and me.", + "Ivo a já jsme stejně staří – jsme totiž dvojčata.": "Ivo and I are the same age – we are twins.", + "Náš otec tu má novou práci.": "Our father has a new job here.", + "Naši rodiče jsou rozvedení.": "Our parents are divorced.", + "Naše matka Maja (50) žije ve Vídni, ale pochází z Chorvatska.": "Our mother Maja (50) lives in Vienna, but she comes from Croatia.", + "Máme v Chorvatsku hodně strýců, tet, sestřenic a bratranců.": "We have many uncles, aunts, male and female cousins in Croatia.", + "Vídáme je někdy o prázdninách.": "We sometimes see them on holiday.", + "křeček": "hamster", + "babička": "grandmother", + "kůň": "horse", + "bratr": "brother", + "kočka": "cat", + "dědeček": "grandfather", + "dcera": "daughter", + "pes": "dog", + "teta": "aunt", + "andulka": "budgerigar", + "Potřebuješ svůj mobil.": "You need your mobile.", + "Má svého koně.": "He has his horse.", + "Dělá svou párty.": "She is throwing her party.", + "Ptá se svého učitele.": "It is asking its teacher.", + "Navštěvujeme náš víkendový dům.": "We are visiting our weekend house.", + "Vy vidíte svého psa.": "You see your dog.", + "Mají své nástroje.": "They have their instruments.", + "u3g_dein": "(your)", + "u3g_sein": "(his)", + "u3g_ihr_sie": "(her)", + "u3g_sein_es": "(its)", + "u3g_unser": "(our)", + "u3g_euer": "(your)", + "u3g_ihr_sie_pl": "(their)", + "Mluvíš španělsky? – Ne, nemluvím španělsky.": "Do you speak Spanish? – No, I don't speak any Spanish.", + "Máš bratra? – Ne, nemám bratra.": "Have you got a brother? – No, I haven't got a brother.", + "Je v Opavě zoo? – Ne, v Opavě žádná zoo není.": "Is there a zoo in Opava? – No, there is no zoo in Opava.", + "Jdeš do bazénu? – Ne, do bazénu nejdu.": "Are you going to the swimming pool? – No, I am not going to the swimming pool.", + "Rád chodí na túry? – Ne, nerad chodí na túry.": "Does he like hiking? – No, he does not like hiking.", + "Navštívíš dnes zámek? – Ne, dnes nenavštívím žádný zámek.": "Are you visiting a castle today? – No, I am not visiting a castle today.", + "Mají želvu.": "They have a tortoise.", + "Co dělá tvoje kamarádka o víkendu?": "What does your friend do at the weekend?", + "Můj otec je povoláním učitel.": "My father is a teacher by profession.", + "Je vás doma hodně?": "Are there many of you at home?", + "Julie představuje svého psa Trixiho.": "Julia is introducing her dog Trixi.", + "Vidím hrad / zámek.": "I see a castle.", + "Vidím jezero.": "I see a lake.", + "Vidím rodinu.": "I see a family.", + "To je jeho mobil.": "That is his mobile.", + "To je její králík.": "That is her rabbit.", + "To jsou jejich brusle.": "Those are their inline skates.", + "To je její dort.": "That is her cake.", + "To je jeho dům.": "That is his house.", + "To jsou jejich děti.": "Those are their children.", + "Je tu koncert.": "There is a concert.", + "Je tu výstava.": "There is an exhibition.", + "Je tu sportovní slavnost.": "There is a sports festival.", + "Je tu rodinné setkání.": "There is a family reunion.", + "Je tu divadelní představení.": "There is a theatre performance.", + "Je tu bleší trh.": "There is a flea market.", + "Vidím ženu.": "I see a woman.", + "Jezdí na kole.": "She is riding a bike.", + "Vidím muže.": "I see a man.", + "Chodí po lese.": "He is hiking in the forest.", + "Vidím dvě děti.": "I see two children.", + "Hrají fotbal.": "They are playing football.", + "Moji prarodiče jedou o víkendu do víkendového domu.": "My grandparents are driving to their weekend house.", + "Můj otec a moje matka navštíví koncert.": "My father and my mother are going to a concert.", + "Moje sestra jde do kina.": "My sister is going to the cinema.", + "Můj bratr jede k jezeru.": "My brother is driving to a lake.", + "A já? Navštívím obchodní centrum.": "And me? I am going to a shopping centre.", + "Strana 10": "Page 10", + "Strana 11": "Page 11", + "Strana 12": "Page 12", + "Strana 13": "Page 13", + "Strana 14": "Page 14", + "Strana 15": "Page 15", + "večer": "evening", + "Dobrý večer!": "Good evening!", + "ty": "you", + "Těší mě.": "Nice to meet you.", + "dobrý": "good", + "Ahoj!": "Hello!", + "Jmenuji se Jens.": "My name is Jens.", + "Ahoj! (neformálně)": "Hi! (informal)", + "já": "I", + "vy": "you (plural)", + "ano": "yes", + "ráno": "morning", + "jméno": "name", + "ne": "no", + "je": "is", + "den": "day", + "Dobrý den!": "Good day!", + "a": "and", + "kdo": "who", + "Kdo jsi?": "Who are you?", + "jak": "how", + "my": "we", + "v": "in", + "poblíž, v blízkosti": "near, in the vicinity", + "hra": "game", + "kde": "where", + "nula": "zero", + "jedna": "one", + "dvě": "two", + "tři": "three", + "čtyři": "four", + "pět": "five", + "sedm": "seven", + "osm": "eight", + "devět": "nine", + "deset": "ten", + "jedenáct": "eleven", + "dvanáct": "twelve", + "patnáct": "fifteen", + "šestnáct": "sixteen", + "osmnáct": "eighteen", + "devatenáct": "nineteen", + "starý": "old", + "on": "he", + "měsíc": "month", + "ona": "she", + "oni": "they", + "ale": "but", + "věk": "age", + "také": "also", + "(hudební) skupina": "(music) band", + "chatovat": "to chat", + "počítačová hra": "computer game", + "e-mail": "email", + "angličtina, anglicky": "English", + "fanoušek": "fan", + "francouzština, francouzsky": "French", + "kamarádka": "friend (f.)", + "nejlepší kamarádka": "best friend (f.)", + "fotbal": "football", + "Je fotbalový fanatik.": "He is a football fanatic.", + "jít": "to go", + "Rád(a) chodím na koncerty.": "I like going to concerts.", + "rád/a": "gladly", + "kytara": "guitar", + "mobil": "mobile phone", + "koníček": "hobby", + "poslouchat": "to listen", + "Rád poslouchá hudbu.": "He likes listening to music.", + "surfovat na internetu": "to surf the internet", + "pořád, neustále": "always", + "rok": "year", + "žádný/žádná/žádné": "no / none", + "klavír": "piano", + "přicházet, pocházet (z)": "to come (from)", + "Pochází z Vídně.": "He comes from Vienna.", + "koncert": "concert", + "ležet": "to lie", + "příjmení": "surname", + "nedaleko od": "not far from", + "cestovat": "to travel", + "psát": "to write", + "škola": "school", + "hrát": "to play", + "Hraje na kytaru.": "She plays the guitar.", + "tancovat": "to dance", + "křestní jméno": "first name", + "bydliště": "place of residence", + "nesprávně, chybně": "wrong, incorrectly", + "flétna": "flute", + "(hudební) nástroj": "(musical) instrument", + "teď": "now", + "dělat": "to do", + "správně": "correctly", + "sport": "sport", + "sportovat": "to do sport", + "squash": "squash", + "jóga": "yoga", + "brzy": "soon", + "Brzy na shledanou!": "See you soon!", + "do": "until", + "Do příštího setkání!": "Until next time!", + "paní": "woman / Mrs.", + "pan": "man / Mr.", + "Měj se hezky!": "Take care!", + "muzeum": "museum", + "Jdou do muzea.": "They are going to the museum.", + "hezký": "beautiful", + "Hezký zbytek dne!": "Have a nice rest of the day!", + "Ahoj! (servus)": "Hi! (Servus)", + "Ahoj! (při loučení)": "Bye!", + "shledání": "reunion", + "Na shledanou!": "Goodbye!", + "John von Neumann – americký matematik": "John von Neumann – American mathematician", + "Americký matematik s objevy v digitálních počítačích": "American mathematician with discoveries in digital computers", + "ALU = aritmeticko-logická jednotka": "ALU = arithmetic-logic unit", + "Řadič řídí činnost ostatních částí": "The control unit directs the other parts", + "Operační paměť uchovává program i data": "Main memory stores both the program and data", + "Byl tvůrcem teorie her": "He created game theory", + "Nultá generace: 1938–1944": "Zeroth generation: 1938–1944", + "Jen několik počítačů, většinou vojenský účel": "Only a few computers, mostly for military use", + "1. generace – objev elektronky": "1st generation – invention of the vacuum tube", + "1. generace – děrné štítky": "1st generation – punch cards", + "2. generace – objev tranzistoru": "2nd generation – invention of the transistor", + "3. generace – integrovaný obvod": "3rd generation – integrated circuit", + "4. generace – programovatelné mikroprocesory": "4th generation – programmable microprocessors", + "1972 – první počítačová hra": "1972 – first computer game", + "Bit = dvojková číslice, nejmenší jednotka informace": "A bit is a binary digit, the smallest unit of information", + "Bit nabývá hodnoty 0 nebo 1": "A bit is either 0 or 1", + "Byte = nejmenší adresovatelná jednotka paměti": "A byte is the smallest addressable unit of memory" + } +} diff --git a/content/i18n/ui.json b/content/i18n/ui.json new file mode 100644 index 0000000..da06c00 --- /dev/null +++ b/content/i18n/ui.json @@ -0,0 +1,541 @@ +{ + "cs": { + "back": "Zpět", + "settings": "Nastavení", + "settings_title": "Nastavení", + "mode": "REŽIM", + "mode_dark": "Tmavý", + "mode_light": "Světlý", + "theme": "TÉMA", + "language": "JAZYK", + "welcome_body": "maturita.C je vzdělávací program pro studenty středních škol a gymnázií na přípravu k maturitě.\n\nProgram je napsaný v Céčku studentama ze SSŠVT!", + "continue": "Pokračuj", + "roadmap_title": "Učební plán", + "roadmap_sub": "Vyberte jednotku na cestě a začněte procvičovat.", + "unit1_sub": "Vyberte cvičení a dokončete je.", + "check": "Zkontrolovat", + "finish": "Dokončit", + "show_sample": "Ukázat vzor", + "your_answer": "Vaše odpověď…", + "feedback_ok": "Výborně!", + "feedback_retry": "Ještě to není správně. Zkuste to znovu.", + "feedback_retry_short": "Ještě to není správně.", + "feedback_sentences": "Některé věty nejsou správně. Zkuste to znovu.", + "tip_ss": "Písmeno „ß“ se dá na klávesnici zaměnit za „ss“!", + "hint_umlauts": "Na klávesnici nemáte německé znaky? Můžete psát ä jako ae, ö jako oe, ü jako ue a ß jako ss.", + "sample_fmt": "Otázka: %s\nVzor: %s (česky: %s)", + "sub_dialog": "Doplňte chybějící slova v dialogu.", + "sub_assembly": "Přetáhněte slova do správného pořadí.", + "sub_choice_num": "Vyberte správnou číslovku.", + "sub_free": "Odpovězte vlastními slovy, poté klikněte na Dokončit.", + "sub_zahlen": "Vyberte správné slovo pro dané číslo.", + "sub_wieviel": "Spočítejte předměty a vyberte počet.", + "sub_reihe": "Doplňte chybějící číslovku.", + "sub_verb": "Vyberte správný tvar slovesa.", + "sub_wer": "Vyberte správné tázací slovo.", + "sub_bild": "Vyberte správný tvar slovesa podle obrázku.", + "sub_gruss": "Roztřiďte pozdravy na pozdravy a rozloučení.", + "sub_land": "Přiřaďte symboly ke správné zemi.", + "sub_translate": "Přeložte slovo. Špatná odpověď se vrátí na konec.", + "trans_wrong": "Špatně. Správně: %s", + "trans_incomplete": "Nepřesné – něco chybí.", + "trans_progress": "Hotovo: %d / %d", + "trans_done": "Hotovo! Zvládl(a) jsi všechna slova.", + "assign_hint": "Vyberte skupinu a klikněte na kartu. Kliknutím na kartu ve skupině ji vrátíte zpět.", + "unit2_sub": "Vyberte cvičení a dokončete je.", + "Bei uns zu Hause": "Bei uns zu Hause", + "unit3_sub": "Vyberte cvičení a dokončete je.", + "sub3_pair": "Přiřaďte každému slovu jeho protějšek.", + "sub3_poss": "Doplňte přivlastňovací zájmena (1. pád).", + "sub3_haustier": "Doplňte ein/kein ve správném tvaru.", + "sub3_buchst": "Doplňte chybějící písmena.", + "sub3_marco": "Doplňte slova z nabídky.", + "sub3_sort": "Roztřiďte slova do dvou skupin.", + "sub3_tabelle": "Doplňte přivlastňovací zájmena do tabulky.", + "sub3_akk": "Doplňte přivlastňovací zájmena (4. pád).", + "sub3_nicht": "Vyberte kein/keine/keinen/nicht.", + "sub3_satz": "Sestavte správné věty.", + "sub3_sehen": "Napište větu „Ich sehe…“.", + "sub3_wem": "Komu to patří? Doplňte zájmeno.", + "sub3_gibt": "Doplňte „Es gibt“ + ein/eine/einen.", + "sub3_saetze": "Doplňte věty podle vzoru.", + "sub3_wochen": "Doplňte chybějící písmena.", + "wordbank": "Nabídka slov:", + "sample_line": "Příklad: %s", + "sub_verben": "Doplňte sloveso ve správném tvaru.", + "sub_ausin": "Vyberte správnou předložku: aus nebo in.", + "sub_sprich": "Doplňte sloveso „sprechen“.", + "sub_nation": "Doplňte národnost – použijte slova z nabídky.", + "sub_woher": "Odkud lidé pocházejí? Napište zemi.", + "sub_laender": "Doplňte chybějící písmena v názvech zemí.", + "sub_verb2": "Vyberte správný tvar slovesa.", + "sub_euro": "Napište částku slovy.", + "sub_wortsuchen": "Najděte skryté slovo a napište ho.", + "sub_ordne": "Přiřaďte správné tázací slovo a odpověď.", + "sub_luecke": "Doplňte chybějící slova do textu.", + "sub_verbinde": "Spojte každé podstatné jméno se správným slovesem.", + "sub_zahlpaar": "Spojte čísla s německými slovy.", + "sub_steckbrief": "Doplňte údaje o sobě.", + "sub_berufe": "Hádejte povolání dřív, než bude oběšenec hotový.", + "sub_bistdu": "Odpovězte podle vlajky – jakou máte národnost?", + "hm_progress": "Slovo %d / %d", + "hm_hint": "Nápověda", + "hm_wrong": "Slovo je uhodnuto!", + "hm_fail": "Oběšenec! Slovo bylo „%s“.", + "hm_retry": "Zkusit znovu", + "hm_done": "Výborně! Uhodli jste všechna povolání.", + "hm_guess": "Hádejte písmeno", + "stats": "Statistiky", + "stats_title": "Statistiky", + "stats_sub": "Přehled vašeho pokroku.", + "stats_ex_label": "Cvičení", + "stats_pct_label": "Hotovo", + "stats_units_label": "Jednotky", + "stats_section": "Předměty", + "stats_locked": "Zamčeno", + "stats_complete": "Hotovo", + "stats_ex_fmt": "%d / %d", + "stats_pct_fmt": "%d %%", + "stats_units_fmt": "%d / %d", + "subjects_title": "Předměty", + "Český jazyk a literatura": "Český jazyk a literatura", + "Občanská nauka": "Občanská nauka", + "English": "English", + "Deutsch": "Deutsch", + "Matematika": "Matematika", + "Fyzika": "Fyzika", + "Základy Přírodopisných věd": "Základy Přírodopisných věd", + "Technická grafika": "Technická grafika", + "Prezentační grafika": "Prezentační grafika", + "Správa počítačových sítí": "Správa počítačových sítí", + "Programování": "Programování", + "Technické vybavení": "Technické vybavení", + "Programové vybavení": "Programové vybavení", + "net_sub": "Vyberte lekci na cestě a začněte procvičovat.", + "net_years_title": "Správa počítačových sítí", + "net_years_sub": "Vyberte ročník a začněte procvičovat.", + "net_year1": "1. ročník", + "net_year2": "2. ročník", + "net_year3": "3. ročník", + "net_year4": "4. ročník", + "net_year_locked_sub": "Zatím bez obsahu", + "net_unit1": "Výpočet IP adres", + "net_unit1_sub": "4 snímky s postupem a pak cvičení.", + "net_ex_title": "Cvičení: výpočet IP adres", + "net_unit2": "Základní pojmy a rozdělení sítí", + "net_unit2_sub": "5 snímků s pojmy a pak kvíz.", + "net_ex2_title": "Kvíz: základní pojmy sítí", + "net_unit3": "Sítě Klient–Server a Cloud", + "net_unit3_sub": "4 snímky o serverech a cloudu a pak kvíz.", + "net_ex3_title": "Kvíz: klient–server a cloud", + "net_unit4": "Přenos dat a jeho zabezpečení", + "net_unit4_sub": "4 snímky o přenosu a zabezpečení a pak kvíz.", + "net_ex4_title": "Kvíz: přenos dat a zabezpečení", + "net_unit5": "Signály a modulace", + "net_unit5_sub": "4 snímky o signálech a modulaci a pak kvíz.", + "net_ex5_title": "Kvíz: signály a modulace", + "net_unit6": "Cesta, kanál a okruh", + "net_unit6_sub": "4 snímky o cestě, kanálu a okruhu a pak kvíz.", + "net_ex6_title": "Kvíz: cesta, kanál a okruh", + "net_unit7": "Multiplex a směry přenosu", + "net_unit7_sub": "4 snímky o multiplexu a směrech a pak kvíz.", + "net_ex7_title": "Kvíz: multiplex a směry přenosu", + "net_unit8": "Přepojování", + "net_unit8_sub": "4 snímky o přepojování a pak kvíz.", + "net_ex8_title": "Kvíz: přepojování", + "net_unit9": "Vrstevnaté modely a protokoly", + "net_unit9_sub": "4 snímky o vrstvách a protokolech a pak kvíz.", + "net_ex9_title": "Kvíz: vrstevnaté modely a protokoly", + "net_unit10": "Model ISO/OSI a TCP/IP", + "net_unit10_sub": "3 snímky o ISO/OSI a TCP/IP a pak kvíz.", + "net_ex10_title": "Kvíz: ISO/OSI a TCP/IP", + "net_unit11": "Podrobný rozbor 7 vrstev ISO/OSI", + "net_unit11_sub": "8 snímků o jednotlivých vrstvách a pak kvíz.", + "net_ex11_title": "Kvíz: 7 vrstev ISO/OSI", + "net_unit12": "Základy architektury TCP/IP", + "net_unit12_sub": "6 snímků o TCP/IP a protokolech a pak kvíz.", + "net_ex12_title": "Kvíz: architektura TCP/IP", + "net_unit13": "Topologie sítě", + "net_unit13_sub": "4 snímky o sběrnici, hvězdě a kruhu a pak kvíz.", + "net_ex13_title": "Kvíz: topologie sítě", + "net_unit14": "Optika", + "net_unit14_sub": "5 snímků o optických vláknech a pak kvíz.", + "net_ex14_title": "Kvíz: optika", + "net_unit15": "Ochrana a montáž optiky", + "net_unit15_sub": "3 snímky o ochraně a montáži a pak kvíz.", + "net_ex15_title": "Kvíz: ochrana a montáž optiky", + "net_unit16": "Metody přístupu", + "net_unit16_sub": "4 snímky o kolizích a CSMA a pak kvíz.", + "net_ex16_title": "Kvíz: metody přístupu", + "net_unit17": "Aktivní prvky", + "net_unit17_sub": "7 snímků o hubu, switchi a routeru a pak kvíz.", + "net_ex17_title": "Kvíz: aktivní prvky", + "net_unit18": "Switch (podrobně)", + "net_unit18_sub": "5 snímků o CAM a přepínání a pak kvíz.", + "net_ex18_title": "Kvíz: switch podrobně", + "net_unit19": "Směrování (Routing)", + "net_unit19_sub": "7 snímků o směrovacích algoritmech a pak kvíz.", + "net_ex19_title": "Kvíz: směrování", + "net_unit20": "Směrovač a brána", + "net_unit20_sub": "7 snímků o routeru a gateway a pak kvíz.", + "net_ex20_title": "Kvíz: směrovač a brána", + "net_unit21": "Adresy a rámce v ethernetu", + "net_unit21_sub": "8 snímků o MAC a typech rámců a pak kvíz.", + "net_ex21_title": "Kvíz: ethernet adresy a rámce", + "net_unit22": "Paket IP", + "net_unit22_sub": "8 snímků o IP datagramu a hlavičce a pak kvíz.", + "net_ex22_title": "Kvíz: paket IP", + "net_unit23": "ICMP", + "net_unit23_sub": "5 snímků o ICMP zprávách a traceroute a pak kvíz.", + "net_ex23_title": "Kvíz: ICMP", + "net_unit24": "ARP", + "net_unit24_sub": "5 snímků o ARP/RARP a cache a pak kvíz.", + "net_ex24_title": "Kvíz: ARP", + "net_unit25": "TCP a UDP", + "net_unit25_sub": "6 snímků o transportní vrstvě a pak kvíz.", + "net_ex25_title": "Kvíz: TCP a UDP", + "net_unit26": "Aplikační protokoly", + "net_unit26_sub": "7 snímků o portech a službách a pak kvíz.", + "net_ex26_title": "Kvíz: Aplikační protokoly", + "net_unit27": "Bezdrátové sítě", + "net_unit27_sub": "8 snímků o družicích, Wi-Fi a zabezpečení a pak kvíz.", + "net_ex27_title": "Kvíz: Bezdrátové sítě", + "net_quiz_intro": "Vyberte u každé otázky jednu správnou odpověď a stiskněte Zkontrolovat.", + "net_quiz2_head": "Kvíz k základním pojmům sítí", + "net_quiz3_head": "Kvíz ke klient–server a cloudu", + "net_quiz4_head": "Kvíz k přenosu dat a zabezpečení", + "net_quiz5_head": "Kvíz k signálům a modulaci", + "net_quiz6_head": "Kvíz k cestě, kanálu a okruhu", + "net_quiz7_head": "Kvíz k multiplexu a směrům přenosu", + "net_quiz8_head": "Kvíz k přepojování", + "net_quiz9_head": "Kvíz k vrstevnatým modelům a protokolům", + "net_quiz10_head": "Kvíz k ISO/OSI a TCP/IP", + "net_quiz11_head": "Kvíz k 7 vrstvám ISO/OSI", + "net_quiz12_head": "Kvíz k architektuře TCP/IP", + "net_quiz13_head": "Kvíz k topologiím sítě", + "net_quiz14_head": "Kvíz k optice", + "net_quiz15_head": "Kvíz k ochraně a montáži optiky", + "net_quiz16_head": "Kvíz k metodám přístupu", + "net_quiz17_head": "Kvíz k aktivním prvkům", + "net_quiz18_head": "Kvíz ke switchi podrobně", + "net_quiz19_head": "Kvíz ke směrování", + "net_quiz20_head": "Kvíz ke směrovači a bráně", + "net_quiz21_head": "Kvíz k ethernetovým adresám a rámcům", + "net_quiz22_head": "Kvíz k IP paketu", + "net_quiz23_head": "Kvíz k ICMP", + "net_quiz24_head": "Kvíz k ARP", + "net_quiz25_head": "Kvíz k TCP a UDP", + "net_quiz26_head": "Kvíz k aplikačním protokolům", + "net_quiz27_head": "Kvíz k bezdrátovým sítím", + "net_slide_next": "Další", + "net_slide_prev": "Zpět", + "net_slide_start": "Přejít na cvičení", + "net_solution": "Ukázat řešení", + "hw_sub": "Vyberte lekci na cestě a začněte procvičovat.", + "hw_unit1": "Architektura počítače", + "hw_unit1_sub": "3 snímky o Von Neumannovi a schématu a pak kvíz.", + "hw_ex1_title": "Kvíz: architektura počítače", + "hw_quiz1_head": "Kvíz k architektuře počítače", + "hw_unit2": "Historie počítačů", + "hw_unit2_sub": "6 snímků o generacích počítačů a pak kvíz.", + "hw_ex2_title": "Kvíz: historie počítačů", + "hw_quiz2_head": "Kvíz k historii počítačů", + "hw_unit3": "Zobrazování dat v počítači", + "hw_unit3_sub": "2 snímky o bitu a bytu a pak kvíz.", + "hw_ex3_title": "Kvíz: zobrazování dat", + "hw_quiz3_head": "Kvíz k zobrazování dat v počítači", + "czech_sub": "Vyberte oblast a začněte procvičovat.", + "Literatura": "Literatura", + "Mluvnice": "Mluvnice", + "Maturitní četba": "Maturitní četba", + "reading_sub": "Vyberte knihu, kterou chcete studovat.", + "book_1984_sub": "Antiutopický román • 1949", + "cetba1984_sub": "Přehled knihy, klíčové pojmy a cvičení.", + "lit_quiz_title": "Kvíz: George Orwell – 1984", + "lit_quiz_sub": "U každé otázky vyberte jednu správnou odpověď.", + "lit_plot_title": "Sestavte děj", + "lit_plot_sub": "Přetáhněte části příběhu do správného pořadí.", + "lit_next": "Další", + "lit_show_result": "Zobrazit výsledek", + "lit_again": "Zkusit znovu", + "lit_question_fmt": "Otázka %d / %d", + "lit_score_fmt": "Skóre: %d / %d", + "lit_finished": "Hotovo!", + "lit_finished_text": "Prošli jste všemi otázkami.", + "cetbaFuks_sub": "Přehled knihy, klíčové pojmy a cvičení.", + "lit_fuks_quiz_title": "Kvíz: Spalovač mrtvol", + "lit_fuks_quiz_sub": "U každé otázky vyberte jednu správnou odpověď.", + "lit_fuks_plot_title": "Sestavte děj", + "lit_fuks_plot_sub": "Přetáhněte části příběhu do správného pořadí." + }, + "en": { + "back": "Back", + "settings": "Settings", + "settings_title": "Settings", + "mode": "MODE", + "mode_dark": "Dark", + "mode_light": "Light", + "theme": "THEME", + "language": "LANGUAGE", + "welcome_body": "maturita.C is an educational app for high-school and gymnasium students to prepare for their maturita exam.\n\nThe program is written in C by students from SSŠVT!", + "continue": "Continue", + "roadmap_title": "Learning path", + "roadmap_sub": "Pick a unit on the path and start practicing.", + "unit1_sub": "Choose an exercise and complete it.", + "check": "Check", + "finish": "Finish", + "show_sample": "Show sample", + "your_answer": "Your answer…", + "feedback_ok": "Great!", + "feedback_retry": "Not quite right yet. Try again.", + "feedback_retry_short": "Not quite right yet.", + "feedback_sentences": "Some sentences are not correct. Try again.", + "tip_ss": "You can type “ss” instead of “ß” on the keyboard!", + "hint_umlauts": "No German keyboard? You can type ä as ae, ö as oe, ü as ue and ß as ss.", + "sample_fmt": "Question: %s\nSample: %s (English: %s)", + "sub_dialog": "Fill in the missing words in the dialogue.", + "sub_assembly": "Drag the words into the correct order.", + "sub_choice_num": "Choose the correct numeral.", + "sub_free": "Answer in your own words, then click Finish.", + "sub_zahlen": "Choose the correct word for the given number.", + "sub_wieviel": "Count the items and choose the amount.", + "sub_reihe": "Fill in the missing numeral.", + "sub_verb": "Choose the correct verb form.", + "sub_wer": "Choose the correct question word.", + "sub_bild": "Choose the correct verb form for the picture.", + "sub_gruss": "Sort the phrases into greetings and farewells.", + "sub_land": "Match the symbols to the correct country.", + "Vokabeltraining": "Vocabulary training", + "sub_translate": "Translate the word. Wrong answers come back at the end.", + "trans_wrong": "Wrong. Correct: %s", + "trans_incomplete": "Almost – something is missing.", + "trans_progress": "Done: %d / %d", + "trans_done": "Done! You mastered all the words.", + "assign_hint": "Pick a group and click a card. Click a card inside a group to send it back.", + "unit2_sub": "Choose an exercise and complete it.", + "Bei uns zu Hause": "At Home with Us", + "unit3_sub": "Choose an exercise and complete it.", + "sub3_pair": "Match each word with its counterpart.", + "sub3_poss": "Fill in the possessive pronouns (nominative).", + "sub3_haustier": "Fill in ein/kein in the correct form.", + "sub3_buchst": "Fill in the missing letters.", + "sub3_marco": "Fill in the words from the box.", + "sub3_sort": "Sort the words into two groups.", + "sub3_tabelle": "Fill the possessive pronouns into the table.", + "sub3_akk": "Fill in the possessive pronouns (accusative).", + "sub3_nicht": "Choose kein/keine/keinen/nicht.", + "sub3_satz": "Build the correct sentences.", + "sub3_sehen": "Write an “Ich sehe…” sentence.", + "sub3_wem": "Whose is it? Fill in the pronoun.", + "sub3_gibt": "Fill in “Es gibt” + ein/eine/einen.", + "sub3_saetze": "Complete the sentences following the example.", + "sub3_wochen": "Fill in the missing letters.", + "wordbank": "Word bank:", + "sample_line": "Sample: %s", + "sub_verben": "Fill in the verb in the correct form.", + "sub_ausin": "Choose the correct preposition: aus or in.", + "sub_sprich": "Fill in the verb “sprechen”.", + "sub_nation": "Fill in the nationality – use the words in the box.", + "sub_woher": "Where are the people from? Type the country.", + "sub_laender": "Type the full country name (the missing letters are shown as _).", + "sub_verb2": "Choose the correct verb form.", + "sub_euro": "Write the amount in words.", + "sub_wortsuchen": "Find the hidden word and type it.", + "sub_ordne": "Match each phrase with the right question word and answer.", + "sub_luecke": "Fill the missing words into the text.", + "sub_verbinde": "Match each noun with the right verb.", + "sub_zahlpaar": "Match the numbers with the German words.", + "sub_steckbrief": "Complete the information about yourself.", + "sub_berufe": "Guess each job before the hangman drawing is finished.", + "sub_bistdu": "Answer according to the flag – what is your nationality?", + "hm_progress": "Word %d / %d", + "hm_hint": "Hint", + "hm_wrong": "Word guessed!", + "hm_fail": "Hanged! The word was “%s”.", + "hm_retry": "Try again", + "hm_done": "Great! You guessed all the jobs.", + "hm_guess": "Guess a letter", + "stats": "Statistics", + "stats_title": "Statistics", + "stats_sub": "Overview of your progress.", + "stats_ex_label": "Exercises", + "stats_pct_label": "Done", + "stats_units_label": "Units", + "stats_section": "Subjects", + "stats_locked": "Locked", + "stats_complete": "Complete", + "stats_ex_fmt": "%d / %d", + "stats_pct_fmt": "%d %%", + "stats_units_fmt": "%d / %d", + "subjects_title": "Subjects", + "Český jazyk a literatura": "Czech Language and Literature", + "Občanská nauka": "Civics", + "English": "English", + "Deutsch": "Deutsch", + "Matematika": "Mathematics", + "Fyzika": "Physics", + "Základy Přírodopisných věd": "Fundamentals of Natural Sciences", + "Technická grafika": "Technical Drawing", + "Prezentační grafika": "Presentation Graphics", + "Správa počítačových sítí": "Computer Network Administration", + "Programování": "Programming", + "Technické vybavení": "Computer Hardware", + "Programové vybavení": "Software", + "net_sub": "Pick a unit on the path and start practicing.", + "net_years_title": "Computer Network Administration", + "net_years_sub": "Pick a school year and start practicing.", + "net_year1": "Year 1", + "net_year2": "Year 2", + "net_year3": "Year 3", + "net_year4": "Year 4", + "net_year_locked_sub": "No content yet", + "net_unit1": "IP Address Calculation", + "net_unit1_sub": "4 slides with the method, then an exercise.", + "net_ex_title": "Exercise: IP address calculation", + "net_unit2": "Basic concepts and network types", + "net_unit2_sub": "5 slides with the concepts, then a quiz.", + "net_ex2_title": "Quiz: basic networking concepts", + "net_unit3": "Client–Server networks and Cloud", + "net_unit3_sub": "4 slides about servers and cloud, then a quiz.", + "net_ex3_title": "Quiz: client–server and cloud", + "net_unit4": "Data transmission and security", + "net_unit4_sub": "4 slides about transmission and security, then a quiz.", + "net_ex4_title": "Quiz: data transmission and security", + "net_unit5": "Signals and modulation", + "net_unit5_sub": "4 slides about signals and modulation, then a quiz.", + "net_ex5_title": "Quiz: signals and modulation", + "net_unit6": "Path, channel and circuit", + "net_unit6_sub": "4 slides about path, channel and circuit, then a quiz.", + "net_ex6_title": "Quiz: path, channel and circuit", + "net_unit7": "Multiplexing and transmission directions", + "net_unit7_sub": "4 slides about multiplexing and directions, then a quiz.", + "net_ex7_title": "Quiz: multiplexing and transmission directions", + "net_unit8": "Switching", + "net_unit8_sub": "4 slides about switching, then a quiz.", + "net_ex8_title": "Quiz: switching", + "net_unit9": "Layered models and protocols", + "net_unit9_sub": "4 slides about layers and protocols, then a quiz.", + "net_ex9_title": "Quiz: layered models and protocols", + "net_unit10": "ISO/OSI and TCP/IP models", + "net_unit10_sub": "3 slides about ISO/OSI and TCP/IP, then a quiz.", + "net_ex10_title": "Quiz: ISO/OSI and TCP/IP", + "net_unit11": "Detailed review of the 7 ISO/OSI layers", + "net_unit11_sub": "8 slides about each layer, then a quiz.", + "net_ex11_title": "Quiz: 7 ISO/OSI layers", + "net_unit12": "Basics of TCP/IP architecture", + "net_unit12_sub": "6 slides about TCP/IP and protocols, then a quiz.", + "net_ex12_title": "Quiz: TCP/IP architecture", + "net_unit13": "Network topologies", + "net_unit13_sub": "4 slides about bus, star and ring, then a quiz.", + "net_ex13_title": "Quiz: network topologies", + "net_unit14": "Fiber optics", + "net_unit14_sub": "5 slides about optical fibers, then a quiz.", + "net_ex14_title": "Quiz: fiber optics", + "net_unit15": "Fiber protection and installation", + "net_unit15_sub": "3 slides about protection and installation, then a quiz.", + "net_ex15_title": "Quiz: fiber protection and installation", + "net_unit16": "Access methods", + "net_unit16_sub": "4 slides about collisions and CSMA, then a quiz.", + "net_ex16_title": "Quiz: access methods", + "net_unit17": "Active network devices", + "net_unit17_sub": "7 slides about hubs, switches and routers, then a quiz.", + "net_ex17_title": "Quiz: active network devices", + "net_unit18": "Switch in detail", + "net_unit18_sub": "5 slides about CAM and switching modes, then a quiz.", + "net_ex18_title": "Quiz: switch in detail", + "net_unit19": "Routing", + "net_unit19_sub": "7 slides about routing algorithms, then a quiz.", + "net_ex19_title": "Quiz: routing", + "net_unit20": "Router and gateway", + "net_unit20_sub": "7 slides about routers and gateways, then a quiz.", + "net_ex20_title": "Quiz: router and gateway", + "net_unit21": "Ethernet addresses and frames", + "net_unit21_sub": "8 slides about MAC and frame types, then a quiz.", + "net_ex21_title": "Quiz: Ethernet addresses and frames", + "net_unit22": "IP packet", + "net_unit22_sub": "8 slides about the IP datagram and header, then a quiz.", + "net_ex22_title": "Quiz: IP packet", + "net_unit23": "ICMP", + "net_unit23_sub": "5 slides about ICMP messages and traceroute, then a quiz.", + "net_ex23_title": "Quiz: ICMP", + "net_unit24": "ARP", + "net_unit24_sub": "5 slides about ARP/RARP and cache, then a quiz.", + "net_ex24_title": "Quiz: ARP", + "net_unit25": "TCP and UDP", + "net_unit25_sub": "6 slides about the transport layer, then a quiz.", + "net_ex25_title": "Quiz: TCP and UDP", + "net_unit26": "Application protocols", + "net_unit26_sub": "7 slides about ports and services, then a quiz.", + "net_ex26_title": "Quiz: Application protocols", + "net_unit27": "Wireless networks", + "net_unit27_sub": "8 slides about satellites, Wi-Fi and security, then a quiz.", + "net_ex27_title": "Quiz: Wireless networks", + "net_quiz_intro": "Choose one correct answer for each question and press Check.", + "net_quiz2_head": "Quiz on basic networking concepts", + "net_quiz3_head": "Quiz on client–server and cloud", + "net_quiz4_head": "Quiz on data transmission and security", + "net_quiz5_head": "Quiz on signals and modulation", + "net_quiz6_head": "Quiz on path, channel and circuit", + "net_quiz7_head": "Quiz on multiplexing and transmission directions", + "net_quiz8_head": "Quiz on switching", + "net_quiz9_head": "Quiz on layered models and protocols", + "net_quiz10_head": "Quiz on ISO/OSI and TCP/IP", + "net_quiz11_head": "Quiz on the 7 ISO/OSI layers", + "net_quiz12_head": "Quiz on TCP/IP architecture", + "net_quiz13_head": "Quiz on network topologies", + "net_quiz14_head": "Quiz on fiber optics", + "net_quiz15_head": "Quiz on fiber protection and installation", + "net_quiz16_head": "Quiz on access methods", + "net_quiz17_head": "Quiz on active network devices", + "net_quiz18_head": "Quiz on switches in detail", + "net_quiz19_head": "Quiz on routing", + "net_quiz20_head": "Quiz on router and gateway", + "net_quiz21_head": "Quiz on Ethernet addresses and frames", + "net_quiz22_head": "Quiz on the IP packet", + "net_quiz23_head": "Quiz on ICMP", + "net_quiz24_head": "Quiz on ARP", + "net_quiz25_head": "Quiz on TCP and UDP", + "net_quiz26_head": "Quiz on application protocols", + "net_quiz27_head": "Quiz on wireless networks", + "net_slide_next": "Next", + "net_slide_prev": "Back", + "net_slide_start": "Go to the exercise", + "net_solution": "Show solution", + "hw_sub": "Pick a unit on the path and start practicing.", + "hw_unit1": "Computer architecture", + "hw_unit1_sub": "3 slides about von Neumann and the model, then a quiz.", + "hw_ex1_title": "Quiz: computer architecture", + "hw_quiz1_head": "Quiz on computer architecture", + "hw_unit2": "History of computers", + "hw_unit2_sub": "6 slides about computer generations, then a quiz.", + "hw_ex2_title": "Quiz: history of computers", + "hw_quiz2_head": "Quiz on the history of computers", + "hw_unit3": "Data representation", + "hw_unit3_sub": "2 slides about bits and bytes, then a quiz.", + "hw_ex3_title": "Quiz: data representation", + "hw_quiz3_head": "Quiz on data representation in computers", + "czech_sub": "Pick an area and start practicing.", + "Literatura": "Literature", + "Mluvnice": "Grammar", + "Maturitní četba": "Maturita reading list", + "reading_sub": "Pick a book to study.", + "book_1984_sub": "Dystopian novel • 1949", + "cetba1984_sub": "Book overview, key terms and exercises.", + "lit_quiz_title": "Quiz: George Orwell – 1984", + "lit_quiz_sub": "Pick one correct answer for each question.", + "lit_plot_title": "Order the plot", + "lit_plot_sub": "Drag the story parts into the correct order.", + "lit_next": "Next", + "lit_show_result": "Show result", + "lit_again": "Try again", + "lit_question_fmt": "Question %d / %d", + "lit_score_fmt": "Score: %d / %d", + "lit_finished": "Done!", + "lit_finished_text": "You have finished all the questions.", + "cetbaFuks_sub": "Book overview, key terms and exercises.", + "lit_fuks_quiz_title": "Quiz: The Cremator", + "lit_fuks_quiz_sub": "Pick one correct answer for each question.", + "lit_fuks_plot_title": "Order the plot", + "lit_fuks_plot_sub": "Drag the story parts into the correct order." + } +} diff --git a/content/lessons/czech/fuks-spalovac-mrtvol.json b/content/lessons/czech/fuks-spalovac-mrtvol.json new file mode 100644 index 0000000..e5b9702 --- /dev/null +++ b/content/lessons/czech/fuks-spalovac-mrtvol.json @@ -0,0 +1,539 @@ +{ + "id": "fuks-spalovac-mrtvol", + "subject": "czech", + "number": 3, + "title": { + "cs": "Ladislav Fuks – Spalovač mrtvol", + "en": "Ladislav Fuks – Spalovač mrtvol" + }, + "subtitle": { + "cs": "Projděte si přehled a pak si vyzkoušejte kvíz a řazení děje.", + "en": "Read the overview, then try the quiz and the plot ordering." + }, + "slides": [ + { + "kicker": "Ladislav Fuks – Spalovač mrtvol", + "title": "O knize", + "tip": null, + "lines": [ + "Autor: Ladislav Fuks (1923–1994)", + "Žánr: psychologický román s prvky grotesky a hororu", + "Poprvé vydáno: 1967", + "Děj: Praha v době protektorátu (konec 30. let)", + "Vyprávění: ich-forma – vypráví sám pan Kopfrkingl" + ] + }, + { + "kicker": "Ladislav Fuks – Spalovač mrtvol", + "title": "Doba a svět", + "tip": null, + "lines": [ + "Děj se odehrává v protektorátu Čechy a Morava za nastupujícího nacismu.", + "Atmosféru tvoří strach, přizpůsobování a touha zalíbit se moci.", + "Krematorium je symbolem smrti a odlidštění.", + "Antisemitismus a árijská ideologie postupně prostupují společnost.", + "Obyčejný úředník se mění v nástroj zla." + ] + }, + { + "kicker": "Ladislav Fuks – Spalovač mrtvol", + "title": "Postavy", + "tip": null, + "lines": [ + "Pan Kopfrkingl – zaměstnanec krematoria, vypravěč a vrah své rodiny.", + "Lakmé – jeho žena, židovského původu.", + "Zina a Mil – jeho děti.", + "Willi Reinke – Němec, který Kopfrkingla přivede k nacismu.", + "Dr. Bettelheim – lékař, s nímž Kopfrkingl rozmlouvá o smrti." + ] + }, + { + "kicker": "Ladislav Fuks – Spalovač mrtvol", + "title": "Klíčové motivy", + "tip": null, + "lines": [ + "Krematorium – symbol smrti a zvrácené „očisty“.", + "Kniha mrtvých – tibetský text, který si Kopfrkingl překrucuje.", + "Reinkarnace a „osvobození“ – záminka pro vraždy.", + "Masky a přetvářka – zlo se tváří jako zdvořilost a řád.", + "Groteska a černý humor – hrůza podaná klidným, slavnostním tónem.", + "Voda a Vltava – motiv smrti a plynutí." + ] + } + ], + "tasks": [ + { + "number": 1, + "title": "Kvíz", + "heading": "Kvíz ke knize", + "subtitleKey": "lit_quiz_sub", + "items": [ + { + "kind": "choice", + "prompt": "Kdo je hlavní postava románu a jaké je jeho povolání?", + "options": [ + "Pan Kopfrkingl – zaměstnanec krematoria", + "Willi Reinke – nacistický důstojník", + "Dr. Bettelheim – psychiatr", + "Pan Kopfrkingl – ředitel školy" + ], + "correct": 0, + "hint": "Hlavní postavou je pan Kopfrkingl, spořádaný zaměstnanec krematoria, který svou práci vnímá jako poslání." + }, + { + "kind": "choice", + "prompt": "V jakém prostředí pan Kopfrkingl pracuje?", + "options": [ + "V nemocnici", + "V krematoriu", + "V divadle", + "Ve škole" + ], + "correct": 1, + "hint": "Kopfrkingl pracuje v krematoriu, kde má na starosti zpopelňování zemřelých." + }, + { + "kind": "choice", + "prompt": "V jaké historické době se děj románu odehrává?", + "options": [ + "Za první republiky", + "Za protektorátu Čechy a Morava (před a během 2. světové války)", + "Po roce 1989", + "V 19. století" + ], + "correct": 1, + "hint": "Román se odehrává v době nastupujícího nacismu a protektorátu, který umožňuje Kopfrkinglovu proměnu." + }, + { + "kind": "choice", + "prompt": "Jak se proměňuje hlavní hrdina v průběhu příběhu?", + "options": [ + "Z laskavého spořádaného muže v chladnokrevného vraha a fanatika", + "Z vraha v kajícníka", + "Z chudáka v boháče", + "Vůbec se nemění" + ], + "correct": 0, + "hint": "Kopfrkingl se postupně mění v člověka, který vraždí své blízké a ospravedlňuje to vyšším dobrem." + }, + { + "kind": "choice", + "prompt": "Jaký je vztah pana Kopfrkingla k jeho rodině na začátku knihy?", + "options": [ + "Nenávidí je", + "Je starostlivý, zdvořilý a především spořádaný", + "S rodinou se nezná", + "Týrá je" + ], + "correct": 1, + "hint": "Na začátku působí jako vzorný manžel a otec, posedlý řádem a zdvořilostí." + }, + { + "kind": "choice", + "prompt": "Jak se jmenuje manželka pana Kopfrkingla a jaký je jejich vztah?", + "options": [ + "Marie – milují se", + "Lakmé – formálně zdvořilý, chladný vztah", + "Zina – nenávidí se", + "Julie – jsou rozvedení" + ], + "correct": 1, + "hint": "Manželka se jmenuje Lakmé. Jejich vztah je spíš zdvořilá forma než opravdová láska." + }, + { + "kind": "choice", + "prompt": "Jaký je vztah pana Kopfrkingla k dětem, Zině a Mílovi?", + "options": [ + "Miluje je víc než sebe", + "Chová se k nim odtažitě, jako k součásti řádu", + "Nevidí je", + "Jsou adoptované" + ], + "correct": 1, + "hint": "K dětem je odměřený; vnímá je spíš jako součást svého spořádaného světa než jako milované bytosti." + }, + { + "kind": "choice", + "prompt": "Kdo je Willi Reinke a jakou roli hraje v proměně hlavního hrdiny?", + "options": [ + "Soused z krematoria", + "Německý úředník a bývalý voják, který Kopfrkingla ovlivní", + "Kopfrkinglův bratr", + "Lékař v nemocnici" + ], + "correct": 1, + "hint": "Reinke je Němec, který v Kopfrkinglovi probudí touhu po árijském původu a kariéře." + }, + { + "kind": "choice", + "prompt": "Jak Willi Reinke ovlivňuje Kopfrkinglovo smýšlení?", + "options": [ + "Přesvědčí ho, aby se přidal k nacistům a byl „lepší“", + "Nabádá ho k odchodu do zahraničí", + "Učí ho tibetštinu", + "Nijak ho neovlivní" + ], + "correct": 0, + "hint": "Reinke v něm posiluje antisemitismus a touhu po moci a uznání v novém režimu." + }, + { + "kind": "choice", + "prompt": "Jaký je Kopfrkinglův vztah ke krematoriu a smrti obecně?", + "options": [ + "Bojí se jich", + "Má je rád, kremaci vnímá jako krásný obřad osvobození", + "Nechce tam pracovat", + "Je mu to lhostejné" + ], + "correct": 1, + "hint": "Smrt a kremace jsou pro něj estetickým a filozofickým rituálem, ne něčím hrůzným." + }, + { + "kind": "choice", + "prompt": "Jak pan Kopfrkingl vnímá a popisuje proces kremace?", + "options": [ + "Jako nutné zlo", + "Jako vznešený, očistný obřad, o kterém rád mluví", + "Jako hroznou povinnost", + "Nikdy o něm nemluví" + ], + "correct": 1, + "hint": "Kopfrkingl o kremaci hovoří básnivě a s nadšením, což ostře kontrastuje s hrůzou jeho činů." + }, + { + "kind": "choice", + "prompt": "Jaká je symbolika krematoria v celém románu?", + "options": [ + "Symbol naděje", + "Smrt, odlidštění a zvrácená ideologie, která z lidí dělá jen těla", + "Symbol lásky", + "Symbol mládí" + ], + "correct": 1, + "hint": "Krematorium je ústředním symbolem – odhaluje chladnou mašinerii smrti, do níž se ideologie snaží proměnit člověka." + }, + { + "kind": "choice", + "prompt": "Co symbolizuje Kopfrkinglova záliba v tibetské Knize mrtvých?", + "options": [ + "Jeho touhu po vědění a zvrácenou víru ve vlastní výjimečnost", + "Historický zájem o Asii", + "Strach ze smrti", + "Lásku k manželce" + ], + "correct": 0, + "hint": "Kopfrkingl si z ní vybírá jen to, co se hodí k ospravedlnění jeho činů a jeho pocitu vyvolenosti." + }, + { + "kind": "choice", + "prompt": "Jak se v knize projevuje motiv buddhismu a reinkarnace?", + "options": [ + "Kopfrkingl jimi ospravedlňuje smrt jako „osvobození duše“", + "Postavy se modlí k Bohu", + "Nikde se neobjevuje", + "Je to hlavní téma manželky" + ], + "correct": 0, + "hint": "Reinkarnace a „osvobození od utrpení“ se v jeho mysli zvrhávají v právo zabíjet." + }, + { + "kind": "choice", + "prompt": "Jak Kopfrkingl zneužívá filozofické a náboženské myšlenky?", + "options": [ + "Ospravedlňuje jimi vlastní vraždy jako službu vyššímu dobru", + "Pomáhá jimi druhým", + "Odmítá je", + "Používá je jen v práci" + ], + "correct": 0, + "hint": "Z vznešených idejí si staví masku, za kterou skrývá krutost a touhu po moci." + }, + { + "kind": "choice", + "prompt": "Jak se postupně mění Kopfrkinglova mluva a způsob vyjadřování?", + "options": [ + "Začíná mluvit vulgárně", + "Mění se v patetickou, ráznou řeč plnou frází o řádu a osvobození", + "Přestane mluvit", + "Od začátku mluví jen německy" + ], + "correct": 1, + "hint": "Jeho zdvořilá mluvnost se postupně mění v ideologické fráze a bezcitný patos." + }, + { + "kind": "choice", + "prompt": "Jaké opakující se fráze nebo návyky pana Kopfrkingla si všímáš?", + "options": [ + "Neustále se ptá na počasí", + "Opakuje „to je takové“, „vidíte“ a lpí na zdvořilosti", + "Zpívá si", + "Mluví jen o jídle" + ], + "correct": 1, + "hint": "Opakující se fráze a zdvořilostní obraty vytvářejí rytmus, který je čím dál tím děsivější." + }, + { + "kind": "choice", + "prompt": "Jaký je vypravěčský styl románu (ich-forma, er-forma)?", + "options": [ + "Er-forma bez vnitřního světa", + "Ich-forma – vypráví sám Kopfrkingl", + "Deníková forma", + "Forma dopisů" + ], + "correct": 1, + "hint": "Ich-forma je klíčová: čtenář sleduje svět zkreslený Kopfrkinglovou myslí a sám postupně propadá jeho logice." + }, + { + "kind": "choice", + "prompt": "Jak se v knize projevuje černý humor a groteska?", + "options": [ + "Vážné scény jsou líčeny s odstupem a absurditou", + "Kniha je čistě vážná", + "Humor je jediný žánr", + "V knize se neprojevuje" + ], + "correct": 0, + "hint": "Groteskní kontrast mezi slavnostním vyprávěním a hrůzou vytváří mrazivý černý humor." + }, + { + "kind": "choice", + "prompt": "Jak kontrastuje banalita každodenního života s hrůzností činů?", + "options": [ + "Vůbec nesouvisí", + "Všední detaily a zdvořilost činí hrůzu ještě děsivější", + "Hrůza je potlačena", + "Den je popsán jen jednou" + ], + "correct": 1, + "hint": "Fuks zesiluje otřes tím, že vraždění je popisováno stejně klidně jako ranní káva nebo kremace." + }, + { + "kind": "choice", + "prompt": "Jak se v knize projevuje antisemitismus?", + "options": [ + "Od začátku otevřeně", + "Postupně, nejdřív v náznacích a vlivem Reinkeho", + "Nikdy", + "Jen mimochodem v závěru" + ], + "correct": 1, + "hint": "Kopfrkinglův antisemitismus se rodí pozvolna a je živen dobovou atmosférou i Reinkem." + }, + { + "kind": "choice", + "prompt": "Jak nacistická ideologie postupně prostupuje Kopfrkinglovo myšlení?", + "options": [ + "Odmítá ji", + "Přijímá ji jako vyšší řád a ospravedlnění vlastní výjimečnosti", + "Nerozumí jí", + "Zajímá ho jen hudba" + ], + "correct": 1, + "hint": "Ideologie se mu stává nástrojem kariéry i vnitřním ospravedlněním vražd." + }, + { + "kind": "choice", + "prompt": "Jak se mění Kopfrkinglův vztah k manželce kvůli jejímu původu?", + "options": [ + "Začne ji milovat víc", + "Odcizí se jí, protože je židovského původu", + "Nijak se nemění", + "Odstěhují se od sebe" + ], + "correct": 1, + "hint": "Kvůli jejímu původu ji přestane vnímat jako rovnocennou a nakonec ji zabije." + }, + { + "kind": "choice", + "prompt": "Co se stane s Kopfrkinglovou rodinou ve druhé polovině románu?", + "options": [ + "Odstěhují se", + "Kopfrkingl svou ženu i děti zabije", + "Všichni přežijí", + "Zachrání je Reinke" + ], + "correct": 1, + "hint": "Pod vlivem ideologie Kopfrkingl vyvraždí vlastní rodinu a považuje to za „osvobození“." + }, + { + "kind": "choice", + "prompt": "Jak Kopfrkingl zdůvodňuje vraždu vlastní ženy?", + "options": [ + "Zlobila se na něj", + "Že je židovského původu a překáží jeho kariéře", + "Že ho podváděla", + "Nijak ji nezdůvodňuje" + ], + "correct": 1, + "hint": "Svou ženu zabije mimo jiné proto, že je židovského původu, tedy „méněcenná“ pro nový režim." + }, + { + "kind": "choice", + "prompt": "Jakým způsobem Kopfrkingl vraždí své blízké?", + "options": [ + "Ve zlosti a afektu", + "Chladně a s pocitem, že je „osvobozuje od utrpení“", + "Omylem", + "Na příkaz úřadů" + ], + "correct": 1, + "hint": "Vraždí klidně, jako by vykonával bohulibý úkon, a svou krutost si vykládá jako soucit." + }, + { + "kind": "choice", + "prompt": "Jak souvisí přesvědčení o „osvobození“ s jeho vražednými činy?", + "options": [ + "Dává mu zdání vyššího smyslu, kterým si vraždy ospravedlňuje", + "Nemá s nimi nic společného", + "Brání mu v zabíjení", + "Je to jen náhodná fráze" + ], + "correct": 0, + "hint": "Zvrácená víra v osvobození od utrpení mu slouží jako mravní alibi pro vraždy." + }, + { + "kind": "choice", + "prompt": "Jaký je vztah pana Kopfrkingla k postavě Dr. Bettelheima?", + "options": [ + "Obdivuje ho a rád s ním mluví", + "Nenávidí ho", + "Nikdy se nepotkají", + "Je to jeho nadřízený" + ], + "correct": 0, + "hint": "S doktorem Bettelheimem vede Kopfrkingl své „filozofické“ rozhovory o smrti a lidskosti." + }, + { + "kind": "choice", + "prompt": "Jak se mění společenské postavení pana Kopfrkingla v době okupace?", + "options": [ + "Upadá", + "Stoupá – díky režimu a touze po árijském původu", + "Nemění se", + "Odchází do penze" + ], + "correct": 1, + "hint": "Spolu s nacistickou mocí roste i Kopfrkinglova kariéra a sebevědomí." + }, + { + "kind": "choice", + "prompt": "Jaký je symbolický význam jména Kopfrkingl?", + "options": [ + "Zdánlivě úřednické, ale zní hrozivě – naznačuje zvrácenost", + "Je to běžné české jméno", + "Znamená „laskavý“", + "Je to pseudonym" + ], + "correct": 0, + "hint": "Zvukomalebné jméno působí úředně a zároveň hrozivě, což podtrhuje dvojí tvář postavy." + }, + { + "kind": "choice", + "prompt": "Jak funguje motiv masek, divadla a přetvářky?", + "options": [ + "Postavy nosí masky dobroty, pod nimiž se skrývá krutost", + "V knize jsou jen skutečné divadelní masky", + "Motiv se neobjevuje", + "Masky symbolizují lásku" + ], + "correct": 0, + "hint": "Přetvářka a předstíraná spořádanost jsou ústřední – zlo se tváří jako slušnost." + }, + { + "kind": "choice", + "prompt": "Jaký je vztah mezi soukromým a kolektivním šílenstvím doby?", + "options": [ + "Kopfrkinglovo osobní šílenství roste spolu s ideologií doby", + "Nijak nesouvisí", + "Doba je klidná a šťastná", + "Lidé režim jednomyslně odmítají" + ], + "correct": 0, + "hint": "Fuks ukazuje, jak se individuální porucha napojí na kolektivní ideologii a čerpá z ní sílu." + }, + { + "kind": "choice", + "prompt": "Jak končí román a co se stane s panem Kopfrkinglem na konci?", + "options": [ + "Uteče do zahraničí", + "Je zatčen a zničen", + "Stane se hrdinou", + "Věří, že je vtělením Dalajlámy, a zůstává zaslepený" + ], + "correct": 3, + "hint": "Kopfrkinglova zaslepenost vrcholí přesvědčením o vlastní božskosti; jeho zvrácená víra ho neopouští." + }, + { + "kind": "choice", + "prompt": "Jak je Spalovač mrtvol adaptován filmově?", + "options": [ + "Film Juraje Herze je vizuálně expresivní a patří k vrcholům české kinematografie", + "Byl zfilmován jen v zahraničí", + "Film neexistuje", + "Vznikl jako animovaný seriál" + ], + "correct": 0, + "hint": "Známá filmová verze je od režiséra Juraje Herze z roku 1968." + }, + { + "kind": "choice", + "prompt": "Které další dílo Ladislava Fukse se dá srovnat s touto knihou?", + "options": [ + "Pan Theodor Mundstock nebo Myši Natálie Mooshabrové", + "Farma zvířat", + "R.U.R.", + "Babička" + ], + "correct": 0, + "hint": "Fuks se opakovaně zabýval osudem židovských postav a atmosférou strachu; srovnat lze např. Pana Theodora Mundstocka." + }, + { + "kind": "choice", + "prompt": "Jaká jsou hlavní témata románu?", + "options": [ + "Moc, manipulace, ideologie, násilí a přetvářka", + "Láska a dobrodružství", + "Sport a přátelství", + "Příroda a vesmír" + ], + "correct": 0, + "hint": "Kniha zkoumá, jak se obyčejný člověk přizpůsobí zlu a stane se jeho nástrojem." + }, + { + "kind": "choice", + "prompt": "Jaké poselství podle tebe chtěl Ladislav Fuks knihou předat?", + "options": [ + "Varování před manipulací a tím, jak se zlo rodí z banality a lhostejnosti", + "Oslavu války", + "Návod k podnikání", + "Kritiku školství" + ], + "correct": 0, + "hint": "Fuks ukazuje, že hrůza může vzniknout z poslušnosti a touhy být „lepší“ než ostatní." + } + ] + }, + { + "number": 2, + "title": "Děj", + "heading": "Seřaďte děj", + "subtitleKey": "lit_plot_sub", + "items": [ + { + "kind": "assembly", + "prompt": "Přetáhněte části příběhu do správného pořadí:", + "words": [ + "Kopfrkingl je spořádaným zaměstnancem krematoria", + "Seznámí se s Willim Reinkem", + "Začne věřit v árijskou nadřazenost", + "Postupně se odcizí své rodině", + "Zabije ženu a děti jako „osvobození“", + "Na konci se považuje za vtělení Dalajlámy" + ], + "meaning": "Správné pořadí: spořádaný úředník → setkání s Reinkem → árijská ideologie → odcizení rodině → vraždy → přesvědčení o vlastní božskosti." + } + ] + } + ] +} diff --git a/content/lessons/czech/mluvnice.json b/content/lessons/czech/mluvnice.json new file mode 100644 index 0000000..ced1917 --- /dev/null +++ b/content/lessons/czech/mluvnice.json @@ -0,0 +1,1657 @@ +{ + "id": "mluvnice", + "subject": "czech", + "number": 1, + "title": { + "cs": "Mluvnice", + "en": "Czech grammar" + }, + "subtitle": { + "cs": "Vyberte cvičení a dokončete je.", + "en": "Pick an exercise and complete it." + }, + "slides": [], + "tasks": [ + { + "number": 1, + "title": "i/y", + "heading": "Pravopis – i/y po obojetných souhláskách", + "subtitleKey": null, + "subtitle": "Doplňte i/í nebo y/ý.", + "items": [ + { + "kind": "fields", + "prompt": "Stará bab_čka sed_la na lav_čce.", + "fields": [ + { + "label": "i/í/y/ý", + "answers": [ + "babička" + ] + }, + { + "label": "i/í/y/ý", + "answers": [ + "seděla", + "sedla" + ] + }, + { + "label": "i/í/y/ý", + "answers": [ + "lavičce" + ] + } + ], + "solution": "babička, seděla, lavičce" + }, + { + "kind": "fields", + "prompt": "Na obloze sv_tily hv_zdy.", + "fields": [ + { + "label": "i/í/y/ý", + "answers": [ + "svítily" + ] + }, + { + "label": "i/í/y/ý", + "answers": [ + "hvězdy" + ] + } + ], + "solution": "svítily, hvězdy" + }, + { + "kind": "fields", + "prompt": "M_sl_m, že m_š pravdu.", + "fields": [ + { + "label": "i/í/y/ý", + "answers": [ + "Myslím" + ] + }, + { + "label": "i/í/y/ý", + "answers": [ + "myš" + ] + } + ], + "solution": "Myslím, myš" + }, + { + "kind": "fields", + "prompt": "V_soký muž nes_l těžký kuf_r.", + "fields": [ + { + "label": "i/í/y/ý", + "answers": [ + "Vysoký" + ] + }, + { + "label": "i/í/y/ý", + "answers": [ + "nesl" + ] + }, + { + "label": "i/í/y/ý", + "answers": [ + "kufr" + ] + } + ], + "solution": "Vysoký, nesl, kufr" + }, + { + "kind": "fields", + "prompt": "Ryb_ář čekal cel_ den u řek_.", + "fields": [ + { + "label": "i/í/y/ý", + "answers": [ + "Rybář" + ] + }, + { + "label": "i/í/y/ý", + "answers": [ + "celý" + ] + }, + { + "label": "i/í/y/ý", + "answers": [ + "řeky" + ] + } + ], + "solution": "Rybář, celý, řeky" + } + ] + }, + { + "number": 2, + "title": "Velká písmena", + "heading": "Pravopis – velká/malá písmena", + "subtitleKey": null, + "subtitle": "Vyberte správnou variantu.", + "items": [ + { + "kind": "choice", + "prompt": "Narodil se v ______ v malé vesnici.", + "options": [ + "Čechách", + "čechách" + ], + "correct": 0 + }, + { + "kind": "choice", + "prompt": "Přečetl jsem román od ______.", + "options": [ + "Boženy Němcové", + "boženy němcové" + ], + "correct": 0 + }, + { + "kind": "choice", + "prompt": "Jedeme na ______.", + "options": [ + "Moravu", + "moravu" + ], + "correct": 0 + }, + { + "kind": "choice", + "prompt": "V ______ žije přes milion lidí.", + "options": [ + "Praze", + "praze" + ], + "correct": 0 + }, + { + "kind": "choice", + "prompt": "Navštívili jsme ______.", + "options": [ + "Národní muzeum", + "národní muzeum" + ], + "correct": 0 + } + ] + }, + { + "number": 3, + "title": "Slovní druhy", + "heading": "Slovní druhy", + "subtitleKey": null, + "subtitle": "Určete slovní druh podtržených slov.", + "note": "Do pole napište název slovního druhu.", + "items": [ + { + "kind": "fields", + "prompt": "Krásný den se chýlil ke konci. — slovo „Krásný“", + "fields": [ + { + "label": "slovní druh", + "answers": [ + "přídavné jméno", + "přídavné jmeno", + "adjektivum" + ] + } + ], + "solution": "přídavné jméno" + }, + { + "kind": "fields", + "prompt": "Šel rychle domů. — slovo „rychle“", + "fields": [ + { + "label": "slovní druh", + "answers": [ + "příslovce", + "adverbium" + ] + } + ], + "solution": "příslovce" + }, + { + "kind": "fields", + "prompt": "Sedím před školou. — slovo „před“", + "fields": [ + { + "label": "slovní druh", + "answers": [ + "předložka", + "prepozice" + ] + } + ], + "solution": "předložka" + }, + { + "kind": "fields", + "prompt": "To je jeho kniha. — slovo „jeho“", + "fields": [ + { + "label": "slovní druh", + "answers": [ + "zájmeno", + "zájmeno", + "pronomen" + ] + } + ], + "solution": "zájmeno" + }, + { + "kind": "fields", + "prompt": "Ach, to je škoda! — slovo „Ach“", + "fields": [ + { + "label": "slovní druh", + "answers": [ + "citoslovce", + "interjekce" + ] + } + ], + "solution": "citoslovce" + }, + { + "kind": "fields", + "prompt": "Přišel jsem, ale bylo pozdě. — slovo „ale“", + "fields": [ + { + "label": "slovní druh", + "answers": [ + "spojka", + "konjunkce" + ] + } + ], + "solution": "spojka" + }, + { + "kind": "fields", + "prompt": "Napočítal jsem pět jablek. — slovo „pět“", + "fields": [ + { + "label": "slovní druh", + "answers": [ + "číslovka", + "cislovka", + "numerale" + ] + } + ], + "solution": "číslovka" + }, + { + "kind": "fields", + "prompt": "Učitel vysvětloval látku. — slovo „Učitel“", + "fields": [ + { + "label": "slovní druh", + "answers": [ + "podstatné jméno", + "podstatné jmeno", + "substantivum" + ] + } + ], + "solution": "podstatné jméno" + } + ] + }, + { + "number": 4, + "title": "Podst. jména", + "heading": "Mluvnické kategorie – podstatná jména", + "subtitleKey": null, + "subtitle": "Určete rod, číslo a pád podtržených slov.", + "note": "Vyplňte tři pole: rod, číslo a pád.", + "items": [ + { + "kind": "fields", + "prompt": "Kniha leží na stole. — slovo „stole“ (stůl)", + "fields": [ + { + "label": "rod", + "answers": [ + "mužský", + "mužský rod", + "maskulinum" + ] + }, + { + "label": "číslo", + "answers": [ + "jednotné", + "jednotné číslo", + "singulár" + ] + }, + { + "label": "pád", + "answers": [ + "6", + "lokál", + "šestý", + "6. pád" + ] + } + ], + "solution": "mužský rod, jednotné číslo, 6. pád (lokál)" + }, + { + "kind": "fields", + "prompt": "Povídám si s kamarády. — slovo „kamarády“ (kamarád)", + "fields": [ + { + "label": "rod", + "answers": [ + "mužský", + "mužský rod", + "maskulinum" + ] + }, + { + "label": "číslo", + "answers": [ + "množné", + "množné číslo", + "plurál" + ] + }, + { + "label": "pád", + "answers": [ + "7", + "instrumentál", + "sedmý", + "7. pád" + ] + } + ], + "solution": "mužský rod, množné číslo, 7. pád (instrumentál)" + }, + { + "kind": "fields", + "prompt": "Vidím krásnou horu. — slovo „horu“ (hora)", + "fields": [ + { + "label": "rod", + "answers": [ + "ženský", + "ženský rod", + "femininum" + ] + }, + { + "label": "číslo", + "answers": [ + "jednotné", + "jednotné číslo", + "singulár" + ] + }, + { + "label": "pád", + "answers": [ + "4", + "akuzativ", + "čtvrtý", + "4. pád" + ] + } + ], + "solution": "ženský rod, jednotné číslo, 4. pád (akuzativ)" + }, + { + "kind": "fields", + "prompt": "To je dům mého souseda. — slovo „souseda“ (soused)", + "fields": [ + { + "label": "rod", + "answers": [ + "mužský", + "mužský rod", + "maskulinum" + ] + }, + { + "label": "číslo", + "answers": [ + "jednotné", + "jednotné číslo", + "singulár" + ] + }, + { + "label": "pád", + "answers": [ + "2", + "genitiv", + "druhý", + "2. pád" + ] + } + ], + "solution": "mužský rod, jednotné číslo, 2. pád (genitiv)" + }, + { + "kind": "fields", + "prompt": "Děti si hrají na zahradě. — slovo „Děti“ (dítě)", + "fields": [ + { + "label": "rod", + "answers": [ + "střední", + "střední rod", + "neutrum" + ] + }, + { + "label": "číslo", + "answers": [ + "množné", + "množné číslo", + "plurál" + ] + }, + { + "label": "pád", + "answers": [ + "1", + "nominativ", + "první", + "1. pád" + ] + } + ], + "solution": "střední rod, množné číslo, 1. pád (nominativ)" + } + ] + }, + { + "number": 5, + "title": "Slovesa", + "heading": "Mluvnické kategorie – slovesa", + "subtitleKey": null, + "subtitle": "Určete osobu, číslo, čas a způsob u těchto sloves.", + "note": "U rozkazovacího a podmiňovacího způsobu napište do pole čas „neurčitý“.", + "items": [ + { + "kind": "fields", + "prompt": "čteme", + "fields": [ + { + "label": "osoba", + "answers": [ + "1", + "1.", + "první", + "první osoba", + "1. osoba" + ] + }, + { + "label": "číslo", + "answers": [ + "množné", + "množné číslo", + "plurál" + ] + }, + { + "label": "čas", + "answers": [ + "přítomný", + "přítomný čas", + "přítomný čas" + ] + }, + { + "label": "způsob", + "answers": [ + "oznamovací", + "oznamovací způsob", + "indikativ" + ] + } + ], + "solution": "1. osoba, množné číslo, přítomný čas, oznamovací způsob" + }, + { + "kind": "fields", + "prompt": "běžel", + "fields": [ + { + "label": "osoba", + "answers": [ + "3", + "3.", + "třetí", + "třetí osoba", + "3. osoba" + ] + }, + { + "label": "číslo", + "answers": [ + "jednotné", + "jednotné číslo", + "singulár" + ] + }, + { + "label": "čas", + "answers": [ + "minulý", + "minulý čas", + "minulý čas" + ] + }, + { + "label": "způsob", + "answers": [ + "oznamovací", + "oznamovací způsob", + "indikativ" + ] + } + ], + "solution": "3. osoba, jednotné číslo, minulý čas, oznamovací způsob" + }, + { + "kind": "fields", + "prompt": "přečtěte", + "fields": [ + { + "label": "osoba", + "answers": [ + "2", + "2.", + "druhý", + "druhá osoba", + "2. osoba" + ] + }, + { + "label": "číslo", + "answers": [ + "množné", + "množné číslo", + "plurál" + ] + }, + { + "label": "čas", + "answers": [ + "neurčitý", + "nestanovený", + "neurčený" + ] + }, + { + "label": "způsob", + "answers": [ + "rozkazovací", + "rozkazovací způsob", + "imperativ" + ] + } + ], + "solution": "2. osoba, množné číslo, rozkazovací způsob (čas se neurčuje)" + }, + { + "kind": "fields", + "prompt": "by zpíval", + "fields": [ + { + "label": "osoba", + "answers": [ + "3", + "3.", + "třetí", + "třetí osoba", + "3. osoba" + ] + }, + { + "label": "číslo", + "answers": [ + "jednotné", + "jednotné číslo", + "singulár" + ] + }, + { + "label": "čas", + "answers": [ + "neurčitý", + "nestanovený", + "přítomný" + ] + }, + { + "label": "způsob", + "answers": [ + "podmiňovací", + "podmiňovací způsob", + "kondicionál" + ] + } + ], + "solution": "3. osoba, jednotné číslo, podmiňovací způsob přítomný" + }, + { + "kind": "fields", + "prompt": "budou pracovat", + "fields": [ + { + "label": "osoba", + "answers": [ + "3", + "3.", + "třetí", + "třetí osoba", + "3. osoba" + ] + }, + { + "label": "číslo", + "answers": [ + "množné", + "množné číslo", + "plurál" + ] + }, + { + "label": "čas", + "answers": [ + "budoucí", + "budoucí čas", + "futurum" + ] + }, + { + "label": "způsob", + "answers": [ + "oznamovací", + "oznamovací způsob", + "indikativ" + ] + } + ], + "solution": "3. osoba, množné číslo, budoucí čas, oznamovací způsob" + } + ] + }, + { + "number": 6, + "title": "Slovotvorba", + "heading": "Slovotvorba", + "subtitleKey": null, + "subtitle": "Rozeberte slova na morfémy.", + "note": "Určete předponu, kořen, příponu a koncovku.", + "items": [ + { + "kind": "reveal", + "prompt": "napsali", + "solution": "na- / ps- / -a- / -li" + }, + { + "kind": "reveal", + "prompt": "přečíst", + "solution": "pře- / číst" + }, + { + "kind": "reveal", + "prompt": "zahradník", + "solution": "za- / hrad- / -ník / -Ø" + }, + { + "kind": "reveal", + "prompt": "nepřátelský", + "solution": "ne- / přátel- / -ský / -Ø" + }, + { + "kind": "reveal", + "prompt": "výběr", + "solution": "vý- / bér- / -Ø / -Ø" + } + ] + }, + { + "number": 7, + "title": "Větné členy", + "heading": "Větné členy", + "subtitleKey": null, + "subtitle": "Určete větný člen podtržených výrazů.", + "items": [ + { + "kind": "fields", + "prompt": "Malá holčička plakala. — větný člen „Malá holčička“", + "fields": [ + { + "label": "větný člen", + "answers": [ + "podmět", + "subjekt" + ] + } + ], + "solution": "podmět" + }, + { + "kind": "fields", + "prompt": "Otec pracuje v garáži. — větný člen „v garáži“", + "fields": [ + { + "label": "větný člen", + "answers": [ + "příslovečné určení místa", + "příslovečné určení místa (PU místa)", + "příslovečné určení", + "adverbiále místa" + ] + } + ], + "solution": "příslovečné určení místa" + }, + { + "kind": "fields", + "prompt": "Sestra je učitelka. — větný člen „je učitelka“", + "fields": [ + { + "label": "větný člen", + "answers": [ + "přísudek jmenný se sponou", + "přísudek jmenný", + "jmenný přísudek se sponou", + "přísudek se sponou" + ] + } + ], + "solution": "přísudek jmenný se sponou" + }, + { + "kind": "fields", + "prompt": "Dal jsem knihu bratrovi. — větný člen „knihu“", + "fields": [ + { + "label": "větný člen", + "answers": [ + "předmět", + "objekt" + ] + } + ], + "solution": "předmět" + }, + { + "kind": "fields", + "prompt": "Přišel unavený. — větný člen „unavený“", + "fields": [ + { + "label": "větný člen", + "answers": [ + "doplněk" + ] + } + ], + "solution": "doplněk" + }, + { + "kind": "fields", + "prompt": "Pomalu šel domů. — větný člen „Pomalu“", + "fields": [ + { + "label": "větný člen", + "answers": [ + "příslovečné určení způsobu", + "příslovečné určení způsobu (PU způsobu)", + "příslovečné určení", + "adverbiále způsobu" + ] + } + ], + "solution": "příslovečné určení způsobu" + } + ] + }, + { + "number": 8, + "title": "Vedlejší věty", + "heading": "Druhy vedlejších vět", + "subtitleKey": null, + "subtitle": "Určete druh vedlejší věty.", + "items": [ + { + "kind": "fields", + "prompt": "Věřím, že uspěješ.", + "fields": [ + { + "label": "druh vedlejší věty", + "answers": [ + "vedlejší věta předmětná", + "věta předmětná", + "předmětná" + ] + } + ], + "solution": "vedlejší věta předmětná" + }, + { + "kind": "fields", + "prompt": "Udělám to, jak budu moci.", + "fields": [ + { + "label": "druh vedlejší věty", + "answers": [ + "vedlejší věta příslovečná způsobová", + "příslovečná způsobová", + "způsobová" + ] + } + ], + "solution": "vedlejší věta příslovečná způsobová" + }, + { + "kind": "fields", + "prompt": "Přišel, protože chtěl pomoci.", + "fields": [ + { + "label": "druh vedlejší věty", + "answers": [ + "vedlejší věta příslovečná příčinná", + "příslovečná příčinná", + "příčinná" + ] + } + ], + "solution": "vedlejší věta příslovečná příčinná" + }, + { + "kind": "fields", + "prompt": "Řekni mi, kde bydlíš.", + "fields": [ + { + "label": "druh vedlejší věty", + "answers": [ + "vedlejší věta předmětná", + "věta předmětná", + "předmětná" + ] + } + ], + "solution": "vedlejší věta předmětná" + }, + { + "kind": "fields", + "prompt": "Byl tak unavený, že usnul okamžitě.", + "fields": [ + { + "label": "druh vedlejší věty", + "answers": [ + "vedlejší věta příslovečná následková", + "příslovečná následková", + "následková" + ] + } + ], + "solution": "vedlejší věta příslovečná následková" + } + ] + }, + { + "number": 9, + "title": "Synonyma", + "heading": "Synonyma", + "subtitleKey": null, + "subtitle": "Ke každému slovu napište synonymum.", + "items": [ + { + "kind": "fields", + "prompt": "rychlý", + "fields": [ + { + "label": "synonymum", + "answers": [ + "hbitý", + "svižný", + "rychlý", + "čilý", + "bystrý", + "prudký" + ] + } + ], + "solution": "hbitý, svižný" + }, + { + "kind": "fields", + "prompt": "smutný", + "fields": [ + { + "label": "synonymum", + "answers": [ + "nešťastný", + "zarmoucený", + "tesklivý", + "skličený", + "žalostný" + ] + } + ], + "solution": "nešťastný, zarmoucený" + }, + { + "kind": "fields", + "prompt": "začít", + "fields": [ + { + "label": "synonymum", + "answers": [ + "zahájit", + "započít", + "začínat", + "rozpoutat", + "zahajovat" + ] + } + ], + "solution": "zahájit, započít" + }, + { + "kind": "fields", + "prompt": "krásný", + "fields": [ + { + "label": "synonymum", + "answers": [ + "nádherný", + "překrásný", + "kouzelný", + "půvabný", + "okouzlující" + ] + } + ], + "solution": "nádherný, překrásný" + }, + { + "kind": "fields", + "prompt": "mluvit", + "fields": [ + { + "label": "synonymum", + "answers": [ + "hovořit", + "promlouvat", + "vyprávět", + "říkat", + "povídat" + ] + } + ], + "solution": "hovořit, promlouvat" + } + ] + }, + { + "number": 10, + "title": "Antonyma", + "heading": "Antonyma", + "subtitleKey": null, + "subtitle": "Napište opak.", + "items": [ + { + "kind": "fields", + "prompt": "starý ×", + "fields": [ + { + "label": "opak", + "answers": [ + "nový", + "mladý" + ] + } + ], + "solution": "nový" + }, + { + "kind": "fields", + "prompt": "začátek ×", + "fields": [ + { + "label": "opak", + "answers": [ + "konec", + "závěr" + ] + } + ], + "solution": "konec" + }, + { + "kind": "fields", + "prompt": "přijít ×", + "fields": [ + { + "label": "opak", + "answers": [ + "odejít", + "odjet", + "odcházet" + ] + } + ], + "solution": "odejít" + }, + { + "kind": "fields", + "prompt": "radost ×", + "fields": [ + { + "label": "opak", + "answers": [ + "smutek", + "žal", + "zármutek" + ] + } + ], + "solution": "smutek" + }, + { + "kind": "fields", + "prompt": "vysoký ×", + "fields": [ + { + "label": "opak", + "answers": [ + "nízký", + "malý" + ] + } + ], + "solution": "nízký" + } + ] + }, + { + "number": 11, + "title": "s/z", + "heading": "Pravopis – s/z na začátku slova", + "subtitleKey": null, + "subtitle": "Vyberte správnou předponu s-/z-.", + "items": [ + { + "kind": "fields", + "prompt": "(s/z)kočit dolů ze stromu", + "fields": [ + { + "label": "s-/z-", + "answers": [ + "skočit" + ] + } + ], + "solution": "skočit" + }, + { + "kind": "fields", + "prompt": "(s/z)epsat úkol", + "fields": [ + { + "label": "s-/z-", + "answers": [ + "sepsat" + ] + } + ], + "solution": "sepsat" + }, + { + "kind": "fields", + "prompt": "(s/z)budovat nový dům", + "fields": [ + { + "label": "s-/z-", + "answers": [ + "zbudovat" + ] + } + ], + "solution": "zbudovat" + }, + { + "kind": "fields", + "prompt": "(s/z)vednout těžký kámen", + "fields": [ + { + "label": "s-/z-", + "answers": [ + "zvednout" + ] + } + ], + "solution": "zvednout" + }, + { + "kind": "fields", + "prompt": "(s/z)pravit auto", + "fields": [ + { + "label": "s-/z-", + "answers": [ + "spravit" + ] + } + ], + "solution": "spravit" + } + ] + }, + { + "number": 12, + "title": "Najdi chybu", + "heading": "Skladba – najděte chybu", + "subtitleKey": null, + "subtitle": "Každá věta obsahuje jednu chybu. Najděte ji a opravte.", + "items": [ + { + "kind": "reveal", + "prompt": "Koupil jsem novej kabát.", + "solution": "nový („novej“ je nespisovné)" + }, + { + "kind": "reveal", + "prompt": "Přišli jsme tam, kdy jsme měli.", + "solution": "kdy → když: „Přišli jsme tam, když jsme měli.“" + }, + { + "kind": "reveal", + "prompt": "Ona mě o tom neřekla nic.", + "solution": "mě → mi (dativ): „Ona mi o tom neřekla nic.“" + }, + { + "kind": "reveal", + "prompt": "Je to nejlepší film, který jsem viděl vůbec.", + "solution": "„vůbec nejlepší film“: „Je to vůbec nejlepší film, který jsem viděl.“" + }, + { + "kind": "reveal", + "prompt": "Byl jsem na nákupu a koupil chléb.", + "solution": "„Byl jsem nakupovat a koupil jsem chléb.“" + } + ] + }, + { + "number": 13, + "title": "Tvary", + "heading": "Tvarosloví – správný tvar", + "subtitleKey": null, + "subtitle": "Dejte slovo do správného tvaru.", + "items": [ + { + "kind": "fields", + "prompt": "Viděl jsem (ten starý muž) ______.", + "fields": [ + { + "label": "správný tvar", + "answers": [ + "toho starého muže", + "toho starého muže," + ] + } + ], + "solution": "toho starého muže" + }, + { + "kind": "fields", + "prompt": "Mluvil jsem s (moje sestra) ______.", + "fields": [ + { + "label": "správný tvar", + "answers": [ + "mojí sestrou", + "mou sestrou", + "svou sestrou" + ] + } + ], + "solution": "mojí sestrou" + }, + { + "kind": "fields", + "prompt": "Jdu do (škola) ______.", + "fields": [ + { + "label": "správný tvar", + "answers": [ + "školy" + ] + } + ], + "solution": "školy" + }, + { + "kind": "fields", + "prompt": "Sedím vedle (kamarád) ______.", + "fields": [ + { + "label": "správný tvar", + "answers": [ + "kamaráda" + ] + } + ], + "solution": "kamaráda" + }, + { + "kind": "fields", + "prompt": "Vzpomínám na (dětství) ______.", + "fields": [ + { + "label": "správný tvar", + "answers": [ + "dětství" + ] + } + ], + "solution": "dětství" + } + ] + }, + { + "number": 14, + "title": "Test A–D", + "heading": "Výběr ze čtyř možností", + "subtitleKey": null, + "subtitle": "Vyberte správnou odpověď.", + "items": [ + { + "kind": "choice", + "prompt": "Slovo „záříjový“ je:", + "options": [ + "správně", + "chybně" + ], + "correct": 1, + "hint": "Správně je „zářijový“ (nikoli „záříjový“)." + }, + { + "kind": "choice", + "prompt": "Které slovo je přídavné jméno?", + "options": [ + "rychle", + "rychlost", + "rychlý", + "zrychlení" + ], + "correct": 2, + "hint": "„rychlý“ je přídavné jméno; „rychle“ je příslovce." + }, + { + "kind": "choice", + "prompt": "Věta „Petr čte knihu.“ je:", + "options": [ + "souvětí", + "věta jednoduchá", + "věta bez podmětu", + "věta zvolací" + ], + "correct": 1, + "hint": "Věta má jen jeden přísudek („čte“), jde o větu jednoduchou." + }, + { + "kind": "choice", + "prompt": "Slovo „příroda“ je utvořeno:", + "options": [ + "odvozením", + "skládáním", + "zkracováním", + "přejímáním" + ], + "correct": 0, + "hint": "„příroda“ je utvořena odvozením, není to složenina." + }, + { + "kind": "choice", + "prompt": "Která dvojice jsou synonyma?", + "options": [ + "rychlý – pomalý", + "jít – přijít", + "smutný – nešťastný", + "velký – malý" + ], + "correct": 2, + "hint": "Synonyma vyjadřují stejný význam: „smutný“ a „nešťastný“." + } + ] + }, + { + "number": 15, + "title": "Přímá řeč", + "heading": "Přímá a nepřímá řeč", + "subtitleKey": null, + "subtitle": "Přepište přímou řeč na nepřímou.", + "items": [ + { + "kind": "reveal", + "prompt": "Matka řekla: „Pojď se najíst.“", + "solution": "Matka řekla, abych přišel se najíst." + }, + { + "kind": "reveal", + "prompt": "Učitel řekl: „Zítra bude písemka.“", + "solution": "Učitel řekl, že zítra bude písemka." + }, + { + "kind": "reveal", + "prompt": "Kamarád se zeptal: „Kde bydlíš?“", + "solution": "Kamarád se zeptal, kde bydlím." + } + ] + }, + { + "number": 16, + "title": "Rozdíly", + "heading": "Slovní zásoba – rozdíly", + "subtitleKey": null, + "subtitle": "Vysvětlete rozdíl mezi těmito dvojicemi slov.", + "items": [ + { + "kind": "reveal", + "prompt": "bydlet × žít", + "solution": "bydlet = mít domov někde; žít = existovat, prožívat život" + }, + { + "kind": "reveal", + "prompt": "říkat × vyprávět", + "solution": "říkat = sdělovat informaci; vyprávět = podrobně popisovat příběh" + }, + { + "kind": "reveal", + "prompt": "dívat se × vidět", + "solution": "dívat se = záměrně sledovat; vidět = vnímat zrakem (i neúmyslně)" + }, + { + "kind": "reveal", + "prompt": "učit × učit se", + "solution": "učit = předávat znalosti druhým; učit se = sám nabývat znalosti" + }, + { + "kind": "reveal", + "prompt": "přinést × donést", + "solution": "přinést = přinést sem (k mluvčímu); donést = odnést tam (od mluvčího)" + } + ] + }, + { + "number": 17, + "title": "Interpunkce", + "heading": "Interpunkce", + "subtitleKey": null, + "subtitle": "Doplňte čárky tam, kde patří.", + "items": [ + { + "kind": "reveal", + "prompt": "Přišel jsem domů unavený hladový a promrzlý.", + "solution": "Přišel jsem domů unavený, hladový a promrzlý." + }, + { + "kind": "reveal", + "prompt": "Když dorazil vlak nastoupili všichni cestující.", + "solution": "Když dorazil vlak, nastoupili všichni cestující." + }, + { + "kind": "reveal", + "prompt": "Myslím že dnes bude pršet.", + "solution": "Myslím, že dnes bude pršet." + }, + { + "kind": "reveal", + "prompt": "Jana která je moje nejlepší kamarádka bydlí vedle.", + "solution": "Jana, která je moje nejlepší kamarádka, bydlí vedle." + }, + { + "kind": "reveal", + "prompt": "Pes štěkal ale nikdo nepřicházel.", + "solution": "Pes štěkal, ale nikdo nepřicházel." + } + ] + }, + { + "number": 18, + "title": "Obrazná pojmen.", + "heading": "Obrazná pojmenování", + "subtitleKey": null, + "subtitle": "Určete, o jaký druh obrazného pojmenování jde.", + "items": [ + { + "kind": "fields", + "prompt": "Slunce se usmívalo na celé město.", + "fields": [ + { + "label": "druh pojmenování", + "answers": [ + "personifikace", + "zosobnění" + ] + } + ], + "solution": "personifikace" + }, + { + "kind": "fields", + "prompt": "Je silný jako býk.", + "fields": [ + { + "label": "druh pojmenování", + "answers": [ + "přirovnání", + "komparace" + ] + } + ], + "solution": "přirovnání" + }, + { + "kind": "fields", + "prompt": "Moře hněvu ho zaplavilo.", + "fields": [ + { + "label": "druh pojmenování", + "answers": [ + "metafora" + ] + } + ], + "solution": "metafora" + }, + { + "kind": "fields", + "prompt": "Čekal jsem na tebe věčnost.", + "fields": [ + { + "label": "druh pojmenování", + "answers": [ + "hyperbola", + "nadsázka" + ] + } + ], + "solution": "hyperbola" + }, + { + "kind": "fields", + "prompt": "Přečetl celého Shakespeara.", + "fields": [ + { + "label": "druh pojmenování", + "answers": [ + "metonymie" + ] + } + ], + "solution": "metonymie" + } + ] + }, + { + "number": 19, + "title": "Slohové útvary", + "heading": "Stylistika – slohové útvary", + "subtitleKey": null, + "subtitle": "Přiřaďte ukázku ke správnému slohovému útvaru.", + "items": [ + { + "kind": "fields", + "prompt": "Narodil se roku 1890 v Praze. Vystudoval práva a poté pracoval jako úředník…", + "fields": [ + { + "label": "slohový útvar", + "answers": [ + "životopis", + "biografie" + ] + } + ], + "solution": "životopis" + }, + { + "kind": "fields", + "prompt": "Byl to chlapec střední postavy, s hnědýma očima a klidným výrazem…", + "fields": [ + { + "label": "slohový útvar", + "answers": [ + "charakteristika" + ] + } + ], + "solution": "charakteristika" + }, + { + "kind": "fields", + "prompt": "Jednoho dne jsem šel lesem, když tu najednou jsem zaslechl podivný zvuk…", + "fields": [ + { + "label": "slohový útvar", + "answers": [ + "vyprávění" + ] + } + ], + "solution": "vyprávění" + }, + { + "kind": "fields", + "prompt": "Mnozí se ptají, zda má smysl číst knihy v době internetu. Domnívám se…", + "fields": [ + { + "label": "slohový útvar", + "answers": [ + "úvaha" + ] + } + ], + "solution": "úvaha" + }, + { + "kind": "fields", + "prompt": "Místnost byla malá, se dvěma okny na jih. U zdi stála stará skříň…", + "fields": [ + { + "label": "slohový útvar", + "answers": [ + "popis" + ] + } + ], + "solution": "popis" + } + ] + }, + { + "number": 20, + "title": "Opakování", + "heading": "Souhrnné opakování", + "subtitleKey": null, + "subtitle": "Vyberte správnou odpověď.", + "items": [ + { + "kind": "choice", + "prompt": "Které slovo není příslovce?", + "options": [ + "rychle", + "tam", + "hezký", + "brzy" + ], + "correct": 2 + }, + { + "kind": "choice", + "prompt": "Ve větě „Petr dal Pavlovi knihu“ je slovo „Pavlovi“:", + "options": [ + "podmět", + "přísudek", + "předmět", + "příslovečné určení" + ], + "correct": 2 + }, + { + "kind": "choice", + "prompt": "Slovo „nejhezčí“ obsahuje:", + "options": [ + "předponu a příponu", + "pouze předponu", + "kořen a příponu", + "pouze příponu" + ], + "correct": 0 + }, + { + "kind": "choice", + "prompt": "Která věta je souvětí souřadné slučovací?", + "options": [ + "Přišel, protože chtěl pomoci.", + "Šel domů a spal.", + "Věřím, že přijdeš.", + "Udělám to, jak budeš chtít." + ], + "correct": 1 + }, + { + "kind": "choice", + "prompt": "Příslovce „rychle“ je stupňováno jako:", + "options": [ + "rychle – rychleji – nejrychleji", + "rychle – více rychle – nejvíce rychle", + "rychle – rychlé – nejrychlejší", + "nelze stupňovat" + ], + "correct": 0 + } + ] + } + ] +} diff --git a/content/lessons/czech/orwell-1984.json b/content/lessons/czech/orwell-1984.json new file mode 100644 index 0000000..e2a0b08 --- /dev/null +++ b/content/lessons/czech/orwell-1984.json @@ -0,0 +1,481 @@ +{ + "id": "orwell-1984", + "subject": "czech", + "number": 2, + "title": { + "cs": "George Orwell – 1984", + "en": "George Orwell – 1984" + }, + "subtitle": { + "cs": "Projděte si přehled a pak si vyzkoušejte kvíz a řazení děje.", + "en": "Read the overview, then try the quiz and the plot ordering." + }, + "slides": [ + { + "kicker": "George Orwell – 1984", + "title": "O knize", + "tip": null, + "lines": [ + "Autor: George Orwell (vl. jm. Eric Arthur Blair)", + "Žánr: antiutopický (dystopický) román", + "Poprvé vydáno: 1949", + "Děj: Londýn, provincie Letopočet 1, stát Oceánie", + "Vyprávění: v er-formě, po deníkových zápiscích Winstona Smithe" + ] + }, + { + "kicker": "George Orwell – 1984", + "title": "Svět a strana", + "tip": null, + "lines": [ + "Svět je rozdělen na tři supervelmoci: Oceánii, Eurasii a Východasii, které spolu vedou trvalou válku.", + "Vládne jediná strana (Angsoc) v čele s kultem Velkého bratra.", + "Ministerstvo pravdy – přepisuje historii a vyrábí „pravdu“.", + "Ministerstvo lásky – mučírny a likvidace nepohodlných.", + "Ministerstvo hojnosti – plánuje hospodářství a drží lidi v nedostatku.", + "Ministerstvo míru – vede válku." + ] + }, + { + "kicker": "George Orwell – 1984", + "title": "Postavy", + "tip": null, + "lines": [ + "Winston Smith – hlavní hrdina, přepisuje historii, touží po svobodě.", + "Julie – mladá členka strany, Winstonova tajná láska.", + "O'Brien – člen vnitřní strany, předstírá odboj a Winstona zničí.", + "Emmanuel Goldstein – nepřítel státu, údajný vůdce Bratrstva.", + "Velký bratr – symbol všemocné moci strany.", + "Pan Charrington – zdánlivý obchodník, ve skutečnosti agent." + ] + }, + { + "kicker": "George Orwell – 1984", + "title": "Klíčové pojmy", + "tip": null, + "lines": [ + "Newspeak – uměle zjednodušovaný jazyk, který omezuje myšlení.", + "Dvojité myšlení – ochota věřit dvěma protikladným pravdám.", + "Zločin myšlení – už samotná zakázaná myšlenka.", + "Policie myšlení – tajná policie, která zatýká a mučí.", + "Bratrstvo – možná neexistující odbojová organizace.", + "Místnost 101 – nejhlubší mučírna, pro každého jeho největší strach." + ] + } + ], + "tasks": [ + { + "number": 1, + "title": "Kvíz", + "heading": "Kvíz ke knize", + "subtitleKey": "lit_quiz_sub", + "items": [ + { + "kind": "choice", + "prompt": "Kdo je hlavní hrdina románu a co dělá?", + "options": [ + "Winston Smith – přepisuje historii na Ministerstvu pravdy", + "O'Brien – řídí Ministerstvo lásky", + "Emmanuel Goldstein – vede Bratrstvo", + "Winston Smith – velí Policii myšlení" + ], + "correct": 0, + "hint": "Winston Smith je vnější člen strany, který na Ministerstvu pravdy upravuje staré záznamy a novinové články." + }, + { + "kind": "choice", + "prompt": "Ve kterém fiktivním státě se děj odehrává?", + "options": [ + "V Eurasii", + "V Oceánii", + "Ve Východasii", + "V Angsocu" + ], + "correct": 1, + "hint": "Příběh se odehrává v Oceánii, v provincii Letopočet 1 (bývalá Anglie), jejímž hlavním městem je Londýn." + }, + { + "kind": "choice", + "prompt": "Co znamená slogan „VÁLKA JE MÍR, SVOBODA JE OTROCTVÍ, NEVĚDOMOST JE SÍLA“?", + "options": [ + "Jsou to tři zásady Bratrstva", + "Jsou to názvy ministerstev", + "Jde o hesla prolety", + "Jsou to paradoxní hesla, kterými strana ospravedlňuje útlak" + ], + "correct": 3, + "hint": "Strana používá dvojité myšlení: hesla znějí vznešeně, ale ve skutečnosti obhajují válku, otroctví a nevědomost." + }, + { + "kind": "choice", + "prompt": "Kdo je Velký bratr a je reálnou osobou?", + "options": [ + "Skutečný vůdce Bratrstva", + "Winstonův nadřízený na ministerstvu", + "Symbol všemocné moci a kultu osobnosti; možná vůbec neexistuje", + "O'Brienův pseudonym" + ], + "correct": 2, + "hint": "Velký bratr je tvář režimu. Není jasné, zda jde o živou osobu, nebo jen o symbol, který drží strach a poslušnost." + }, + { + "kind": "choice", + "prompt": "Co je Newspeak (novořeč) a proč ho strana zavádí?", + "options": [ + "Tajná řeč Bratrstva", + "Zjednodušená angličtina omezující slovní zásobu, aby nešlo vyslovit zakázané myšlenky", + "Úřední jazyk prolety", + "Šifra Policie myšlení" + ], + "correct": 1, + "hint": "Newspeak neustále ubírá slova. Když pro svobodu nebo odpor neexistuje slovo, nelze o nich ani myslet." + }, + { + "kind": "choice", + "prompt": "Co je teleobrazovka (telescreen) a jak funguje?", + "options": [ + "Televize určená jen pro zábavu", + "Zařízení, které vysílá i sleduje; nelze ji úplně vypnout", + "Rozhlasová stanice", + "Počítač Ministerstva pravdy" + ], + "correct": 1, + "hint": "Telescreen funguje obousměrně – neustále sleduje občany. Vypnout lze jen zvuk, obraz běží dál." + }, + { + "kind": "choice", + "prompt": "Jak se jmenují tři supervelmoci světa 1984?", + "options": [ + "Oceánie, Eurasie a Východasie", + "Oceánie, Evropa a Asie", + "Anglie, Eurasie a Ostasie", + "Oceánie, Východasie a Afrika" + ], + "correct": 0, + "hint": "Svět je rozdělen na tři státy ve věčném, ale nerozhodném konfliktu: Oceánii, Eurasii a Východasii." + }, + { + "kind": "choice", + "prompt": "Čím se zabývá Ministerstvo pravdy?", + "options": [ + "Vede válku", + "Dohlíží na morálku a sňatky", + "Upravuje a přepisuje historii, noviny a archivy", + "Rozděluje potraviny" + ], + "correct": 2, + "hint": "Ministerstvo pravdy vyrábí „pravdu“ – Winston v něm přepisuje staré záznamy tak, aby vždy odpovídaly současné linii strany." + }, + { + "kind": "choice", + "prompt": "K čemu slouží Ministerstvo lásky?", + "options": [ + "Zajišťuje sňatky a lásku", + "Je to budova bez oken, kde se mučí a likvidují nepřátelé strany", + "Vyrábí zbraně", + "Školí děti" + ], + "correct": 1, + "hint": "Ministerstvo lásky je opakem svého názvu – sídlí tam mučírny a nachází se v něm i obávaná místnost 101." + }, + { + "kind": "choice", + "prompt": "V čem je paradox Ministerstva hojnosti?", + "options": [ + "Má na starosti hospodářství, ale ve skutečnosti drží lidi v nedostatku", + "Rozdává jídlo a zboží zdarma", + "Zajišťuje dostatek pro všechny", + "Starají se o něj prolety" + ], + "correct": 0, + "hint": "Ministerstvo hojnosti plánuje výrobu, ale ekonomika je záměrně nastavena tak, aby lidé žili v trvalém nedostatku." + }, + { + "kind": "choice", + "prompt": "Co je Ministerstvo míru a čím se zabývá?", + "options": [ + "Uzavírá mírové smlouvy", + "Dojednává příměří", + "Ve skutečnosti vede válku", + "Velí Policii myšlení" + ], + "correct": 2, + "hint": "Název je přesně opačný: Ministerstvo míru řídí válku, protože trvalý válečný stav pomáhá udržet moc strany." + }, + { + "kind": "choice", + "prompt": "Kdo je Julie a jaký vztah s ní Winston naváže?", + "options": [ + "Winstonova žena", + "Mladá členka strany, s níž Winston prožije tajnou milostnou aféru", + "O'Brienova asistentka", + "Proletka a obchodnice" + ], + "correct": 1, + "hint": "Julie pracuje v oddělení beletrie a naoko je vzornou členkou strany. S Winstonem vytvoří tajný milostný vztah." + }, + { + "kind": "choice", + "prompt": "Proč je vztah Winstona a Julie zakázaný?", + "options": [ + "Strana zakazuje lásku a sexualitu jako zločin; vztah je navíc tajný", + "Julie je vdaná za člena vnitřní strany", + "Winston je jejím nadřízeným", + "Julie patří k proletům" + ], + "correct": 0, + "hint": "Strana potlačuje citové a sexuální vazby, protože oddanost má patřit jen straně. Tajný vztah je proto dvojnásob nebezpečný." + }, + { + "kind": "choice", + "prompt": "Kdo je O'Brien a jakou roli hraje v příběhu?", + "options": [ + "Skutečný vůdce Bratrstva", + "Vysoce postavený člen vnitřní strany, který Winstona nakonec mučí a „vyléčí“", + "Winstonův přítel z dětství", + "Proletářský básník" + ], + "correct": 1, + "hint": "Winston věří, že O'Brien je odbojář. Ve skutečnosti je to věrný člen vnitřní strany, který ho dostane do místnosti 101." + }, + { + "kind": "choice", + "prompt": "Co je Bratrstvo a existuje vůbec?", + "options": [ + "Skutečná armáda Oceánie", + "Náboženská organizace", + "Údajná tajná organizace odporu; není jisté, zda existuje", + "Odbory prolety" + ], + "correct": 2, + "hint": "Bratrstvo zmiňuje Goldstein i O'Brien, ale kniha nikdy nepotvrdí, že doopravdy existuje – může jít o past strany." + }, + { + "kind": "choice", + "prompt": "Kdo je Emmanuel Goldstein?", + "options": [ + "Ministr pravdy", + "Oficiální nepřítel státu a údajný vůdce Bratrstva", + "Winstonův kolega", + "Velký bratrův dvojník" + ], + "correct": 1, + "hint": "Goldstein je terčem dvouminutovky nenávisti. Má ztělesňovat nepřítele, proti kterému strana sjednocuje občany." + }, + { + "kind": "choice", + "prompt": "Co je dvojité myšlení (doublethink)?", + "options": [ + "Schopnost myslet ve dvou jazycích", + "Zdvojení osobnosti", + "Schopnost věřit dvěma protikladným tvrzením zároveň", + "Tajné zapisování myšlenek" + ], + "correct": 2, + "hint": "Dvojité myšlení je jádro stranické ideologie – člověk přijme i zjevné rozpory, jako „válka je mír“." + }, + { + "kind": "choice", + "prompt": "Proč strana neustále přepisuje minulost?", + "options": [ + "Aby opravila chyby v archivech", + "Aby měla vždy pravdu a nepřítel jí nemohl dokázat opak", + "Aby ušetřila papír", + "Aby potěšila prolety" + ], + "correct": 1, + "hint": "Kdo ovládá minulost, ovládá i budoucnost. Přepisováním historie strana udržuje absolutní kontrolu nad pravdou." + }, + { + "kind": "choice", + "prompt": "Co je zločin myšlení (thoughtcrime)?", + "options": [ + "Pouhá myšlenka nebo názor, který se nelíbí straně", + "Krádež státního majetku", + "Nelegální obchod", + "Opomenutí dvouminutovky" + ], + "correct": 0, + "hint": "Strana trestá už samotné myšlenky. Winston se proviní tím, že si do deníku napíše „Dolů s Velkým bratrem“." + }, + { + "kind": "choice", + "prompt": "Kdo je pan Charrington a jaké je jeho skutečné postavení?", + "options": [ + "Winstonův přítel a majitel hospody", + "Proletářský básník", + "Zdánlivě starý majitel obchodu, ve skutečnosti agent Policie myšlení", + "Člen Bratrstva" + ], + "correct": 2, + "hint": "Charrington Winstonovi pronajme pokoj bez teleobrazovky, ale právě on nakonec oba milence udá." + }, + { + "kind": "choice", + "prompt": "Co je místnost 101?", + "options": [ + "Winstonova cela na policii", + "Skladiště knih", + "Místnost, ve které každého čeká jeho největší strach", + "Zasedací místnost vnitřní strany" + ], + "correct": 2, + "hint": "Místnost 101 je vrcholný mučicí nástroj. Winstonovi v ní hrozí krysy – jeho největší fobie." + }, + { + "kind": "choice", + "prompt": "Jak skončí vztah Winstona a Julie?", + "options": [ + "Utečou spolu do Eurasie", + "Vezmou se a žijí svobodně", + "Winston se stane členem Bratrstva", + "Zradí se a nakonec se přestanou milovat" + ], + "correct": 3, + "hint": "Oba jsou po mučení zlomení a vzájemně se zradí. Na konci už k sobě nic necítí." + }, + { + "kind": "choice", + "prompt": "Co znamená závěrečná věta „Miloval Velkého bratra“?", + "options": [ + "Winstonův vzdor se změnil v pokornou lásku k režimu", + "Winston se stal novým vůdcem", + "Byl to jen Winstonův sen", + "Julie mu to řekla" + ], + "correct": 0, + "hint": "Winston byl vnitřně zlomen. Přestal být sám sebou a nakonec režim opravdu přijal za svůj." + }, + { + "kind": "choice", + "prompt": "Které tvrzení NENÍ jedním z hlavních témat románu?", + "options": [ + "Moc a absolutní kontrola", + "Pravda a přepisování historie", + "Svoboda a identita", + "Idylický venkovský život" + ], + "correct": 3, + "hint": "1984 je temná antiutopie. Hlavními tématy jsou moc, kontrola, manipulace s pravdou a ztráta svobody, ne venkovská idyla." + }, + { + "kind": "choice", + "prompt": "V jakém roce byl román 1984 poprvé vydán?", + "options": [ + "1936", + "1949", + "1954", + "1984" + ], + "correct": 1, + "hint": "Román vyšel v roce 1949; letopočet 1984 označuje blízkou budoucnost, do níž Orwell příběh zasadil." + }, + { + "kind": "choice", + "prompt": "Které další Orwellovo dílo se dá s 1984 srovnat?", + "options": [ + "Farma zvířat", + "Velký Gatsby", + "Zločin a trest", + "Babička" + ], + "correct": 0, + "hint": "Obě Orwellova díla varují před totalitou. Farma zvířat ji líčí alegoricky pomocí zvířat, 1984 očima jedince." + }, + { + "kind": "choice", + "prompt": "Co je „dvouminutovka nenávisti“?", + "options": [ + "Krátká každodenní akce, při níž občané společně nenávidí Goldsteina a nepřítele", + "Pravidelná modlitba ke Velkému bratrovi", + "Sportovní přestávka ve škole", + "Porada vedení ministerstva" + ], + "correct": 0, + "hint": "Slouží k uvolnění a přesměrování agrese občanů na nepřítele státu, čímž strana posiluje svou moc." + }, + { + "kind": "choice", + "prompt": "Proč je podle knihy válka pro systém nezbytná?", + "options": [ + "Přináší mír a blahobyt", + "Udržuje strach, spotřebovává výrobu a zachovává chudobu i hierarchii", + "Rozvíjí vědu a techniku", + "Sjednocuje vládu s prolety" + ], + "correct": 1, + "hint": "Trvalá válka pohlcuje nadbytečnou produkci a udržuje lidi ve strachu i chudobě, takže se nemohou vzbouřit." + }, + { + "kind": "choice", + "prompt": "Jaký je rozdíl mezi vnějšími členy strany a prolety?", + "options": [ + "Proleti mají více práv než členové strany", + "Vnější členové jsou dozíráni, kdežto proleti žijí v chudobě a strana o ně nestojí", + "Není mezi nimi žádný rozdíl", + "Proleti tvoří vedení strany" + ], + "correct": 1, + "hint": "Proleti tvoří asi 85 % obyvatel. Žijí v bídě a jsou považováni za neškodné, dokud si neuvědomí svou sílu." + }, + { + "kind": "choice", + "prompt": "Jak strana kontroluje sexualitu a osobní vztahy?", + "options": [ + "Podporuje volnou lásku a nezávislost", + "Potlačuje lásku a sexualitu, děti vede k oddanosti straně", + "Zakazuje veškerá manželství", + "Povoluje vztahy jen s prolety" + ], + "correct": 1, + "hint": "Strana chce, aby veškerá oddanost a energie patřily jí. Proto podporuje zdrženlivost a vede děti v Antisexuální lize mládeže." + }, + { + "kind": "choice", + "prompt": "Co symbolizuje papírové těžítko, které si Winston koupí?", + "options": [ + "Jeho nenávist ke Goldsteinovi", + "Kousek krásy a minulosti, kterou už nelze vrátit", + "Moc Velkého bratra", + "Lásku k Julii" + ], + "correct": 1, + "hint": "Těžítko je drobný, krásný předmět z minulosti. Pro Winstona ztělesňuje svět, který strana zničila." + }, + { + "kind": "choice", + "prompt": "Jaké poselství chtěl Orwell románem nejspíš předat?", + "options": [ + "Varování před totalitou a ztrátou svobody i pravdy", + "Oslavu technického pokroku", + "Návod, jak založit stát", + "Kritiku sportu a zábavy" + ], + "correct": 0, + "hint": "1984 je varování: když lidé přestanou bránit pravdu a svobodu, mohou o ně nenávratně přijít." + } + ] + }, + { + "number": 2, + "title": "Děj", + "heading": "Seřaďte děj", + "subtitleKey": "lit_plot_sub", + "items": [ + { + "kind": "assembly", + "prompt": "Přetáhněte části příběhu do správného pořadí:", + "words": [ + "Winston upravuje historii na Ministerstvu pravdy", + "Seznámí se s Julií a začnou se tajně scházet", + "Pronajme si pokoj nad obchodem pana Charringtona", + "Přečte Goldsteinovu knihu u O'Briena", + "Jsou zatčeni Policií myšlení", + "Winston se zlomí v místnosti 101" + ], + "meaning": "Správné pořadí: přepisování historie → seznámení s Julií → pronájem pokoje → četba Goldsteinovy knihy → zatčení → místnost 101." + } + ] + } + ] +} diff --git a/content/lessons/deutsch/unit-01.json b/content/lessons/deutsch/unit-01.json new file mode 100644 index 0000000..2f0578b --- /dev/null +++ b/content/lessons/deutsch/unit-01.json @@ -0,0 +1,2200 @@ +{ + "id": "unit-01", + "subject": "deutsch", + "number": 1, + "title": { + "cs": "Neue Freunde", + "en": "Neue Freunde" + }, + "slides": [], + "tasks": [ + { + "number": 1, + "title": "Dialog", + "subtitleKey": "sub_dialog", + "pool": [ + "bin", + "heiße", + "kommst", + "aus", + "Morgen", + "geht", + "danke", + "Wiedersehen", + "Bis", + "Tschüss" + ], + "items": [ + { + "kind": "dialogue", + "title": "Sich vorstellen", + "rows": [ + { + "speaker": "A:", + "before": "Hallo! Ich ", + "answer": "bin|heiße", + "after": " Anna.", + "meaning": "Ahoj! Jmenuji se Anna." + }, + { + "speaker": "B:", + "before": "Hallo! Ich ", + "answer": "bin|heiße", + "after": " Peter.", + "meaning": "Ahoj! Jmenuji se Petr." + }, + { + "speaker": "A:", + "before": "Woher ", + "answer": "kommst", + "after": " du?", + "meaning": "Odkud jsi?" + }, + { + "speaker": "B:", + "before": "Ich komme ", + "answer": "aus", + "after": " Tschechien.", + "meaning": "Pocházím z Česka." + } + ] + }, + { + "kind": "dialogue", + "title": "Begrüßung", + "rows": [ + { + "speaker": "A:", + "before": "Guten ", + "answer": "Morgen", + "after": "!", + "meaning": "Dobré ráno!" + }, + { + "speaker": "B:", + "before": "Wie ", + "answer": "geht", + "after": " es dir?", + "meaning": "Jak se máš?" + }, + { + "speaker": "A:", + "before": "Mir geht es gut, ", + "answer": "danke", + "after": ".", + "meaning": "Mám se dobře, děkuji." + } + ] + }, + { + "kind": "dialogue", + "title": "Verabschiedung", + "rows": [ + { + "speaker": "A:", + "before": "Ich muss gehen. Auf ", + "answer": "Wiedersehen", + "after": "!", + "meaning": "Musím jít. Na shledanou!" + }, + { + "speaker": "B:", + "before": "", + "answer": "Bis", + "after": " bald!", + "meaning": "Brzy na viděnou!" + }, + { + "speaker": "A:", + "before": "", + "answer": "Tschüss", + "after": "!", + "meaning": "Čau!" + } + ] + } + ] + }, + { + "number": 2, + "title": "Sätze bilden", + "subtitleKey": "sub_assembly", + "items": [ + { + "kind": "assembly", + "prompt": "", + "words": [ + "Ich", + "heiße", + "Anna", + "." + ], + "meaning": "Jmenuji se Anna." + }, + { + "kind": "assembly", + "prompt": "", + "words": [ + "Woher", + "kommst", + "du", + "?" + ], + "meaning": "Odkud jsi?" + }, + { + "kind": "assembly", + "prompt": "", + "words": [ + "Ich", + "komme", + "aus", + "Tschechien", + "." + ], + "meaning": "Pocházím z Česka." + }, + { + "kind": "assembly", + "prompt": "", + "words": [ + "Wie", + "geht", + "es", + "dir", + "?" + ], + "meaning": "Jak se máš?" + } + ] + }, + { + "number": 3, + "title": "Was ist richtig?", + "subtitleKey": "sub_choice_num", + "items": [ + { + "kind": "choice", + "prompt": "Welche Zahl ist „vierzehn“?", + "options": [ + "4", + "14", + "40" + ], + "correct": 1, + "meaning": "„vierzehn“ = čtrnáct (14)" + }, + { + "kind": "choice", + "prompt": "Welche Zahl ist „siebzehn“?", + "options": [ + "7", + "17", + "70" + ], + "correct": 1, + "meaning": "„siebzehn“ = sedmnáct (17)" + }, + { + "kind": "choice", + "prompt": "Welche Zahl ist „zwanzig“?", + "options": [ + "2", + "12", + "20" + ], + "correct": 2, + "meaning": "„zwanzig“ = dvacet (20)" + }, + { + "kind": "choice", + "prompt": "Welche Zahl ist „sechs“?", + "options": [ + "6", + "16", + "60" + ], + "correct": 0, + "meaning": "„sechs“ = šest (6)" + } + ] + }, + { + "number": 4, + "title": "Freie Antwort", + "subtitleKey": "sub_free", + "items": [ + { + "kind": "free", + "question": "Wie heißt du?", + "questionCs": "Jak se jmenuješ?", + "sample": "Ich heiße Anna.", + "sampleCs": "Jmenuji se Anna." + }, + { + "kind": "free", + "question": "Woher kommst du?", + "questionCs": "Odkud pocházíš?", + "sample": "Ich komme aus Tschechien.", + "sampleCs": "Pocházím z Česka." + }, + { + "kind": "free", + "question": "Wie alt bist du?", + "questionCs": "Kolik je ti let?", + "sample": "Ich bin sechzehn Jahre alt.", + "sampleCs": "Je mi šestnáct let." + }, + { + "kind": "free", + "question": "Wie geht es dir?", + "questionCs": "Jak se máš?", + "sample": "Mir geht es gut, danke.", + "sampleCs": "Mám se dobře, děkuji." + } + ] + }, + { + "number": 5, + "title": "Zahlen", + "subtitleKey": "sub_zahlen", + "pool": [ + "vierzehn", + "siebzehn", + "zwanzig", + "sechs", + "dreizehn" + ], + "items": [ + { + "kind": "fill", + "segments": [ + "", + "" + ], + "answers": [ + "vierzehn" + ], + "input": "select", + "clue": "14", + "meaning": "čtrnáct" + }, + { + "kind": "fill", + "segments": [ + "", + "" + ], + "answers": [ + "siebzehn" + ], + "input": "select", + "clue": "17", + "meaning": "sedmnáct" + }, + { + "kind": "fill", + "segments": [ + "", + "" + ], + "answers": [ + "zwanzig" + ], + "input": "select", + "clue": "20", + "meaning": "dvacet" + }, + { + "kind": "fill", + "segments": [ + "", + "" + ], + "answers": [ + "sechs" + ], + "input": "select", + "clue": "6", + "meaning": "šest" + }, + { + "kind": "fill", + "segments": [ + "", + "" + ], + "answers": [ + "dreizehn" + ], + "input": "select", + "clue": "13", + "meaning": "třináct" + } + ] + }, + { + "number": 6, + "title": "Wie viel?", + "subtitleKey": "sub_wieviel", + "pool": [ + "zwei", + "fünf", + "sieben", + "neun", + "drei", + "elf", + "vier", + "acht", + "sechs" + ], + "items": [ + { + "kind": "fill", + "segments": [ + "", + " Äpfel" + ], + "answers": [ + "zwei" + ], + "input": "select", + "emoji": "🍎 🍎", + "meaning": "dvě jablka" + }, + { + "kind": "fill", + "segments": [ + "", + " Sterne" + ], + "answers": [ + "fünf" + ], + "input": "select", + "emoji": "⭐ ⭐ ⭐ ⭐ ⭐", + "meaning": "pět hvězd" + }, + { + "kind": "fill", + "segments": [ + "", + " Katzen" + ], + "answers": [ + "sieben" + ], + "input": "select", + "emoji": "🐱 🐱 🐱 🐱 🐱 🐱 🐱", + "meaning": "sedm koček" + }, + { + "kind": "fill", + "segments": [ + "", + " Blumen" + ], + "answers": [ + "neun" + ], + "input": "select", + "emoji": "🌸 🌸 🌸 🌸 🌸 🌸 🌸 🌸 🌸", + "meaning": "devět květin" + }, + { + "kind": "fill", + "segments": [ + "", + " Autos" + ], + "answers": [ + "drei" + ], + "input": "select", + "emoji": "🚗 🚗 🚗", + "meaning": "tři auta" + }, + { + "kind": "fill", + "segments": [ + "", + " Bücher" + ], + "answers": [ + "elf" + ], + "input": "select", + "emoji": "📚 📚 📚 📚 📚 📚 📚 📚 📚 📚 📚", + "meaning": "jedenáct knih" + }, + { + "kind": "fill", + "segments": [ + "", + " Kerzen" + ], + "answers": [ + "vier" + ], + "input": "select", + "emoji": "🕯️ 🕯️ 🕯️ 🕯️", + "meaning": "čtyři svíčky" + }, + { + "kind": "fill", + "segments": [ + "", + " Bälle" + ], + "answers": [ + "acht" + ], + "input": "select", + "emoji": "⚽ ⚽ ⚽ ⚽ ⚽ ⚽ ⚽ ⚽", + "meaning": "osm míčů" + }, + { + "kind": "fill", + "segments": [ + "", + " Vögel" + ], + "answers": [ + "sechs" + ], + "input": "select", + "emoji": "🐦 🐦 🐦 🐦 🐦 🐦", + "meaning": "šest ptáků" + } + ] + }, + { + "number": 7, + "title": "Zahlenreihe", + "subtitleKey": "sub_reihe", + "pool": [ + "acht", + "vierzehn", + "zwanzig", + "sechs", + "zwölf" + ], + "items": [ + { + "kind": "fill", + "segments": [ + "sechs, sieben, ", + ", neun" + ], + "answers": [ + "acht" + ], + "input": "select", + "meaning": "šest, sedm, osm, devět" + }, + { + "kind": "fill", + "segments": [ + "zwölf, dreizehn, ", + ", fünfzehn" + ], + "answers": [ + "vierzehn" + ], + "input": "select", + "meaning": "dvanáct, třináct, čtrnáct, patnáct" + }, + { + "kind": "fill", + "segments": [ + "achtzehn, neunzehn, ", + ", einundzwanzig" + ], + "answers": [ + "zwanzig" + ], + "input": "select", + "meaning": "osmnáct, devatenáct, dvacet, dvacet jedna" + }, + { + "kind": "fill", + "segments": [ + "vier, fünf, ", + ", sieben" + ], + "answers": [ + "sechs" + ], + "input": "select", + "meaning": "čtyři, pět, šest, sedm" + }, + { + "kind": "fill", + "segments": [ + "zehn, elf, ", + ", dreizehn" + ], + "answers": [ + "zwölf" + ], + "input": "select", + "meaning": "deset, jedenáct, dvanáct, třináct" + } + ] + }, + { + "number": 8, + "title": "Verb einsetzen", + "subtitleKey": "sub_verb", + "pool": [ + "heißen", + "kommen", + "wohnen", + "sein", + "spielen", + "machen", + "heiße", + "kommst", + "wohne", + "bist", + "spiele", + "machst" + ], + "items": [ + { + "kind": "fill", + "segments": [ + "Ich ", + " Peter." + ], + "answers": [ + "heiße" + ], + "input": "select", + "meaning": "Jmenuji se Petr." + }, + { + "kind": "fill", + "segments": [ + "Woher ", + " du?" + ], + "answers": [ + "kommst" + ], + "input": "select", + "meaning": "Odkud jsi?" + }, + { + "kind": "fill", + "segments": [ + "Ich ", + " in Prag." + ], + "answers": [ + "wohne" + ], + "input": "select", + "meaning": "Bydlím v Praze." + }, + { + "kind": "fill", + "segments": [ + "Wie alt ", + " du?" + ], + "answers": [ + "bist" + ], + "input": "select", + "meaning": "Kolik je ti let?" + }, + { + "kind": "fill", + "segments": [ + "Ich ", + " Fußball." + ], + "answers": [ + "spiele" + ], + "input": "select", + "meaning": "Hraji fotbal." + }, + { + "kind": "fill", + "segments": [ + "Was ", + " du gern?" + ], + "answers": [ + "machst" + ], + "input": "select", + "meaning": "Co rád/a děláš?" + } + ] + }, + { + "number": 9, + "title": "Wer? Wie? Wo?", + "subtitleKey": "sub_wer", + "items": [ + { + "kind": "choice", + "prompt": "___ heißt du?", + "options": [ + "Wer", + "Wie", + "Wo" + ], + "correct": 1, + "meaning": "Jak se jmenuješ?" + }, + { + "kind": "choice", + "prompt": "___ kommst du?", + "options": [ + "Woher", + "Wie", + "Wer" + ], + "correct": 0, + "meaning": "Odkud jsi?" + }, + { + "kind": "choice", + "prompt": "___ wohnst du?", + "options": [ + "Wo", + "Wer", + "Was" + ], + "correct": 0, + "meaning": "Kde bydlíš?" + }, + { + "kind": "choice", + "prompt": "___ ist das?", + "options": [ + "Wer", + "Wo", + "Wie" + ], + "correct": 0, + "meaning": "Kdo to je?" + }, + { + "kind": "choice", + "prompt": "___ alt bist du?", + "options": [ + "Wie", + "Woher", + "Was" + ], + "correct": 0, + "meaning": "Kolik je ti let?" + } + ] + }, + { + "number": 10, + "title": "Wörter trennen", + "subtitleKey": "sub_assembly", + "items": [ + { + "kind": "assembly", + "prompt": "wiespätistes", + "words": [ + "wie", + "spät", + "ist", + "es" + ], + "meaning": "Kolik je hodin?" + }, + { + "kind": "assembly", + "prompt": "ichheißeanna", + "words": [ + "ich", + "heiße", + "anna" + ], + "meaning": "Jmenuji se Anna." + }, + { + "kind": "assembly", + "prompt": "woherkommstdu", + "words": [ + "woher", + "kommst", + "du" + ], + "meaning": "Odkud jsi?" + }, + { + "kind": "assembly", + "prompt": "aufwiedersehen", + "words": [ + "auf", + "wiedersehen" + ], + "meaning": "Na shledanou." + }, + { + "kind": "assembly", + "prompt": "dankeschön", + "words": [ + "danke", + "schön" + ], + "meaning": "Moc děkuji." + } + ] + }, + { + "number": 11, + "title": "Grußformen", + "subtitleKey": "sub_gruss", + "items": [ + { + "kind": "assign", + "groups": [ + "Begrüßung", + "Verabschiedung" + ], + "items": [ + { + "emoji": null, + "label": "Hallo", + "group": 0, + "meaning": "Ahoj" + }, + { + "emoji": null, + "label": "Guten Morgen", + "group": 0, + "meaning": "Dobré ráno" + }, + { + "emoji": null, + "label": "Guten Tag", + "group": 0, + "meaning": "Dobrý den" + }, + { + "emoji": null, + "label": "Guten Abend", + "group": 0, + "meaning": "Dobrý večer" + }, + { + "emoji": null, + "label": "Grüß Gott", + "group": 0, + "meaning": "Dobrý den (Bavorsko, Rakousko)" + }, + { + "emoji": null, + "label": "Servus", + "group": 0, + "meaning": "Ahoj / Čau" + }, + { + "emoji": null, + "label": "Tschüss", + "group": 1, + "meaning": "Čau" + }, + { + "emoji": null, + "label": "Auf Wiedersehen", + "group": 1, + "meaning": "Na shledanou" + }, + { + "emoji": null, + "label": "Bis bald", + "group": 1, + "meaning": "Brzy na viděnou" + }, + { + "emoji": null, + "label": "Bis morgen", + "group": 1, + "meaning": "Do zítřka" + }, + { + "emoji": null, + "label": "Gute Nacht", + "group": 1, + "meaning": "Dobrou noc" + }, + { + "emoji": null, + "label": "Bis später", + "group": 1, + "meaning": "Zatím / Na viděnou" + } + ] + } + ] + }, + { + "number": 12, + "title": "Was macht er/sie?", + "subtitleKey": "sub_bild", + "pool": [ + "schwimmt", + "singt", + "kocht", + "liest", + "fährt", + "malt", + "spielt", + "schläft" + ], + "items": [ + { + "kind": "fill", + "segments": [ + "Er ", + " im See." + ], + "answers": [ + "schwimmt" + ], + "input": "select", + "meaning": "Plave v jezeře.", + "emoji": "🏊" + }, + { + "kind": "fill", + "segments": [ + "Sie ", + " ein Lied." + ], + "answers": [ + "singt" + ], + "input": "select", + "meaning": "Zpívá píseň.", + "emoji": "🎤" + }, + { + "kind": "fill", + "segments": [ + "Er ", + " Suppe." + ], + "answers": [ + "kocht" + ], + "input": "select", + "meaning": "Vaří polévku.", + "emoji": "🍳" + }, + { + "kind": "fill", + "segments": [ + "Sie ", + " ein Buch." + ], + "answers": [ + "liest" + ], + "input": "select", + "meaning": "Čte knihu.", + "emoji": "📖" + }, + { + "kind": "fill", + "segments": [ + "Er ", + " Auto." + ], + "answers": [ + "fährt" + ], + "input": "select", + "meaning": "Řídí auto.", + "emoji": "🚗" + }, + { + "kind": "fill", + "segments": [ + "Sie ", + " ein Bild." + ], + "answers": [ + "malt" + ], + "input": "select", + "meaning": "Maluje obraz.", + "emoji": "🎨" + }, + { + "kind": "fill", + "segments": [ + "Er ", + " Fußball." + ], + "answers": [ + "spielt" + ], + "input": "select", + "meaning": "Hraje fotbal.", + "emoji": "⚽" + }, + { + "kind": "fill", + "segments": [ + "Sie ", + " ." + ], + "answers": [ + "schläft" + ], + "input": "select", + "meaning": "Spí.", + "emoji": "🛏️" + } + ] + }, + { + "number": 13, + "title": "Länder", + "subtitleKey": "sub_land", + "items": [ + { + "kind": "assign", + "groups": [ + "Deutschland (D)", + "Österreich (A)", + "Schweiz (CH)" + ], + "items": [ + { + "emoji": "🥨", + "label": "Brezel", + "group": 0, + "meaning": "Preclík" + }, + { + "emoji": "🌭", + "label": "Bratwurst", + "group": 0, + "meaning": "Klobása" + }, + { + "emoji": "🏰", + "label": "Brandenburger Tor", + "group": 0, + "meaning": "Braniborská brána" + }, + { + "emoji": "🚗", + "label": "Volkswagen", + "group": 0, + "meaning": "Značka aut" + }, + { + "emoji": "🎻", + "label": "Mozart", + "group": 1, + "meaning": "Rakouský skladatel" + }, + { + "emoji": "🍰", + "label": "Sachertorte", + "group": 1, + "meaning": "Čokoládový dort (Vídeň)" + }, + { + "emoji": "🥩", + "label": "Wiener Schnitzel", + "group": 1, + "meaning": "Vídeňský řízek" + }, + { + "emoji": "🧀", + "label": "Käse", + "group": 2, + "meaning": "Sýr" + }, + { + "emoji": "⛰️", + "label": "Matterhorn", + "group": 2, + "meaning": "Švýcarská hora" + }, + { + "emoji": "🍫", + "label": "Schokolade", + "group": 2, + "meaning": "Čokoláda" + } + ] + } + ] + } + ], + "vocab": [ + { + "header": "Strana 10", + "items": [ + { + "prompt": "der Abend, -e", + "answers": [ + "večer", + "evening" + ], + "meaning": "večer" + }, + { + "prompt": "Guten Abend!", + "answers": [ + "dobrý večer", + "good evening" + ], + "meaning": "Dobrý večer!" + }, + { + "prompt": "du", + "answers": [ + "ty", + "you" + ], + "meaning": "ty" + }, + { + "prompt": "(Es) freut mich.", + "answers": [ + "těší mě", + "nice to meet you", + "pleased to meet you" + ], + "meaning": "Těší mě." + }, + { + "prompt": "gut", + "answers": [ + "dobrý", + "dobře", + "good" + ], + "meaning": "dobrý" + }, + { + "prompt": "Hallo!", + "answers": [ + "ahoj", + "hello" + ], + "meaning": "Ahoj!" + }, + { + "prompt": "heißen (Infinitiv)", + "answers": [ + "jmenovat se", + "jmenuje se", + "to be called", + "to be named" + ], + "meaning": "jmenovat se" + }, + { + "prompt": "Ich heiße Jens.", + "answers": [ + "jmenuji se jens", + "jmenuju se jens", + "my name is jens" + ], + "meaning": "Jmenuji se Jens." + }, + { + "prompt": "Hi!", + "answers": [ + "ahoj", + "čau", + "hi" + ], + "meaning": "Ahoj! (neformálně)" + }, + { + "prompt": "ich", + "answers": [ + "já", + "i" + ], + "meaning": "já" + }, + { + "prompt": "ihr", + "answers": [ + "vy", + "you" + ], + "meaning": "vy" + }, + { + "prompt": "ja", + "answers": [ + "ano", + "jo", + "yes" + ], + "meaning": "ano" + }, + { + "prompt": "der Morgen", + "answers": [ + "ráno", + "morning" + ], + "meaning": "ráno" + }, + { + "prompt": "Guten Morgen!", + "answers": [ + "dobré ráno", + "good morning" + ], + "meaning": "Dobré ráno!" + }, + { + "prompt": "der Name, -n", + "answers": [ + "jméno", + "name" + ], + "meaning": "jméno" + }, + { + "prompt": "nein", + "answers": [ + "ne", + "no" + ], + "meaning": "ne" + }, + { + "prompt": "(er/sie/es) ist", + "answers": [ + "je", + "is" + ], + "meaning": "je" + }, + { + "prompt": "der Tag, -e", + "answers": [ + "den", + "day" + ], + "meaning": "den" + }, + { + "prompt": "Guten Tag!", + "answers": [ + "dobrý den", + "good day" + ], + "meaning": "Dobrý den!" + }, + { + "prompt": "und", + "answers": [ + "a", + "and" + ], + "meaning": "a" + }, + { + "prompt": "wer", + "answers": [ + "kdo", + "who" + ], + "meaning": "kdo" + }, + { + "prompt": "Wer bist du?", + "answers": [ + "kdo jsi", + "kdo jste", + "who are you" + ], + "meaning": "Kdo jsi?" + }, + { + "prompt": "wie", + "answers": [ + "jak", + "how" + ], + "meaning": "jak" + }, + { + "prompt": "Wie heißt du?", + "answers": [ + "jak se jmenuješ", + "jak se jmenujete", + "what is your name", + "what's your name" + ], + "meaning": "Jak se jmenuješ?" + }, + { + "prompt": "wir", + "answers": [ + "my", + "we" + ], + "meaning": "my" + } + ] + }, + { + "header": "Strana 11", + "items": [ + { + "prompt": "in", + "answers": [ + "v", + "ve", + "in" + ], + "meaning": "v" + }, + { + "prompt": "in der Nähe (von)", + "answers": [ + "poblíž", + "v blízkosti", + "nedaleko", + "blízko", + "near", + "nearby", + "close to" + ], + "meaning": "poblíž, v blízkosti" + }, + { + "prompt": "das Spiel, -e", + "answers": [ + "hra", + "game" + ], + "meaning": "hra" + }, + { + "prompt": "wo", + "answers": [ + "kde", + "where" + ], + "meaning": "kde" + }, + { + "prompt": "wohnen (Infinitiv)", + "answers": [ + "bydlet", + "bydlí", + "to live" + ], + "meaning": "bydlet" + }, + { + "prompt": "Wo wohnst du?", + "answers": [ + "kde bydlíš", + "kde bydlíte", + "where do you live" + ], + "meaning": "Kde bydlíš?" + }, + { + "prompt": "Ich wohne in Prag.", + "answers": [ + "bydlím v praze", + "i live in prague" + ], + "meaning": "Bydlím v Praze." + }, + { + "prompt": "null", + "answers": [ + "nula", + "zero" + ], + "meaning": "nula" + }, + { + "prompt": "eins", + "answers": [ + "jedna", + "jeden", + "one" + ], + "meaning": "jedna" + }, + { + "prompt": "zwei", + "answers": [ + "dvě", + "dva", + "two" + ], + "meaning": "dvě" + }, + { + "prompt": "drei", + "answers": [ + "tři", + "three" + ], + "meaning": "tři" + }, + { + "prompt": "vier", + "answers": [ + "čtyři", + "four" + ], + "meaning": "čtyři" + }, + { + "prompt": "fünf", + "answers": [ + "pět", + "five" + ], + "meaning": "pět" + }, + { + "prompt": "sechs", + "answers": [ + "šest", + "six" + ], + "meaning": "šest" + }, + { + "prompt": "sieben", + "answers": [ + "sedm", + "seven" + ], + "meaning": "sedm" + }, + { + "prompt": "acht", + "answers": [ + "osm", + "eight" + ], + "meaning": "osm" + }, + { + "prompt": "neun", + "answers": [ + "devět", + "nine" + ], + "meaning": "devět" + }, + { + "prompt": "zehn", + "answers": [ + "deset", + "ten" + ], + "meaning": "deset" + }, + { + "prompt": "elf", + "answers": [ + "jedenáct", + "eleven" + ], + "meaning": "jedenáct" + }, + { + "prompt": "zwölf", + "answers": [ + "dvanáct", + "twelve" + ], + "meaning": "dvanáct" + }, + { + "prompt": "dreizehn", + "answers": [ + "třináct", + "thirteen" + ], + "meaning": "třináct" + }, + { + "prompt": "vierzehn", + "answers": [ + "čtrnáct", + "fourteen" + ], + "meaning": "čtrnáct" + }, + { + "prompt": "fünfzehn", + "answers": [ + "patnáct", + "fifteen" + ], + "meaning": "patnáct" + }, + { + "prompt": "sechzehn", + "answers": [ + "šestnáct", + "sixteen" + ], + "meaning": "šestnáct" + }, + { + "prompt": "siebzehn", + "answers": [ + "sedmnáct", + "seventeen" + ], + "meaning": "sedmnáct" + }, + { + "prompt": "achtzehn", + "answers": [ + "osmnáct", + "eighteen" + ], + "meaning": "osmnáct" + }, + { + "prompt": "neunzehn", + "answers": [ + "devatenáct", + "nineteen" + ], + "meaning": "devatenáct" + }, + { + "prompt": "zwanzig", + "answers": [ + "dvacet", + "twenty" + ], + "meaning": "dvacet" + } + ] + }, + { + "header": "Strana 12", + "items": [ + { + "prompt": "alt", + "answers": [ + "starý", + "old" + ], + "meaning": "starý" + }, + { + "prompt": "er", + "answers": [ + "on", + "he" + ], + "meaning": "on" + }, + { + "prompt": "der Monat, -e", + "answers": [ + "měsíc", + "month" + ], + "meaning": "měsíc" + }, + { + "prompt": "sie (Singular)", + "answers": [ + "ona", + "she" + ], + "meaning": "ona" + }, + { + "prompt": "sie (Plural)", + "answers": [ + "oni", + "they" + ], + "meaning": "oni" + } + ] + }, + { + "header": "Strana 13", + "items": [ + { + "prompt": "aber", + "answers": [ + "ale", + "but" + ], + "meaning": "ale" + }, + { + "prompt": "das Alter", + "answers": [ + "věk", + "age" + ], + "meaning": "věk" + }, + { + "prompt": "auch", + "answers": [ + "také", + "taky", + "also", + "too" + ], + "meaning": "také" + }, + { + "prompt": "aus", + "answers": [ + "z", + "ze", + "from" + ], + "meaning": "z" + }, + { + "prompt": "die Band, -s", + "answers": [ + "skupina", + "hudební skupina", + "kapela", + "hudební kapela", + "band" + ], + "meaning": "(hudební) skupina" + }, + { + "prompt": "chatten (Infinitiv)", + "answers": [ + "chatovat", + "chatuje", + "to chat" + ], + "meaning": "chatovat" + }, + { + "prompt": "das Computerspiel, -e", + "answers": [ + "počítačová hra", + "computer game" + ], + "meaning": "počítačová hra" + }, + { + "prompt": "die/das E-Mail, -s", + "answers": [ + "e-mail", + "email" + ], + "meaning": "e-mail" + }, + { + "prompt": "das Englisch", + "answers": [ + "angličtina", + "anglicky", + "english" + ], + "meaning": "angličtina, anglicky" + }, + { + "prompt": "der Fan, -s", + "answers": [ + "fanoušek", + "fanda", + "fan" + ], + "meaning": "fanoušek" + }, + { + "prompt": "das Französisch", + "answers": [ + "francouzština", + "francouzsky", + "french" + ], + "meaning": "francouzština, francouzsky" + }, + { + "prompt": "der Freund, -e", + "answers": [ + "kamarád", + "přítel", + "friend" + ], + "meaning": "kamarád" + }, + { + "prompt": "die Freundin, -nen", + "answers": [ + "kamarádka", + "přítelkyně", + "friend" + ], + "meaning": "kamarádka" + }, + { + "prompt": "beste Freundin", + "answers": [ + "nejlepší kamarádka", + "nejlepší přítelkyně", + "best friend" + ], + "meaning": "nejlepší kamarádka" + }, + { + "prompt": "der Fußball", + "answers": [ + "fotbal", + "football", + "soccer" + ], + "meaning": "fotbal" + }, + { + "prompt": "Er ist Fußballfanatiker.", + "answers": [ + "je fotbalový fanatik", + "he is a football fanatic" + ], + "meaning": "Je fotbalový fanatik." + }, + { + "prompt": "gehen (Infinitiv)", + "answers": [ + "jít", + "jde", + "chodit", + "to go" + ], + "meaning": "jít" + }, + { + "prompt": "Ich gehe gern auf Konzerte.", + "answers": [ + "rád chodím na koncerty", + "ráda chodím na koncerty", + "chodím rád na koncerty", + "chodím ráda na koncerty", + "i like going to concerts" + ], + "meaning": "Rád(a) chodím na koncerty." + }, + { + "prompt": "gern", + "answers": [ + "rád", + "ráda", + "gladly" + ], + "meaning": "rád/a" + }, + { + "prompt": "die Gitarre, -n", + "answers": [ + "kytara", + "guitar" + ], + "meaning": "kytara" + }, + { + "prompt": "das Handy, -s", + "answers": [ + "mobil", + "mobilní telefon", + "mobile phone" + ], + "meaning": "mobil" + }, + { + "prompt": "das Hobby, -s", + "answers": [ + "koníček", + "hobby" + ], + "meaning": "koníček" + }, + { + "prompt": "hören (Infinitiv)", + "answers": [ + "poslouchat", + "poslouchá", + "slyšet", + "to listen", + "to hear" + ], + "meaning": "poslouchat" + }, + { + "prompt": "Er hört gern Musik.", + "answers": [ + "rád poslouchá hudbu", + "he likes listening to music" + ], + "meaning": "Rád poslouchá hudbu." + }, + { + "prompt": "im Internet surfen (Infinitiv)", + "answers": [ + "surfovat na internetu", + "to surf the internet" + ], + "meaning": "surfovat na internetu" + }, + { + "prompt": "immer", + "answers": [ + "pořád", + "neustále", + "vždy", + "vždycky", + "always" + ], + "meaning": "pořád, neustále" + }, + { + "prompt": "das Jahr, -e", + "answers": [ + "rok", + "year" + ], + "meaning": "rok" + }, + { + "prompt": "kein/keine/kein", + "answers": [ + "žádný", + "žádná", + "žádné", + "no", + "none" + ], + "meaning": "žádný/žádná/žádné" + }, + { + "prompt": "das Klavier, -e", + "answers": [ + "klavír", + "piano" + ], + "meaning": "klavír" + }, + { + "prompt": "kommen (Infinitiv, aus)", + "answers": [ + "přicházet", + "přijít", + "přichází", + "pocházet", + "pochází", + "to come", + "to come from" + ], + "meaning": "přicházet, pocházet (z)" + }, + { + "prompt": "Er kommt aus Wien.", + "answers": [ + "pochází z vídně", + "he comes from vienna", + "he is from vienna" + ], + "meaning": "Pochází z Vídně." + }, + { + "prompt": "das Konzert, -e", + "answers": [ + "koncert", + "concert" + ], + "meaning": "koncert" + }, + { + "prompt": "lernen (Infinitiv)", + "answers": [ + "učit se", + "učí se", + "to learn" + ], + "meaning": "učit se" + }, + { + "prompt": "liegen (Infinitiv)", + "answers": [ + "ležet", + "leží", + "to lie", + "to be located" + ], + "meaning": "ležet" + }, + { + "prompt": "der Nachname, -n", + "answers": [ + "příjmení", + "surname", + "last name" + ], + "meaning": "příjmení" + }, + { + "prompt": "nicht weit von", + "answers": [ + "nedaleko od", + "not far from" + ], + "meaning": "nedaleko od" + }, + { + "prompt": "reisen (Infinitiv)", + "answers": [ + "cestovat", + "cestuje", + "to travel" + ], + "meaning": "cestovat" + }, + { + "prompt": "schreiben (Infinitiv)", + "answers": [ + "psát", + "píše", + "to write" + ], + "meaning": "psát" + }, + { + "prompt": "die Schule, -n", + "answers": [ + "škola", + "school" + ], + "meaning": "škola" + }, + { + "prompt": "spielen (Infinitiv)", + "answers": [ + "hrát", + "hraje", + "to play" + ], + "meaning": "hrát" + }, + { + "prompt": "Sie spielt Gitarre.", + "answers": [ + "hraje na kytaru", + "she plays the guitar" + ], + "meaning": "Hraje na kytaru." + }, + { + "prompt": "tanzen (Infinitiv)", + "answers": [ + "tancovat", + "tančí", + "tancuje", + "to dance" + ], + "meaning": "tancovat" + }, + { + "prompt": "der Vorname, -n", + "answers": [ + "křestní jméno", + "first name" + ], + "meaning": "křestní jméno" + }, + { + "prompt": "der Wohnort, -e", + "answers": [ + "bydliště", + "místo bydliště", + "place of residence" + ], + "meaning": "bydliště" + } + ] + }, + { + "header": "Strana 14", + "items": [ + { + "prompt": "falsch", + "answers": [ + "nesprávně", + "chybně", + "špatně", + "nepravda", + "wrong", + "incorrect" + ], + "meaning": "nesprávně, chybně" + }, + { + "prompt": "die Flöte, -n", + "answers": [ + "flétna", + "flute" + ], + "meaning": "flétna" + }, + { + "prompt": "haben (Infinitiv)", + "answers": [ + "mít", + "má", + "to have" + ], + "meaning": "mít" + }, + { + "prompt": "das Instrument, -e", + "answers": [ + "nástroj", + "hudební nástroj", + "instrument" + ], + "meaning": "(hudební) nástroj" + }, + { + "prompt": "jetzt", + "answers": [ + "teď", + "nyní", + "now" + ], + "meaning": "teď" + }, + { + "prompt": "machen (Infinitiv)", + "answers": [ + "dělat", + "dělá", + "to do", + "to make" + ], + "meaning": "dělat" + }, + { + "prompt": "richtig", + "answers": [ + "správně", + "správný", + "correct", + "right" + ], + "meaning": "správně" + }, + { + "prompt": "der Sport", + "answers": [ + "sport" + ], + "meaning": "sport" + }, + { + "prompt": "Sport treiben (Infinitiv)", + "answers": [ + "sportovat", + "sportuje", + "provozovat sport", + "dělat sport", + "to do sport" + ], + "meaning": "sportovat" + }, + { + "prompt": "das Squash", + "answers": [ + "squash" + ], + "meaning": "squash" + }, + { + "prompt": "das/der Yoga", + "answers": [ + "jóga", + "yoga" + ], + "meaning": "jóga" + } + ] + }, + { + "header": "Strana 15", + "items": [ + { + "prompt": "bald", + "answers": [ + "brzy", + "brzo", + "soon" + ], + "meaning": "brzy" + }, + { + "prompt": "Bis bald!", + "answers": [ + "brzy na shledanou", + "brzo na shledanou", + "brzy se uvidíme", + "brzo se uvidíme", + "see you soon" + ], + "meaning": "Brzy na shledanou!" + }, + { + "prompt": "bis", + "answers": [ + "do", + "až", + "until" + ], + "meaning": "do" + }, + { + "prompt": "Bis zum nächsten Mal!", + "answers": [ + "do příštího setkání", + "do příště", + "until next time" + ], + "meaning": "Do příštího setkání!" + }, + { + "prompt": "die Frau, -en", + "answers": [ + "paní", + "žena", + "manželka", + "woman", + "mrs", + "wife" + ], + "meaning": "paní" + }, + { + "prompt": "der Herr, -en", + "answers": [ + "pan", + "muž", + "man", + "mr" + ], + "meaning": "pan" + }, + { + "prompt": "Mach's gut!", + "answers": [ + "měj se hezky", + "měj se", + "mějte se hezky", + "mějte se", + "take care" + ], + "meaning": "Měj se hezky!" + }, + { + "prompt": "das Museum, Museen", + "answers": [ + "muzeum", + "museum" + ], + "meaning": "muzeum" + }, + { + "prompt": "Sie gehen ins Museum.", + "answers": [ + "jdou do muzea", + "they are going to the museum", + "they go to the museum" + ], + "meaning": "Jdou do muzea." + }, + { + "prompt": "schön", + "answers": [ + "hezký", + "krásný", + "pěkný", + "beautiful", + "nice" + ], + "meaning": "hezký" + }, + { + "prompt": "Einen schönen Tag noch!", + "answers": [ + "hezký zbytek dne", + "měj hezký den", + "have a nice day" + ], + "meaning": "Hezký zbytek dne!" + }, + { + "prompt": "Servus!", + "answers": [ + "ahoj", + "servus", + "hi" + ], + "meaning": "Ahoj! (servus)" + }, + { + "prompt": "Tschüs!", + "answers": [ + "ahoj", + "čau", + "bye" + ], + "meaning": "Ahoj! (při loučení)" + }, + { + "prompt": "das Wiedersehen", + "answers": [ + "shledání", + "reunion" + ], + "meaning": "shledání" + }, + { + "prompt": "Auf Wiedersehen!", + "answers": [ + "na shledanou", + "na viděnou", + "goodbye" + ], + "meaning": "Na shledanou!" + } + ] + } + ] +} diff --git a/content/lessons/deutsch/unit-02.json b/content/lessons/deutsch/unit-02.json new file mode 100644 index 0000000..1431993 --- /dev/null +++ b/content/lessons/deutsch/unit-02.json @@ -0,0 +1,2788 @@ +{ + "id": "unit-02", + "subject": "deutsch", + "number": 2, + "title": { + "cs": "Aus aller Welt", + "en": "Aus aller Welt" + }, + "slides": [], + "tasks": [ + { + "number": 1, + "title": "Verben konjugieren", + "subtitleKey": "sub_verben", + "pool": [ + "kommt", + "kommst", + "komme", + "kommen", + "wohnt", + "wohnst", + "wohne", + "wohnen", + "spielt", + "spielst", + "spiele", + "spielen", + "spricht", + "sprichst", + "spreche", + "sprechen", + "tanzt", + "tanze", + "tanzen", + "reist", + "reise", + "reisen", + "ist", + "bist", + "bin", + "sind", + "seid" + ], + "items": [ + { + "kind": "fill", + "segments": [ + "Er ", + " aus Österreich. (kommen)" + ], + "answers": [ + "kommt" + ], + "input": "select", + "meaning": "Pochází z Rakouska.", + "heading": "Peter Fritsch:" + }, + { + "kind": "fill", + "segments": [ + "Er ", + " in Graz. (wohnen)" + ], + "answers": [ + "wohnt" + ], + "input": "select", + "meaning": "Bydlí ve Štýrském Hradci (Graz)." + }, + { + "kind": "fill", + "segments": [ + "Er ", + " gern Golf. (spielen)" + ], + "answers": [ + "spielt" + ], + "input": "select", + "meaning": "Rád hraje golf." + }, + { + "kind": "fill", + "segments": [ + "Er ", + " Deutsch, Englisch und Italienisch. (sprechen)" + ], + "answers": [ + "spricht" + ], + "input": "select", + "meaning": "Mluví německy, anglicky a italsky." + }, + { + "kind": "fill", + "segments": [ + "Sie ", + " aus der Slowakei. (kommen)" + ], + "answers": [ + "kommen" + ], + "input": "select", + "meaning": "Pocházejí ze Slovenska.", + "heading": "Jana Nová und Pavol Korčák:" + }, + { + "kind": "fill", + "segments": [ + "Sie ", + " in Bratislava. (wohnen)" + ], + "answers": [ + "wohnen" + ], + "input": "select", + "meaning": "Bydlí v Bratislavě (ona)." + }, + { + "kind": "fill", + "segments": [ + "Sie ", + " gern. (tanzen)" + ], + "answers": [ + "tanzt" + ], + "input": "select", + "meaning": "Ona ráda tancuje." + }, + { + "kind": "fill", + "segments": [ + "Er ", + " gern. (reisen)" + ], + "answers": [ + "reist" + ], + "input": "select", + "meaning": "On rád cestuje." + }, + { + "kind": "fill", + "segments": [ + "Sie ", + " gute Freunde. (sein)" + ], + "answers": [ + "sind" + ], + "input": "select", + "meaning": "Jsou dobří přátelé." + } + ] + }, + { + "number": 2, + "title": "aus oder in", + "subtitleKey": "sub_ausin", + "items": [ + { + "kind": "choice", + "prompt": "1. Ich komme ___ Athen.", + "options": [ + "aus", + "in" + ], + "correct": 0, + "meaning": "Pocházím z Atén." + }, + { + "kind": "choice", + "prompt": "2. Peter wohnt ___ Salzburg.", + "options": [ + "aus", + "in" + ], + "correct": 1, + "meaning": "Petr bydlí v Salcburku." + }, + { + "kind": "choice", + "prompt": "3. Berlin liegt ___ Deutschland.", + "options": [ + "aus", + "in" + ], + "correct": 1, + "meaning": "Berlín leží v Německu." + }, + { + "kind": "choice", + "prompt": "4. Wir wohnen ___ Paris.", + "options": [ + "aus", + "in" + ], + "correct": 1, + "meaning": "Bydlíme v Paříži." + }, + { + "kind": "choice", + "prompt": "5. Sie kommen ___ Griechenland.", + "options": [ + "aus", + "in" + ], + "correct": 0, + "meaning": "Pocházejí z Řecka." + } + ] + }, + { + "number": 3, + "title": "Fragewörter", + "subtitleKey": "sub_wer", + "items": [ + { + "kind": "choice", + "prompt": "1. ___ kommt er? → Aus London.", + "options": [ + "Wer", + "Wie", + "Wo", + "Woher", + "Was" + ], + "correct": 3, + "meaning": "Odkud je? – Z Londýna." + }, + { + "kind": "choice", + "prompt": "2. ___ heißt sie? → Andrea.", + "options": [ + "Wer", + "Wie", + "Wo", + "Woher", + "Was" + ], + "correct": 1, + "meaning": "Jak se jmenuje? – Andrea." + }, + { + "kind": "choice", + "prompt": "3. ___ kommt aus Russland? → Alexander.", + "options": [ + "Wer", + "Wie", + "Wo", + "Woher", + "Was" + ], + "correct": 0, + "meaning": "Kdo pochází z Ruska? – Alexandr." + }, + { + "kind": "choice", + "prompt": "4. ___ liegt Prag? → In Tschechien.", + "options": [ + "Wer", + "Wie", + "Wo", + "Woher", + "Was" + ], + "correct": 2, + "meaning": "Kde leží Praha? – V Česku." + }, + { + "kind": "choice", + "prompt": "5. ___ wohnen sie? → In Bratislava.", + "options": [ + "Wer", + "Wie", + "Wo", + "Woher", + "Was" + ], + "correct": 2, + "meaning": "Kde bydlí? – V Bratislavě." + }, + { + "kind": "choice", + "prompt": "6. ___ macht ihr? → Wir studieren Germanistik.", + "options": [ + "Wer", + "Wie", + "Wo", + "Woher", + "Was" + ], + "correct": 4, + "meaning": "Co děláte? – Studujeme germanistiku." + } + ] + }, + { + "number": 4, + "title": "sprechen", + "subtitleKey": "sub_sprich", + "pool": [ + "spreche", + "sprichst", + "spricht", + "sprechen", + "sprecht" + ], + "items": [ + { + "kind": "fill", + "segments": [ + "• Ich ", + " Deutsch und du?" + ], + "answers": [ + "spreche" + ], + "input": "select", + "meaning": "Mluvím německy. A ty?" + }, + { + "kind": "fill", + "segments": [ + "• Welche Sprachen ", + " Sie?" + ], + "answers": [ + "sprechen" + ], + "input": "select", + "meaning": "Kterými jazyky mluvíte?" + }, + { + "kind": "fill", + "segments": [ + "• ", + " du Französisch?" + ], + "answers": [ + "sprichst" + ], + "input": "select", + "meaning": "Mluvíš francouzsky? – Ano, trochu." + }, + { + "kind": "fill", + "segments": [ + "• Wir ", + " Polnisch und ihr?" + ], + "answers": [ + "sprechen" + ], + "input": "select", + "meaning": "My mluvíme polsky a vy?" + }, + { + "kind": "fill", + "segments": [ + "• ", + " ihr Englisch?" + ], + "answers": [ + "sprecht" + ], + "input": "select", + "meaning": "Mluvíte anglicky? – Ano, velmi dobře." + }, + { + "kind": "fill", + "segments": [ + "• Er ", + " kein Wort Türkisch." + ], + "answers": [ + "spricht" + ], + "input": "select", + "meaning": "Nemluví ani slovo turecky." + } + ] + }, + { + "number": 5, + "title": "Nationalitäten", + "subtitleKey": "sub_nation", + "note": "Tscheche, Tschechin, Spanier, Spanierin, Türke, Türkin, Kroate, Kroatin, Deutscher, Deutsche, Österreicher, Österreicherin, Slowake, Slowakin", + "items": [ + { + "kind": "typed", + "prompt": "Er kommt aus Tschechien. Er ist _________.", + "answers": [ + "tscheche" + ], + "meaning": "Čech" + }, + { + "kind": "typed", + "prompt": "Sie kommt aus Spanien. Sie ist _________.", + "answers": [ + "spanierin" + ], + "meaning": "Španělka" + }, + { + "kind": "typed", + "prompt": "Er kommt aus der Türkei. Er ist _________.", + "answers": [ + "türke", + "turke" + ], + "meaning": "Turek" + }, + { + "kind": "typed", + "prompt": "Sie kommt aus Kroatien. Sie ist _________.", + "answers": [ + "kroatin" + ], + "meaning": "Chorvatka" + }, + { + "kind": "typed", + "prompt": "Sie kommt aus Deutschland. Sie ist _________.", + "answers": [ + "deutsche" + ], + "meaning": "Němka" + }, + { + "kind": "typed", + "prompt": "Sie kommt aus Österreich. Sie ist _________.", + "answers": [ + "österreicherin", + "osterreicherin" + ], + "meaning": "Rakušanka" + }, + { + "kind": "typed", + "prompt": "Er kommt aus der Slowakei. Er ist _________.", + "answers": [ + "slowake" + ], + "meaning": "Slovák" + } + ] + }, + { + "number": 6, + "title": "Woher?", + "subtitleKey": "sub_woher", + "items": [ + { + "kind": "typed", + "prompt": "Ich heiße Thomas. Ich spreche Deutsch. Ich komme aus D________.", + "answers": [ + "deutschland", + "eutschland" + ], + "meaning": "Deutschland – Německo" + }, + { + "kind": "typed", + "prompt": "Ich heiße Martina. Ich spreche Slowakisch. Ich komme aus der S________.", + "answers": [ + "slowakei", + "lowakei" + ], + "meaning": "Slowakei – Slovensko" + }, + { + "kind": "typed", + "prompt": "Ich heiße Petra. Ich spreche Deutsch. Ich komme aus Ö________.", + "answers": [ + "österreich", + "osterreich", + "sterreich" + ], + "meaning": "Österreich – Rakousko" + }, + { + "kind": "typed", + "prompt": "Ich heiße Miguel. Ich spreche Spanisch. Ich komme aus S________.", + "answers": [ + "spanien", + "panien" + ], + "meaning": "Spanien – Španělsko" + }, + { + "kind": "typed", + "prompt": "Ich heiße George. Ich spreche Englisch. Ich komme aus E________.", + "answers": [ + "england", + "ngland" + ], + "meaning": "England – Anglie" + }, + { + "kind": "typed", + "prompt": "Ich heiße Maria. Ich spreche Polnisch. Ich komme aus P________.", + "answers": [ + "polen", + "olen" + ], + "meaning": "Polen – Polsko" + } + ] + }, + { + "number": 7, + "title": "Länder schreiben", + "subtitleKey": "sub_laender", + "items": [ + { + "kind": "typed", + "prompt": "1. Ru__land", + "answers": [ + "russland", + "ss" + ], + "meaning": "Russland – Rusko" + }, + { + "kind": "typed", + "prompt": "2. T_rkei", + "answers": [ + "türkei", + "turkei", + "ü", + "u" + ], + "meaning": "Türkei – Turecko" + }, + { + "kind": "typed", + "prompt": "3. Slo__kei", + "answers": [ + "slowakei", + "wa" + ], + "meaning": "Slowakei – Slovensko" + }, + { + "kind": "typed", + "prompt": "4. Kro__ien", + "answers": [ + "kroatien", + "at" + ], + "meaning": "Kroatien – Chorvatsko" + }, + { + "kind": "typed", + "prompt": "5. Deut___land", + "answers": [ + "deutschland", + "sch" + ], + "meaning": "Deutschland – Německo" + }, + { + "kind": "typed", + "prompt": "6. Öst__reich", + "answers": [ + "österreich", + "osterreich", + "er" + ], + "meaning": "Österreich – Rakousko" + }, + { + "kind": "typed", + "prompt": "7. Gr__chenland", + "answers": [ + "griechenland", + "ie" + ], + "meaning": "Griechenland – Řecko" + }, + { + "kind": "typed", + "prompt": "8. Ita__en", + "answers": [ + "italien", + "li" + ], + "meaning": "Italien – Itálie" + } + ] + }, + { + "number": 8, + "title": "Verben einsetzen", + "subtitleKey": "sub_verb2", + "pool": [ + "liest", + "lese", + "lest", + "lesen", + "studiert", + "studiere", + "studiert", + "studieren", + "fährt", + "fahre", + "fahrt", + "fahren", + "lebt", + "lebe", + "lebt", + "leben", + "arbeitet", + "arbeite", + "arbeitet", + "arbeiten" + ], + "items": [ + { + "kind": "fill", + "segments": [ + "Was ", + " er? → Ein Buch. (lesen)" + ], + "answers": [ + "liest" + ], + "input": "select", + "meaning": "Co čte? – Knihu." + }, + { + "kind": "fill", + "segments": [ + "Was ", + " sie? → Medizin. (studieren)" + ], + "answers": [ + "studiert" + ], + "input": "select", + "meaning": "Co studuje? – Medicínu." + }, + { + "kind": "fill", + "segments": [ + "Was ", + " Jan gern? → Auto. (fahren)" + ], + "answers": [ + "fährt" + ], + "input": "select", + "meaning": "Čím Jan rád jezdí? – Autem." + }, + { + "kind": "fill", + "segments": [ + "Wo ", + " ihr? → In Wien. (leben)" + ], + "answers": [ + "lebt" + ], + "input": "select", + "meaning": "Kde bydlíte? – Ve Vídni." + }, + { + "kind": "fill", + "segments": [ + "Wer ", + " bei Siemens? → Meine Freundin Vera. (arbeiten)" + ], + "answers": [ + "arbeitet" + ], + "input": "select", + "meaning": "Kdo pracuje u Siemensu? – Moje kamarádka Věra." + } + ] + }, + { + "number": 9, + "title": "Freie Antwort", + "subtitleKey": "sub_free", + "items": [ + { + "kind": "free", + "question": "Wie heißt du?", + "questionCs": "Jak se jmenuješ?", + "sample": "Ich heiße Lukas.", + "sampleCs": "Jmenuji se Lukáš." + }, + { + "kind": "free", + "question": "Wo wohnst du?", + "questionCs": "Kde bydlíš?", + "sample": "Ich wohne in Prag.", + "sampleCs": "Bydlím v Praze." + }, + { + "kind": "free", + "question": "Wohin fährst du?", + "questionCs": "Kam jedeš?", + "sample": "Ich fahre nach Deutschland.", + "sampleCs": "Jedu do Německa." + }, + { + "kind": "free", + "question": "Was liest du gern?", + "questionCs": "Co rád/a čteš?", + "sample": "Ich lese gern Krimis.", + "sampleCs": "Rád/a čtu detektivky." + }, + { + "kind": "free", + "question": "Was spielst du gern?", + "questionCs": "Co rád/a hraješ?", + "sample": "Ich spiele gern Golf.", + "sampleCs": "Rád/a hraju golf." + } + ] + }, + { + "number": 10, + "title": "Euro", + "subtitleKey": "sub_euro", + "pool": [ + "dreiundsechzig", + "achtunddreißig", + "fünfundvierzig", + "siebenundfünfzig", + "neunundneunzig" + ], + "items": [ + { + "kind": "fill", + "segments": [ + "Julia hat ", + " Euro." + ], + "answers": [ + "dreiundsechzig" + ], + "input": "select", + "meaning": "šedesát tři eur" + }, + { + "kind": "fill", + "segments": [ + "Tina hat ", + " Euro." + ], + "answers": [ + "achtunddreißig" + ], + "input": "select", + "meaning": "třicet osm eur" + }, + { + "kind": "fill", + "segments": [ + "Peter hat ", + " Euro." + ], + "answers": [ + "fünfundvierzig" + ], + "input": "select", + "meaning": "čtyřicet pět eur" + }, + { + "kind": "fill", + "segments": [ + "Hans hat ", + " Euro." + ], + "answers": [ + "siebenundfünfzig" + ], + "input": "select", + "meaning": "padesát sedm eur" + }, + { + "kind": "fill", + "segments": [ + "Barbara hat ", + " Euro." + ], + "answers": [ + "neunundneunzig" + ], + "input": "select", + "meaning": "devadesát devět eur" + } + ] + }, + { + "number": 11, + "title": "Wörter suchen", + "subtitleKey": "sub_wortsuchen", + "items": [ + { + "kind": "typed", + "prompt": "tergehvatereikauwauzeh", + "answers": [ + "vater" + ], + "meaning": "otec" + }, + { + "kind": "typed", + "prompt": "berelternnemrerhobschaz", + "answers": [ + "eltern" + ], + "meaning": "rodiče" + }, + { + "kind": "typed", + "prompt": "nefrastschechinreiabtab", + "answers": [ + "tschechin" + ], + "meaning": "Češka" + }, + { + "kind": "typed", + "prompt": "hejkosstudentaldwsahujoi", + "answers": [ + "student" + ], + "meaning": "student" + } + ] + }, + { + "number": 12, + "title": "Was ist richtig?", + "subtitleKey": "sub_verb2", + "items": [ + { + "kind": "choice", + "prompt": "1. Peter ___ gern Bücher.", + "options": [ + "liest", + "lest", + "lesen" + ], + "correct": 0, + "meaning": "Petr rád čte knihy." + }, + { + "kind": "choice", + "prompt": "2. Filip ___ in Salzburg.", + "options": [ + "arbeit", + "arbeitet", + "arbeite" + ], + "correct": 1, + "meaning": "Filip pracuje v Salcburku." + }, + { + "kind": "choice", + "prompt": "3. Magda ___ gut Englisch.", + "options": [ + "spricht", + "sprecht", + "sprechen" + ], + "correct": 0, + "meaning": "Magda dobře mluví anglicky." + }, + { + "kind": "choice", + "prompt": "4. Marek ___ das Gymnasium.", + "options": [ + "besuchst", + "besucht", + "besuchen" + ], + "correct": 1, + "meaning": "Marek navštěvuje gymnázium." + }, + { + "kind": "choice", + "prompt": "5. Dominika ___ 15 Jahre alt.", + "options": [ + "ist", + "seid", + "bin" + ], + "correct": 0, + "meaning": "Dominice je 15 let." + }, + { + "kind": "choice", + "prompt": "6. Meine Schwester ___ Marta.", + "options": [ + "heiße", + "heißt", + "heißen" + ], + "correct": 1, + "meaning": "Moje sestra se jmenuje Marta." + } + ] + }, + { + "number": 13, + "title": "Ordne zu", + "subtitleKey": "sub_ordne", + "pool": [ + "Was", + "Wer", + "Wie", + "Wo", + "Woher" + ], + "altPool": [ + "Jana und Michael.", + "Jacek.", + "In Plzeň.", + "Aus Deutschland.", + "Wir studieren Germanistik.", + "Slowakisch." + ], + "items": [ + { + "kind": "fill", + "segments": [ + "", + " heißen sie? → ", + "" + ], + "answers": [ + "Wie", + "Jana und Michael." + ], + "input": "select", + "gapPool": [ + "main", + "alt" + ], + "label": "1.", + "meaning": "Jak se jmenují? – Jana a Michael." + }, + { + "kind": "fill", + "segments": [ + "", + " spricht Polnisch? → ", + "" + ], + "answers": [ + "Wer", + "Jacek." + ], + "input": "select", + "gapPool": [ + "main", + "alt" + ], + "label": "2.", + "meaning": "Kdo mluví polsky? – Jacek." + }, + { + "kind": "fill", + "segments": [ + "", + " wohnt Eva? → ", + "" + ], + "answers": [ + "Wo", + "In Plzeň." + ], + "input": "select", + "gapPool": [ + "main", + "alt" + ], + "label": "3.", + "meaning": "Kde bydlí Eva? – V Plzni." + }, + { + "kind": "fill", + "segments": [ + "", + " kommt Markus? → ", + "" + ], + "answers": [ + "Woher", + "Aus Deutschland." + ], + "input": "select", + "gapPool": [ + "main", + "alt" + ], + "label": "4.", + "meaning": "Odkud pochází Markus? – Z Německa." + }, + { + "kind": "fill", + "segments": [ + "", + " macht ihr? → ", + "" + ], + "answers": [ + "Was", + "Wir studieren Germanistik." + ], + "input": "select", + "gapPool": [ + "main", + "alt" + ], + "label": "5.", + "meaning": "Co děláte? – Studujeme germanistiku." + }, + { + "kind": "fill", + "segments": [ + "", + " spricht Jana? → ", + "" + ], + "answers": [ + "Was", + "Slowakisch." + ], + "input": "select", + "gapPool": [ + "main", + "alt" + ], + "label": "6.", + "meaning": "Jakým jazykem mluví Jana? – Slovensky." + } + ] + }, + { + "number": 14, + "title": "Lückentext", + "subtitleKey": "sub_luecke", + "pool": [ + "aus", + "macht", + "Freund", + "lebt", + "Sprache", + "gut" + ], + "items": [ + { + "kind": "fill", + "segments": [ + "Agnieszka Kowalski kommt ", + " Polen, aus Kraków." + ], + "answers": [ + "aus" + ], + "input": "select", + "meaning": "Agnieszka Kowalski pochází z Polska, z Krakova.", + "glosses": [ + "z" + ] + }, + { + "kind": "fill", + "segments": [ + "Sie ist 18 Jahre alt und ", + " dieses Jahr Abitur." + ], + "answers": [ + "macht" + ], + "input": "select", + "meaning": "Je jí 18 let a letos dělá maturitu.", + "glosses": [ + "dělá" + ] + }, + { + "kind": "fill", + "segments": [ + "Sie chattet gerne mit ihrem deutschen ", + "." + ], + "answers": [ + "Freund" + ], + "input": "select", + "meaning": "Ráda chatuje se svým německým přítelem.", + "glosses": [ + "kamarád" + ] + }, + { + "kind": "fill", + "segments": [ + "Er heißt Stefan Böhmermann und ", + " in Dresden." + ], + "answers": [ + "lebt" + ], + "input": "select", + "meaning": "Jmenuje se Stefan Böhmermann a bydlí v Drážďanech.", + "glosses": [ + "žije" + ] + }, + { + "kind": "fill", + "segments": [ + "Agnieszka findet die ", + " cool." + ], + "answers": [ + "Sprache" + ], + "input": "select", + "meaning": "Agnieszce přijde ten jazyk super.", + "glosses": [ + "jazyk" + ] + }, + { + "kind": "fill", + "segments": [ + "Sie spricht schon sehr ", + " Deutsch." + ], + "answers": [ + "gut" + ], + "input": "select", + "meaning": "Už mluví velmi dobře německy.", + "glosses": [ + "dobře" + ] + } + ] + }, + { + "number": 15, + "title": "Verbinde", + "subtitleKey": "sub_verbinde", + "pool": [ + "brauchen", + "arbeiten", + "fahren", + "besuchen", + "sprechen", + "lesen" + ], + "items": [ + { + "kind": "fill", + "segments": [ + "ein Handy ", + "" + ], + "answers": [ + "brauchen" + ], + "input": "select", + "meaning": "potřebovat mobil", + "glosses": [ + "potřebovat" + ] + }, + { + "kind": "fill", + "segments": [ + "bei BMW ", + "" + ], + "answers": [ + "arbeiten" + ], + "input": "select", + "meaning": "pracovat ve BMW", + "glosses": [ + "pracovat" + ] + }, + { + "kind": "fill", + "segments": [ + "Auto ", + "" + ], + "answers": [ + "fahren" + ], + "input": "select", + "meaning": "řídit auto", + "glosses": [ + "řídit" + ] + }, + { + "kind": "fill", + "segments": [ + "das Gymnasium ", + "" + ], + "answers": [ + "besuchen" + ], + "input": "select", + "meaning": "navštěvovat gymnázium", + "glosses": [ + "navštěvovat" + ] + }, + { + "kind": "fill", + "segments": [ + "Spanisch ", + "" + ], + "answers": [ + "sprechen" + ], + "input": "select", + "meaning": "mluvit španělsky", + "glosses": [ + "mluvit" + ] + }, + { + "kind": "fill", + "segments": [ + "Krimis ", + "" + ], + "answers": [ + "lesen" + ], + "input": "select", + "meaning": "číst detektivky", + "glosses": [ + "číst" + ] + } + ] + }, + { + "number": 16, + "title": "Zahlen", + "subtitleKey": "sub_zahlpaar", + "pool": [ + "vierundfünfzig", + "fünfundvierzig", + "dreihundertneunundsechzig", + "hundertzwölf", + "hundertzweiundzwanzig", + "achtundsechzig" + ], + "items": [ + { + "kind": "fill", + "segments": [ + "54 = ", + "" + ], + "answers": [ + "vierundfünfzig" + ], + "input": "select", + "meaning": "padesát čtyři" + }, + { + "kind": "fill", + "segments": [ + "45 = ", + "" + ], + "answers": [ + "fünfundvierzig" + ], + "input": "select", + "meaning": "čtyřicet pět" + }, + { + "kind": "fill", + "segments": [ + "369 = ", + "" + ], + "answers": [ + "dreihundertneunundsechzig" + ], + "input": "select", + "meaning": "tři sta šedesát devět" + }, + { + "kind": "fill", + "segments": [ + "112 = ", + "" + ], + "answers": [ + "hundertzwölf" + ], + "input": "select", + "meaning": "sto dvanáct" + }, + { + "kind": "fill", + "segments": [ + "122 = ", + "" + ], + "answers": [ + "hundertzweiundzwanzig" + ], + "input": "select", + "meaning": "sto dvacet dva" + }, + { + "kind": "fill", + "segments": [ + "68 = ", + "" + ], + "answers": [ + "achtundsechzig" + ], + "input": "select", + "meaning": "šedesát osm" + } + ] + }, + { + "number": 17, + "title": "Steckbrief", + "subtitleKey": "sub_steckbrief", + "items": [ + { + "kind": "profile", + "stem": "Ich heiße …", + "sample": "Ich heiße Petra." + }, + { + "kind": "profile", + "stem": "Ich komme …", + "sample": "Ich komme aus Tschechien." + }, + { + "kind": "profile", + "stem": "Ich lebe …", + "sample": "Ich lebe in Prag." + }, + { + "kind": "profile", + "stem": "Ich bin …", + "sample": "Ich bin fünfzehn Jahre alt." + }, + { + "kind": "profile", + "stem": "Ich spreche …", + "sample": "Ich spreche Tschechisch und Deutsch." + }, + { + "kind": "profile", + "stem": "Ich besuche …", + "sample": "Ich besuche das Gymnasium." + }, + { + "kind": "profile", + "stem": "Ich finde …", + "sample": "Ich finde Deutsch toll." + }, + { + "kind": "profile", + "stem": "Ich arbeite …", + "sample": "Ich arbeite noch nicht." + } + ] + }, + { + "number": 18, + "title": "Berufe", + "subtitleKey": "sub_berufe", + "items": [ + { + "kind": "hangman", + "word": "KOCH", + "hint": "vaří v restauraci" + }, + { + "kind": "hangman", + "word": "ARZT", + "hint": "léčí nemocné lidi" + }, + { + "kind": "hangman", + "word": "LEHRER", + "hint": "učí ve škole" + }, + { + "kind": "hangman", + "word": "POLIZIST", + "hint": "pracuje u policie" + }, + { + "kind": "hangman", + "word": "VERKÄUFER", + "hint": "prodává v obchodě" + } + ] + }, + { + "number": 19, + "title": "Nationalität", + "subtitleKey": "sub_bistdu", + "items": [ + { + "kind": "typed", + "prompt": "1. 🇨🇿 Bist du Russe? – Nein, ich bin _________.", + "answers": [ + "tscheche" + ], + "meaning": "Čech" + }, + { + "kind": "typed", + "prompt": "2. 🇦🇹 Bist du Tschechin? – Nein, ich bin _________.", + "answers": [ + "österreicherin", + "osterreicherin" + ], + "meaning": "Rakušanka" + }, + { + "kind": "typed", + "prompt": "3. 🇨🇭 Bist du Deutsche? – Nein, ich bin _________.", + "answers": [ + "schweizerin" + ], + "meaning": "Švýcarka" + }, + { + "kind": "typed", + "prompt": "4. 🇩🇪 Bist du Engländer? – Nein, ich bin _________.", + "answers": [ + "deutscher" + ], + "meaning": "Němec" + }, + { + "kind": "typed", + "prompt": "5. 🇨🇭 Bist du Amerikanerin? – Nein, ich bin _________.", + "answers": [ + "schweizerin" + ], + "meaning": "Švýcarka" + } + ] + } + ], + "vocab": [ + { + "header": "Strana 22", + "items": [ + { + "prompt": "arbeiten (Infinitiv)", + "answers": [ + "pracovat", + "pracuje", + "to work" + ], + "meaning": "pracovat" + }, + { + "prompt": "das Auto, -s", + "answers": [ + "auto", + "car" + ], + "meaning": "auto" + }, + { + "prompt": "brauchen (Infinitiv)", + "answers": [ + "potřebovat", + "potřebuje", + "to need" + ], + "meaning": "potřebovat" + }, + { + "prompt": "die Britin, -nen", + "answers": [ + "britka", + "british woman" + ], + "meaning": "Britka" + }, + { + "prompt": "britisch", + "answers": [ + "britský", + "british" + ], + "meaning": "britský" + }, + { + "prompt": "deutsch", + "answers": [ + "německý", + "german" + ], + "meaning": "německý" + }, + { + "prompt": "das Deutsch", + "answers": [ + "němčina", + "německy", + "němčina, německy", + "german" + ], + "meaning": "němčina, německy" + }, + { + "prompt": "die Eisschnelläuferin, -nen", + "answers": [ + "rychlobruslařka", + "speed skater" + ], + "meaning": "rychlobruslařka" + }, + { + "prompt": "fahren (Infinitiv)", + "answers": [ + "jezdit", + "jet", + "řídit", + "to drive", + "to go" + ], + "meaning": "jezdit" + }, + { + "prompt": "Er fährt gern Auto.", + "answers": [ + "rád řídí auto", + "rád jezdí autem", + "he likes driving a car" + ], + "meaning": "Rád řídí auto." + }, + { + "prompt": "Frankreich", + "answers": [ + "francie", + "france" + ], + "meaning": "Francie" + }, + { + "prompt": "für", + "answers": [ + "pro", + "za", + "for" + ], + "meaning": "pro, za" + }, + { + "prompt": "der Fußballspieler", + "answers": [ + "fotbalista", + "footballer", + "football player" + ], + "meaning": "fotbalista" + }, + { + "prompt": "das Jahrhunderttalent, -e", + "answers": [ + "talent století", + "talent of the century" + ], + "meaning": "talent století" + }, + { + "prompt": "das Kind, -er", + "answers": [ + "dítě", + "child" + ], + "meaning": "dítě" + }, + { + "prompt": "lesen (Infinitiv)", + "answers": [ + "číst", + "to read" + ], + "meaning": "číst" + }, + { + "prompt": "das Model, -s", + "answers": [ + "model", + "modelka", + "model, modelka" + ], + "meaning": "model, modelka" + }, + { + "prompt": "die Nummer, -n", + "answers": [ + "číslo", + "number" + ], + "meaning": "číslo" + }, + { + "prompt": "die Schauspielerin, -nen", + "answers": [ + "herečka", + "actress" + ], + "meaning": "herečka" + }, + { + "prompt": "der Schüler, -", + "answers": [ + "žák", + "pupil", + "schoolboy" + ], + "meaning": "žák" + }, + { + "prompt": "die Sportinitiative, -n", + "answers": [ + "sportovní iniciativa", + "sports initiative" + ], + "meaning": "sportovní iniciativa" + }, + { + "prompt": "sprechen (Infinitiv)", + "answers": [ + "mluvit", + "to speak" + ], + "meaning": "mluvit" + }, + { + "prompt": "Sie spricht Englisch.", + "answers": [ + "mluví anglicky", + "ona mluví anglicky", + "she speaks english" + ], + "meaning": "Mluví anglicky." + }, + { + "prompt": "der Trainer, -", + "answers": [ + "trenér", + "coach", + "trainer" + ], + "meaning": "trenér" + } + ] + }, + { + "header": "Strana 23", + "items": [ + { + "prompt": "besuchen (Infinitiv)", + "answers": [ + "navštěvovat", + "navštívit", + "to visit" + ], + "meaning": "navštěvovat, navštívit" + }, + { + "prompt": "Er besucht das Gymnasium.", + "answers": [ + "chodí na gymnázium", + "navštěvuje gymnázium", + "he attends grammar school" + ], + "meaning": "Chodí na gymnázium." + }, + { + "prompt": "dort", + "answers": [ + "tam", + "there" + ], + "meaning": "tam" + }, + { + "prompt": "dreifach", + "answers": [ + "trojnásobný", + "threefold", + "triple" + ], + "meaning": "trojnásobný" + }, + { + "prompt": "gewinnen (Infinitiv)", + "answers": [ + "vyhrát", + "vyhrávat", + "to win" + ], + "meaning": "vyhrát, vyhrávat" + }, + { + "prompt": "die Goldmedaille, -n", + "answers": [ + "zlatá medaile", + "gold medal" + ], + "meaning": "zlatá medaile" + }, + { + "prompt": "das Gymnasium, Gymnasien", + "answers": [ + "gymnázium", + "grammar school" + ], + "meaning": "gymnázium" + }, + { + "prompt": "heute", + "answers": [ + "dnes", + "dneska", + "today" + ], + "meaning": "dnes" + }, + { + "prompt": "das Kroatisch", + "answers": [ + "chorvatština", + "chorvatsky", + "chorvatština, chorvatsky", + "croatian" + ], + "meaning": "chorvatština, chorvatsky" + }, + { + "prompt": "leben (Infinitiv)", + "answers": [ + "žít", + "to live" + ], + "meaning": "žít" + }, + { + "prompt": "Sie lebt in Österreich.", + "answers": [ + "žije v rakousku", + "she lives in austria" + ], + "meaning": "Žije v Rakousku." + }, + { + "prompt": "die Muttersprache, -n", + "answers": [ + "mateřský jazyk", + "mother tongue" + ], + "meaning": "mateřský jazyk" + }, + { + "prompt": "oft", + "answers": [ + "často", + "often" + ], + "meaning": "často" + }, + { + "prompt": "Österreich", + "answers": [ + "rakousko", + "austria" + ], + "meaning": "Rakousko" + }, + { + "prompt": "die Rad(renn)fahrerin, -nen", + "answers": [ + "cyklistka", + "cyclist" + ], + "meaning": "cyklistka" + }, + { + "prompt": "das Spanisch", + "answers": [ + "španělština", + "španělsky", + "španělština, španělsky", + "spanish" + ], + "meaning": "španělština, španělsky" + }, + { + "prompt": "die Sportlerin, -nen", + "answers": [ + "sportovkyně", + "sportswoman", + "athlete" + ], + "meaning": "sportovkyně" + }, + { + "prompt": "sportlich", + "answers": [ + "sportovní", + "sporty" + ], + "meaning": "sportovní" + }, + { + "prompt": "tschechisch", + "answers": [ + "český", + "czech" + ], + "meaning": "český" + }, + { + "prompt": "das Tschechisch", + "answers": [ + "čeština", + "česky", + "čeština, česky", + "czech" + ], + "meaning": "čeština, česky" + } + ] + }, + { + "header": "Strana 24", + "items": [ + { + "prompt": "das Amerika", + "answers": [ + "amerika", + "america" + ], + "meaning": "Amerika" + }, + { + "prompt": "die Assistentin, -nen", + "answers": [ + "asistentka", + "assistant" + ], + "meaning": "asistentka" + }, + { + "prompt": "der Beruf, -e", + "answers": [ + "povolání", + "profese", + "job", + "profession" + ], + "meaning": "povolání" + }, + { + "prompt": "Was ist er von Beruf?", + "answers": [ + "jaké má povolání", + "čím je", + "what is his job" + ], + "meaning": "Jaké má povolání?" + }, + { + "prompt": "Deutschland", + "answers": [ + "německo", + "germany" + ], + "meaning": "Německo" + }, + { + "prompt": "England", + "answers": [ + "anglie", + "england" + ], + "meaning": "Anglie" + }, + { + "prompt": "die Flagge, -n", + "answers": [ + "vlajka", + "flag" + ], + "meaning": "vlajka" + }, + { + "prompt": "Griechenland", + "answers": [ + "řecko", + "greece" + ], + "meaning": "Řecko" + }, + { + "prompt": "das Griechisch", + "answers": [ + "řečtina", + "řecky", + "řečtina, řecky", + "greek" + ], + "meaning": "řečtina, řecky" + }, + { + "prompt": "Großbritannien", + "answers": [ + "velká británie", + "great britain" + ], + "meaning": "Velká Británie" + }, + { + "prompt": "die Herkunft", + "answers": [ + "původ", + "origin" + ], + "meaning": "původ" + }, + { + "prompt": "Italien", + "answers": [ + "itálie", + "italy" + ], + "meaning": "Itálie" + }, + { + "prompt": "das Italienisch", + "answers": [ + "italština", + "italsky", + "italština, italsky", + "italian" + ], + "meaning": "italština, italsky" + }, + { + "prompt": "Kroatien", + "answers": [ + "chorvatsko", + "croatia" + ], + "meaning": "Chorvatsko" + }, + { + "prompt": "das Land, Länder", + "answers": [ + "země", + "stát", + "country" + ], + "meaning": "země, stát" + }, + { + "prompt": "der Lehrer, -", + "answers": [ + "učitel", + "teacher" + ], + "meaning": "učitel" + }, + { + "prompt": "die Lehrerin, -nen", + "answers": [ + "učitelka", + "teacher" + ], + "meaning": "učitelka" + }, + { + "prompt": "der Manager, -", + "answers": [ + "manažer", + "manager" + ], + "meaning": "manažer" + }, + { + "prompt": "Polen", + "answers": [ + "polsko", + "poland" + ], + "meaning": "Polsko" + }, + { + "prompt": "das Polnisch", + "answers": [ + "polština", + "polsky", + "polština, polsky", + "polish" + ], + "meaning": "polština, polsky" + }, + { + "prompt": "das Russisch", + "answers": [ + "ruština", + "rusky", + "ruština, rusky", + "russian" + ], + "meaning": "ruština, rusky" + }, + { + "prompt": "Russland", + "answers": [ + "rusko", + "russia" + ], + "meaning": "Rusko" + }, + { + "prompt": "die Schweiz", + "answers": [ + "švýcarsko", + "switzerland" + ], + "meaning": "Švýcarsko" + }, + { + "prompt": "die Slowakei", + "answers": [ + "slovensko", + "slovakia" + ], + "meaning": "Slovensko" + }, + { + "prompt": "das Slowakisch", + "answers": [ + "slovenština", + "slovensky", + "slovenština, slovensky", + "slovak" + ], + "meaning": "slovenština, slovensky" + }, + { + "prompt": "Spanien", + "answers": [ + "španělsko", + "spain" + ], + "meaning": "Španělsko" + }, + { + "prompt": "die Sprache, -n", + "answers": [ + "jazyk", + "řeč", + "language" + ], + "meaning": "jazyk, řeč" + }, + { + "prompt": "der Student, -en", + "answers": [ + "student", + "student" + ], + "meaning": "student" + }, + { + "prompt": "die Studentin, -nen", + "answers": [ + "studentka", + "student" + ], + "meaning": "studentka" + }, + { + "prompt": "Tschechien", + "answers": [ + "česko", + "czechia" + ], + "meaning": "Česko" + }, + { + "prompt": "die Türkei", + "answers": [ + "turecko", + "turkey" + ], + "meaning": "Turecko" + }, + { + "prompt": "das Türkisch", + "answers": [ + "turečtina", + "turecky", + "turečtina, turecky", + "turkish" + ], + "meaning": "turečtina, turecky" + }, + { + "prompt": "das Ungarisch", + "answers": [ + "maďarština", + "maďarsky", + "maďarština, maďarsky", + "hungarian" + ], + "meaning": "maďarština, maďarsky" + }, + { + "prompt": "Ungarn", + "answers": [ + "maďarsko", + "hungary" + ], + "meaning": "Maďarsko" + }, + { + "prompt": "die Verkäuferin, -nen", + "answers": [ + "prodavačka", + "shop assistant", + "saleswoman" + ], + "meaning": "prodavačka" + }, + { + "prompt": "welcher/welche/welches", + "answers": [ + "jaký", + "jaká", + "jaké", + "which" + ], + "meaning": "jaký/jaká/jaké" + }, + { + "prompt": "Welche Sprachen spricht sie?", + "answers": [ + "jakými jazyky mluví", + "které jazyky mluví", + "which languages does she speak" + ], + "meaning": "Jakými jazyky mluví?" + }, + { + "prompt": "super", + "answers": [ + "super", + "skvělý", + "great", + "super, skvělý" + ], + "meaning": "super, skvělý" + }, + { + "prompt": "wenig", + "answers": [ + "málo", + "little", + "few" + ], + "meaning": "málo" + }, + { + "prompt": "ein wenig", + "answers": [ + "trochu", + "a little", + "a bit" + ], + "meaning": "trochu" + }, + { + "prompt": "das Wort, Wörter", + "answers": [ + "slovo", + "word" + ], + "meaning": "slovo" + } + ] + }, + { + "header": "Strana 25", + "items": [ + { + "prompt": "das Abitur, -e", + "answers": [ + "maturita", + "a-levels" + ], + "meaning": "maturita" + }, + { + "prompt": "der Austausch, -e", + "answers": [ + "výměna", + "exchange" + ], + "meaning": "výměna" + }, + { + "prompt": "ein bisschen", + "answers": [ + "trochu", + "a bit", + "a little" + ], + "meaning": "trochu" + }, + { + "prompt": "finden (Infinitiv)", + "answers": [ + "najít", + "považovat", + "shledávat", + "myslet si", + "to find" + ], + "meaning": "najít, považovat" + }, + { + "prompt": "Sie findet den Kurs...", + "answers": [ + "kurz se jí líbí", + "kurz shledává skvělým", + "she likes the course" + ], + "meaning": "Kurz se jí líbí. (Kurz shledává skvělým.)" + }, + { + "prompt": "interessant", + "answers": [ + "zajímavý", + "interesting" + ], + "meaning": "zajímavý" + }, + { + "prompt": "der Kurs, -e", + "answers": [ + "kurz", + "course" + ], + "meaning": "kurz" + }, + { + "prompt": "leider", + "answers": [ + "bohužel", + "unfortunately" + ], + "meaning": "bohužel" + }, + { + "prompt": "mein/meine/mein", + "answers": [ + "můj", + "moje", + "my" + ], + "meaning": "můj/moje/moje" + }, + { + "prompt": "der Mensch, -en", + "answers": [ + "člověk", + "human", + "person" + ], + "meaning": "člověk" + }, + { + "prompt": "die Mutter, Mütter", + "answers": [ + "matka", + "mother" + ], + "meaning": "matka" + }, + { + "prompt": "noch", + "answers": [ + "ještě", + "still" + ], + "meaning": "ještě" + }, + { + "prompt": "Portugal", + "answers": [ + "portugalsko", + "portugal" + ], + "meaning": "Portugalsko" + }, + { + "prompt": "das Portugiesisch", + "answers": [ + "portugalština", + "portugalsky", + "portugalština, portugalsky", + "portuguese" + ], + "meaning": "portugalština, portugalsky" + }, + { + "prompt": "Schweden", + "answers": [ + "švédsko", + "sweden" + ], + "meaning": "Švédsko" + }, + { + "prompt": "das Schwedisch", + "answers": [ + "švédština", + "švédsky", + "švédština, švédsky", + "swedish" + ], + "meaning": "švédština, švédsky" + }, + { + "prompt": "sehr", + "answers": [ + "velmi", + "very" + ], + "meaning": "velmi" + }, + { + "prompt": "nicht sehr gut", + "answers": [ + "ne moc dobře", + "not very well" + ], + "meaning": "ne moc dobře" + }, + { + "prompt": "studieren (Infinitiv)", + "answers": [ + "studovat", + "to study" + ], + "meaning": "studovat" + }, + { + "prompt": "das Südamerika", + "answers": [ + "jižní amerika", + "south america" + ], + "meaning": "Jižní Amerika" + }, + { + "prompt": "die USA (mn. č.)", + "answers": [ + "usa", + "united states", + "spojené státy" + ], + "meaning": "USA" + }, + { + "prompt": "viel", + "answers": [ + "hodně", + "much", + "a lot" + ], + "meaning": "hodně" + }, + { + "prompt": "wie viel", + "answers": [ + "kolik", + "how much", + "how many" + ], + "meaning": "kolik" + } + ] + }, + { + "header": "Strana 26", + "items": [ + { + "prompt": "Deutscher/Deutsche", + "answers": [ + "němec", + "němka", + "němec/němka" + ], + "meaning": "Němec/Němka" + }, + { + "prompt": "Engländer/Engländerin", + "answers": [ + "angličan", + "angličanka", + "angličan/angličanka" + ], + "meaning": "Angličan/Angličanka" + }, + { + "prompt": "Franzose/Französin", + "answers": [ + "francouz", + "francouzka", + "francouz/francouzka" + ], + "meaning": "Francouz/Francouzka" + }, + { + "prompt": "Italiener/Italienerin", + "answers": [ + "ital", + "italka", + "ital/italka" + ], + "meaning": "Ital/Italka" + }, + { + "prompt": "die Nationalität, -en", + "answers": [ + "národnost", + "nationality" + ], + "meaning": "národnost" + }, + { + "prompt": "Österreicher/Österreicherin", + "answers": [ + "rakušan", + "rakušanka", + "rakušan/rakušanka" + ], + "meaning": "Rakušan/Rakušanka" + }, + { + "prompt": "Russe/Russin", + "answers": [ + "rus", + "ruska", + "rus/ruska" + ], + "meaning": "Rus/Ruska" + }, + { + "prompt": "Schweizer/Schweizerin", + "answers": [ + "švýcar", + "švýcarka", + "švýcar/švýcarka" + ], + "meaning": "Švýcar/Švýcarka" + }, + { + "prompt": "Slowake/Slowakin", + "answers": [ + "slovák", + "slovenka", + "slovák/slovenka" + ], + "meaning": "Slovák/Slovenka" + }, + { + "prompt": "Spanier/Spanierin", + "answers": [ + "španěl", + "španělka", + "španěl/španělka" + ], + "meaning": "Španěl/Španělka" + }, + { + "prompt": "Tscheche/Tschechin", + "answers": [ + "čech", + "češka", + "čech/češka" + ], + "meaning": "Čech/Češka" + } + ] + }, + { + "header": "Strana 26", + "items": [ + { + "prompt": "dreißig", + "answers": [ + "30", + "třicet" + ], + "meaning": "třicet (30)" + }, + { + "prompt": "vierzig", + "answers": [ + "40", + "čtyřicet" + ], + "meaning": "čtyřicet (40)" + }, + { + "prompt": "fünfzig", + "answers": [ + "50", + "padesát" + ], + "meaning": "padesát (50)" + }, + { + "prompt": "sechzig", + "answers": [ + "60", + "šedesát" + ], + "meaning": "šedesát (60)" + }, + { + "prompt": "siebzig", + "answers": [ + "70", + "sedmdesát" + ], + "meaning": "sedmdesát (70)" + }, + { + "prompt": "achtzig", + "answers": [ + "80", + "osmdesát" + ], + "meaning": "osmdesát (80)" + }, + { + "prompt": "neunzig", + "answers": [ + "90", + "devadesát" + ], + "meaning": "devadesát (90)" + }, + { + "prompt": "(ein)hundert", + "answers": [ + "100", + "sto" + ], + "meaning": "sto (100)" + }, + { + "prompt": "(ein)tausend", + "answers": [ + "1000", + "tisíc" + ], + "meaning": "tisíc (1000)" + } + ] + }, + { + "header": "Strana 27", + "items": [ + { + "prompt": "das Afrika", + "answers": [ + "afrika", + "africa" + ], + "meaning": "Afrika" + }, + { + "prompt": "die Arbeit, -en", + "answers": [ + "práce", + "work", + "job" + ], + "meaning": "práce" + }, + { + "prompt": "Asien", + "answers": [ + "asie", + "asia" + ], + "meaning": "Asie" + }, + { + "prompt": "das Australien", + "answers": [ + "austrálie", + "australia" + ], + "meaning": "Austrálie" + }, + { + "prompt": "beginnen (Infinitiv)", + "answers": [ + "začít", + "začínat", + "to begin", + "to start" + ], + "meaning": "začít, začínat" + }, + { + "prompt": "danke", + "answers": [ + "děkuji", + "díky", + "thanks", + "thank you" + ], + "meaning": "děkuji, díky" + }, + { + "prompt": "das Europa", + "answers": [ + "evropa", + "europe" + ], + "meaning": "Evropa" + }, + { + "prompt": "ganz", + "answers": [ + "celý", + "whole" + ], + "meaning": "celý" + }, + { + "prompt": "gehen (Infinitiv)", + "answers": [ + "jít", + "chodit", + "to go" + ], + "meaning": "jít" + }, + { + "prompt": "Wie geht es Ihnen?", + "answers": [ + "jak se máte", + "how are you" + ], + "meaning": "Jak se máte?" + }, + { + "prompt": "Wie geht es dir?", + "answers": [ + "jak se máš", + "how are you" + ], + "meaning": "Jak se máš?" + }, + { + "prompt": "genau", + "answers": [ + "přesně", + "exactly" + ], + "meaning": "přesně" + }, + { + "prompt": "morgen", + "answers": [ + "zítra", + "tomorrow" + ], + "meaning": "zítra" + }, + { + "prompt": "nur", + "answers": [ + "jen", + "only" + ], + "meaning": "jen" + }, + { + "prompt": "der Rekord, -e", + "answers": [ + "rekord", + "record" + ], + "meaning": "rekord" + }, + { + "prompt": "schon", + "answers": [ + "již", + "už", + "already" + ], + "meaning": "již, už" + }, + { + "prompt": "das Semester, -", + "answers": [ + "semestr", + "semester" + ], + "meaning": "semestr" + }, + { + "prompt": "viel", + "answers": [ + "hodně", + "much", + "a lot" + ], + "meaning": "hodně" + }, + { + "prompt": "wie viel", + "answers": [ + "kolik", + "how much", + "how many" + ], + "meaning": "kolik" + }, + { + "prompt": "die Welt", + "answers": [ + "svět", + "world" + ], + "meaning": "svět" + }, + { + "prompt": "aus der ganzen Welt", + "answers": [ + "z celého světa", + "from all over the world" + ], + "meaning": "z celého světa" + } + ] + } + ] +} diff --git a/content/lessons/deutsch/unit-03.json b/content/lessons/deutsch/unit-03.json new file mode 100644 index 0000000..565a069 --- /dev/null +++ b/content/lessons/deutsch/unit-03.json @@ -0,0 +1,2731 @@ +{ + "id": "unit-03", + "subject": "deutsch", + "number": 3, + "title": { + "cs": "Bei uns zu Hause", + "en": "Bei uns zu Hause" + }, + "slides": [], + "tasks": [ + { + "number": 1, + "title": "Familienpaare", + "subtitleKey": "sub3_pair", + "example": "Beispiel: der Vater ↔ die Mutter", + "pool": [ + "die Cousine", + "die Tante", + "die Oma", + "der Bruder", + "die Freundin", + "der Sohn" + ], + "items": [ + { + "kind": "fill", + "segments": [ + "der Cousin", + "" + ], + "answers": [ + "die Cousine" + ], + "input": "select", + "label": "1.", + "meaning": "bratranec / sestřenice" + }, + { + "kind": "fill", + "segments": [ + "der Onkel", + "" + ], + "answers": [ + "die Tante" + ], + "input": "select", + "label": "2.", + "meaning": "strýc / teta" + }, + { + "kind": "fill", + "segments": [ + "der Opa", + "" + ], + "answers": [ + "die Oma" + ], + "input": "select", + "label": "3.", + "meaning": "dědeček / babička" + }, + { + "kind": "fill", + "segments": [ + "die Schwester", + "" + ], + "answers": [ + "der Bruder" + ], + "input": "select", + "label": "4.", + "meaning": "sestra / bratr" + }, + { + "kind": "fill", + "segments": [ + "der Freund", + "" + ], + "answers": [ + "die Freundin" + ], + "input": "select", + "label": "5.", + "meaning": "kamarád / kamarádka" + }, + { + "kind": "fill", + "segments": [ + "die Tochter", + "" + ], + "answers": [ + "der Sohn" + ], + "input": "select", + "label": "6.", + "meaning": "dcera / syn" + } + ] + }, + { + "number": 2, + "title": "mein oder dein", + "subtitleKey": "sub3_poss", + "example": "Beispiel: Ist das dein Vater? – Nein, das ist nicht mein Vater. Das ist sein Onkel.", + "pool": [ + "dein", + "deine", + "mein", + "meine", + "sein", + "seine" + ], + "items": [ + { + "kind": "fill", + "segments": [ + "Ist das ", + " Mutter? – Nein, das ist nicht ", + " Mutter." + ], + "answers": [ + "deine", + "meine" + ], + "input": "select", + "label": "2.", + "meaning": "Je to tvoje matka? – Ne, to není moje matka. To je jeho teta." + }, + { + "kind": "fill", + "segments": [ + "Das ist ", + " Tante." + ], + "answers": [ + "seine" + ], + "input": "select", + "meaning": "Je to tvoje matka? – Ne, to není moje matka. To je jeho teta." + }, + { + "kind": "fill", + "segments": [ + "Ist das ", + " Bruder? – Nein, das ist nicht ", + " Bruder." + ], + "answers": [ + "dein", + "mein" + ], + "input": "select", + "label": "3.", + "meaning": "Je to tvůj bratr? – Ne, to není můj bratr. To je jeho bratranec." + }, + { + "kind": "fill", + "segments": [ + "Das ist ", + " Cousin." + ], + "answers": [ + "sein" + ], + "input": "select", + "meaning": "Je to tvůj bratr? – Ne, to není můj bratr. To je jeho bratranec." + }, + { + "kind": "fill", + "segments": [ + "Sind das ", + " Eltern? – Nein, das sind nicht ", + " Eltern. Das sind die Eltern von Markus." + ], + "answers": [ + "deine", + "meine" + ], + "input": "select", + "label": "4.", + "meaning": "Jsou to tvoji rodiče? – Ne, to nejsou moji rodiče. To jsou rodiče Markuse." + } + ] + }, + { + "number": 3, + "title": "ein / kein", + "subtitleKey": "sub3_haustier", + "example": "Beispiel: Hast du eine Katze? – Nein, ich habe keine Katze. Ich habe einen Hund.", + "pool": [ + "ein", + "eine", + "einen", + "kein", + "keine", + "keinen" + ], + "items": [ + { + "kind": "fill", + "segments": [ + "Hast du ", + " Hamster? – Nein, ich habe ", + " Hamster." + ], + "answers": [ + "einen", + "keinen" + ], + "input": "select", + "label": "2." + }, + { + "kind": "fill", + "segments": [ + "Ich habe ", + " Schildkröte." + ], + "answers": [ + "eine" + ], + "input": "select", + "meaning": "Máš křečka? – Ne, nemám křečka. Mám želvu." + }, + { + "kind": "fill", + "segments": [ + "Hast du ", + " Pferd? – Nein, ich habe ", + " Pferd." + ], + "answers": [ + "ein", + "kein" + ], + "input": "select", + "label": "3." + }, + { + "kind": "fill", + "segments": [ + "Ich habe ", + " Kaninchen." + ], + "answers": [ + "ein" + ], + "input": "select", + "meaning": "Máš koně? – Ne, nemám koně. Mám králíka." + }, + { + "kind": "fill", + "segments": [ + "Hast du ", + " Fisch? – Nein, ich habe ", + " Fisch." + ], + "answers": [ + "einen", + "keinen" + ], + "input": "select", + "label": "4." + }, + { + "kind": "fill", + "segments": [ + "Ich habe ", + " Vogel." + ], + "answers": [ + "einen" + ], + "input": "select", + "meaning": "Máš rybu? – Ne, nemám rybu. Mám ptáka." + }, + { + "kind": "fill", + "segments": [ + "Hast du ", + " Meerschweinchen? – Nein, ich habe ", + " Meerschweinchen." + ], + "answers": [ + "ein", + "kein" + ], + "input": "select", + "label": "5." + }, + { + "kind": "fill", + "segments": [ + "Ich habe ", + " Wellensittich." + ], + "answers": [ + "einen" + ], + "input": "select", + "meaning": "Máš morče? – Ne, nemám morče. Mám andulku." + } + ] + }, + { + "number": 4, + "title": "Lückentext", + "subtitleKey": "sub3_buchst", + "items": [ + { + "kind": "fill", + "segments": [ + "Wir hab", + "n Fre", + "nde in Öster", + "ich. Sie wo", + "nen in Wien." + ], + "answers": [ + "e", + "u", + "re", + "h" + ], + "input": "text", + "letters": true, + "meaning": "Máme přátele v Rakousku. Bydlí ve Vídni.", + "glosses": [ + "haben — mít", + "Freunde — přátelé", + "Österreich — Rakousko", + "wohnen — bydlet" + ] + }, + { + "kind": "fill", + "segments": [ + "Sie hei", + "en Elfriede und Jiri. Sie haben auch ", + "inder." + ], + "answers": [ + "ß", + "K" + ], + "input": "text", + "letters": true, + "meaning": "Jmenují se Elfriede a Jiří. Mají také děti.", + "glosses": [ + "heißen — jmenovat se", + "Kinder — děti" + ] + }, + { + "kind": "fill", + "segments": [ + "Ihr S", + "hn heißt Philipp und ihr", + " Tochter heißt Sabine." + ], + "answers": [ + "o", + "e" + ], + "input": "text", + "letters": true, + "meaning": "Jejich syn se jmenuje Philipp a jejich dcera Sabine.", + "glosses": [ + "Sohn — syn", + "ihre — jejich" + ] + }, + { + "kind": "fill", + "segments": [ + "Die Famili", + " re", + "st gern." + ], + "answers": [ + "e", + "i" + ], + "input": "text", + "letters": true, + "meaning": "Rodina ráda cestuje.", + "glosses": [ + "Familie — rodina", + "reist — cestuje" + ] + }, + { + "kind": "fill", + "segments": [ + "Sie ist o", + "t bei uns zu Bes", + "ch in Tsche", + "ien." + ], + "answers": [ + "f", + "u", + "ch" + ], + "input": "text", + "letters": true, + "meaning": "Často je u nás na návštěvě v Česku.", + "glosses": [ + "oft — často", + "Besuch — návštěva", + "Tschechien — Česko" + ] + }, + { + "kind": "fill", + "segments": [ + "Die Kinder ler", + "en auch Tsche", + "isch." + ], + "answers": [ + "n", + "ch" + ], + "input": "text", + "letters": true, + "meaning": "Děti se učí také česky.", + "glosses": [ + "lernen — učit se", + "Tschechisch — čeština" + ] + } + ] + }, + { + "number": 5, + "title": "Marcos Familie", + "subtitleKey": "sub3_marco", + "note": "Tanten | Job | Vater | Ferien | Zwillinge | Eltern | Kroatien", + "items": [ + { + "kind": "typed", + "prompt": "Wir haben eine Männer-Wohngemeinschaft: Mein ________ Johann (50), Ivo (16) und ich.", + "answers": [ + "vater" + ], + "meaning": "Máme mužskou domácnost: Můj otec Johann (50), Ivo (16) a já." + }, + { + "kind": "typed", + "prompt": "Ivo und ich sind gleich alt – wir sind nämlich ________.", + "answers": [ + "zwillinge" + ], + "meaning": "Ivo a já jsme stejně staří – jsme totiž dvojčata." + }, + { + "kind": "typed", + "prompt": "Jetzt wohnen wir in Hannover, unser Vater hat hier einen neuen ________.", + "answers": [ + "job" + ], + "meaning": "Náš otec tu má novou práci." + }, + { + "kind": "typed", + "prompt": "Unsere ________ sind geschieden.", + "answers": [ + "eltern" + ], + "meaning": "Naši rodiče jsou rozvedení." + }, + { + "kind": "typed", + "prompt": "Unsere Mutter Maja (50) lebt in Wien, aber sie kommt aus ________.", + "answers": [ + "kroatien" + ], + "meaning": "Naše matka Maja (50) žije ve Vídni, ale pochází z Chorvatska." + }, + { + "kind": "typed", + "prompt": "Wir haben viele Onkel, ________, Cousinen und Cousins in Kroatien.", + "answers": [ + "tanten" + ], + "meaning": "Máme v Chorvatsku hodně strýců, tet, sestřenic a bratranců." + }, + { + "kind": "typed", + "prompt": "Wir sehen sie manchmal in den ________.", + "answers": [ + "ferien" + ], + "meaning": "Vídáme je někdy o prázdninách." + } + ] + }, + { + "number": 6, + "title": "Sortieren", + "subtitleKey": "sub3_sort", + "items": [ + { + "kind": "assign", + "groups": [ + "Familienmitglieder", + "Haustiere" + ], + "items": [ + { + "emoji": null, + "label": "die Oma", + "group": 0, + "meaning": "babička" + }, + { + "emoji": null, + "label": "der Bruder", + "group": 0, + "meaning": "bratr" + }, + { + "emoji": null, + "label": "der Opa", + "group": 0, + "meaning": "dědeček" + }, + { + "emoji": null, + "label": "die Tochter", + "group": 0, + "meaning": "dcera" + }, + { + "emoji": null, + "label": "die Tante", + "group": 0, + "meaning": "teta" + }, + { + "emoji": null, + "label": "der Hamster", + "group": 1, + "meaning": "křeček" + }, + { + "emoji": null, + "label": "das Pferd", + "group": 1, + "meaning": "kůň" + }, + { + "emoji": null, + "label": "die Katze", + "group": 1, + "meaning": "kočka" + }, + { + "emoji": null, + "label": "der Hund", + "group": 1, + "meaning": "pes" + }, + { + "emoji": null, + "label": "der Wellensittich", + "group": 1, + "meaning": "andulka" + } + ] + } + ] + }, + { + "number": 7, + "title": "Possessivtabelle", + "subtitleKey": "sub3_tabelle", + "items": [ + { + "kind": "table", + "columns": [ + "ich", + "du", + "er", + "sie", + "es", + "wir", + "ihr", + "sie / Sie" + ], + "rows": [ + "der Garten", + "die Idee", + "das Fest", + "die Geschwister" + ], + "answers": [ + [ + { + "value": "mein" + }, + { + "value": "dein" + }, + { + "value": "sein" + }, + { + "value": "ihr" + }, + { + "value": "sein" + }, + { + "value": "unser" + }, + { + "value": "euer" + }, + { + "value": "ihr" + } + ], + [ + { + "value": "meine" + }, + { + "value": "deine" + }, + { + "value": "seine" + }, + { + "value": "ihre" + }, + { + "value": "seine" + }, + { + "value": "unsere" + }, + { + "value": "eure" + }, + { + "value": "ihre" + } + ], + [ + { + "value": "mein" + }, + { + "value": "dein" + }, + { + "value": "sein" + }, + { + "value": "ihr" + }, + { + "value": "sein" + }, + { + "value": "unser" + }, + { + "value": "euer" + }, + { + "value": "ihr" + } + ], + [ + { + "value": "meine" + }, + { + "value": "deine" + }, + { + "value": "seine" + }, + { + "value": "ihre" + }, + { + "value": "seine" + }, + { + "value": "unsere" + }, + { + "value": "eure" + }, + { + "value": "ihre" + } + ] + ] + } + ] + }, + { + "number": 8, + "title": "Akkusativ", + "subtitleKey": "sub3_akk", + "example": "Beispiel: die Inliner (ich) → Ich brauche meine Inliner.", + "pool": [ + "mein", + "meine", + "meinen", + "dein", + "deine", + "deinen", + "sein", + "seine", + "seinen", + "ihr", + "ihre", + "ihren", + "unser", + "unsere", + "unseren", + "euer", + "eure", + "euren" + ], + "items": [ + { + "kind": "fill", + "segments": [ + "das Handy → Du brauchst ", + " Handy." + ], + "answers": [ + "dein" + ], + "input": "select", + "label": "2.", + "meaning": "Potřebuješ svůj mobil.", + "glosses": [ + "u3g_dein" + ] + }, + { + "kind": "fill", + "segments": [ + "das Pferd → Er hat ", + " Pferd." + ], + "answers": [ + "sein" + ], + "input": "select", + "label": "3.", + "meaning": "Má svého koně.", + "glosses": [ + "u3g_sein" + ] + }, + { + "kind": "fill", + "segments": [ + "die Party → Sie macht ", + " Party." + ], + "answers": [ + "ihre" + ], + "input": "select", + "label": "4.", + "meaning": "Dělá svou párty.", + "glosses": [ + "u3g_ihr_sie" + ] + }, + { + "kind": "fill", + "segments": [ + "der Lehrer → Es fragt ", + " Lehrer." + ], + "answers": [ + "seinen" + ], + "input": "select", + "label": "5.", + "meaning": "Ptá se svého učitele.", + "glosses": [ + "u3g_sein_es" + ] + }, + { + "kind": "fill", + "segments": [ + "das Wochenendhaus → Wir besuchen ", + " Wochenendhaus." + ], + "answers": [ + "unser" + ], + "input": "select", + "label": "6.", + "meaning": "Navštěvujeme náš víkendový dům.", + "glosses": [ + "u3g_unser" + ] + }, + { + "kind": "fill", + "segments": [ + "der Hund → Ihr seht ", + " Hund." + ], + "answers": [ + "euren" + ], + "input": "select", + "label": "7.", + "meaning": "Vy vidíte svého psa.", + "glosses": [ + "u3g_euer" + ] + }, + { + "kind": "fill", + "segments": [ + "die Instrumente → Sie haben ", + " Instrumente." + ], + "answers": [ + "ihre" + ], + "input": "select", + "label": "8.", + "meaning": "Mají své nástroje.", + "glosses": [ + "u3g_ihr_sie_pl" + ] + } + ] + }, + { + "number": 9, + "title": "kein / nicht", + "subtitleKey": "sub3_nicht", + "pool": [ + "kein", + "keine", + "keinen", + "nicht" + ], + "items": [ + { + "kind": "fill", + "segments": [ + "● Sprichst du Spanisch? ○ Nein, ich spreche ", + " Spanisch." + ], + "answers": [ + "kein" + ], + "input": "select", + "label": "1.", + "meaning": "Mluvíš španělsky? – Ne, nemluvím španělsky." + }, + { + "kind": "fill", + "segments": [ + "● Hast du einen Bruder? ○ Nein, ich habe ", + " Bruder." + ], + "answers": [ + "keinen" + ], + "input": "select", + "label": "2.", + "meaning": "Máš bratra? – Ne, nemám bratra." + }, + { + "kind": "fill", + "segments": [ + "● Gibt es in Opava einen Zoo? ○ Nein, in Opava gibt es ", + " Zoo." + ], + "answers": [ + "keinen" + ], + "input": "select", + "label": "3.", + "meaning": "Je v Opavě zoo? – Ne, v Opavě žádná zoo není." + }, + { + "kind": "fill", + "segments": [ + "● Gehst du ins Schwimmbad? ○ Nein, ich gehe ", + " ins Schwimmbad." + ], + "answers": [ + "nicht" + ], + "input": "select", + "label": "4.", + "meaning": "Jdeš do bazénu? – Ne, do bazénu nejdu." + }, + { + "kind": "fill", + "segments": [ + "● Wandert er gern? ○ Nein, er wandert ", + " gern." + ], + "answers": [ + "nicht" + ], + "input": "select", + "label": "5.", + "meaning": "Rád chodí na túry? – Ne, nerad chodí na túry." + }, + { + "kind": "fill", + "segments": [ + "● Besuchst du heute ein Schloss? ○ Nein, heute besuche ich ", + " Schloss." + ], + "answers": [ + "kein" + ], + "input": "select", + "label": "6.", + "meaning": "Navštívíš dnes zámek? – Ne, dnes nenavštívím žádný zámek." + } + ] + }, + { + "number": 10, + "title": "Sätze bauen", + "subtitleKey": "sub3_satz", + "items": [ + { + "kind": "assembly", + "prompt": "", + "words": [ + "Sie", + "haben", + "eine", + "Schildkröte", + "." + ], + "meaning": "Mají želvu." + }, + { + "kind": "assembly", + "prompt": "", + "words": [ + "Was", + "macht", + "deine", + "Freundin", + "am", + "Wochenende?" + ], + "meaning": "Co dělá tvoje kamarádka o víkendu?" + }, + { + "kind": "assembly", + "prompt": "", + "words": [ + "Mein", + "Vater", + "ist", + "Lehrer", + "von", + "Beruf." + ], + "meaning": "Můj otec je povoláním učitel." + }, + { + "kind": "assembly", + "prompt": "", + "words": [ + "Seid", + "ihr", + "viele", + "zu", + "Hause?" + ], + "meaning": "Je vás doma hodně?" + }, + { + "kind": "assembly", + "prompt": "", + "words": [ + "Julia", + "stellt", + "ihren", + "Hund", + "Trixi", + "vor." + ], + "meaning": "Julie představuje svého psa Trixiho." + } + ] + }, + { + "number": 11, + "title": "Was siehst du?", + "subtitleKey": "sub3_sehen", + "example": "Beispiel: Ich sehe eine Burg. / Ich sehe ein Schloss.", + "items": [ + { + "kind": "typed", + "prompt": "Ein altes Gebäude aus dem Mittelalter. Es steht auf einem Berg.", + "answers": [ + "burg", + "schloss" + ], + "substring": true, + "meaning": "Vidím hrad / zámek.", + "model": "Ich sehe eine Burg. / Ich sehe ein Schloss." + }, + { + "kind": "typed", + "prompt": "Wasser, Bäume und Berge. Es ist sehr ruhig.", + "answers": [ + "see" + ], + "substring": true, + "meaning": "Vidím jezero.", + "model": "Ich sehe einen See." + }, + { + "kind": "typed", + "prompt": "Eine Frau, ein Mann und zwei Kinder essen zusammen.", + "answers": [ + "familie" + ], + "substring": true, + "meaning": "Vidím rodinu.", + "model": "Ich sehe eine Familie." + } + ] + }, + { + "number": 12, + "title": "Wem gehört das?", + "subtitleKey": "sub3_wem", + "pool": [ + "mein", + "meine", + "dein", + "deine", + "sein", + "seine", + "ihr", + "ihre", + "unser", + "unsere", + "euer", + "eure" + ], + "items": [ + { + "kind": "fill", + "segments": [ + "Das ist Tom. → Das ist ", + " Handy." + ], + "answers": [ + "sein" + ], + "input": "select", + "label": "1.", + "meaning": "To je jeho mobil." + }, + { + "kind": "fill", + "segments": [ + "Das ist Maria. → Das ist ", + " Kaninchen." + ], + "answers": [ + "ihr" + ], + "input": "select", + "label": "2.", + "meaning": "To je její králík." + }, + { + "kind": "fill", + "segments": [ + "Das sind Max und Lisa. → Das sind ", + " Inliner." + ], + "answers": [ + "ihre" + ], + "input": "select", + "label": "3.", + "meaning": "To jsou jejich brusle." + }, + { + "kind": "fill", + "segments": [ + "Das ist Frau Berger. → Das ist ", + " Kuchen." + ], + "answers": [ + "ihr" + ], + "input": "select", + "label": "4.", + "meaning": "To je její dort." + }, + { + "kind": "fill", + "segments": [ + "Das ist Herr Müller. → Das ist ", + " Haus." + ], + "answers": [ + "sein" + ], + "input": "select", + "label": "5.", + "meaning": "To je jeho dům." + }, + { + "kind": "fill", + "segments": [ + "Das sind die Schmidts. → Das sind ", + " Kinder." + ], + "answers": [ + "ihre" + ], + "input": "select", + "label": "6.", + "meaning": "To jsou jejich děti." + } + ] + }, + { + "number": 13, + "title": "Es gibt …", + "subtitleKey": "sub3_gibt", + "pool": [ + "ein", + "eine", + "einen" + ], + "items": [ + { + "kind": "fill", + "segments": [ + "(das Konzert) → Es gibt ", + " Konzert." + ], + "answers": [ + "ein" + ], + "input": "select", + "label": "1.", + "meaning": "Je tu koncert." + }, + { + "kind": "fill", + "segments": [ + "(die Ausstellung) → Es gibt ", + " Ausstellung." + ], + "answers": [ + "eine" + ], + "input": "select", + "label": "2.", + "meaning": "Je tu výstava." + }, + { + "kind": "fill", + "segments": [ + "(das Sportfest) → Es gibt ", + " Sportfest." + ], + "answers": [ + "ein" + ], + "input": "select", + "label": "3.", + "meaning": "Je tu sportovní slavnost." + }, + { + "kind": "fill", + "segments": [ + "(das Familientreffen) → Es gibt ", + " Familientreffen." + ], + "answers": [ + "ein" + ], + "input": "select", + "label": "4.", + "meaning": "Je tu rodinné setkání." + }, + { + "kind": "fill", + "segments": [ + "(die Theatervorstellung) → Es gibt ", + " Theatervorstellung." + ], + "answers": [ + "eine" + ], + "input": "select", + "label": "5.", + "meaning": "Je tu divadelní představení." + }, + { + "kind": "fill", + "segments": [ + "(der Flohmarkt) → Es gibt ", + " Flohmarkt." + ], + "answers": [ + "einen" + ], + "input": "select", + "label": "6.", + "meaning": "Je tu bleší trh." + } + ] + }, + { + "number": 14, + "title": "Beschreiben", + "subtitleKey": "sub3_saetze", + "example": "Beispiel: Ich sehe einen Jungen. Er liest ein Buch.", + "items": [ + { + "kind": "typed", + "prompt": "Eine Frau fährt Fahrrad. → Ich sehe ________.", + "answers": [ + "eine frau", + "frau" + ], + "substring": true, + "meaning": "Vidím ženu.", + "model": "Ich sehe eine Frau." + }, + { + "kind": "typed", + "prompt": "→ Sie ________.", + "answers": [ + "sie fährt fahrrad", + "sie fährt", + "fährt fahrrad", + "fährt" + ], + "substring": true, + "meaning": "Jezdí na kole.", + "model": "Sie fährt Fahrrad." + }, + { + "kind": "typed", + "prompt": "Ein Mann wandert im Wald. → Ich sehe ________.", + "answers": [ + "einen mann", + "mann" + ], + "substring": true, + "meaning": "Vidím muže.", + "model": "Ich sehe einen Mann." + }, + { + "kind": "typed", + "prompt": "→ Er ________.", + "answers": [ + "er wandert im wald", + "er wandert", + "wandert im wald", + "wandert" + ], + "substring": true, + "meaning": "Chodí po lese.", + "model": "Er wandert im Wald." + }, + { + "kind": "typed", + "prompt": "Zwei Kinder spielen Fußball. → Ich sehe ________.", + "answers": [ + "zwei kinder", + "kinder" + ], + "substring": true, + "meaning": "Vidím dvě děti.", + "model": "Ich sehe zwei Kinder." + }, + { + "kind": "typed", + "prompt": "→ Sie ________.", + "answers": [ + "sie spielen fußball", + "sie spielen fussball", + "spielen fußball", + "spielen fussball", + "spielen" + ], + "substring": true, + "meaning": "Hrají fotbal.", + "model": "Sie spielen Fußball." + } + ] + }, + { + "number": 15, + "title": "Wochenende", + "subtitleKey": "sub3_wochen", + "items": [ + { + "kind": "fill", + "segments": [ + "Meine Gr", + "eltern fahr", + " ins Wochen", + "haus." + ], + "answers": [ + "oß", + "en", + "end" + ], + "input": "text", + "letters": true, + "label": "1.", + "meaning": "Moji prarodiče jedou o víkendu do víkendového domu." + }, + { + "kind": "fill", + "segments": [ + "Mein ", + "ter und mein", + " Mutter besuch", + " ein Konz", + "t." + ], + "answers": [ + "Va", + "e", + "en", + "er" + ], + "input": "text", + "letters": true, + "label": "2.", + "meaning": "Můj otec a moje matka navštíví koncert." + }, + { + "kind": "fill", + "segments": [ + "Mein", + " Sch", + "ester geh", + " ins K", + "o." + ], + "answers": [ + "e", + "w", + "t", + "in" + ], + "input": "text", + "letters": true, + "label": "3.", + "meaning": "Moje sestra jde do kina." + }, + { + "kind": "fill", + "segments": [ + "Mein Bru", + "er f", + "rt an ", + "nen S", + "." + ], + "answers": [ + "d", + "äh", + "ei", + "ee" + ], + "input": "text", + "letters": true, + "label": "4.", + "meaning": "Můj bratr jede k jezeru." + }, + { + "kind": "fill", + "segments": [ + "Und ich? Ich besuch", + " ein Einka", + "zentrum." + ], + "answers": [ + "e", + "ufs" + ], + "input": "text", + "letters": true, + "label": "5.", + "meaning": "A já? Navštívím obchodní centrum." + } + ] + } + ], + "vocab": [ + { + "header": "Strana 32", + "items": [ + { + "prompt": "die Geburtstagsparty, -s", + "answers": [ + "narozeninová slavnost", + "narozeninová oslava", + "birthday party" + ], + "meaning": "narozeninová slavnost" + }, + { + "prompt": "das Haustier, -e", + "answers": [ + "domácí zvíře", + "domácí mazlíček", + "pet" + ], + "meaning": "domácí zvíře" + } + ] + }, + { + "header": "Strana 33", + "items": [ + { + "prompt": "die Aktivität, -en", + "answers": [ + "aktivita", + "činnost", + "activity" + ], + "meaning": "aktivita" + }, + { + "prompt": "der Stammbaum, Stammbäume", + "answers": [ + "rodokmen", + "family tree" + ], + "meaning": "rodokmen" + } + ] + }, + { + "header": "Strana 34", + "items": [ + { + "prompt": "der Bruder, Brüder", + "answers": [ + "bratr", + "brother" + ], + "meaning": "bratr" + }, + { + "prompt": "der Cousin, -s", + "answers": [ + "bratranec", + "cousin" + ], + "meaning": "bratranec" + }, + { + "prompt": "die Cousine, -n", + "answers": [ + "sestřenice", + "cousin" + ], + "meaning": "sestřenice" + }, + { + "prompt": "die Ehefrau, -en", + "answers": [ + "manželka", + "žena", + "wife" + ], + "meaning": "manželka" + }, + { + "prompt": "der Ehemann, Ehemänner", + "answers": [ + "manžel", + "muž", + "husband" + ], + "meaning": "manžel" + }, + { + "prompt": "das Einzelkind, -er", + "answers": [ + "jedináček", + "only child" + ], + "meaning": "jedináček" + }, + { + "prompt": "die Eltern (mn. č.)", + "answers": [ + "rodiče", + "parents" + ], + "meaning": "rodiče" + }, + { + "prompt": "die Familie, -n", + "answers": [ + "rodina", + "family" + ], + "meaning": "rodina" + }, + { + "prompt": "feiern (Infinitiv)", + "answers": [ + "slavit", + "oslavovat", + "to celebrate" + ], + "meaning": "slavit, oslavovat" + }, + { + "prompt": "das Fest, -e", + "answers": [ + "oslava", + "slavnost", + "svátek", + "celebration", + "festival" + ], + "meaning": "oslava, slavnost" + }, + { + "prompt": "der Garten, Gärten", + "answers": [ + "zahrada", + "garden" + ], + "meaning": "zahrada" + }, + { + "prompt": "gehören (Infinitiv)", + "answers": [ + "patřit", + "to belong" + ], + "meaning": "patřit" + }, + { + "prompt": "Er gehört zur Familie.", + "answers": [ + "patří k rodině", + "he belongs to the family" + ], + "meaning": "Patří k rodině." + }, + { + "prompt": "geschieden", + "answers": [ + "rozvedený", + "rozvedená", + "divorced" + ], + "meaning": "rozvedený" + }, + { + "prompt": "Meine Eltern sind geschieden.", + "answers": [ + "moji rodiče jsou rozvedení", + "my parents are divorced" + ], + "meaning": "Moji rodiče jsou rozvedení." + }, + { + "prompt": "die Geschwister (mn. č.)", + "answers": [ + "sourozenci", + "siblings" + ], + "meaning": "sourozenci" + }, + { + "prompt": "gleich", + "answers": [ + "stejný", + "rovný", + "same", + "equal" + ], + "meaning": "stejný" + }, + { + "prompt": "groß", + "answers": [ + "velký", + "big", + "large", + "tall" + ], + "meaning": "velký" + }, + { + "prompt": "haben (Infinitiv)", + "answers": [ + "mít", + "to have" + ], + "meaning": "mít" + }, + { + "prompt": "Unser Haus hat einen großen Garten.", + "answers": [ + "náš dům má velkou zahradu", + "our house has a big garden" + ], + "meaning": "Náš dům má velkou zahradu." + }, + { + "prompt": "das Haus, Häuser", + "answers": [ + "dům", + "house" + ], + "meaning": "dům" + }, + { + "prompt": "hier", + "answers": [ + "zde", + "tady", + "tu", + "here" + ], + "meaning": "zde, tady" + }, + { + "prompt": "der Hund, -e", + "answers": [ + "pes", + "dog" + ], + "meaning": "pes" + }, + { + "prompt": "ihr, ihre, ihr", + "answers": [ + "její", + "jejich", + "její, jejich", + "her", + "their" + ], + "meaning": "její" + }, + { + "prompt": "der Iran", + "answers": [ + "írán", + "iran" + ], + "meaning": "Írán" + }, + { + "prompt": "der Job, -s", + "answers": [ + "pracovní místo", + "zaměstnání", + "práce", + "job" + ], + "meaning": "(pracovní) místo, zaměstnání" + }, + { + "prompt": "der Kater, -", + "answers": [ + "kocour", + "tomcat" + ], + "meaning": "kocour" + }, + { + "prompt": "lange", + "answers": [ + "dlouho", + "long" + ], + "meaning": "dlouho" + }, + { + "prompt": "manchmal", + "answers": [ + "někdy", + "občas", + "sometimes" + ], + "meaning": "někdy, občas" + }, + { + "prompt": "mehr", + "answers": [ + "více", + "víc", + "již", + "more" + ], + "meaning": "více, již" + }, + { + "prompt": "Ich bin kein Einzelkind mehr.", + "answers": [ + "již nejsem jedináček", + "už nejsem jedináček", + "i am no longer an only child" + ], + "meaning": "Již nejsem jedináček." + }, + { + "prompt": "nämlich", + "answers": [ + "totiž", + "namely" + ], + "meaning": "totiž" + }, + { + "prompt": "natürlich", + "answers": [ + "samozřejmě", + "přirozeně", + "of course", + "naturally" + ], + "meaning": "samozřejmě" + }, + { + "prompt": "neu", + "answers": [ + "nový", + "new" + ], + "meaning": "nový" + }, + { + "prompt": "die Oma, -s", + "answers": [ + "babička", + "babi", + "grandma", + "grandmother" + ], + "meaning": "babička" + }, + { + "prompt": "der Onkel, -", + "answers": [ + "strýc", + "uncle" + ], + "meaning": "strýc" + }, + { + "prompt": "der Opa, -s", + "answers": [ + "dědeček", + "děda", + "grandpa", + "grandfather" + ], + "meaning": "dědeček" + }, + { + "prompt": "die Patchworkfamilie, -n", + "answers": [ + "patchworková rodina", + "patchwork family", + "blended family" + ], + "meaning": "patchworková rodina" + }, + { + "prompt": "Persisch", + "answers": [ + "perština", + "persky", + "persian" + ], + "meaning": "perština, persky" + }, + { + "prompt": "die Person, -en", + "answers": [ + "osoba", + "person" + ], + "meaning": "osoba" + }, + { + "prompt": "die Schwester, -n", + "answers": [ + "sestra", + "sister" + ], + "meaning": "sestra" + }, + { + "prompt": "sehen (Infinitiv)", + "answers": [ + "vidět", + "to see" + ], + "meaning": "vidět" + }, + { + "prompt": "Wir sehen sie manchmal in den Ferien.", + "answers": [ + "vídáme je občas o prázdninách", + "vidíme je někdy o prázdninách", + "we see them sometimes during the holidays" + ], + "meaning": "Vídáme je občas o prázdninách." + }, + { + "prompt": "die Stiefmutter, Stiefmütter", + "answers": [ + "nevlastní matka", + "macecha", + "stepmother" + ], + "meaning": "nevlastní matka" + }, + { + "prompt": "die Stiefschwester, -n", + "answers": [ + "nevlastní sestra", + "stepsister" + ], + "meaning": "nevlastní sestra" + }, + { + "prompt": "die Tante, -n", + "answers": [ + "teta", + "téta", + "aunt" + ], + "meaning": "teta" + }, + { + "prompt": "die Tochter, Töchter", + "answers": [ + "dcera", + "daughter" + ], + "meaning": "dcera" + }, + { + "prompt": "tot", + "answers": [ + "mrtvý", + "dead" + ], + "meaning": "mrtvý" + }, + { + "prompt": "Er ist leider schon tot.", + "answers": [ + "on je již bohužel mrtvý", + "je bohužel už mrtvý", + "he is unfortunately already dead" + ], + "meaning": "(On) Je již bohužel mrtvý." + }, + { + "prompt": "typisch", + "answers": [ + "typický", + "klasický", + "typical" + ], + "meaning": "typický, klasický" + }, + { + "prompt": "unser, unsere, unser", + "answers": [ + "náš", + "naše", + "our" + ], + "meaning": "náš, naše, naše" + }, + { + "prompt": "der Vater, Väter", + "answers": [ + "otec", + "táta", + "father", + "dad" + ], + "meaning": "otec" + }, + { + "prompt": "verstehen sich", + "answers": [ + "rozumět si", + "rozumí si", + "to get along", + "to understand each other" + ], + "meaning": "rozumět si" + }, + { + "prompt": "Wir verstehen uns alle sehr gut.", + "answers": [ + "všichni si moc dobře rozumíme", + "všichni si velmi dobře rozumíme", + "we all get along very well" + ], + "meaning": "Všichni si moc dobře rozumíme." + }, + { + "prompt": "der/die Verwandte, -n", + "answers": [ + "příbuzný", + "příbuzná", + "relative" + ], + "meaning": "příbuzný/příbuzná" + }, + { + "prompt": "die Wohngemeinschaft, -en", + "answers": [ + "společné bydlení", + "spolubydlení", + "flat share", + "shared apartment" + ], + "meaning": "společné bydlení (studentů)" + }, + { + "prompt": "die Männer-Wohngemeinschaft", + "answers": [ + "mužská domácnost", + "mužské spolubydlení", + "men's shared flat" + ], + "meaning": "mužská domácnost" + }, + { + "prompt": "zusammen", + "answers": [ + "spolu", + "dohromady", + "together" + ], + "meaning": "spolu, dohromady" + }, + { + "prompt": "der Zwilling, -e", + "answers": [ + "dvojče", + "dvojčata", + "twin", + "twins" + ], + "meaning": "dvojče" + } + ] + }, + { + "header": "Strana 35", + "items": [ + { + "prompt": "dein, deine, dein", + "answers": [ + "tvůj", + "tvoje", + "your" + ], + "meaning": "tvůj, tvoje, tvoje" + }, + { + "prompt": "euer, eure, euer", + "answers": [ + "váš", + "vaše", + "your" + ], + "meaning": "váš, vaše, vaše" + }, + { + "prompt": "ihr, ihre, ihr", + "answers": [ + "jejich", + "její", + "their", + "her" + ], + "meaning": "jejich" + }, + { + "prompt": "sein, seine, sein", + "answers": [ + "jeho", + "his" + ], + "meaning": "jeho" + } + ] + }, + { + "header": "Strana 36", + "items": [ + { + "prompt": "bitte", + "answers": [ + "prosím", + "please" + ], + "meaning": "prosím" + }, + { + "prompt": "dann", + "answers": [ + "tak", + "pak", + "then" + ], + "meaning": "tak, pak" + }, + { + "prompt": "dauern (Infinitiv)", + "answers": [ + "trvat", + "to last", + "to take" + ], + "meaning": "trvat" + }, + { + "prompt": "Die Vorbereitung dauert nicht so lange.", + "answers": [ + "příprava netrvá moc dlouho", + "příprava netrvá tak dlouho", + "the preparation doesn't take that long" + ], + "meaning": "Příprava netrvá moc dlouho." + }, + { + "prompt": "doch", + "answers": [ + "přece", + "přeci", + "ale ano", + "yet", + "but" + ], + "meaning": "přece" + }, + { + "prompt": "einladen (Infinitiv)", + "answers": [ + "pozvat", + "zvát", + "to invite" + ], + "meaning": "pozvat" + }, + { + "prompt": "Wir laden Oma und Opa ein.", + "answers": [ + "pozveme babičku a dědečka", + "zveme babičku a dědečka", + "we invite grandma and grandpa" + ], + "meaning": "Pozveme babičku a dědečka." + }, + { + "prompt": "die Feier, -n", + "answers": [ + "oslava", + "slavnost", + "celebration", + "party" + ], + "meaning": "oslava, slavnost" + }, + { + "prompt": "fragen (Infinitiv)", + "answers": [ + "ptát se", + "zeptat se", + "to ask" + ], + "meaning": "ptát se, zeptat se" + }, + { + "prompt": "Ich frage meine Schwester.", + "answers": [ + "zeptám se své sestry", + "ptám se své sestry", + "i ask my sister" + ], + "meaning": "Zeptám se své sestry." + }, + { + "prompt": "der Geburtstag, -e", + "answers": [ + "narozeniny", + "birthday" + ], + "meaning": "narozeniny" + }, + { + "prompt": "grillen (Infinitiv)", + "answers": [ + "grilovat", + "to grill", + "to barbecue" + ], + "meaning": "grilovat" + }, + { + "prompt": "die Idee, -n", + "answers": [ + "nápad", + "myšlenka", + "idea" + ], + "meaning": "nápad, myšlenka" + }, + { + "prompt": "die Köchin, -nen", + "answers": [ + "kuchařka", + "cook", + "chef" + ], + "meaning": "kuchařka" + }, + { + "prompt": "der Kuchen, -", + "answers": [ + "koláč", + "moučník", + "dort", + "cake" + ], + "meaning": "koláč, moučník" + }, + { + "prompt": "das Menü, -s", + "answers": [ + "menu", + "jídelní lístek" + ], + "meaning": "menu" + }, + { + "prompt": "5-Gänge-Menü", + "answers": [ + "pětichodové menu", + "pětchodové menu", + "five-course menu" + ], + "meaning": "pětichodové menu" + }, + { + "prompt": "ob", + "answers": [ + "zda", + "jestli", + "whether", + "if" + ], + "meaning": "zda, jestli" + }, + { + "prompt": "der Papa, -s", + "answers": [ + "tatínek", + "táta", + "dad", + "daddy" + ], + "meaning": "tatínek" + }, + { + "prompt": "die Party, -s", + "answers": [ + "party", + "večírek", + "oslava" + ], + "meaning": "party, večírek" + }, + { + "prompt": "das Restaurant", + "answers": [ + "restaurace", + "restaurant" + ], + "meaning": "restaurace" + }, + { + "prompt": "schrecklich", + "answers": [ + "strašný", + "hrozný", + "terrible", + "awful" + ], + "meaning": "strašný, hrozný" + }, + { + "prompt": "die Schwarzwälder Kirschtorte", + "answers": [ + "schwarzwaldský dort", + "black forest cake" + ], + "meaning": "Schwarzwaldský dort" + }, + { + "prompt": "singen (Infinitiv)", + "answers": [ + "zpívat", + "to sing" + ], + "meaning": "zpívat" + }, + { + "prompt": "Wir singen Happy Birthday.", + "answers": [ + "zpíváme happy birthday", + "we sing happy birthday" + ], + "meaning": "Zpíváme Happy Birthday." + }, + { + "prompt": "stimmen (Infinitiv)", + "answers": [ + "souhlasit", + "to be right", + "to be correct" + ], + "meaning": "souhlasit" + }, + { + "prompt": "Ja, stimmt.", + "answers": [ + "ano, správně", + "ano, souhlasí", + "yes, that's right", + "yes, right" + ], + "meaning": "Ano, správně." + }, + { + "prompt": "die Vorbereitung, -en", + "answers": [ + "příprava", + "preparation" + ], + "meaning": "příprava" + }, + { + "prompt": "wieder", + "answers": [ + "opět", + "zase", + "again" + ], + "meaning": "opět, zase" + }, + { + "prompt": "zu Hause", + "answers": [ + "doma", + "at home" + ], + "meaning": "doma" + } + ] + }, + { + "header": "Strana 37", + "items": [ + { + "prompt": "das Chamäleon, -s", + "answers": [ + "chameleon", + "chameleón" + ], + "meaning": "chameleon" + }, + { + "prompt": "der Goldfisch, -e", + "answers": [ + "zlatá rybka", + "karas", + "goldfish" + ], + "meaning": "zlatá rybka (karas)" + }, + { + "prompt": "der Hamster, -", + "answers": [ + "křeček", + "hamster" + ], + "meaning": "křeček" + }, + { + "prompt": "der Kanarienvogel, Kanarienvögel", + "answers": [ + "kanárek", + "kanár", + "canary" + ], + "meaning": "kanárek" + }, + { + "prompt": "das Kaninchen, -", + "answers": [ + "králík", + "rabbit" + ], + "meaning": "králík" + }, + { + "prompt": "die Katze, -n", + "answers": [ + "kočka", + "cat" + ], + "meaning": "kočka" + }, + { + "prompt": "das Meerschweinchen, -", + "answers": [ + "morče", + "guinea pig" + ], + "meaning": "morče" + }, + { + "prompt": "das Pferd, -e", + "answers": [ + "kůň", + "horse" + ], + "meaning": "kůň" + }, + { + "prompt": "die Schildkröte, -n", + "answers": [ + "želva", + "turtle", + "tortoise" + ], + "meaning": "želva" + }, + { + "prompt": "das Tier, -e", + "answers": [ + "zvíře", + "animal" + ], + "meaning": "zvíře" + } + ] + }, + { + "header": "Strana 38", + "items": [ + { + "prompt": "der Ausflug, Ausflüge", + "answers": [ + "výlet", + "trip", + "excursion" + ], + "meaning": "výlet" + }, + { + "prompt": "die Ausstellung, -en", + "answers": [ + "výstava", + "exhibition" + ], + "meaning": "výstava" + }, + { + "prompt": "die Burg, -en", + "answers": [ + "hrad", + "castle" + ], + "meaning": "hrad" + }, + { + "prompt": "cool", + "answers": [ + "cool", + "skvělý", + "super" + ], + "meaning": "cool, skvělý" + }, + { + "prompt": "es gibt", + "answers": [ + "je", + "existuje", + "there is", + "there are" + ], + "meaning": "je, existuje" + }, + { + "prompt": "das Hochzeitsfest, -e", + "answers": [ + "svatební party", + "svatební oslava", + "wedding party" + ], + "meaning": "svatební party" + }, + { + "prompt": "die Hochzeitstorte, -n", + "answers": [ + "svatební dort", + "wedding cake" + ], + "meaning": "svatební dort" + }, + { + "prompt": "nach", + "answers": [ + "do", + "to" + ], + "meaning": "do" + }, + { + "prompt": "Ich fahre nach Wien.", + "answers": [ + "jedu do vídně", + "i go to vienna", + "i'm going to vienna" + ], + "meaning": "Jedu do Vídně." + }, + { + "prompt": "nächster, nächste, nächstes", + "answers": [ + "příští", + "next" + ], + "meaning": "příští" + }, + { + "prompt": "nächsten Monat / nächste Woche / nächstes Jahr", + "answers": [ + "příští měsíc / příští týden / příští rok", + "příští měsíc, příští týden, příští rok", + "next month / next week / next year", + "next month, next week, next year" + ], + "meaning": "příští měsíc / příští týden / příští rok" + }, + { + "prompt": "das Schloss, Schlösser", + "answers": [ + "zámek", + "castle", + "palace" + ], + "meaning": "zámek" + }, + { + "prompt": "das Schwimmbad, Schwimmbäder", + "answers": [ + "koupaliště", + "plavecký bazén", + "swimming pool" + ], + "meaning": "koupaliště, plavecký bazén" + }, + { + "prompt": "der Schwimmbadbesuch, -e", + "answers": [ + "návštěva koupaliště", + "návštěva plaveckého bazénu", + "visit to the swimming pool" + ], + "meaning": "návštěva koupaliště, plaveckého bazénu" + }, + { + "prompt": "schwimmen (Infinitiv)", + "answers": [ + "plavat", + "to swim" + ], + "meaning": "plavat" + }, + { + "prompt": "Meine Mutter schwimmt gern.", + "answers": [ + "moje matka ráda plave", + "my mother likes swimming" + ], + "meaning": "Moje matka ráda plave." + }, + { + "prompt": "shoppen (Infinitiv)", + "answers": [ + "nakupovat", + "to shop" + ], + "meaning": "nakupovat" + }, + { + "prompt": "Wir gehen shoppen.", + "answers": [ + "jdeme nakupovat", + "jdem nakupovat", + "we go shopping" + ], + "meaning": "Jdeme nakupovat." + }, + { + "prompt": "das Sportevent, -s", + "answers": [ + "sportovní akce", + "sportovní událost", + "sports event" + ], + "meaning": "sportovní akce (zápas, závody)" + }, + { + "prompt": "der Vergnügungspark, -s", + "answers": [ + "zábavní park", + "amusement park", + "theme park" + ], + "meaning": "zábavní park" + }, + { + "prompt": "Wir gehen in den Vergnügungspark.", + "answers": [ + "jdeme do zábavního parku", + "we go to the amusement park" + ], + "meaning": "Jdeme do zábavního parku." + }, + { + "prompt": "wandern (Infinitiv)", + "answers": [ + "putovat", + "cestovat", + "to hike", + "to wander" + ], + "meaning": "putovat, cestovat" + }, + { + "prompt": "Ich wandere gern.", + "answers": [ + "rád(a) putuji", + "rád putuji", + "ráda putuji", + "i like hiking" + ], + "meaning": "Rád(a) putuji." + }, + { + "prompt": "die Woche, -n", + "answers": [ + "týden", + "week" + ], + "meaning": "týden" + }, + { + "prompt": "diese Woche", + "answers": [ + "tento týden", + "this week" + ], + "meaning": "tento týden" + }, + { + "prompt": "der Zoo, -s", + "answers": [ + "zoo", + "zoologická zahrada" + ], + "meaning": "zoo" + }, + { + "prompt": "der Zoobesuch, -e", + "answers": [ + "návštěva zoo", + "visit to the zoo" + ], + "meaning": "návštěva zoo" + } + ] + }, + { + "header": "Strana 39", + "items": [ + { + "prompt": "das Einkaufszentrum", + "answers": [ + "nákupní centrum", + "shopping centre", + "shopping mall", + "shopping center" + ], + "meaning": "nákupní centrum" + }, + { + "prompt": "die Inliner (mn. č.)", + "answers": [ + "inline brusle", + "inline bruslení", + "inliners" + ], + "meaning": "inline brusle" + }, + { + "prompt": "Sie fährt Inliner.", + "answers": [ + "(ona) jezdí na inline bruslích", + "jezdí na inline bruslích", + "she goes inline skating" + ], + "meaning": "(Ona) Jezdí na inline bruslích." + }, + { + "prompt": "der See, -n", + "answers": [ + "jezero", + "lake" + ], + "meaning": "jezero" + }, + { + "prompt": "Am Wochenende fahren wir an einen See.", + "answers": [ + "o víkendu pojedeme k jezeru", + "o víkendu jedeme k jezeru", + "at the weekend we drive to a lake" + ], + "meaning": "O víkendu pojedeme k (nějakému) jezeru." + }, + { + "prompt": "das Wochenende, -n", + "answers": [ + "víkend", + "weekend" + ], + "meaning": "víkend" + }, + { + "prompt": "am Wochenende", + "answers": [ + "o víkendu", + "on the weekend" + ], + "meaning": "o víkendu" + }, + { + "prompt": "dieses Wochenende", + "answers": [ + "tento víkend", + "this weekend" + ], + "meaning": "tento víkend" + }, + { + "prompt": "das Wochenendhaus, Wochenendhäuser", + "answers": [ + "chata", + "chalupa", + "víkendový dům", + "weekend house" + ], + "meaning": "chata, chalupa" + }, + { + "prompt": "Wir fahren dieses Wochenende ins Wochenendhaus.", + "answers": [ + "tento víkend jedeme na chatu", + "tento víkend jedeme na chalupu", + "this weekend we go to the cottage" + ], + "meaning": "Tento víkend jedeme na chatu." + } + ] + } + ] +} diff --git a/content/lessons/hardware/unit-01.json b/content/lessons/hardware/unit-01.json new file mode 100644 index 0000000..20dc348 --- /dev/null +++ b/content/lessons/hardware/unit-01.json @@ -0,0 +1,125 @@ +{ + "id": "unit-01", + "subject": "hardware", + "number": 1, + "titleKey": "hw_unit1", + "subtitleKey": "hw_unit1_sub", + "slides": [ + { + "kicker": "1 / 3 • Úvod", + "title": "Architektura počítače", + "tip": "Architektura popisuje, z jakých částí se počítač skládá a jak spolu spolupracují.", + "lines": [ + "Architektura počítače je základní model, podle kterého jsou počítače navrhovány.", + "Nejznámější model je Von Neumannovo schéma.", + "Používá se dodnes u většiny běžných počítačů." + ] + }, + { + "kicker": "2 / 3 • Osobnost", + "title": "John von Neumann", + "tip": "Tip: zapamatuj si jméno – podle něj se jmenuje celé schéma.", + "lines": [ + "John von Neumann byl americký matematik.", + "Pracoval na poli digitálních počítačů a operační teorie kvantové mechaniky.", + "Je autorem Von Neumannovy algebry.", + "Byl tvůrcem teorie her.", + "Podílel se na vývoji atomové a vodíkové bomby." + ] + }, + { + "kicker": "3 / 3 • Schéma", + "title": "Von Neumannovo schéma", + "tip": "ALU = aritmeticko-logická jednotka", + "lines": [ + "Von Neumannovo schéma má pět hlavních částí:", + "ALU – aritmeticko-logická jednotka (výpočty a logika)", + "Řadič – řídí činnost ostatních částí", + "Operační paměť – uchovává program i data", + "Vstupní jednotka – přivádí data do počítače", + "Výstupní jednotka – předává výsledky ven" + ] + } + ], + "tasks": [ + { + "number": 1, + "title": "Quiz", + "subtitleKey": "hw_quiz1_head", + "items": [ + { + "kind": "choice", + "prompt": "Kdo je autorem Von Neumannova schématu?", + "options": [ + "Alan Turing", + "John von Neumann", + "Bill Gates", + "Steve Jobs" + ], + "correct": 1, + "hint": "John von Neumann – americký matematik" + }, + { + "kind": "choice", + "prompt": "Čím byl John von Neumann?", + "options": [ + "Americký matematik", + "Německý fyzik", + "Anglický chemik", + "Francouzský lékař" + ], + "correct": 0, + "hint": "Americký matematik s objevy v digitálních počítačích" + }, + { + "kind": "choice", + "prompt": "Co znamená zkratka ALU?", + "options": [ + "Automatická logická síť", + "Aritmeticko-logická jednotka", + "Analogová linková sestava", + "Adresová listová sekce" + ], + "correct": 1, + "hint": "ALU = aritmeticko-logická jednotka" + }, + { + "kind": "choice", + "prompt": "Která část Von Neumannova schématu řídí ostatní části?", + "options": [ + "Operační paměť", + "Vstupní jednotka", + "Řadič", + "Výstupní jednotka" + ], + "correct": 2, + "hint": "Řadič řídí činnost ostatních částí" + }, + { + "kind": "choice", + "prompt": "Kde se podle Von Neumannova schématu uchovává program i data?", + "options": [ + "Jen na pevném disku", + "V operační paměti", + "Jen ve vstupní jednotce", + "Jen v ALU" + ], + "correct": 1, + "hint": "Operační paměť uchovává program i data" + }, + { + "kind": "choice", + "prompt": "Čím se John von Neumann také zabýval?", + "options": [ + "Jen malířstvím", + "Teorií her", + "Jen botanikou", + "Jen hudbou" + ], + "correct": 1, + "hint": "Byl tvůrcem teorie her" + } + ] + } + ] +} diff --git a/content/lessons/hardware/unit-02.json b/content/lessons/hardware/unit-02.json new file mode 100644 index 0000000..dc0c329 --- /dev/null +++ b/content/lessons/hardware/unit-02.json @@ -0,0 +1,177 @@ +{ + "id": "unit-02", + "subject": "hardware", + "number": 2, + "titleKey": "hw_unit2", + "subtitleKey": "hw_unit2_sub", + "slides": [ + { + "kicker": "1 / 6 • Přehled", + "title": "Historie počítačů", + "tip": "Generace se dělí podle klíčové technologie své doby.", + "lines": [ + "1. Předchůdci – do 30. let 19. století", + "2. Nultá generace – 1938–1944", + "3. První generace – 1944–1955", + "4. Druhá generace – 1955–1964", + "5. Třetí generace – 1964–1971", + "Další snímky shrnují znaky jednotlivých generací." + ] + }, + { + "kicker": "2 / 6 • 0. generace", + "title": "Počítače 0. generace (1938–1944)", + "tip": "Tip: počítačů bylo málo a často sloužily armádě.", + "lines": [ + "Existovalo jen několik počítačů na světě.", + "Většinou měly vojenský účel." + ] + }, + { + "kicker": "3 / 6 • 1. generace", + "title": "Počítače 1. generace (1944–1955)", + "tip": "Klíčový objev: elektronka", + "lines": [ + "Objev elektronky umožnil tuto generaci.", + "Ještě neexistoval software v dnešním smyslu.", + "Data a programy se zadávaly pomocí děrných štítků." + ] + }, + { + "kicker": "4 / 6 • 2. generace", + "title": "Počítače 2. generace (1955–1964)", + "tip": "Klíčový objev: tranzistor", + "lines": [ + "Objev tranzistoru nahradil elektronky.", + "Používala se hlavní externí paměť.", + "Počítače měly menší rozměry než v 1. generaci." + ] + }, + { + "kicker": "5 / 6 • 3. generace", + "title": "Počítače 3. generace (1964–1971)", + "tip": "Klíčový objev: integrovaný obvod", + "lines": [ + "Objev integrovaného obvodu.", + "Stále se používala hlavní externí paměť.", + "Rozměry počítačů se dál zmenšovaly." + ] + }, + { + "kicker": "6 / 6 • 4. generace", + "title": "Počítače 4. generace", + "tip": "Klíčové: programovatelné mikroprocesory", + "lines": [ + "Nastupují programovatelné mikroprocesory.", + "1972 – první počítačová hra", + "1973 – první disketa", + "1979 – první CD" + ] + } + ], + "tasks": [ + { + "number": 1, + "title": "Quiz", + "subtitleKey": "hw_quiz2_head", + "items": [ + { + "kind": "choice", + "prompt": "Kdy probíhala nultá generace počítačů?", + "options": [ + "1938–1944", + "1944–1955", + "1955–1964", + "1964–1971" + ], + "correct": 0, + "hint": "Nultá generace: 1938–1944" + }, + { + "kind": "choice", + "prompt": "Co bylo typické pro počítače 0. generace?", + "options": [ + "Byly v každé domácnosti", + "Jen několik kusů, často vojenský účel", + "Měly mikroprocesory", + "Používaly CD" + ], + "correct": 1, + "hint": "Jen několik počítačů, většinou vojenský účel" + }, + { + "kind": "choice", + "prompt": "Která technologie patří k 1. generaci?", + "options": [ + "Tranzistor", + "Elektronka", + "Integrovaný obvod", + "Mikroprocesor" + ], + "correct": 1, + "hint": "1. generace – objev elektronky" + }, + { + "kind": "choice", + "prompt": "Čím se zadávaly data v 1. generaci?", + "options": [ + "USB fleškou", + "Děrnými štítky", + "CD", + "Disketou" + ], + "correct": 1, + "hint": "1. generace – děrné štítky" + }, + { + "kind": "choice", + "prompt": "Která technologie patří k 2. generaci?", + "options": [ + "Elektronka", + "Tranzistor", + "Mikroprocesor", + "CD" + ], + "correct": 1, + "hint": "2. generace – objev tranzistoru" + }, + { + "kind": "choice", + "prompt": "Která technologie patří k 3. generaci?", + "options": [ + "Elektronka", + "Tranzistor", + "Integrovaný obvod", + "Disketa" + ], + "correct": 2, + "hint": "3. generace – integrovaný obvod" + }, + { + "kind": "choice", + "prompt": "Co je typické pro 4. generaci?", + "options": [ + "Jen děrné štítky", + "Programovatelné mikroprocesory", + "Jen vojenské použití", + "Žádný software" + ], + "correct": 1, + "hint": "4. generace – programovatelné mikroprocesory" + }, + { + "kind": "choice", + "prompt": "Kdy vznikla první počítačová hra (podle lekce)?", + "options": [ + "1964", + "1972", + "1973", + "1979" + ], + "correct": 1, + "hint": "1972 – první počítačová hra" + } + ] + } + ] +} diff --git a/content/lessons/hardware/unit-03.json b/content/lessons/hardware/unit-03.json new file mode 100644 index 0000000..748bf36 --- /dev/null +++ b/content/lessons/hardware/unit-03.json @@ -0,0 +1,86 @@ +{ + "id": "unit-03", + "subject": "hardware", + "number": 3, + "titleKey": "hw_unit3", + "subtitleKey": "hw_unit3_sub", + "slides": [ + { + "kicker": "1 / 2 • Bit", + "title": "Bit – nejmenší jednotka informace", + "tip": "Bit = binary digit (dvojková číslice)", + "lines": [ + "Bit je dvojková číslice – nabývá hodnoty 0 nebo 1.", + "Je to nejmenší zobrazitelná jednotka informace.", + "Z bitů se skládají větší jednotky (např. byte)." + ] + }, + { + "kicker": "2 / 2 • Byte", + "title": "Byte – adresovatelná jednotka paměti", + "tip": "Tip: 1 B = 8 b", + "lines": [ + "Byte je nejmenší adresovatelná jednotka paměti.", + "Počítač tedy paměť adresuje po bytech, ne po jednotlivých bitech.", + "Jeden byte obvykle obsahuje 8 bitů." + ] + } + ], + "tasks": [ + { + "number": 1, + "title": "Quiz", + "subtitleKey": "hw_quiz3_head", + "items": [ + { + "kind": "choice", + "prompt": "Co je bit?", + "options": [ + "Největší jednotka paměti", + "Dvojková číslice – nejmenší jednotka informace", + "Jen klávesa na klávesnici", + "Typ procesoru" + ], + "correct": 1, + "hint": "Bit = dvojková číslice, nejmenší jednotka informace" + }, + { + "kind": "choice", + "prompt": "Jaké hodnoty může nabývat bit?", + "options": [ + "Jen 0", + "Jen 1", + "0 nebo 1", + "0 až 255" + ], + "correct": 2, + "hint": "Bit nabývá hodnoty 0 nebo 1" + }, + { + "kind": "choice", + "prompt": "Co je byte?", + "options": [ + "Nejmenší adresovatelná jednotka paměti", + "Nejmenší zobrazitelná jednotka informace", + "Jen síťový kabel", + "Jen grafická karta" + ], + "correct": 0, + "hint": "Byte = nejmenší adresovatelná jednotka paměti" + }, + { + "kind": "choice", + "prompt": "Kolik bitů má obvykle jeden byte?", + "options": [ + "2", + "4", + "8", + "16" + ], + "correct": 2, + "hint": "1 B = 8 b" + } + ] + } + ] +} diff --git a/content/lessons/networks/unit-01.json b/content/lessons/networks/unit-01.json new file mode 100644 index 0000000..d5d33eb --- /dev/null +++ b/content/lessons/networks/unit-01.json @@ -0,0 +1,178 @@ +{ + "id": "unit-01", + "subject": "networks", + "number": 1, + "titleKey": "net_unit1", + "subtitleKey": "net_unit1_sub", + "slides": [ + { + "kicker": "1 / 4 • VLSM", + "title": "Podsíťování sítí", + "tip": "Tip: prefix /n = počet jedniček v masce. /24 = 255.255.255.0", + "lines": [ + "Cíl: rozdělit jednu IP síť na menší podsítě podle počtu uzlů.", + "Pamatuj si tři role adres v každém bloku:", + "síťová = první adresa bloku", + "broadcast = poslední adresa bloku", + "uzly = vše mezi nimi (síť + 1 až broadcast − 1)" + ] + }, + { + "kicker": "2 / 4 • Velikosti", + "title": "Jak velký blok potřebuji?", + "tip": "Počet bitů pro uzly h = log₂(velikost), prefix = 32 − h", + "lines": [ + "Pro X uzlů potřebuješ blok, do kterého se vejde X + 2 adresy (síť a broadcast).", + "Velikost bloku je vždy mocnina dvojky – vezmi nejmenší blok, který je větší nebo roven X + 2.", + "60 uzlů → 62 → blok 64 → /26", + "30 uzlů → 32 → blok 32 → /27", + "14 uzlů → 16 → blok 16 → /28", + "7 uzlů → 9 → blok 16 → /28" + ] + }, + { + "kicker": "3 / 4 • Postup", + "title": "Jak na to krok za krokem", + "tip": null, + "lines": [ + "1. Seřaď podsítě od největší po nejmenší.", + "2. Pro každou najdi potřebný prefix.", + "3. Začni na síťové adrese ze zadání.", + "4. Rozsah podsítě = od síťové adresy po broadcast.", + "5. Rozsah uzlů = síťová + 1 až broadcast − 1.", + "6. Posuň se hned za broadcast a pokračuj dál." + ] + }, + { + "kicker": "4 / 4 • Příklad", + "title": "Ukázka: 10.0.0.0/24", + "tip": "A: 60 uzlů, B: 30, C: 14, D: 7", + "lines": [ + "A → 10.0.0.0/26 uzly 10.0.0.1–10.0.0.62 broadcast 10.0.0.63", + "B → 10.0.0.64/27 uzly 10.0.0.65–10.0.0.94 broadcast 10.0.0.95", + "C → 10.0.0.96/28 uzly 10.0.0.97–10.0.0.110 broadcast 10.0.0.111", + "D → 10.0.0.112/28 uzly 10.0.0.113–10.0.0.126 broadcast 10.0.0.127" + ] + } + ], + "tasks": [ + { + "number": 1, + "title": "VLSM", + "subtitleKey": "net_ex1_title", + "items": [ + { + "kind": "subnet", + "scenario": "1.) Síť má adresu 10.0.0.0/24. Rozdělte ji do podsítí s následujícími požadavky:\n\nPodsíť A: 60 uzlů\nPodsíť B: 30 uzlů\nPodsíť C: 14 uzlů\nPodsíť D: 7 uzlů", + "solution": "A: 10.0.0.0/26 síť 10.0.0.0 uzly 10.0.0.1–10.0.0.62 broadcast 10.0.0.63\nB: 10.0.0.64/27 síť 10.0.0.64 uzly 10.0.0.65–10.0.0.94 broadcast 10.0.0.95\nC: 10.0.0.96/28 síť 10.0.0.96 uzly 10.0.0.97–10.0.0.110 broadcast 10.0.0.111\nD: 10.0.0.112/28 síť 10.0.0.112 uzly 10.0.0.113–10.0.0.126 broadcast 10.0.0.127", + "blocks": [ + { + "prefix": 26, + "network": "10.0.0.0", + "broadcast": "10.0.0.63", + "firstHost": "10.0.0.1", + "lastHost": "10.0.0.62" + }, + { + "prefix": 27, + "network": "10.0.0.64", + "broadcast": "10.0.0.95", + "firstHost": "10.0.0.65", + "lastHost": "10.0.0.94" + }, + { + "prefix": 28, + "network": "10.0.0.96", + "broadcast": "10.0.0.111", + "firstHost": "10.0.0.97", + "lastHost": "10.0.0.110" + }, + { + "prefix": 28, + "network": "10.0.0.112", + "broadcast": "10.0.0.127", + "firstHost": "10.0.0.113", + "lastHost": "10.0.0.126" + } + ] + }, + { + "kind": "subnet", + "scenario": "2.) Síť má adresu 172.16.0.0/16. Rozdělte ji do podsítí s následujícími požadavky:\n\nPodsíť A: 500 uzlů\nPodsíť B: 200 uzlů\nPodsíť C: 100 uzlů\nPodsíť D: 50 uzlů", + "solution": "A: 172.16.0.0/23 síť 172.16.0.0 uzly 172.16.0.1–172.16.1.254 broadcast 172.16.1.255\nB: 172.16.2.0/24 síť 172.16.2.0 uzly 172.16.2.1–172.16.2.254 broadcast 172.16.2.255\nC: 172.16.3.0/25 síť 172.16.3.0 uzly 172.16.3.1–172.16.3.126 broadcast 172.16.3.127\nD: 172.16.3.128/26 síť 172.16.3.128 uzly 172.16.3.129–172.16.3.190 broadcast 172.16.3.191", + "blocks": [ + { + "prefix": 23, + "network": "172.16.0.0", + "broadcast": "172.16.1.255", + "firstHost": "172.16.0.1", + "lastHost": "172.16.1.254" + }, + { + "prefix": 24, + "network": "172.16.2.0", + "broadcast": "172.16.2.255", + "firstHost": "172.16.2.1", + "lastHost": "172.16.2.254" + }, + { + "prefix": 25, + "network": "172.16.3.0", + "broadcast": "172.16.3.127", + "firstHost": "172.16.3.1", + "lastHost": "172.16.3.126" + }, + { + "prefix": 26, + "network": "172.16.3.128", + "broadcast": "172.16.3.191", + "firstHost": "172.16.3.129", + "lastHost": "172.16.3.190" + } + ] + }, + { + "kind": "subnet", + "scenario": "3.) Síť má adresu 192.168.10.0/24. Rozdělte ji do podsítí s následujícími požadavky:\n\nPodsíť A: 120 uzlů\nPodsíť B: 70 uzlů\nPodsíť C: 35 uzlů\nPodsíť D: 15 uzlů", + "solution": "Do sítě /24 se tyto požadavky nevejdou: A i B potřebují /25 (2 × 128 = 256 adres), na C a D už nezbude žádný blok. Při zachování velikostí by bylo nutné větší síť (např. /23).", + "blocks": null + }, + { + "kind": "subnet", + "scenario": "4.) Síť má adresu 192.168.2.0/25. Rozdělte ji do podsítí s následujícími požadavky:\n\nPodsíť A: 50 uzlů\nPodsíť B: 25 uzlů\nPodsíť C: 12 uzlů\nPodsíť D: 5 uzlů", + "solution": "A: 192.168.2.0/26 síť 192.168.2.0 uzly 192.168.2.1–192.168.2.62 broadcast 192.168.2.63\nB: 192.168.2.64/27 síť 192.168.2.64 uzly 192.168.2.65–192.168.2.94 broadcast 192.168.2.95\nC: 192.168.2.96/28 síť 192.168.2.96 uzly 192.168.2.97–192.168.2.110 broadcast 192.168.2.111\nD: 192.168.2.112/28 síť 192.168.2.112 uzly 192.168.2.113–192.168.2.126 broadcast 192.168.2.127", + "blocks": [ + { + "prefix": 26, + "network": "192.168.2.0", + "broadcast": "192.168.2.63", + "firstHost": "192.168.2.1", + "lastHost": "192.168.2.62" + }, + { + "prefix": 27, + "network": "192.168.2.64", + "broadcast": "192.168.2.95", + "firstHost": "192.168.2.65", + "lastHost": "192.168.2.94" + }, + { + "prefix": 28, + "network": "192.168.2.96", + "broadcast": "192.168.2.111", + "firstHost": "192.168.2.97", + "lastHost": "192.168.2.110" + }, + { + "prefix": 28, + "network": "192.168.2.112", + "broadcast": "192.168.2.127", + "firstHost": "192.168.2.113", + "lastHost": "192.168.2.126" + } + ] + } + ] + } + ] +} diff --git a/content/lessons/networks/unit-02.json b/content/lessons/networks/unit-02.json new file mode 100644 index 0000000..f13e8e7 --- /dev/null +++ b/content/lessons/networks/unit-02.json @@ -0,0 +1,173 @@ +{ + "id": "unit-02", + "subject": "networks", + "number": 2, + "titleKey": "net_unit2", + "subtitleKey": "net_unit2_sub", + "slides": [ + { + "kicker": "1 / 5 • Jednotky", + "title": "Bit, byte a počítačová síť", + "tip": "Tip: 1 B = 8 b → 2⁸ = 256 možných hodnot", + "lines": [ + "Bit (1 b): základní jednotka informace – 0 nebo 1.", + "0 = nevede proud, 1 = vede proud.", + "Byte (1 B): 1 B = 8 b, nabývá 256 hodnot.", + "Počítačová síť: propojení uzlů (PC a dalších prvků).", + "Vyžaduje hardwarové i softwarové prostředky." + ] + }, + { + "kicker": "2 / 5 • Propojení", + "title": "Trvalé, dočasné a důvody zapojení", + "tip": null, + "lines": [ + "Trvalé propojení: kabely – síť zůstává připojená i po přenosu.", + "Dočasné propojení: modem, Wi‑Fi – po přenosu se odpojuje.", + "Důvody zapojení do sítě:", + "sdílení dat (nutná podpora aplikací)", + "sdílení HW (tiskárny, disky) a SW (databáze)", + "vyšší spolehlivost, bezpečnost (přístupová práva)", + "komunikace (e‑mail, hlas)" + ] + }, + { + "kicker": "3 / 5 • Pojmy", + "title": "Terminologie sítí", + "tip": "Architektura = topologie + standard", + "lines": [ + "Uzel: jakékoli zařízení (stanice, server, aktivní prvek).", + "Topologie: způsob propojení (hvězda, kruh, sběrnice).", + "Standard: normy pro zpracování dat.", + "Architektura: topologie + standard." + ] + }, + { + "kicker": "4 / 5 • Rozlehlost", + "title": "WAN, MAN a LAN", + "tip": null, + "lines": [ + "WAN: rozsáhlé sítě (státy, kontinenty), např. internet.", + "MAN: městské sítě – propojují lokální sítě.", + "LAN: lokální sítě (budova), kabeláž v řádu km,", + "jednotná architektura." + ] + }, + { + "kicker": "5 / 5 • Uzly", + "title": "Server, stanice a peer‑to‑peer", + "tip": null, + "lines": [ + "Server: nadřazený, řídící, poskytuje služby, vyšší výkon.", + "Pracovní stanice: pro uživatele, jednodušší konfigurace.", + "Peer‑to‑peer: síť bez serverů – jen stanice,", + "které sdílejí data a tiskárny." + ] + } + ], + "tasks": [ + { + "number": 1, + "title": "Quiz", + "subtitleKey": "net_quiz2_head", + "items": [ + { + "kind": "choice", + "prompt": "Kolik bitů má jeden byte?", + "options": [ + "4", + "8", + "16", + "32" + ], + "correct": 1, + "hint": "1 B = 8 b" + }, + { + "kind": "choice", + "prompt": "Kolik různých hodnot nabývá jeden byte?", + "options": [ + "128", + "255", + "256", + "512" + ], + "correct": 2, + "hint": "2⁸ = 256 hodnot (0–255)" + }, + { + "kind": "choice", + "prompt": "Co je trvalé propojení sítě?", + "options": [ + "Modem", + "Wi‑Fi", + "Kabely", + "Bluetooth" + ], + "correct": 2, + "hint": "Kabely – síť zůstává připojená i po přenosu" + }, + { + "kind": "choice", + "prompt": "Co označuje zkratka WAN?", + "options": [ + "Lokální síť v budově", + "Městskou síť", + "Rozsáhlou síť (státy, kontinenty)", + "Bezdrátovou síť" + ], + "correct": 2, + "hint": "WAN = Wide Area Network, např. internet" + }, + { + "kind": "choice", + "prompt": "Co je topologie sítě?", + "options": [ + "Norma pro zpracování dat", + "Způsob propojení uzlů", + "Název serveru", + "Rychlost přenosu" + ], + "correct": 1, + "hint": "Např. hvězda, kruh, sběrnice" + }, + { + "kind": "choice", + "prompt": "Architektura sítě je:", + "options": [ + "Jen topologie", + "Jen standard", + "Topologie + standard", + "Pouze typ kabelu" + ], + "correct": 2, + "hint": "Architektura = topologie + standard" + }, + { + "kind": "choice", + "prompt": "Peer‑to‑peer síť znamená:", + "options": [ + "Síť s jedním výkonným serverem", + "Síť bez serverů – stanice sdílejí data", + "Jen internetovou síť", + "Síť pouze s tiskárnami" + ], + "correct": 1, + "hint": "Bez centrálního serveru – stanice si sdílejí data a tiskárny" + }, + { + "kind": "choice", + "prompt": "Server v síti je:", + "options": [ + "Jednoduchá stanice pro uživatele", + "Nadřazený uzel poskytující služby", + "Jen aktivní prvek kabeláže", + "Dočasné Wi‑Fi připojení" + ], + "correct": 1, + "hint": "Server řídí a poskytuje služby, má vyšší výkon" + } + ] + } + ] +} diff --git a/content/lessons/networks/unit-03.json b/content/lessons/networks/unit-03.json new file mode 100644 index 0000000..b0f3b00 --- /dev/null +++ b/content/lessons/networks/unit-03.json @@ -0,0 +1,161 @@ +{ + "id": "unit-03", + "subject": "networks", + "number": 3, + "titleKey": "net_unit3", + "subtitleKey": "net_unit3_sub", + "slides": [ + { + "kicker": "1 / 4 • Servery", + "title": "Role serverů a typy podle služby", + "tip": null, + "lines": [ + "Servery ověřují uživatele a povolují přístup.", + "Souborový server (fileserver): sdílení souborů.", + "Tiskový server: sdílení tiskáren.", + "Poštovní server: e‑mailové služby.", + "Databázový server: správa a přístup k databázím." + ] + }, + { + "kicker": "2 / 4 • Rozložení", + "title": "Centralizovaný a distribuovaný server", + "tip": null, + "lines": [ + "Centralizovaný: jeden server v síti.", + "Výpadek = nedostupnost služby.", + "Distribuovaný: více serverů, každý obsluhuje část.", + "Vyšší spolehlivost a rychlost." + ] + }, + { + "kicker": "3 / 4 • Využití", + "title": "Vyhrazený, nevyhrazený a mainframe", + "tip": null, + "lines": [ + "Nevyhrazený: slouží i jako stanice (levnější).", + "Vyhrazený: jen síťové služby – vysoký výkon a bezpečnost,", + "typicky v racku.", + "Mainframe: obří sálové počítače (IBM, Siemens),", + "stovky procesorů, OS Unix (AIX, Solaris).", + "Použití: banky a státní správa." + ] + }, + { + "kicker": "4 / 4 • Cloud", + "title": "Cloudové služby", + "tip": "Tip: SaaS = software jako služba", + "lines": [ + "Cloud: globální síť vzdálených serverů propojených internetem.", + "Fungují jako jeden systém: ukládání dat, SaaS,", + "streamování, webová pošta.", + "Přístup online z jakéhokoli zařízení." + ] + } + ], + "tasks": [ + { + "number": 1, + "title": "Quiz", + "subtitleKey": "net_quiz3_head", + "items": [ + { + "kind": "choice", + "prompt": "Co typicky dělají servery v síti?", + "options": [ + "Jen tisknou dokumenty", + "Ověřují uživatele a povolují přístup", + "Nahrazují kabely", + "Slouží jen jako Wi‑Fi" + ], + "correct": 1, + "hint": "Ověřují uživatele a povolují přístup ke službám" + }, + { + "kind": "choice", + "prompt": "Fileserver je:", + "options": [ + "Tiskový server", + "Poštovní server", + "Souborový server", + "Databázový server" + ], + "correct": 2, + "hint": "Fileserver = souborový server" + }, + { + "kind": "choice", + "prompt": "Centralizovaný server znamená:", + "options": [ + "Více serverů v síti", + "Jeden server – výpadek = nedostupnost služby", + "Server jen pro tisk", + "Cloud bez internetu" + ], + "correct": 1, + "hint": "Jeden server – při výpadku je služba nedostupná" + }, + { + "kind": "choice", + "prompt": "Distribuovaný model serverů nabízí hlavně:", + "options": [ + "Nižší spolehlivost", + "Vyšší spolehlivost a rychlost", + "Jen levnější kabely", + "Odstranění uživatelů" + ], + "correct": 1, + "hint": "Více serverů, každý obsluhuje část – vyšší spolehlivost" + }, + { + "kind": "choice", + "prompt": "Nevyhrazený server:", + "options": [ + "Slouží jen síťovým službám", + "Slouží i jako pracovní stanice", + "Je vždy mainframe", + "Nemůže ověřovat uživatele" + ], + "correct": 1, + "hint": "Slouží zároveň i jako pracovní stanice" + }, + { + "kind": "choice", + "prompt": "Vyhrazený server je určen:", + "options": [ + "Jen jako stanice uživatele", + "Jen pro síťové služby", + "Jen pro Bluetooth", + "Jen pro dočasné Wi‑Fi" + ], + "correct": 1, + "hint": "Jen síťové služby – vysoký výkon a bezpečnost, často v racku" + }, + { + "kind": "choice", + "prompt": "Mainframe se typicky používá:", + "options": [ + "Jen v domácnostech", + "V bankách a státní správě", + "Jen pro streamování hudby", + "Jen jako tiskárna" + ], + "correct": 1, + "hint": "Obří sálové počítače (IBM, Siemens) pro banky a státní správu" + }, + { + "kind": "choice", + "prompt": "Cloud a SaaS znamenají především:", + "options": [ + "Lokální síť bez internetu", + "Vzdálené servery a software jako služba online", + "Jen jeden kabel v budově", + "Peer‑to‑peer bez serverů" + ], + "correct": 1, + "hint": "SaaS = software jako služba, přístup online z libovolného zařízení" + } + ] + } + ] +} diff --git a/content/lessons/networks/unit-04.json b/content/lessons/networks/unit-04.json new file mode 100644 index 0000000..d7a9a97 --- /dev/null +++ b/content/lessons/networks/unit-04.json @@ -0,0 +1,156 @@ +{ + "id": "unit-04", + "subject": "networks", + "number": 4, + "titleKey": "net_unit4", + "subtitleKey": "net_unit4_sub", + "slides": [ + { + "kicker": "1 / 4 • Přenos", + "title": "Paralelní a sériový přenos", + "tip": null, + "lines": [ + "Paralelní: více bitů současně po více vodičích.", + "Problém: přeslechy (rušení) při delších kabelech", + "a vysokých frekvencích.", + "Sériový: bit po bitu po jednom vodiči.", + "Umožňuje vyšší frekvence i délky – celkově rychlejší." + ] + }, + { + "kicker": "2 / 4 • Časování", + "title": "Asynchronní přenos", + "tip": "Tip: Start-bit = 0, Stop-bit = 1", + "lines": [ + "Data se posílají v blocích (znaky 5–8 bitů).", + "Start-bit (0) synchronizuje začátek znaku.", + "Stop-bit (1) znak ukončuje." + ] + }, + { + "kicker": "3 / 4 • Časování", + "title": "Synchronní přenos", + "tip": null, + "lines": [ + "Řízeno společným hodinovým signálem.", + "Přesné časování mezi vysílačem a přijímačem." + ] + }, + { + "kicker": "4 / 4 • Zabezpečení", + "title": "Parita, checksum a CRC", + "tip": "Tip: CRC je nejbezpečnější z těchto tří metod", + "lines": [ + "Parita: nejslabší – přidá bit pro sudý/lichý počet jedniček.", + "Checksum: součet znaků jako dvojkových čísel.", + "CRC (cyklické kódy): nejbezpečnější,", + "počítá se z jednotlivých bitů v bloku." + ] + } + ], + "tasks": [ + { + "number": 1, + "title": "Quiz", + "subtitleKey": "net_quiz4_head", + "items": [ + { + "kind": "choice", + "prompt": "Paralelní přenos znamená:", + "options": [ + "Bit po bitu po jednom vodiči", + "Více bitů současně po více vodičích", + "Jen Wi‑Fi bez kabelů", + "Jen cloudové ukládání" + ], + "correct": 1, + "hint": "Více bitů najednou po více vodičích; problém jsou přeslechy" + }, + { + "kind": "choice", + "prompt": "Hlavní problém paralelního přenosu při delších kabelech je:", + "options": [ + "Absence serveru", + "Přeslechy (rušení)", + "Chybějící SaaS", + "Peer‑to‑peer režim" + ], + "correct": 1, + "hint": "Přeslechy vznikají při delších kabelech a vysokých frekvencích" + }, + { + "kind": "choice", + "prompt": "Sériový přenos je oproti paralelnímu celkově:", + "options": [ + "Vždy pomalejší", + "Rychlejší díky vyšším frekvencím a délkám", + "Jen pro tiskárny", + "Bez jakéhokoli kabelu" + ], + "correct": 1, + "hint": "Bit po bitu po jednom vodiči – vyšší frekvence i délky" + }, + { + "kind": "choice", + "prompt": "V asynchronním přenosu start-bit má hodnotu:", + "options": [ + "1", + "0", + "8", + "255" + ], + "correct": 1, + "hint": "Start-bit (0) synchronizuje, Stop-bit (1) ukončuje znak" + }, + { + "kind": "choice", + "prompt": "Synchronní přenos je řízen:", + "options": [ + "Jen stop-bitem", + "Společným hodinovým signálem", + "Jen paritou", + "Jen checksumem" + ], + "correct": 1, + "hint": "Řízeno společným hodinovým signálem a přesným časováním" + }, + { + "kind": "choice", + "prompt": "Nejslabší metoda zabezpečení z uvedených je:", + "options": [ + "CRC", + "Checksum", + "Parita", + "Mainframe" + ], + "correct": 2, + "hint": "Nejslabší – přidá bit pro sudý/lichý počet jedniček" + }, + { + "kind": "choice", + "prompt": "Checksum spočívá v:", + "options": [ + "Přidání start-bitu", + "Součtu znaků jako dvojkových čísel", + "Jen Wi‑Fi šifrování", + "Výměně kabelů" + ], + "correct": 1, + "hint": "Součet znaků jako dvojkových čísel" + }, + { + "kind": "choice", + "prompt": "CRC (cyklické kódy) je z uvedených metod:", + "options": [ + "Nejslabší", + "Stejně slabá jako parita", + "Nejbezpečnější", + "Jen pro paralelní přenos" + ], + "correct": 2, + "hint": "Nejbezpečnější – počítá se z jednotlivých bitů v bloku" + } + ] + } + ] +} diff --git a/content/lessons/networks/unit-05.json b/content/lessons/networks/unit-05.json new file mode 100644 index 0000000..abd0577 --- /dev/null +++ b/content/lessons/networks/unit-05.json @@ -0,0 +1,156 @@ +{ + "id": "unit-05", + "subject": "networks", + "number": 5, + "titleKey": "net_unit5", + "subtitleKey": "net_unit5_sub", + "slides": [ + { + "kicker": "1 / 4 • Signál", + "title": "Analogový a digitální signál", + "tip": "Tip: f = 1/T", + "lines": [ + "Analogový: spojitý, nabývá libovolných hodnot.", + "Digitální: diskrétní, hodnoty 0 a 1.", + "Parametry signálu:", + "perioda T, frekvence f = 1/T,", + "amplituda A, fázový posun Φ." + ] + }, + { + "kicker": "2 / 4 • Modulace", + "title": "Základní typy modulace", + "tip": "Modulace = přenos v přeloženém pásmu", + "lines": [ + "AM – amplitudová modulace.", + "FM – frekvenční modulace.", + "PM – fázová modulace." + ] + }, + { + "kicker": "3 / 4 • Kombinované", + "title": "QPSK a 256-QAM", + "tip": null, + "lines": [ + "QPSK: 2 bity v jednom prvku (symbolu).", + "256-QAM: 8 bitů v jednom prvku." + ] + }, + { + "kicker": "4 / 4 • Rychlosti", + "title": "Modulační, přenosová a šířka pásma", + "tip": null, + "lines": [ + "Modulační rychlost: počet změn signálu za sekundu [Baud, Bd/s].", + "Přenosová rychlost: velikost přenesené informace [bit/s, bps].", + "Šířka pásma: rozsah frekvencí –", + "určuje maximální možnou rychlost." + ] + } + ], + "tasks": [ + { + "number": 1, + "title": "Quiz", + "subtitleKey": "net_quiz5_head", + "items": [ + { + "kind": "choice", + "prompt": "Digitální signál nabývá:", + "options": [ + "Libovolných spojitých hodnot", + "Diskrétních hodnot 0 a 1", + "Jen frekvence FM", + "Jen šířky pásma" + ], + "correct": 1, + "hint": "Analogový je spojitý, digitální má diskrétní hodnoty 0 a 1" + }, + { + "kind": "choice", + "prompt": "Frekvence f je:", + "options": [ + "Stejná jako amplituda", + "f = 1/T", + "Jen fázový posun", + "Počet bitů v QPSK" + ], + "correct": 1, + "hint": "Frekvence f = 1/T, kde T je perioda" + }, + { + "kind": "choice", + "prompt": "AM, FM a PM jsou:", + "options": [ + "Typy kabelů", + "Základní typy modulace", + "Jen CRC metody", + "Typy serverů" + ], + "correct": 1, + "hint": "AM mění amplitudu, FM frekvenci, PM fázi" + }, + { + "kind": "choice", + "prompt": "QPSK přenáší v jednom prvku:", + "options": [ + "1 bit", + "2 bity", + "8 bitů", + "256 bitů" + ], + "correct": 1, + "hint": "QPSK nese 2 bity v prvku, 256-QAM nese 8 bitů" + }, + { + "kind": "choice", + "prompt": "256-QAM přenáší v jednom prvku:", + "options": [ + "2 bity", + "4 bity", + "8 bitů", + "16 bitů" + ], + "correct": 2, + "hint": "QPSK nese 2 bity v prvku, 256-QAM nese 8 bitů" + }, + { + "kind": "choice", + "prompt": "Modulační rychlost se udává v:", + "options": [ + "Jen bit/s", + "Baud (Bd/s)", + "Jen metrech", + "Jen hertzech amplitudy" + ], + "correct": 1, + "hint": "Modulační rychlost = počet změn signálu za sekundu [Bd/s]" + }, + { + "kind": "choice", + "prompt": "Přenosová rychlost vyjadřuje:", + "options": [ + "Počet změn signálu za sekundu", + "Velikost přenesené informace [bit/s]", + "Jen fázový posun", + "Jen periodu T" + ], + "correct": 1, + "hint": "Přenosová rychlost = množství informace za sekundu [bit/s]" + }, + { + "kind": "choice", + "prompt": "Šířka pásma určuje:", + "options": [ + "Jen barvu kabelu", + "Maximální možnou přenosovou rychlost", + "Jen počet serverů", + "Jen start-bit" + ], + "correct": 1, + "hint": "Šířka pásma určuje maximální možnou přenosovou rychlost" + } + ] + } + ] +} diff --git a/content/lessons/networks/unit-06.json b/content/lessons/networks/unit-06.json new file mode 100644 index 0000000..b342102 --- /dev/null +++ b/content/lessons/networks/unit-06.json @@ -0,0 +1,139 @@ +{ + "id": "unit-06", + "subject": "networks", + "number": 6, + "titleKey": "net_unit6", + "subtitleKey": "net_unit6_sub", + "slides": [ + { + "kicker": "1 / 4 • Spoj", + "title": "Datový spoj", + "tip": null, + "lines": [ + "Datový spoj umožňuje výměnu informací.", + "Může být dvoubodový nebo vícebodový." + ] + }, + { + "kicker": "2 / 4 • Cesta", + "title": "Přenosová cesta", + "tip": null, + "lines": [ + "Přenosová cesta je fyzické médium.", + "Příklady: metalické nebo optické kabely,", + "mikrovlny, družice." + ] + }, + { + "kicker": "3 / 4 • Kanál a okruh", + "title": "Přenosový kanál a okruh", + "tip": "Tip: okruh = dva kanály → obousměrný přenos", + "lines": [ + "Přenosový kanál: jednosměrný souhrn prostředků pro spojení.", + "Okruh: tvořen dvěma kanály – umožňuje obousměrný přenos." + ] + }, + { + "kicker": "4 / 4 • Trunking", + "title": "Spojování cest", + "tip": null, + "lines": [ + "Trunking spojuje více cest do jednoho okruhu.", + "Cíl: zvýšení šířky pásma." + ] + } + ], + "tasks": [ + { + "number": 1, + "title": "Quiz", + "subtitleKey": "net_quiz6_head", + "items": [ + { + "kind": "choice", + "prompt": "Datový spoj slouží k:", + "options": [ + "Jen měření amplitudy", + "Výměně informací", + "Jen FM modulaci", + "Jen tisku dokumentů" + ], + "correct": 1, + "hint": "Datový spoj umožňuje výměnu informací mezi uzly" + }, + { + "kind": "choice", + "prompt": "Přenosová cesta je:", + "options": [ + "Jen softwarová služba", + "Fyzické médium přenosu", + "Jen CRC kód", + "Jen peer‑to‑peer účet" + ], + "correct": 1, + "hint": "Fyzické médium: kabely, mikrovlny nebo družice" + }, + { + "kind": "choice", + "prompt": "Mezi přenosová média patří:", + "options": [ + "Jen parita", + "Kabely, mikrovlny a družice", + "Jen Baud", + "Jen start-bit" + ], + "correct": 1, + "hint": "Fyzické médium: kabely, mikrovlny nebo družice" + }, + { + "kind": "choice", + "prompt": "Přenosový kanál je:", + "options": [ + "Obousměrný vždy", + "Jednosměrný souhrn prostředků pro spojení", + "Jen název serveru", + "Jen typ QPSK" + ], + "correct": 1, + "hint": "Kanál je jednosměrný souhrn prostředků pro spojení" + }, + { + "kind": "choice", + "prompt": "Okruh vzniká:", + "options": [ + "Z jednoho kanálu", + "Ze dvou kanálů pro obousměrný přenos", + "Jen z parity", + "Jen z Wi‑Fi hesla" + ], + "correct": 1, + "hint": "Okruh tvoří dva kanály pro obousměrný přenos" + }, + { + "kind": "choice", + "prompt": "Trunking znamená:", + "options": [ + "Odpojení všech kabelů", + "Spojení více cest do jednoho okruhu", + "Jen asynchronní stop-bit", + "Jen digitální 0 a 1" + ], + "correct": 1, + "hint": "Trunking spojuje více cest do jednoho okruhu" + }, + { + "kind": "choice", + "prompt": "Hlavní cíl trunkingu je:", + "options": [ + "Snížit šířku pásma", + "Zvýšit šířku pásma", + "Zrušit kanály", + "Nahradit mainframe" + ], + "correct": 1, + "hint": "Trunking zvyšuje šířku pásma spojením cest" + } + ] + } + ] +} diff --git a/content/lessons/networks/unit-07.json b/content/lessons/networks/unit-07.json new file mode 100644 index 0000000..e4a5950 --- /dev/null +++ b/content/lessons/networks/unit-07.json @@ -0,0 +1,152 @@ +{ + "id": "unit-07", + "subject": "networks", + "number": 7, + "titleKey": "net_unit7", + "subtitleKey": "net_unit7_sub", + "slides": [ + { + "kicker": "1 / 4 • Multiplex", + "title": "Rozdělení kanálu", + "tip": null, + "lines": [ + "Multiplex: rozdělení jednoho kanálu", + "na více logických podkanálů." + ] + }, + { + "kicker": "2 / 4 • Typy", + "title": "FDM, TDM a STDM", + "tip": null, + "lines": [ + "FDM (frekvenční): každému kanálu část frekvenčního pásma.", + "TDM (časový): každému kanálu vyhrazený časový slot.", + "STDM (statistický): kapacita dle potřeby (paketový přenos),", + "negarantuje 100% dostupnost." + ] + }, + { + "kicker": "3 / 4 • Směry", + "title": "Simplex, poloduplex a duplex", + "tip": null, + "lines": [ + "Simplex: jen jeden směr (např. optické vlákno).", + "Poloduplex (half-duplex): oběma směry, ne současně.", + "Duplex (full-duplex): oběma směry současně." + ] + }, + { + "kicker": "4 / 4 • Agregace", + "title": "Sdílení kapacity", + "tip": null, + "lines": [ + "Agregace: sdílení kapacity kanálu více uživateli." + ] + } + ], + "tasks": [ + { + "number": 1, + "title": "Quiz", + "subtitleKey": "net_quiz7_head", + "items": [ + { + "kind": "choice", + "prompt": "Multiplex znamená:", + "options": [ + "Jen jeden uživatel na kanál", + "Rozdělení jednoho kanálu na více logických podkanálů", + "Jen CRC kontrolu", + "Jen digitální 0 a 1" + ], + "correct": 1, + "hint": "Multiplex dělí jeden kanál na více logických podkanálů" + }, + { + "kind": "choice", + "prompt": "FDM přiděluje každému kanálu:", + "options": [ + "Časový slot", + "Část frekvenčního pásma", + "Jen start-bit", + "Jen mainframe" + ], + "correct": 1, + "hint": "FDM: každému kanálu část frekvenčního pásma" + }, + { + "kind": "choice", + "prompt": "TDM přiděluje každému kanálu:", + "options": [ + "Část frekvenčního pásma", + "Vyhrazený časový slot", + "Jen SaaS účet", + "Jen paritu" + ], + "correct": 1, + "hint": "TDM: každému kanálu vyhrazený časový slot" + }, + { + "kind": "choice", + "prompt": "STDM:", + "options": [ + "Garantuje vždy 100% dostupnost", + "Přiděluje kapacitu dle potřeby a negarantuje 100%", + "Je jen simplex", + "Je jen trunking kabelů" + ], + "correct": 1, + "hint": "STDM přiděluje kapacitu dle potřeby, negarantuje 100 %" + }, + { + "kind": "choice", + "prompt": "Simplex umožňuje přenos:", + "options": [ + "Oběma směry současně", + "Jen jedním směrem", + "Oběma směry, ale ne současně", + "Jen přes CRC" + ], + "correct": 1, + "hint": "Simplex = jen jeden směr přenosu" + }, + { + "kind": "choice", + "prompt": "Half-duplex znamená:", + "options": [ + "Jen jeden směr", + "Oběma směry, ne současně", + "Oběma směry současně", + "Jen FDM" + ], + "correct": 1, + "hint": "Half-duplex = oběma směry, ale ne současně" + }, + { + "kind": "choice", + "prompt": "Full-duplex znamená:", + "options": [ + "Jen jeden směr", + "Oběma směry, ne současně", + "Oběma směry současně", + "Jen STDM" + ], + "correct": 2, + "hint": "Full-duplex = oběma směry současně" + }, + { + "kind": "choice", + "prompt": "Agregace je:", + "options": [ + "Sdílení kapacity kanálu více uživateli", + "Jen fázová modulace", + "Jen dvoubodový spoj", + "Jen stop-bit" + ], + "correct": 0, + "hint": "Agregace = sdílení kapacity kanálu více uživateli" + } + ] + } + ] +} diff --git a/content/lessons/networks/unit-08.json b/content/lessons/networks/unit-08.json new file mode 100644 index 0000000..892c510 --- /dev/null +++ b/content/lessons/networks/unit-08.json @@ -0,0 +1,153 @@ +{ + "id": "unit-08", + "subject": "networks", + "number": 8, + "titleKey": "net_unit8", + "subtitleKey": "net_unit8_sub", + "slides": [ + { + "kicker": "1 / 4 • Okruhy", + "title": "Přepojování okruhů", + "tip": "Tip: spojovaná služba – jako telefon", + "lines": [ + "Cesta se vytýčí předem (spojovaná služba).", + "Kapacita je garantována.", + "Přenos probíhá v reálném čase." + ] + }, + { + "kicker": "2 / 4 • Pakety", + "title": "Přepojování paketů", + "tip": null, + "lines": [ + "Data se dělí na pakety s adresami.", + "Každý paket může jít jinou cestou." + ] + }, + { + "kicker": "3 / 4 • Hodnocení", + "title": "Výhody a nevýhody paketů", + "tip": null, + "lines": [ + "Výhody: reakce na zátěž, lepší využití kapacity.", + "Nevýhody: negarantuje pořadí ani plynulost.", + "Nevhodné pro video v reálném čase." + ] + }, + { + "kicker": "4 / 4 • Virtuální", + "title": "Virtuální spoje", + "tip": null, + "lines": [ + "Cesta je vytýčena předem,", + "ale prostředky se využívají jen při průchodu paketu.", + "Výsledek: zrychlení datagramů." + ] + } + ], + "tasks": [ + { + "number": 1, + "title": "Quiz", + "subtitleKey": "net_quiz8_head", + "items": [ + { + "kind": "choice", + "prompt": "Přepojování okruhů znamená:", + "options": [ + "Pakety jdou vždy jinou cestou", + "Cesta se vytýčí předem a kapacita je garantována", + "Jen FDM multiplex", + "Jen half-duplex" + ], + "correct": 1, + "hint": "Cesta se vytýčí předem, kapacita je garantována" + }, + { + "kind": "choice", + "prompt": "Přepojování okruhů je vhodné pro:", + "options": [ + "Jen náhodné datagramy bez cesty", + "Přenos v reálném čase (jako telefon)", + "Jen CRC", + "Jen peer‑to‑peer tisk" + ], + "correct": 1, + "hint": "Cesta se vytýčí předem, kapacita je garantována" + }, + { + "kind": "choice", + "prompt": "Při přepojování paketů:", + "options": [ + "Vždy existuje jedna pevná cesta", + "Každý paket může jít jinou cestou", + "Kapacita je vždy garantována", + "Neexistují adresy" + ], + "correct": 1, + "hint": "Data se dělí na pakety, každý může jít jinou cestou" + }, + { + "kind": "choice", + "prompt": "Výhoda přepojování paketů je:", + "options": [ + "Garantované pořadí vždy", + "Reakce na zátěž a využití kapacity", + "Jen simplex", + "Jen trunking" + ], + "correct": 1, + "hint": "Výhody: reakce na zátěž a lepší využití kapacity" + }, + { + "kind": "choice", + "prompt": "Nevýhoda přepojování paketů je:", + "options": [ + "Nereaguje na zátěž", + "Negarantuje pořadí ani plynulost", + "Nelze použít adresy", + "Vždy blokuje kanál jako telefon" + ], + "correct": 1, + "hint": "Negarantuje pořadí ani plynulost – nevhodné pro živé video" + }, + { + "kind": "choice", + "prompt": "Pro video v reálném čase je přepojování paketů:", + "options": [ + "Ideální vždy", + "Spíše nevhodné kvůli plynulosti", + "Jediná možná metoda", + "Stejné jako AM modulace" + ], + "correct": 1, + "hint": "Negarantuje pořadí ani plynulost – nevhodné pro živé video" + }, + { + "kind": "choice", + "prompt": "Virtuální spoje:", + "options": [ + "Nemají předem žádnou cestu", + "Mají cestu předem, prostředky jen při průchodu paketu", + "Jsou jen FDM", + "Jsou jen parita" + ], + "correct": 1, + "hint": "Cesta je předem, prostředky se použijí jen při průchodu paketu" + }, + { + "kind": "choice", + "prompt": "Virtuální spoje slouží hlavně k:", + "options": [ + "Zrušení paketů", + "Zrychlení datagramů", + "Jen simplexu", + "Jen analogovému signálu" + ], + "correct": 1, + "hint": "Virtuální spoje zrychlují přenos datagramů" + } + ] + } + ] +} diff --git a/content/lessons/networks/unit-09.json b/content/lessons/networks/unit-09.json new file mode 100644 index 0000000..0f2a28f --- /dev/null +++ b/content/lessons/networks/unit-09.json @@ -0,0 +1,151 @@ +{ + "id": "unit-09", + "subject": "networks", + "number": 9, + "titleKey": "net_unit9", + "subtitleKey": "net_unit9_sub", + "slides": [ + { + "kicker": "1 / 4 • Proč", + "title": "Standardizace a dekompozice", + "tip": null, + "lines": [ + "Standardizace zajišťuje kompatibilitu mezi výrobci.", + "Dekompozice: rozklad složitého problému přenosu na vrstvy." + ] + }, + { + "kicker": "2 / 4 • Vrstvy", + "title": "Komunikace mezi vrstvami", + "tip": "Tip: SAP = Service Access Point", + "lines": [ + "Vrstvy komunikují jen se sousedy přes rozhraní (SAP)." + ] + }, + { + "kicker": "3 / 4 • Protokol", + "title": "Pravidla komunikace", + "tip": null, + "lines": [ + "Protokol: pravidla komunikace mezi stejnými vrstvami", + "na různých uzlech." + ] + }, + { + "kicker": "4 / 4 • Jednotky", + "title": "Hlavičky a PDU", + "tip": null, + "lines": [ + "Každá vrstva přidá k datům hlavičku (header).", + "Rámec – linková vrstva.", + "Paket – síťová vrstva.", + "Segment – transportní vrstva." + ] + } + ], + "tasks": [ + { + "number": 1, + "title": "Quiz", + "subtitleKey": "net_quiz9_head", + "items": [ + { + "kind": "choice", + "prompt": "Standardizace v sítích především:", + "options": [ + "Zvyšuje nekompatibilitu", + "Zajišťuje kompatibilitu mezi výrobci", + "Ruší protokoly", + "Nahrazuje kabely" + ], + "correct": 1, + "hint": "Standardizace zajišťuje kompatibilitu mezi výrobci" + }, + { + "kind": "choice", + "prompt": "Dekompozice znamená:", + "options": [ + "Spojení všeho do jedné vrstvy", + "Rozklad složitého přenosu na vrstvy", + "Jen FDM", + "Jen CRC" + ], + "correct": 1, + "hint": "Dekompozice rozkládá přenos na jednotlivé vrstvy" + }, + { + "kind": "choice", + "prompt": "Vrstvy komunikují:", + "options": [ + "Se všemi vrstvami najednou", + "Jen se sousedy přes rozhraní (SAP)", + "Jen přes satelit", + "Jen bez protokolu" + ], + "correct": 1, + "hint": "Vrstvy komunikují jen se sousedy přes rozhraní SAP" + }, + { + "kind": "choice", + "prompt": "Protokol je:", + "options": [ + "Fyzický kabel", + "Pravidla komunikace mezi stejnými vrstvami", + "Jen amplituda signálu", + "Jen tiskový server" + ], + "correct": 1, + "hint": "Protokol = pravidla mezi stejnými vrstvami na různých uzlech" + }, + { + "kind": "choice", + "prompt": "Každá vrstva k datům typicky přidá:", + "options": [ + "Jen stop-bit", + "Hlavičku (header)", + "Jen šířku pásma", + "Jen mainframe" + ], + "correct": 1, + "hint": "Každá vrstva přidává k datům hlavičku (header)" + }, + { + "kind": "choice", + "prompt": "Jednotka linkové vrstvy se nazývá:", + "options": [ + "Segment", + "Paket", + "Rámec", + "Baud" + ], + "correct": 2, + "hint": "Rámec = linková, paket = síťová, segment = transportní" + }, + { + "kind": "choice", + "prompt": "Jednotka síťové vrstvy se nazývá:", + "options": [ + "Rámec", + "Paket", + "Segment", + "Simplex" + ], + "correct": 1, + "hint": "Rámec = linková, paket = síťová, segment = transportní" + }, + { + "kind": "choice", + "prompt": "Jednotka transportní vrstvy se nazývá:", + "options": [ + "Rámec", + "Paket", + "Segment", + "Trunk" + ], + "correct": 2, + "hint": "Rámec = linková, paket = síťová, segment = transportní" + } + ] + } + ] +} diff --git a/content/lessons/networks/unit-10.json b/content/lessons/networks/unit-10.json new file mode 100644 index 0000000..3a1e981 --- /dev/null +++ b/content/lessons/networks/unit-10.json @@ -0,0 +1,120 @@ +{ + "id": "unit-10", + "subject": "networks", + "number": 10, + "titleKey": "net_unit10", + "subtitleKey": "net_unit10_sub", + "slides": [ + { + "kicker": "1 / 3 • ISO/OSI", + "title": "Sedmivrstvý model", + "tip": null, + "lines": [ + "ISO/OSI: 7vrstvý model.", + "Je univerzální – popisuje komunikaci obecně.", + "V praxi je ale pomalejší: každá vrstva řešila spolehlivost." + ] + }, + { + "kicker": "2 / 3 • TCP/IP", + "title": "Praktická architektura", + "tip": null, + "lines": [ + "TCP/IP: architektura, která zvítězila v praxi.", + "Vycházela ze skutečných potřeb sítí.", + "Spolehlivost řeší až vyšší vrstvy." + ] + }, + { + "kicker": "3 / 3 • Srovnání", + "title": "Proč zvítězil TCP/IP", + "tip": "Tip: méně režie na nižších vrstvách = rychlejší provoz", + "lines": [ + "ISO/OSI: teoretický, univerzální, těžší a pomalejší.", + "TCP/IP: praktický, jednodušší dělení odpovědností.", + "Proto se TCP/IP stal základem dnešního internetu." + ] + } + ], + "tasks": [ + { + "number": 1, + "title": "Quiz", + "subtitleKey": "net_quiz10_head", + "items": [ + { + "kind": "choice", + "prompt": "Model ISO/OSI má:", + "options": [ + "4 vrstvy", + "5 vrstev", + "7 vrstev", + "10 vrstev" + ], + "correct": 2, + "hint": "ISO/OSI má 7 vrstev a je univerzální model" + }, + { + "kind": "choice", + "prompt": "ISO/OSI je především:", + "options": [ + "Jen typ kabelu", + "Univerzální referenční model", + "Jen tiskový server", + "Jen FDM" + ], + "correct": 1, + "hint": "ISO/OSI má 7 vrstev a je univerzální model" + }, + { + "kind": "choice", + "prompt": "Proč je ISO/OSI v praxi pomalejší?", + "options": [ + "Nemá žádné vrstvy", + "Každá vrstva řešila spolehlivost", + "Nepoužívá protokoly", + "Nemá SAP" + ], + "correct": 1, + "hint": "V praxi je ISO/OSI pomalejší – spolehlivost řeší každá vrstva" + }, + { + "kind": "choice", + "prompt": "TCP/IP v praxi:", + "options": [ + "Prohrál proti ISO/OSI", + "Zvítězil jako praktická architektura", + "Je jen analogový signál", + "Je jen half-duplex" + ], + "correct": 1, + "hint": "TCP/IP zvítězil, protože vycházel ze skutečných potřeb" + }, + { + "kind": "choice", + "prompt": "TCP/IP vycházel z:", + "options": [ + "Jen teoretických schémat bez praxe", + "Skutečných potřeb sítí", + "Jen parity", + "Jen trunkingu" + ], + "correct": 1, + "hint": "TCP/IP zvítězil, protože vycházel ze skutečných potřeb" + }, + { + "kind": "choice", + "prompt": "V TCP/IP spolehlivost řeší:", + "options": [ + "Vždy jen fyzická vrstva", + "Až vyšší vrstvy", + "Jen metalické kabely", + "Jen mainframe" + ], + "correct": 1, + "hint": "V TCP/IP řeší spolehlivost až vyšší vrstvy" + } + ] + } + ] +} diff --git a/content/lessons/networks/unit-11.json b/content/lessons/networks/unit-11.json new file mode 100644 index 0000000..f50babe --- /dev/null +++ b/content/lessons/networks/unit-11.json @@ -0,0 +1,181 @@ +{ + "id": "unit-11", + "subject": "networks", + "number": 11, + "titleKey": "net_unit11", + "subtitleKey": "net_unit11_sub", + "slides": [ + { + "kicker": "1 / 8 • Přehled", + "title": "Tři skupiny vrstev", + "tip": "Tip: přenos → přizpůsobení → aplikace", + "lines": [ + "Vrstvy orientované na přenos: fyzická, spojová, síťová.", + "Přizpůsobovací vrstva: transportní.", + "Vrstvy orientované na aplikace: relační, prezentační,", + "aplikační." + ] + }, + { + "kicker": "2 / 8 • Fyzická", + "title": "Přenos bitů", + "tip": null, + "lines": [ + "Přenos bitů po médiu.", + "Definuje napětí, kabely, konektory, kódování a modulaci.", + "Řeší také duplex / simplex." + ] + }, + { + "kicker": "3 / 8 • Spojová", + "title": "Rámce a MAC", + "tip": "Tip: podvrstvy MAC (přístup k médiu) a LLC (logické řízení)", + "lines": [ + "Tvorba rámců a fyzické (MAC) adresy.", + "Kontrola chyb (CRC) a řízení toku mezi sousedními uzly.", + "Podvrstvy: MAC a LLC." + ] + }, + { + "kicker": "4 / 8 • Síťová", + "title": "Směrování paketů", + "tip": null, + "lines": [ + "Směrování (routing) paketů.", + "Funguje i v sítích bez přímého spojení mezi uzly." + ] + }, + { + "kicker": "5 / 8 • Transportní", + "title": "Segmenty end-to-end", + "tip": "Tip: v routerech transportní vrstva není", + "lines": [ + "Rozklad zpráv na segmenty a jejich zpětné složení.", + "Kontrola pořadí a náprava chyb.", + "Existuje jen v koncových uzlech – není v routerech." + ] + }, + { + "kicker": "6 / 8 • Relační", + "title": "Relace a dialog", + "tip": null, + "lines": [ + "Navazuje, udržuje a ukončuje relace.", + "Řídí dialog („neskákat si do řeči“).", + "Synchronizace – navázání po přerušení." + ] + }, + { + "kicker": "7 / 8 • Prezentační", + "title": "Formát dat", + "tip": null, + "lines": [ + "Formátování dat (např. ASCII).", + "Komprese a šifrování.", + "Převod mezi různými standardy." + ] + }, + { + "kicker": "8 / 8 • Aplikační", + "title": "Rozhraní pro programy", + "tip": null, + "lines": [ + "Rozhraní pro aplikace a služby.", + "Například e-mail, HTTP, FTP nebo terminál." + ] + } + ], + "tasks": [ + { + "number": 1, + "title": "Quiz", + "subtitleKey": "net_quiz11_head", + "items": [ + { + "kind": "choice", + "prompt": "Fyzická vrstva se stará o:", + "options": [ + "Přenos bitů", + "Směrování paketů", + "Navazování relací", + "Formátování ASCII" + ], + "correct": 0, + "hint": "Fyzická vrstva přenáší bity a řeší médium" + }, + { + "kind": "choice", + "prompt": "MAC a LLC jsou podvrstvy:", + "options": [ + "Síťové vrstvy", + "Spojové (linkové) vrstvy", + "Transportní vrstvy", + "Aplikační vrstvy" + ], + "correct": 1, + "hint": "Spojová vrstva má podvrstvy MAC a LLC" + }, + { + "kind": "choice", + "prompt": "Směrování paketů v sítích bez přímého spojení řeší:", + "options": [ + "Fyzická vrstva", + "Relační vrstva", + "Síťová vrstva", + "Prezentační vrstva" + ], + "correct": 2, + "hint": "Síťová vrstva směruje pakety i bez přímého spojení" + }, + { + "kind": "choice", + "prompt": "Transportní vrstva existuje:", + "options": [ + "Jen v koncových uzlech", + "I v routerech", + "Jen ve switchech", + "Jen na hubu" + ], + "correct": 0, + "hint": "Transportní vrstva je jen v koncových uzlech, ne v routerech" + }, + { + "kind": "choice", + "prompt": "Relační vrstva především:", + "options": [ + "Definuje napětí a kabely", + "Navazuje, udržuje a ukončuje relace", + "Přidává MAC adresy", + "Směruje pakety" + ], + "correct": 1, + "hint": "Relační vrstva řídí relace, dialog a synchronizaci" + }, + { + "kind": "choice", + "prompt": "Komprese a šifrování patří do vrstvy:", + "options": [ + "Fyzické", + "Spojové", + "Prezentační", + "Síťové" + ], + "correct": 2, + "hint": "Prezentační vrstva formátuje data, komprimuje a šifruje" + }, + { + "kind": "choice", + "prompt": "Aplikační vrstva poskytuje:", + "options": [ + "CRC mezi sousedy", + "Rozhraní pro programy (HTTP, FTP, e-mail…)", + "Jen duplex/simplex", + "Jen směrování" + ], + "correct": 1, + "hint": "Aplikační vrstva je rozhraní pro programy a služby" + } + ] + } + ] +} diff --git a/content/lessons/networks/unit-12.json b/content/lessons/networks/unit-12.json new file mode 100644 index 0000000..094b4a8 --- /dev/null +++ b/content/lessons/networks/unit-12.json @@ -0,0 +1,172 @@ +{ + "id": "unit-12", + "subject": "networks", + "number": 12, + "titleKey": "net_unit12", + "subtitleKey": "net_unit12_sub", + "slides": [ + { + "kicker": "1 / 6 • Mapování", + "title": "TCP/IP vs ISO/OSI", + "tip": null, + "lines": [ + "Aplikační TCP/IP = aplikační + prezentační + relační ISO/OSI.", + "Transportní TCP/IP = transportní ISO/OSI.", + "Síťová (internetová) = síťová ISO/OSI.", + "Vrstva síťového rozhraní = linková + fyzická ISO/OSI." + ] + }, + { + "kicker": "2 / 6 • Vznik", + "title": "Nejprve protokoly", + "tip": "Tip: opačný postup než u ISO/OSI", + "lines": [ + "Nejprve vznikly protokoly pro Internet.", + "Až poté byl definován model TCP/IP.", + "U ISO/OSI to bylo naopak: nejdřív model, pak protokoly." + ] + }, + { + "kicker": "3 / 6 • Aplikace", + "title": "Aplikační protokoly", + "tip": null, + "lines": [ + "HTTP, HTTPS, FTP, DHCP, DNS.", + "Pošta: POP3, IMAP, SMTP." + ] + }, + { + "kicker": "4 / 6 • Transport", + "title": "TCP a UDP", + "tip": null, + "lines": [ + "TCP: spolehlivý, spojovaný.", + "UDP: nespolehlivý, rychlý." + ] + }, + { + "kicker": "5 / 6 • Síť", + "title": "Internetové protokoly", + "tip": null, + "lines": [ + "IP – základní přenos paketů.", + "ICMP, ARP.", + "Směrování: RIP, OSPF." + ] + }, + { + "kicker": "6 / 6 • Rozhraní", + "title": "Síťové rozhraní", + "tip": null, + "lines": [ + "Ethernet, Token Ring, PPP, ATM.", + "Odpovídá linkové a fyzické vrstvě ISO/OSI." + ] + } + ], + "tasks": [ + { + "number": 1, + "title": "Quiz", + "subtitleKey": "net_quiz12_head", + "items": [ + { + "kind": "choice", + "prompt": "Aplikační vrstva TCP/IP odpovídá v ISO/OSI:", + "options": [ + "Jen aplikační vrstvě", + "Aplikační + prezentační + relační", + "Jen fyzické vrstvě", + "Linkové + síťové" + ], + "correct": 1, + "hint": "Aplikační TCP/IP = aplikační + prezentační + relační ISO/OSI" + }, + { + "kind": "choice", + "prompt": "Vrstva síťového rozhraní TCP/IP odpovídá:", + "options": [ + "Jen síťové ISO/OSI", + "Linkové + fyzické ISO/OSI", + "Jen transportní ISO/OSI", + "Jen aplikační ISO/OSI" + ], + "correct": 1, + "hint": "Síťové rozhraní TCP/IP = linková + fyzická ISO/OSI" + }, + { + "kind": "choice", + "prompt": "Model TCP/IP vznikl:", + "options": [ + "Nejdřív model, pak protokoly", + "Nejdřív protokoly, pak model", + "Současně s Token Ring", + "Jen jako náhrada za ATM" + ], + "correct": 1, + "hint": "U TCP/IP vznikly nejdřív protokoly, až pak model" + }, + { + "kind": "choice", + "prompt": "TCP je:", + "options": [ + "Nespolehlivý a rychlý", + "Spolehlivý a spojovaný", + "Jen směrovací protokol", + "Jen fyzické kódování" + ], + "correct": 1, + "hint": "TCP je spolehlivý a spojovaný" + }, + { + "kind": "choice", + "prompt": "UDP je:", + "options": [ + "Spolehlivý a spojovaný", + "Nespolehlivý a rychlý", + "Jen e-mailový protokol", + "Jen ARP" + ], + "correct": 1, + "hint": "UDP je nespolehlivý a rychlý" + }, + { + "kind": "choice", + "prompt": "HTTP, DNS a SMTP patří do vrstvy:", + "options": [ + "Aplikační", + "Transportní", + "Síťové", + "Síťového rozhraní" + ], + "correct": 0, + "hint": "HTTP, DNS a SMTP jsou aplikační protokoly" + }, + { + "kind": "choice", + "prompt": "IP, ICMP a OSPF patří do vrstvy:", + "options": [ + "Aplikační", + "Transportní", + "Síťové (internetové)", + "Síťového rozhraní" + ], + "correct": 2, + "hint": "IP, ICMP a OSPF patří na síťovou (internetovou) vrstvu" + }, + { + "kind": "choice", + "prompt": "Ethernet a PPP patří do vrstvy:", + "options": [ + "Aplikační", + "Transportní", + "Síťové", + "Síťového rozhraní" + ], + "correct": 3, + "hint": "Ethernet a PPP patří na vrstvu síťového rozhraní" + } + ] + } + ] +} diff --git a/content/lessons/networks/unit-13.json b/content/lessons/networks/unit-13.json new file mode 100644 index 0000000..320888d --- /dev/null +++ b/content/lessons/networks/unit-13.json @@ -0,0 +1,130 @@ +{ + "id": "unit-13", + "subject": "networks", + "number": 13, + "titleKey": "net_unit13", + "subtitleKey": "net_unit13_sub", + "slides": [ + { + "kicker": "1 / 4 • Přehled", + "title": "Topologie sítě", + "tip": null, + "lines": [ + "Topologie popisuje, jak jsou uzly propojené.", + "Základní typy: sběrnice, hvězda a kruh." + ] + }, + { + "kicker": "2 / 4 • Sběrnice", + "title": "Bus", + "tip": "Tip: dříve typicky koaxiální kabel", + "lines": [ + "Médium sdílí všichni – jednoduchá a levná topologie.", + "Malá délka kabelů.", + "Nevýhody: nízká bezpečnost (všichni slyší vše).", + "Přerušení kabelu nebo terminátoru vyřadí celou síť." + ] + }, + { + "kicker": "3 / 4 • Hvězda", + "title": "Star", + "tip": "Tip: kroucená dvoulinka nebo optika", + "lines": [ + "Uzly jdou přes centrální prvek (hub nebo switch).", + "Výhody: odolnost proti poruchám kabelů k uzlům,", + "snadná diagnostika.", + "Nevýhody: aktivní prvky a více kabeláže." + ] + }, + { + "kicker": "4 / 4 • Kruh", + "title": "Ring", + "tip": "Tip: často zdvojený kruh pro odolnost", + "lines": [ + "Kabely tvoří souvislý kruh.", + "Zprávy obíhají, dokud nenajdou adresáta." + ] + } + ], + "tasks": [ + { + "number": 1, + "title": "Quiz", + "subtitleKey": "net_quiz13_head", + "items": [ + { + "kind": "choice", + "prompt": "Topologie sběrnice (bus) znamená, že:", + "options": [ + "Každý uzel má vlastní centrální switch", + "Médium sdílí všichni", + "Kabely tvoří jen zdvojený kruh", + "Používá jen OSPF" + ], + "correct": 1, + "hint": "Sběrnice: médium sdílí všichni" + }, + { + "kind": "choice", + "prompt": "Nevýhoda sběrnice je hlavně:", + "options": [ + "Že potřebuje hub u každého uzlu", + "Nízká bezpečnost a náchylnost na poruchu kabelu", + "Že nelze použít koaxiál", + "Že zprávy neobíhají" + ], + "correct": 1, + "hint": "Sběrnice: nízká bezpečnost a porucha kabelu vyřadí síť" + }, + { + "kind": "choice", + "prompt": "Topologie hvězda propojuje uzly přes:", + "options": [ + "Jen jeden společný koaxiál bez centra", + "Centrální prvek (hub nebo switch)", + "Jen Token Ring", + "Jen ATM" + ], + "correct": 1, + "hint": "Hvězda: uzly jdou přes hub nebo switch" + }, + { + "kind": "choice", + "prompt": "Výhoda hvězdy je:", + "options": [ + "Že přerušení jednoho kabelu k uzlu nevyřadí celou síť", + "Že všichni slyší vše", + "Že nepotřebuje žádnou kabeláž", + "Že nemá aktivní prvky" + ], + "correct": 0, + "hint": "Hvězda: porucha kabelu k uzlu nevyřadí celou síť" + }, + { + "kind": "choice", + "prompt": "Hvězda typicky používá:", + "options": [ + "Jen koaxiální kabel", + "Kroucenou dvoulinku nebo optiku", + "Jen simplexní rádio", + "Jen FDM" + ], + "correct": 1, + "hint": "Hvězda používá kroucenou dvoulinku nebo optiku" + }, + { + "kind": "choice", + "prompt": "V topologii kruh (ring):", + "options": [ + "Zprávy obíhají, dokud nenajdou adresáta", + "Každý paket jde jen přes DNS", + "Médium sdílí hub bez kabelů", + "Neexistuje žádná kabeláž" + ], + "correct": 0, + "hint": "V kruhu zprávy obíhají, dokud nenajdou adresáta" + } + ] + } + ] +} diff --git a/content/lessons/networks/unit-14.json b/content/lessons/networks/unit-14.json new file mode 100644 index 0000000..bc7f7ef --- /dev/null +++ b/content/lessons/networks/unit-14.json @@ -0,0 +1,140 @@ +{ + "id": "unit-14", + "subject": "networks", + "number": 14, + "titleKey": "net_unit14", + "subtitleKey": "net_unit14_sub", + "slides": [ + { + "kicker": "1 / 5 • Princip", + "title": "Světlo místo proudu", + "tip": "Tip: obousměrný provoz = dvě vlákna", + "lines": [ + "Elektrické impulsy se převádí na světlo (LED nebo laser).", + "Zpět je zachytí fotodioda.", + "Přenos jedním vláknem je jednosměrný." + ] + }, + { + "kicker": "2 / 5 • Výhody", + "title": "Proč optika", + "tip": null, + "lines": [ + "Imunita vůči elektromagnetickému rušení.", + "Obrovská šířka pásma a dosah až kolem 100 km.", + "Lepší bezpečnost proti odposlechu.", + "Malý průměr a nízká váha." + ] + }, + { + "kicker": "3 / 5 • Nevýhody", + "title": "Cena a montáž", + "tip": null, + "lines": [ + "Náročná montáž.", + "Dražší aktivní prvky a konektory." + ] + }, + { + "kicker": "4 / 5 • MM", + "title": "Mnohovidová vlákna", + "tip": null, + "lines": [ + "Větší jádro: 50 / 62,5 µm.", + "Více cest světla (vidů).", + "Levnější zdroje – typicky LED." + ] + }, + { + "kicker": "5 / 5 • SM", + "title": "Jednovidová vlákna", + "tip": null, + "lines": [ + "Malé jádro: 7–10 µm.", + "Jen jeden paprsek osou vlákna.", + "Velký dosah, vyžaduje laser." + ] + } + ], + "tasks": [ + { + "number": 1, + "title": "Quiz", + "subtitleKey": "net_quiz14_head", + "items": [ + { + "kind": "choice", + "prompt": "Princip optiky je:", + "options": [ + "Převod el. impulsů na světlo a zpět fotodiodou", + "Jen směrování paketů OSPF", + "Jen sdílená sběrnice", + "Jen UDP spojení" + ], + "correct": 0, + "hint": "Optika: el. impulsy → světlo (LED/laser) → fotodioda" + }, + { + "kind": "choice", + "prompt": "Jedním vláknem je přenos:", + "options": [ + "Vždy plně duplexní bez výjimky", + "Jednosměrný (obousměrně dvě vlákna)", + "Jen poloviční kruh", + "Jen Token Ring" + ], + "correct": 1, + "hint": "Jedno vlákno = jednosměrný přenos; obousměrně dvě vlákna" + }, + { + "kind": "choice", + "prompt": "Výhoda optiky není:", + "options": [ + "Imunita vůči el.mag. rušení", + "Velký dosah a šířka pásma", + "Levná a snadná montáž konektorů", + "Lepší ochrana proti odposlechu" + ], + "correct": 2, + "hint": "Nevýhody: náročná montáž a cena prvků/konektorů" + }, + { + "kind": "choice", + "prompt": "Mnohovidové vlákno (MM) má:", + "options": [ + "Jádro 7–10 µm a vyžaduje laser", + "Větší jádro 50/62,5 µm a více vidů", + "Jen koaxiální stínění", + "Jen jednu MAC adresu" + ], + "correct": 1, + "hint": "MM: jádro 50/62,5 µm a více vidů" + }, + { + "kind": "choice", + "prompt": "Jednovidové vlákno (SM):", + "options": [ + "Má větší jádro a LED zdroj", + "Má malé jádro, jeden paprsek a laser", + "Nepřenáší světlo", + "Funguje jen jako hub" + ], + "correct": 1, + "hint": "SM: jádro 7–10 µm, jeden paprsek, laser" + }, + { + "kind": "choice", + "prompt": "Levnější zdroje (LED) typicky patří k:", + "options": [ + "Jednovidovým vláknům", + "Mnohovidovým vláknům", + "Jen kruhové topologii", + "Jen ATM" + ], + "correct": 1, + "hint": "MM typicky používá levnější LED zdroje" + } + ] + } + ] +} diff --git a/content/lessons/networks/unit-15.json b/content/lessons/networks/unit-15.json new file mode 100644 index 0000000..f6ce598 --- /dev/null +++ b/content/lessons/networks/unit-15.json @@ -0,0 +1,118 @@ +{ + "id": "unit-15", + "subject": "networks", + "number": 15, + "titleKey": "net_unit15", + "subtitleKey": "net_unit15_sub", + "slides": [ + { + "kicker": "1 / 3 • Primární", + "title": "Ochrana 250 µm", + "tip": null, + "lines": [ + "Primární ochrana má průměr 250 µm.", + "Chrání samotné vlákno hned po výrobě." + ] + }, + { + "kicker": "2 / 3 • Sekundární", + "title": "Ochrana 900 µm", + "tip": "Tip: těsná pro svislé, volná pro vodorovné instalace", + "lines": [ + "Sekundární ochrana má průměr 900 µm.", + "Těsná varianta: vhodné pro svislé instalace.", + "Volná varianta: vhodné pro vodorovné instalace." + ] + }, + { + "kicker": "3 / 3 • Montáž", + "title": "Lámání a sváření", + "tip": "Tip: kolmost lomu do 0,5°", + "lines": [ + "Vyžaduje precizní lámání lámačkou.", + "Spojování se dělá svářečkou optických vláken." + ] + } + ], + "tasks": [ + { + "number": 1, + "title": "Quiz", + "subtitleKey": "net_quiz15_head", + "items": [ + { + "kind": "choice", + "prompt": "Primární ochrana optického vlákna má průměr:", + "options": [ + "900 µm", + "250 µm", + "50 µm", + "7–10 µm" + ], + "correct": 1, + "hint": "Primární ochrana: 250 µm" + }, + { + "kind": "choice", + "prompt": "Sekundární ochrana má průměr:", + "options": [ + "250 µm", + "900 µm", + "62,5 µm", + "1 km" + ], + "correct": 1, + "hint": "Sekundární ochrana: 900 µm" + }, + { + "kind": "choice", + "prompt": "Těsná sekundární ochrana je vhodná hlavně:", + "options": [ + "Pro svislé instalace", + "Jen pro kruhovou topologii", + "Jen pro UDP", + "Jen pro hub" + ], + "correct": 0, + "hint": "Těsná sekundární ochrana: svislé instalace" + }, + { + "kind": "choice", + "prompt": "Volná sekundární ochrana je vhodná hlavně:", + "options": [ + "Pro vodorovné instalace", + "Jen pro ATM", + "Jen pro LED bez vlákna", + "Jen pro sběrnici" + ], + "correct": 0, + "hint": "Volná sekundární ochrana: vodorovné instalace" + }, + { + "kind": "choice", + "prompt": "Montáž optiky vyžaduje:", + "options": [ + "Jen nůžky na koaxiál", + "Precizní lámání a svářečku vláken", + "Jen hub bez konektorů", + "Jen Token Ring" + ], + "correct": 1, + "hint": "Montáž: lámačka a svářečka optických vláken" + }, + { + "kind": "choice", + "prompt": "Při lámání se požaduje kolmost zhruba:", + "options": [ + "Do 0,5°", + "Do 45°", + "Přesně 90° bez tolerance", + "Bez významu" + ], + "correct": 0, + "hint": "Lámání vyžaduje kolmost asi 0,5°" + } + ] + } + ] +} diff --git a/content/lessons/networks/unit-16.json b/content/lessons/networks/unit-16.json new file mode 100644 index 0000000..721760a --- /dev/null +++ b/content/lessons/networks/unit-16.json @@ -0,0 +1,129 @@ +{ + "id": "unit-16", + "subject": "networks", + "number": 16, + "titleKey": "net_unit16", + "subtitleKey": "net_unit16_sub", + "slides": [ + { + "kicker": "1 / 4 • Kolize", + "title": "Sdílené médium", + "tip": null, + "lines": [ + "Kolize nastane, když na sdíleném médiu vysílá více uzlů najednou." + ] + }, + { + "kicker": "2 / 4 • Aloha", + "title": "Vysílej kdykoliv", + "tip": "Tip: časté kolize, primitivní metoda", + "lines": [ + "Uzel vysílá kdykoliv chce.", + "Když nepřijde potvrzení, pošle data znovu.", + "Kolize jsou časté." + ] + }, + { + "kicker": "3 / 4 • CSMA/CD", + "title": "Ethernet", + "tip": "Tip: Carrier Sense + Collision Detection", + "lines": [ + "Nejdřív se poslouchá nosná (Carrier Sense).", + "Je-li ticho, uzel vysílá.", + "Při kolizi se vysílání zastaví a zkusí se znovu", + "po náhodném čase." + ] + }, + { + "kicker": "4 / 4 • CSMA/CA", + "title": "Wi-Fi", + "tip": "Tip: Collision Avoidance přes RTS/CTS", + "lines": [ + "Předchází kolizím (Collision Avoidance).", + "RTS (Request to Send) a CTS (Clear to Send)", + "rezervují médium před vysíláním." + ] + } + ], + "tasks": [ + { + "number": 1, + "title": "Quiz", + "subtitleKey": "net_quiz16_head", + "items": [ + { + "kind": "choice", + "prompt": "Kolize nastane, když:", + "options": [ + "Na sdíleném médiu vysílá více uzlů najednou", + "Router vypne OSPF", + "Vlákno má ochranu 250 µm", + "Použijeme jen TCP" + ], + "correct": 0, + "hint": "Kolize = více uzlů vysílá na sdíleném médiu najednou" + }, + { + "kind": "choice", + "prompt": "Metoda Aloha znamená především:", + "options": [ + "Vysílej kdykoliv; bez potvrzení pošli znovu", + "Vždy rezervuj médium RTS/CTS", + "Nikdy nevysílej při tichu", + "Jen směrování RIP" + ], + "correct": 0, + "hint": "Aloha: vysílej kdykoliv, při chybě znovu" + }, + { + "kind": "choice", + "prompt": "CSMA/CD se typicky pojí s:", + "options": [ + "Wi-Fi", + "Ethernetem", + "Jen SMTP", + "Jen ATM" + ], + "correct": 1, + "hint": "CSMA/CD patří k Ethernetu" + }, + { + "kind": "choice", + "prompt": "Při CSMA/CD uzel před vysíláním:", + "options": [ + "Ignoruje médium", + "Monitoruje nosnou (Carrier Sense)", + "Vždy čeká přesně 1 hodinu", + "Použije jen laser" + ], + "correct": 1, + "hint": "CSMA/CD nejdřív poslouchá nosnou (Carrier Sense)" + }, + { + "kind": "choice", + "prompt": "Když CSMA/CD detekuje kolizi:", + "options": [ + "Pokračuje vysíláním bez změny", + "Zastaví vysílání a zkusí to po náhodném čase", + "Přepne síť na sběrnici", + "Smaže IP adresu" + ], + "correct": 1, + "hint": "Po kolizi CSMA/CD čeká náhodný čas a zkusí znovu" + }, + { + "kind": "choice", + "prompt": "CSMA/CA na Wi-Fi předchází kolizím pomocí:", + "options": [ + "RTS a CTS", + "Jen CRC bez nosné", + "Jen hubu", + "Jen koaxiálu" + ], + "correct": 0, + "hint": "CSMA/CA rezervuje médium přes RTS/CTS" + } + ] + } + ] +} diff --git a/content/lessons/networks/unit-17.json b/content/lessons/networks/unit-17.json new file mode 100644 index 0000000..e1084d9 --- /dev/null +++ b/content/lessons/networks/unit-17.json @@ -0,0 +1,162 @@ +{ + "id": "unit-17", + "subject": "networks", + "number": 17, + "titleKey": "net_unit17", + "subtitleKey": "net_unit17_sub", + "slides": [ + { + "kicker": "1 / 7 • Přehled", + "title": "Aktivní prvky", + "tip": null, + "lines": [ + "Aktivní prvky zpracovávají nebo převádí signál / data.", + "Liší se podle vrstvy ISO/OSI, na které pracují." + ] + }, + { + "kicker": "2 / 7 • Repeater", + "title": "Opakovač", + "tip": "Tip: fyzická vrstva", + "lines": [ + "Zesiluje signál a tím zvyšuje dosah." + ] + }, + { + "kicker": "3 / 7 • Transceiver", + "title": "Konvertor", + "tip": "Tip: fyzická vrstva", + "lines": [ + "Převádí signál mezi různými médii.", + "Například metaliku na optiku." + ] + }, + { + "kicker": "4 / 7 • Hub", + "title": "Rozbočovač", + "tip": "Tip: fyzická vrstva – „hloupý“ prvek", + "lines": [ + "Co přijme na jednom portu, rozešle do všech ostatních." + ] + }, + { + "kicker": "5 / 7 • Bridge/Switch", + "title": "Most a přepínač", + "tip": "Tip: linková vrstva – rámce a MAC", + "lines": [ + "Pracují s rámci a MAC adresami.", + "Switch dělí síť na kolizní domény." + ] + }, + { + "kicker": "6 / 7 • Router", + "title": "Směrovač", + "tip": "Tip: síťová vrstva – pakety a IP", + "lines": [ + "Pracuje s pakety a IP adresami.", + "Propojuje různé sítě." + ] + }, + { + "kicker": "7 / 7 • Gateway", + "title": "Brána", + "tip": "Tip: vyšší vrstvy", + "lines": [ + "Převádí mezi odlišnými architekturami nebo protokoly." + ] + } + ], + "tasks": [ + { + "number": 1, + "title": "Quiz", + "subtitleKey": "net_quiz17_head", + "items": [ + { + "kind": "choice", + "prompt": "Repeater (opakovač) hlavně:", + "options": [ + "Zesiluje signál a zvyšuje dosah", + "Směruje IP pakety", + "Převádí mezi protokoly vyšších vrstev", + "Rezervuje médium RTS/CTS" + ], + "correct": 0, + "hint": "Repeater zesiluje signál na fyzické vrstvě" + }, + { + "kind": "choice", + "prompt": "Transceiver typicky:", + "options": [ + "Převádí signál mezi různými médii", + "Dělí síť jen podle DNS", + "Je vždy jen brána", + "Pracuje jen s UDP" + ], + "correct": 0, + "hint": "Transceiver převádí mezi médii (např. metalika ↔ optika)" + }, + { + "kind": "choice", + "prompt": "Hub (rozbočovač) je:", + "options": [ + "„Hloupý“ prvek – data z jednoho portu pošle všem ostatním", + "Směrovač na síťové vrstvě", + "Jen laserový zdroj", + "Jen MAC filtr bez portů" + ], + "correct": 0, + "hint": "Hub rozešle přijatá data do všech ostatních portů" + }, + { + "kind": "choice", + "prompt": "Bridge a switch pracují na vrstvě:", + "options": [ + "Fyzické", + "Linkové (rámce a MAC)", + "Aplikační", + "Jen transportní" + ], + "correct": 1, + "hint": "Bridge/switch = linková vrstva, rámce a MAC" + }, + { + "kind": "choice", + "prompt": "Switch mimo jiné:", + "options": [ + "Dělí síť na kolizní domény", + "Nikdy nepoužívá MAC adresy", + "Funguje jen jako hub bez portů", + "Převádí jen ASCII" + ], + "correct": 0, + "hint": "Switch dělí síť na kolizní domény" + }, + { + "kind": "choice", + "prompt": "Router pracuje s:", + "options": [ + "Pakety a IP adresami a propojuje sítě", + "Jen koaxiálem bez IP", + "Jen huby bez směrování", + "Jen RTS/CTS" + ], + "correct": 0, + "hint": "Router = síťová vrstva, pakety a IP, propojuje sítě" + }, + { + "kind": "choice", + "prompt": "Gateway (brána) především:", + "options": [ + "Převádí mezi odlišnými architekturami/protokoly", + "Jen zesiluje bitový signál", + "Jen tvoří kolize", + "Jen lámání vlákna" + ], + "correct": 0, + "hint": "Gateway převádí mezi odlišnými architekturami/protokoly" + } + ] + } + ] +} diff --git a/content/lessons/networks/unit-18.json b/content/lessons/networks/unit-18.json new file mode 100644 index 0000000..e736284 --- /dev/null +++ b/content/lessons/networks/unit-18.json @@ -0,0 +1,139 @@ +{ + "id": "unit-18", + "subject": "networks", + "number": 18, + "titleKey": "net_unit18", + "subtitleKey": "net_unit18_sub", + "slides": [ + { + "kicker": "1 / 5 • Funkce", + "title": "Učení MAC adres", + "tip": "Tip: CAM tabulka = adresa → port", + "lines": [ + "Switch se učí MAC adresy odesílatelů.", + "Ukládá je do CAM tabulky.", + "Rámce pak posílá jen na konkrétní port." + ] + }, + { + "kicker": "2 / 5 • Metody", + "title": "Tři způsoby přepínání", + "tip": null, + "lines": [ + "Cut-through, store-and-forward a fragment-free.", + "Liší se rychlostí a kontrolou chyb." + ] + }, + { + "kicker": "3 / 5 • Cut-through", + "title": "Hned po adrese", + "tip": null, + "lines": [ + "Čte jen adresu příjemce a hned posílá dál.", + "Nejrychlejší metoda.", + "Nevýhoda: posílá i chybné rámce." + ] + }, + { + "kicker": "4 / 5 • Store-and-forward", + "title": "Celý rámec + CRC", + "tip": null, + "lines": [ + "Přijme celý rámec a zkontroluje CRC.", + "Teprve pak rámec pošle.", + "Nejpomalejší, ale nejbezpečnější metoda." + ] + }, + { + "kicker": "5 / 5 • Fragment-free", + "title": "Modifikovaný cut-through", + "tip": "Tip: prvních 64 bytů = detekce kolizí", + "lines": [ + "Čte prvních 64 bytů rámce.", + "To stačí k odhalení kolizních fragmentů.", + "Kompromis mezi rychlostí a bezpečností." + ] + } + ], + "tasks": [ + { + "number": 1, + "title": "Quiz", + "subtitleKey": "net_quiz18_head", + "items": [ + { + "kind": "choice", + "prompt": "Switch se učí MAC adresy a ukládá je do:", + "options": [ + "CAM tabulky", + "Jen DNS cache", + "Jen ARP bez portů", + "Jen OSPF" + ], + "correct": 0, + "hint": "MAC adresy switch ukládá do CAM tabulky" + }, + { + "kind": "choice", + "prompt": "Díky CAM tabulce switch posílá rámce:", + "options": [ + "Jen na konkrétní port", + "Vždy na všechny porty jako hub", + "Jen na routery", + "Jen přes laser" + ], + "correct": 0, + "hint": "Podle CAM tabulky posílá rámec jen na cílový port" + }, + { + "kind": "choice", + "prompt": "Cut-through přepínání:", + "options": [ + "Čte jen adresu příjemce a hned posílá", + "Vždy čeká na celé CRC", + "Nikdy neposílá rámce", + "Pracuje jen s IP směrováním" + ], + "correct": 0, + "hint": "Cut-through čte adresu příjemce a hned přeposílá" + }, + { + "kind": "choice", + "prompt": "Nevýhoda cut-through je:", + "options": [ + "Že posílá i chybné rámce", + "Že je nejpomalejší", + "Že nemá MAC adresy", + "Že vyžaduje gateway" + ], + "correct": 0, + "hint": "Cut-through je rychlý, ale propustí i chyby" + }, + { + "kind": "choice", + "prompt": "Store-and-forward:", + "options": [ + "Přijme celý rámec, zkontroluje CRC a pak pošle", + "Čte jen první 2 byty", + "Nikdy nekontroluje chyby", + "Funguje jen jako Aloha" + ], + "correct": 0, + "hint": "Store-and-forward kontroluje celý rámec včetně CRC" + }, + { + "kind": "choice", + "prompt": "Fragment-free (modifikovaný cut-through) čte:", + "options": [ + "Prvních 64 bytů (detekce kolizí)", + "Jen poslední byte", + "Celý paket IP včetně směrování", + "Jen SMTP hlavičku" + ], + "correct": 0, + "hint": "Fragment-free čte prvních 64 bytů kvůli kolizím" + } + ] + } + ] +} diff --git a/content/lessons/networks/unit-19.json b/content/lessons/networks/unit-19.json new file mode 100644 index 0000000..49391b5 --- /dev/null +++ b/content/lessons/networks/unit-19.json @@ -0,0 +1,173 @@ +{ + "id": "unit-19", + "subject": "networks", + "number": 19, + "titleKey": "net_unit19", + "subtitleKey": "net_unit19_sub", + "slides": [ + { + "kicker": "1 / 7 • Princip", + "title": "Směrování paketů", + "tip": "Tip: 3. vrstva ISO/OSI – síťová", + "lines": [ + "Rozhodování o dalším směru přenosu paketů do cílové sítě.", + "Probíhá na síťové vrstvě modelu ISO/OSI.", + "K rozhodování se používají směrovací algoritmy." + ] + }, + { + "kicker": "2 / 7 • Adaptivní", + "title": "Dynamické algoritmy", + "tip": null, + "lines": [ + "Reagují na změny v síti (výpadek linky, přetížení).", + "Vyžadují pravidelnou výměnu informací mezi směrovači." + ] + }, + { + "kicker": "3 / 7 • Neadaptivní", + "title": "Statické algoritmy", + "tip": null, + "lines": [ + "Nereagují na změny v síti.", + "Cesty pevně definuje správce.", + "Při výpadku části sítě může spojení spadnout." + ] + }, + { + "kicker": "4 / 7 • Řízení", + "title": "Centralizované a izolované", + "tip": null, + "lines": [ + "Centralizované: centrum počítá cesty pro všechny směrovače.", + "Výpadek centra = pád směrování; v praxi skoro nepoužívané.", + "Izolované: směrovač se rozhoduje sám z lokálních informací.", + "Izolované se používá spíš jako doplněk při přetížení." + ] + }, + { + "kicker": "5 / 7 • Distribuované", + "title": "Výměna mezi směrovači", + "tip": null, + "lines": [ + "Směrovače si vyměňují informace.", + "Každý si udržuje vlastní směrovací tabulku." + ] + }, + { + "kicker": "6 / 7 • Tabulka", + "title": "Next Hop a metrika", + "tip": "Tip: nižší metrika = lepší / rychlejší trasa", + "lines": [ + "Záznam: cílová síť, next hop a metrika.", + "Next hop = nejbližší soused, kterému paket předáme.", + "Metrika číselně ohodnocuje cestu.", + "Při více cestách se volí ta s nejnižší metrikou." + ] + }, + { + "kicker": "7 / 7 • Distance Vector", + "title": "Příklad algoritmu", + "tip": "Tip: např. výměna tabulek každých 30 s", + "lines": [ + "Směrovače znají jen své přímé sousedy.", + "Pravidelně si posílají kopie směrovacích tabulek.", + "Informace se šíří krok za krokem po celé síti.", + "Každý směrovač si spočítá nejlepší trasu do známých sítí." + ] + } + ], + "tasks": [ + { + "number": 1, + "title": "Quiz", + "subtitleKey": "net_quiz19_head", + "items": [ + { + "kind": "choice", + "prompt": "Směrování probíhá na vrstvě:", + "options": [ + "Fyzické", + "Síťové (3. ISO/OSI)", + "Jen aplikační", + "Jen linkové" + ], + "correct": 1, + "hint": "Směrování běží na síťové (3.) vrstvě ISO/OSI" + }, + { + "kind": "choice", + "prompt": "Adaptivní (dynamické) algoritmy:", + "options": [ + "Reagují na změny a vyměňují informace mezi směrovači", + "Nikdy nemění cesty", + "Fungují jen na fyzické vrstvě", + "Nepoužívají metriku" + ], + "correct": 0, + "hint": "Adaptivní algoritmy reagují na změny a sdílí stav sítě" + }, + { + "kind": "choice", + "prompt": "Neadaptivní (statické) směrování:", + "options": [ + "Má cesty pevně nastavené správcem", + "Samo opraví každý výpadek", + "Nepotřebuje směrovací tabulku", + "Běží jen na Wi-Fi" + ], + "correct": 0, + "hint": "Statické cesty nastaví správce a samy se nemění" + }, + { + "kind": "choice", + "prompt": "Centralizované směrování v praxi:", + "options": [ + "Se skoro nepoužívá – výpadek centra shodí směrování", + "Je jediný standard internetu", + "Neexistuje žádné centrum", + "Pracuje jen s MAC adresami" + ], + "correct": 0, + "hint": "Centralizované směrování padá s výpadkem centra" + }, + { + "kind": "choice", + "prompt": "Distribuované směrování znamená, že:", + "options": [ + "Směrovače si vyměňují informace a každý má vlastní tabulku", + "Jedno centrum řídí všechny cesty", + "Směrovač nezná žádné sousedy", + "Pakety jdou jen přes hub" + ], + "correct": 0, + "hint": "Distribuované: výměna informací a vlastní tabulky" + }, + { + "kind": "choice", + "prompt": "Metrika ve směrovací tabulce:", + "options": [ + "Číselně hodnotí cestu – nižší je lepší", + "Je vždy jen MAC adresa", + "Nemá vliv na výběr trasy", + "Nahrazuje next hop" + ], + "correct": 0, + "hint": "Nižší metrika = lepší / rychlejší trasa" + }, + { + "kind": "choice", + "prompt": "Distance Vector typicky:", + "options": [ + "Posílá sousedům kopie tabulek a šíří informace krok za krokem", + "Počítá cesty jen v jednom centru", + "Ignoruje přímé sousedy", + "Pracuje jen na aplikační vrstvě" + ], + "correct": 0, + "hint": "Distance Vector: výměna tabulek se sousedy (např. každých 30 s)" + } + ] + } + ] +} diff --git a/content/lessons/networks/unit-20.json b/content/lessons/networks/unit-20.json new file mode 100644 index 0000000..f3ff317 --- /dev/null +++ b/content/lessons/networks/unit-20.json @@ -0,0 +1,172 @@ +{ + "id": "unit-20", + "subject": "networks", + "number": 20, + "titleKey": "net_unit20", + "subtitleKey": "net_unit20_sub", + "slides": [ + { + "kicker": "1 / 7 • Router", + "title": "Síťová vrstva", + "tip": "Tip: má vlastní IP a je vidět např. pingen", + "lines": [ + "Pracuje na 3. (síťové) vrstvě.", + "Segmentuje síť na podsítě nebo propojuje LAN do většího celku.", + "Umožňuje přístup na WAN (např. internet).", + "Podporuje soustavy protokolů (např. TCP/IP) a má vlastní adresu." + ] + }, + { + "kicker": "2 / 7 • Bezpečnost", + "title": "Firewall na routeru", + "tip": null, + "lines": [ + "Router s firewallem filtruje pakety.", + "Může zakázat nebo povolit určité síťové služby." + ] + }, + { + "kicker": "3 / 7 • Multiprotokol", + "title": "Různé standardy", + "tip": null, + "lines": [ + "Multiprotokolový router spojuje různé soustavy protokolů.", + "Například TCP/IP se sítěmi IPX/SPX.", + "Umí i různý síťový hardware (Ethernet ↔ Token Ring).", + "Konvertuje formát rámců i paketů." + ] + }, + { + "kicker": "4 / 7 • Routing", + "title": "Směrování a tabulky", + "tip": null, + "lines": [ + "Každému paketu hledá vhodnou cestu k cíli.", + "Zohledňuje např. okamžité zatížení sítí.", + "Používá směrovací tabulky a musí znát topologii.", + "Směrovače si tabulky vyměňují (např. broadcastem)." + ] + }, + { + "kicker": "5 / 7 • Broadcast", + "title": "Broadcastové domény", + "tip": null, + "lines": [ + "Router rozděluje síť na broadcastové domény.", + "Broadcasty lze filtrovat – nešíří se na všechny porty." + ] + }, + { + "kicker": "6 / 7 • Gateway", + "title": "Brána", + "tip": "Tip: pracuje až na aplikační vrstvě (i nižších)", + "lines": [ + "Připojuje LAN na zcela odlišné prostředí.", + "Například mainframe nebo GSM síť.", + "Často PC s kartou/emulací terminálu nebo s modemem na WAN." + ] + }, + { + "kicker": "7 / 7 • Poznámka", + "title": "Gateway vs router", + "tip": null, + "lines": [ + "Někdy se pod pojmem brána rozumí spíše router.", + "Gateway také označuje připojení LAN na WAN / internet." + ] + } + ], + "tasks": [ + { + "number": 1, + "title": "Quiz", + "subtitleKey": "net_quiz20_head", + "items": [ + { + "kind": "choice", + "prompt": "Směrovač (router) pracuje na vrstvě:", + "options": [ + "Fyzické", + "Síťové (3.)", + "Jen aplikační", + "Jen prezentační" + ], + "correct": 1, + "hint": "Router pracuje na síťové (3.) vrstvě" + }, + { + "kind": "choice", + "prompt": "Router mimo jiné umožňuje:", + "options": [ + "Segmentaci na podsítě a přístup na WAN", + "Jen lámání optiky", + "Jen Aloha bez IP", + "Jen cut-through bez MAC" + ], + "correct": 0, + "hint": "Router segmentuje podsítě a zajišťuje WAN přístup" + }, + { + "kind": "choice", + "prompt": "Firewall na routeru dokáže:", + "options": [ + "Filtrovat pakety a řídit služby", + "Jen zesílit bitový signál", + "Jen uložit CAM bez IP", + "Jen nahradit fotodiodu" + ], + "correct": 0, + "hint": "Firewall filtruje pakety a služby" + }, + { + "kind": "choice", + "prompt": "Multiprotokolový router:", + "options": [ + "Propojí sítě různých protokolů/standardů", + "Umí jen jeden protokol", + "Nepracuje s IP adresou", + "Nikdy nekonvertuje rámce" + ], + "correct": 0, + "hint": "Multiprotokolový router spojuje různé protokoly/standardy" + }, + { + "kind": "choice", + "prompt": "Router rozděluje síť na:", + "options": [ + "Broadcastové domény", + "Jen fyzické kabely bez domén", + "Jen aplikační servery", + "Jen Token Ring bez Ethernetu" + ], + "correct": 0, + "hint": "Router dělí síť na broadcastové domény" + }, + { + "kind": "choice", + "prompt": "Brána (gateway) typicky:", + "options": [ + "Připojuje LAN na odlišné prostředí (mainframe, GSM, WAN)", + "Pracuje jen jako hub", + "Nikdy nemá software", + "Funguje jen na fyzické vrstvě" + ], + "correct": 0, + "hint": "Gateway připojuje LAN na odlišné prostředí" + }, + { + "kind": "choice", + "prompt": "Poznámka k pojmu brána:", + "options": [ + "Někdy se jí myslí spíše router / LAN–WAN připojení", + "Vždy znamená jen fotodiodu", + "Nikdy nesouvisí s internetem", + "Nahrazuje jen lámačku vláken" + ], + "correct": 0, + "hint": "Pojem brána někdy označuje router nebo LAN–WAN připojení" + } + ] + } + ] +} diff --git a/content/lessons/networks/unit-21.json b/content/lessons/networks/unit-21.json new file mode 100644 index 0000000..dd1dc97 --- /dev/null +++ b/content/lessons/networks/unit-21.json @@ -0,0 +1,180 @@ +{ + "id": "unit-21", + "subject": "networks", + "number": 21, + "titleKey": "net_unit21", + "subtitleKey": "net_unit21_sub", + "slides": [ + { + "kicker": "1 / 8 • Ethernet", + "title": "Síťový hardware", + "tip": null, + "lines": [ + "Jeden ze standardů síťového hardware.", + "Dnes nejpoužívanější." + ] + }, + { + "kicker": "2 / 8 • Adresy", + "title": "48bitová MAC", + "tip": "Tip: IEEE přidělí první 3 B, výrobce další 3 B", + "lines": [ + "Adresa má 48 bitů (6 bytů) a je celosvětově jedinečná.", + "Je pevně v síťové kartě už od výroby.", + "Výrobci dostávají bloky adres od IEEE." + ] + }, + { + "kicker": "3 / 8 • Rámce", + "title": "Typy hlaviček", + "tip": null, + "lines": [ + "Rámec = skupina bitů na linkové vrstvě.", + "Hlavička má adresy odesílatele/příjemce a typ obsahu.", + "Typy: Ethernet II, IEEE 802.3, 802.3 SNAP, raw 802.3." + ] + }, + { + "kicker": "4 / 8 • Ethernet II", + "title": "DIX + EtherType", + "tip": "Tip: EtherType > 1500 (např. IP = 0800h)", + "lines": [ + "Původní DIX Ethernet.", + "Hlavička: příjemce 6 B, odesílatel 6 B, EtherType 2 B.", + "EtherType identifikuje protokol (IP, IPX…)." + ] + }, + { + "kicker": "5 / 8 • IEEE 802.3", + "title": "Délka místo typu", + "tip": null, + "lines": [ + "Místo EtherType je údaj o délce (vždy ≤ 1500).", + "Uvnitř je rámec 802.2 (stejný i pro Token Ring).", + "Typ protokolu je v SAP mezi linkovou a síťovou vrstvou." + ] + }, + { + "kicker": "6 / 8 • Raw 802.3", + "title": "Novell / IPX", + "tip": null, + "lines": [ + "„Holý“ rámec 802.3 bez 802.2 (Novell).", + "Funguje jen v prostředí IPX.", + "Paket začíná dvěma byty FFFFh." + ] + }, + { + "kicker": "7 / 8 • SNAP", + "title": "802.2 SNAP", + "tip": "Tip: byty 15–16 za délkou = AAAAh", + "lines": [ + "Vložen do rámce 802.3.", + "Rozšiřuje identifikaci protokolu až na 5 bytů." + ] + }, + { + "kicker": "8 / 8 • Velikost", + "title": "Min / max / MTU", + "tip": null, + "lines": [ + "Max. Ethernet II: 1500 + 18 = 1518 B.", + "Min. velikost: 64 B (kolizní okénko).", + "MTU je obvyklé omezení velikosti na routerech." + ] + } + ], + "tasks": [ + { + "number": 1, + "title": "Quiz", + "subtitleKey": "net_quiz21_head", + "items": [ + { + "kind": "choice", + "prompt": "Ethernetová adresa má:", + "options": [ + "48 bitů (6 bytů) a je jedinečná", + "Jen 16 bitů", + "Jen 32 bitů IP", + "Jen 8 bitů SAP" + ], + "correct": 0, + "hint": "MAC adresa Ethernetu má 48 bitů a je unikátní" + }, + { + "kind": "choice", + "prompt": "První 3 byty MAC adresy přiděluje:", + "options": [ + "IEEE výrobci", + "Jen uživatel v BIOS", + "Jen DNS server", + "Jen Aloha" + ], + "correct": 0, + "hint": "IEEE přidělí výrobci první 3 byty adresy" + }, + { + "kind": "choice", + "prompt": "Ethernet II v hlavičce používá:", + "options": [ + "EtherType (např. IP = 0800h, hodnota > 1500)", + "Jen délku ≤ 1500 bez typu", + "Jen FFFFh bez adres", + "Jen AAAAh bez MAC" + ], + "correct": 0, + "hint": "Ethernet II: EtherType > 1500 (IP = 0800h)" + }, + { + "kind": "choice", + "prompt": "IEEE 802.3 místo EtherType má:", + "options": [ + "Údaj o délce (≤ 1500) a uvnitř 802.2", + "Jen cut-through", + "Jen 64 B MTU bez délky", + "Jen laserovou hlavičku" + ], + "correct": 0, + "hint": "IEEE 802.3: délka ≤ 1500 a rámec 802.2" + }, + { + "kind": "choice", + "prompt": "Raw 802.3 (Novell):", + "options": [ + "Bez 802.2, jen IPX, začíná FFFFh", + "Funguje jen s HTTP", + "Má vždy EtherType 0800h", + "Nemá žádné adresy" + ], + "correct": 0, + "hint": "Raw 802.3: Novell/IPX, začíná FFFFh" + }, + { + "kind": "choice", + "prompt": "Maximální rámec Ethernet II je:", + "options": [ + "1518 B (1500 + 18)", + "64 B", + "900 µm", + "250 µm" + ], + "correct": 0, + "hint": "Max. Ethernet II = 1518 B" + }, + { + "kind": "choice", + "prompt": "Minimální velikost rámce plyne z:", + "options": [ + "Kolizního okénka (64 B)", + "Jen z MTU routeru", + "Jen z SNAP AAAAh", + "Jen z Token Ring" + ], + "correct": 0, + "hint": "Min. rámec 64 B kvůli koliznímu okénku" + } + ] + } + ] +} diff --git a/content/lessons/networks/unit-22.json b/content/lessons/networks/unit-22.json new file mode 100644 index 0000000..d6fd503 --- /dev/null +++ b/content/lessons/networks/unit-22.json @@ -0,0 +1,198 @@ +{ + "id": "unit-22", + "subject": "networks", + "number": 22, + "titleKey": "net_unit22", + "subtitleKey": "net_unit22_sub", + "slides": [ + { + "kicker": "1 / 8 • Paket", + "title": "Header a data", + "tip": null, + "lines": [ + "Paket/segment: hlavička (pro partnerskou vrstvu) + data.", + "Protokol určuje strukturu a pravidla stejnolehlých vrstev.", + "Může běžet na různých platformách." + ] + }, + { + "kicker": "2 / 8 • TCP/IP", + "title": "Protokoly po vrstvách", + "tip": null, + "lines": [ + "Aplikační: aplikační protokoly.", + "Transportní: TCP, UDP.", + "Síťová: IP, ARP, RARP, ICMP, IGMP, RIP, OSPF.", + "Síťové rozhraní: Ethernet, Token Ring, ATM, PPP…" + ] + }, + { + "kicker": "3 / 8 • IP", + "title": "Univerzální přenos", + "tip": "Tip: nespojovaný a nespolehlivý", + "lines": [ + "Jediný přenosový protokol TCP/IP nad libovolnou technologií.", + "Pracuje s virtuálními pakety – IP datagramy.", + "Stará se o směrování a přenos; velikost volí odesílatel.", + "Nezaručuje pořadí, dobu ani nepoškozené doručení." + ] + }, + { + "kicker": "4 / 8 • Routing", + "title": "Routing vs forwarding", + "tip": null, + "lines": [ + "Routing: rozhodnutí o dalším směru datagramu.", + "Forwarding: vložení do linkového rámce a odeslání.", + "Linkové adresy se mění podle konkrétní sítě." + ] + }, + { + "kicker": "5 / 8 • Datagram", + "title": "Velikost a HLEN", + "tip": "Tip: Length 5 = 20 B hlavičky", + "lines": [ + "Velikost: od 576 B do 64 kB.", + "Části: hlavička + data.", + "HLEN: délka hlavičky ve 32bitových slovech.", + "TOTAL LENGTH: délka celého paketu v bytech." + ] + }, + { + "kicker": "6 / 8 • Hlavička", + "title": "Klíčová pole", + "tip": null, + "lines": [ + "VERSION (IPv4 = 4), LENGTH, TOTAL LENGTH.", + "IDENTIFICATION + FLAGS + OFFSET = fragmentace.", + "TTL: čítač směrovačů proti zacyklení.", + "PROTOCOL, HEADER CHECKSUM, zdrojová/cílová IP." + ] + }, + { + "kicker": "7 / 8 • PROTOCOL", + "title": "Čísla protokolů", + "tip": null, + "lines": [ + "1 = ICMP, 2 = IGMP, 6 = TCP.", + "17 = UDP, 89 = OSPF.", + "Položka je 8bitová → max. 256 hodnot." + ] + }, + { + "kicker": "8 / 8 • Fragmentace", + "title": "MTU a Ethernet", + "tip": "Tip: Ethernet MTU = 1500 B", + "lines": [ + "Fragmentace, když se datagram nevejde do menšího rámce.", + "MTU udává max. velikost rámce podle hardwaru.", + "DF = nefragmentuj; MF = další fragmenty." + ] + } + ], + "tasks": [ + { + "number": 1, + "title": "Quiz", + "subtitleKey": "net_quiz22_head", + "items": [ + { + "kind": "choice", + "prompt": "IP protokol je:", + "options": [ + "Nespojovaný a nespolehlivý přenos datagramů", + "Spolehlivý a spojovaný jako TCP", + "Jen fyzické kódování", + "Jen EtherType bez IP" + ], + "correct": 0, + "hint": "IP je nespojovaný a nespolehlivý" + }, + { + "kind": "choice", + "prompt": "Routing u IP znamená:", + "options": [ + "Rozhodnutí o dalším směru datagramu", + "Jen CRC na lince", + "Jen MAC učení ve switchi", + "Jen lámání vlákna" + ], + "correct": 0, + "hint": "Routing = rozhodnutí o směru datagramu" + }, + { + "kind": "choice", + "prompt": "Forwarding u IP znamená:", + "options": [ + "Vložení do linkového rámce a odeslání", + "Jen výpočet metriky OSPF", + "Jen DNS překlad", + "Jen Aloha" + ], + "correct": 0, + "hint": "Forwarding = vložení do rámce a odeslání" + }, + { + "kind": "choice", + "prompt": "HLEN (LENGTH) s hodnotou 5 znamená:", + "options": [ + "Hlavičku dlouhou 20 B", + "TTL 5", + "PROTOCOL = 5", + "MTU 5" + ], + "correct": 0, + "hint": "HLEN 5 = 5 × 4 B = 20 B hlavičky" + }, + { + "kind": "choice", + "prompt": "TTL v IP hlavičce:", + "options": [ + "Počítá průchody směrovači a brání zacyklení", + "Udává EtherType", + "Nahrazuje MAC adresu", + "Je vždy 1500" + ], + "correct": 0, + "hint": "TTL snižují směrovače proti zacyklení" + }, + { + "kind": "choice", + "prompt": "Číslo protokolu 6 v IP hlavičce znamená:", + "options": [ + "TCP", + "UDP", + "ICMP", + "OSPF" + ], + "correct": 0, + "hint": "PROTOCOL 6 = TCP" + }, + { + "kind": "choice", + "prompt": "Číslo protokolu 17 znamená:", + "options": [ + "UDP", + "TCP", + "IGMP", + "ARP" + ], + "correct": 0, + "hint": "PROTOCOL 17 = UDP" + }, + { + "kind": "choice", + "prompt": "Ethernet MTU je typicky:", + "options": [ + "1500 B", + "64 kB", + "576 B bez dat", + "20 B hlavičky" + ], + "correct": 0, + "hint": "Ethernet MTU = 1500 B" + } + ] + } + ] +} diff --git a/content/lessons/networks/unit-23.json b/content/lessons/networks/unit-23.json new file mode 100644 index 0000000..61b5af4 --- /dev/null +++ b/content/lessons/networks/unit-23.json @@ -0,0 +1,139 @@ +{ + "id": "unit-23", + "subject": "networks", + "number": 23, + "titleKey": "net_unit23", + "subtitleKey": "net_unit23_sub", + "slides": [ + { + "kicker": "1 / 5 • ICMP", + "title": "Řídicí zprávy", + "tip": "Tip: síťová vrstva, ale nese se v IP datagramu", + "lines": [ + "Zasílá informace o chybách a stavu přenosu.", + "ICMP paket jede přímo v IP datagramu.", + "Směrovače s ním pracují i bez transportní vrstvy." + ] + }, + { + "kicker": "2 / 5 • Zprávy I", + "title": "Quench, TTL, Unreachable", + "tip": null, + "lines": [ + "Source Quench: hrozí zahlcení – zpomal odesílání.", + "Time Exceeded: TTL kleslo na 0, paket zahozen (tracert).", + "Destination Unreachable: cíl (síť/uzel/protokol/port)", + "není dostupný." + ] + }, + { + "kicker": "3 / 5 • Zprávy II", + "title": "Redirect a Echo", + "tip": null, + "lines": [ + "Redirect: přesměruj přenos na jiný (rychlejší) router.", + "Echo Request / Echo Reply: test dostupnosti (ping)." + ] + }, + { + "kicker": "4 / 5 • Traceroute", + "title": "Princip TTL", + "tip": "Tip: typicky max. 30 skoků", + "lines": [ + "Odešle paket s TTL = 1; první router odpoví Time Exceeded.", + "Pak TTL = 2, 3… a tak se zjišťují skoky na cestě.", + "Pokračuje, dokud paket nedorazí do cíle nebo nevyprší limit." + ] + }, + { + "kicker": "5 / 5 • Shrnutí", + "title": "K čemu ICMP slouží", + "tip": null, + "lines": [ + "Diagnostika a hlášení chyb na síťové vrstvě.", + "Základ příkazů ping a traceroute / tracert." + ] + } + ], + "tasks": [ + { + "number": 1, + "title": "Quiz", + "subtitleKey": "net_quiz23_head", + "items": [ + { + "kind": "choice", + "prompt": "ICMP slouží především k:", + "options": [ + "Zasílání informací o chybách a stavu přenosu", + "Jen směrování OSPF tabulek", + "Jen lámání optiky", + "Jen EtherType 0800h" + ], + "correct": 0, + "hint": "ICMP posílá informace o chybách a stavu přenosu" + }, + { + "kind": "choice", + "prompt": "ICMP paket se přenáší:", + "options": [ + "Přímo v IP datagramu", + "Jen jako Ethernet II bez IP", + "Jen v UDP bez IP", + "Jen jako MAC bez datagramu" + ], + "correct": 0, + "hint": "ICMP jede uvnitř IP datagramu" + }, + { + "kind": "choice", + "prompt": "Source Quench znamená:", + "options": [ + "Varování před zahlcením – zpomal odesílání", + "TTL kleslo na 0", + "Cíl je nedostupný", + "Echo Reply" + ], + "correct": 0, + "hint": "Source Quench = zpomal odesílání kvůli zahlcení" + }, + { + "kind": "choice", + "prompt": "Time Exceeded nastane, když:", + "options": [ + "TTL v IP hlavičce klesne na 0", + "Router nemá firewall", + "Použijeme jen SNAP", + "MTU je 1500" + ], + "correct": 0, + "hint": "Time Exceeded = TTL kleslo na 0" + }, + { + "kind": "choice", + "prompt": "Echo Request / Reply využívá příkaz:", + "options": [ + "ping", + "lámačka", + "cut-through", + "hub" + ], + "correct": 0, + "hint": "Echo Request/Reply = ping" + }, + { + "kind": "choice", + "prompt": "Traceroute zjišťuje cestu tak, že:", + "options": [ + "Postupně zvyšuje TTL a čeká na Time Exceeded", + "Posílá jen ARP bez IP", + "Ignoruje směrovače", + "Používá jen CAM tabulku" + ], + "correct": 0, + "hint": "Traceroute zvyšuje TTL a čte Time Exceeded" + } + ] + } + ] +} diff --git a/content/lessons/networks/unit-24.json b/content/lessons/networks/unit-24.json new file mode 100644 index 0000000..2272275 --- /dev/null +++ b/content/lessons/networks/unit-24.json @@ -0,0 +1,138 @@ +{ + "id": "unit-24", + "subject": "networks", + "number": 24, + "titleKey": "net_unit24", + "subtitleKey": "net_unit24_sub", + "slides": [ + { + "kicker": "1 / 5 • ARP / RARP", + "title": "Převod adres", + "tip": null, + "lines": [ + "ARP: z IP adresy na MAC (fyzickou) adresu.", + "RARP: z MAC adresy na IP adresu." + ] + }, + { + "kicker": "2 / 5 • Způsoby", + "title": "Jak zjistit MAC", + "tip": null, + "lines": [ + "Tabulkový převod: ruční správa (malé sítě).", + "Výpočet: funkce, kde MAC plyne z IP.", + "Dotaz a odpověď: dynamické zjišťování (nejčastější)." + ] + }, + { + "kicker": "3 / 5 • Mechanismus", + "title": "Broadcast a unicast", + "tip": "Tip: „Kdo má IP x.x.x.x?“", + "lines": [ + "ARP využívá broadcast v Ethernetu.", + "Odpoví jen uzel s danou IP.", + "Odpověď jde unicastem a obsahuje MAC adresu." + ] + }, + { + "kicker": "4 / 5 • Cache", + "title": "Dočasná paměť", + "tip": "Tip: zobrazení příkazem arp -a", + "lines": [ + "Výsledky se ukládají do ARP cache.", + "Dotazy se tak nemusí stále opakovat.", + "Položky: dynamické (učené) nebo statické (ruční)." + ] + }, + { + "kicker": "5 / 5 • Shrnutí", + "title": "K čemu ARP slouží", + "tip": null, + "lines": [ + "Propojuje síťovou adresu (IP) s linkovou (MAC).", + "Bez ARP by IP datagram nešel vložit do Ethernet rámce." + ] + } + ], + "tasks": [ + { + "number": 1, + "title": "Quiz", + "subtitleKey": "net_quiz24_head", + "items": [ + { + "kind": "choice", + "prompt": "ARP převádí:", + "options": [ + "IP adresu na MAC adresu", + "MAC adresu na IP adresu", + "TCP na UDP", + "TTL na MTU" + ], + "correct": 0, + "hint": "ARP: IP → MAC" + }, + { + "kind": "choice", + "prompt": "RARP převádí:", + "options": [ + "MAC adresu na IP adresu", + "IP adresu na MAC adresu", + "EtherType na SAP", + "OSPF na RIP" + ], + "correct": 0, + "hint": "RARP: MAC → IP" + }, + { + "kind": "choice", + "prompt": "Nejčastější způsob ARP je:", + "options": [ + "Dotaz a odpověď v síti", + "Jen ruční tabulka bez sítě", + "Jen cut-through", + "Jen ICMP Echo" + ], + "correct": 0, + "hint": "Nejčastější je dynamický dotaz a odpověď" + }, + { + "kind": "choice", + "prompt": "ARP dotaz v Ethernetu používá:", + "options": [ + "Broadcast", + "Jen unicast bez broadcastu", + "Jen laser", + "Jen Token Ring bez IP" + ], + "correct": 0, + "hint": "ARP dotaz jde broadcastem" + }, + { + "kind": "choice", + "prompt": "ARP odpověď typicky přichází jako:", + "options": [ + "Unicast s MAC adresou uzlu", + "Broadcast bez MAC", + "Jen Time Exceeded", + "Jen Source Quench" + ], + "correct": 0, + "hint": "ARP odpověď je unicast s MAC" + }, + { + "kind": "choice", + "prompt": "ARP cache slouží k tomu, aby:", + "options": [ + "Se nemusely stále opakovat stejné dotazy", + "Se nahradil směrovač", + "Se zrušila IP adresa", + "Se vypnul Ethernet" + ], + "correct": 0, + "hint": "ARP cache ukládá výsledky dočasně (arp -a)" + } + ] + } + ] +} diff --git a/content/lessons/networks/unit-25.json b/content/lessons/networks/unit-25.json new file mode 100644 index 0000000..78b8985 --- /dev/null +++ b/content/lessons/networks/unit-25.json @@ -0,0 +1,164 @@ +{ + "id": "unit-25", + "subject": "networks", + "number": 25, + "titleKey": "net_unit25", + "subtitleKey": "net_unit25_sub", + "slides": [ + { + "kicker": "1 / 6 • TCP vs UDP", + "title": "Základní rozdíly", + "tip": null, + "lines": [ + "TCP: spolehlivý a spojovaný přenos.", + "Potvrzování, kontrola pořadí a řízení toku.", + "UDP: nespolehlivý a nespojovaný.", + "Minimální režie – neřeší potvrzení ani pořadí." + ] + }, + { + "kicker": "2 / 6 • Porty", + "title": "Multiplex a demultiplex", + "tip": null, + "lines": [ + "Porty rozlišují aplikace (procesy) na jednom uzlu.", + "Multiplex: sběr dat od aplikací do segmentů/datagramů.", + "Demultiplex: doručení příchozích dat správné aplikaci", + "podle čísla portu." + ] + }, + { + "kicker": "3 / 6 • TCP", + "title": "Spojení a vlastnosti", + "tip": "Tip: three-way handshake", + "lines": [ + "Navázání spojení: třícestné podání ruky.", + "Streamově orientovaný a full duplex.", + "Jen unicast – bez multicastu a broadcastu." + ] + }, + { + "kicker": "4 / 6 • Nevýhody TCP", + "title": "Režie a real-time", + "tip": null, + "lines": [ + "Větší režie: hlavička 20 B (UDP má 8 B).", + "Nevhodný pro real-time média: ztráta segmentu", + "zastaví proud a čeká se na znovudoručení.", + "Bez multihomingu – výpadek rozhraní shodí spojení." + ] + }, + { + "kicker": "5 / 6 • Alternativy", + "title": "SCTP a DCCP", + "tip": null, + "lines": [ + "SCTP: multihoming a multistreaming (až 64k proudů).", + "DCCP: datagramy s řízením zahlcení", + "(streaming, IP telefonie)." + ] + }, + { + "kicker": "6 / 6 • Shrnutí", + "title": "Kdy co použít", + "tip": null, + "lines": [ + "TCP: spolehlivá data (web, pošta, soubory).", + "UDP: rychlost a nízká režie (DNS, hry, real-time)." + ] + } + ], + "tasks": [ + { + "number": 1, + "title": "Quiz", + "subtitleKey": "net_quiz25_head", + "items": [ + { + "kind": "choice", + "prompt": "TCP je:", + "options": [ + "Spolehlivý a spojovaný", + "Nespolehlivý a nespojovaný", + "Jen fyzická vrstva", + "Jen ARP cache" + ], + "correct": 0, + "hint": "TCP = spolehlivý a spojovaný" + }, + { + "kind": "choice", + "prompt": "UDP je:", + "options": [ + "Nespolehlivý a nespojovaný s malou režií", + "Spolehlivý se třícestným handshake", + "Jen store-and-forward", + "Jen ICMP Time Exceeded" + ], + "correct": 0, + "hint": "UDP = nespolehlivý, nespojovaný, malá režie" + }, + { + "kind": "choice", + "prompt": "Porty slouží k:", + "options": [ + "Rozlišení aplikací na jednom uzlu", + "Jen směrování IP", + "Jen MAC učení", + "Jen lámání vlákna" + ], + "correct": 0, + "hint": "Porty rozlišují aplikace na uzlu" + }, + { + "kind": "choice", + "prompt": "Navázání TCP spojení používá:", + "options": [ + "Třícestné podání ruky (three-way handshake)", + "Jen broadcast ARP", + "Jen Source Quench", + "Jen cut-through" + ], + "correct": 0, + "hint": "TCP se navazuje three-way handshake" + }, + { + "kind": "choice", + "prompt": "Hlavička TCP má typicky:", + "options": [ + "20 B (UDP 8 B)", + "8 B (UDP 20 B)", + "1500 B", + "64 B min. rámec" + ], + "correct": 0, + "hint": "TCP hlavička 20 B, UDP 8 B" + }, + { + "kind": "choice", + "prompt": "TCP není vhodný pro real-time média hlavně proto, že:", + "options": [ + "Ztráta segmentu zastaví proud a čeká se na znovudoručení", + "Nemá žádné porty", + "Nepodporuje unicast", + "Nemá hlavičku" + ], + "correct": 0, + "hint": "TCP čeká na znovudoručení – špatné pro real-time" + }, + { + "kind": "choice", + "prompt": "SCTP oproti TCP nabízí:", + "options": [ + "Multihoming a multistreaming", + "Jen Ethernet II", + "Jen RARP", + "Jen hub flooding" + ], + "correct": 0, + "hint": "SCTP: multihoming a multistreaming" + } + ] + } + ] +} diff --git a/content/lessons/networks/unit-26.json b/content/lessons/networks/unit-26.json new file mode 100644 index 0000000..023174a --- /dev/null +++ b/content/lessons/networks/unit-26.json @@ -0,0 +1,185 @@ +{ + "id": "unit-26", + "subject": "networks", + "number": 26, + "titleKey": "net_unit26", + "subtitleKey": "net_unit26_sub", + "slides": [ + { + "kicker": "1 / 7 • Úvod", + "title": "Aplikační protokoly", + "tip": null, + "lines": [ + "Na uzlu běží více síťových aplikací současně.", + "Běžící aplikace = v operační paměti (1+ procesů).", + "Pracují podle pravidel – protokolů aplikační vrstvy.", + "Data posílají po síti přes TCP nebo UDP." + ] + }, + { + "kicker": "2 / 7 • Porty", + "title": "Procesy a porty", + "tip": null, + "lines": [ + "Port v TCP/UDP říká, které aplikaci data patří.", + "Jeden proces může používat více portů.", + "Dva procesy nesmí používat stejný port." + ] + }, + { + "kicker": "3 / 7 • Rozsahy", + "title": "Well-known, registrované, dynamické", + "tip": "Tip: IANA", + "lines": [ + "Well-known: 0–1023 – vyhrazené službám (norma IANA).", + "Registrované: 1024–49151 – IANA jen registruje použití.", + "Dynamické/privátní: 49152–65535 – volně k použití." + ] + }, + { + "kicker": "4 / 7 • Spojení", + "title": "Pětice hodnot", + "tip": null, + "lines": [ + "Aplikační spojení určuje pětice:", + "(transport, IP1, port1, IP2, port2).", + "Klient osloví server na well-known portu." + ] + }, + { + "kicker": "5 / 7 • Více spojení", + "title": "Stejný server, různí klienti", + "tip": null, + "lines": [ + "Na jeden uzel (např. web server) může být", + "více aplikačních spojení z různých klientů.", + "Rozlišují je IP a porty klientů (i transport)." + ] + }, + { + "kicker": "6 / 7 • Porty I", + "title": "Časté well-known služby", + "tip": null, + "lines": [ + "20/21 FTP, 22 SSH, 23 Telnet, 25 SMTP, 53 DNS.", + "67/68 DHCP, 80 HTTP, 110 POP3, 143 IMAP.", + "123 NTP, 161 SNMP, 389 LDAP, 443 HTTPS." + ] + }, + { + "kicker": "7 / 7 • Porty II", + "title": "Zabezpečené a registrované", + "tip": null, + "lines": [ + "587 SMTPS, 636 LDAPS, 993 IMAPS, 995 POP3S.", + "Registrované: 3306 MySQL, 3389 RDP, 5900 VNC.", + "Dynamické porty: 49152–65535." + ] + } + ], + "tasks": [ + { + "number": 1, + "title": "Quiz", + "subtitleKey": "net_quiz26_head", + "items": [ + { + "kind": "choice", + "prompt": "Aplikační protokoly typicky posílají data přes:", + "options": [ + "TCP nebo UDP", + "Jen fyzickou vrstvu", + "Jen ARP", + "Jen CAM tabulku" + ], + "correct": 0, + "hint": "Aplikace posílají data přes TCP/UDP" + }, + { + "kind": "choice", + "prompt": "Dva běžící procesy:", + "options": [ + "Nesmí používat stejný port", + "Musí sdílet jeden port", + "Nesmí mít žádný port", + "Používají jen MAC" + ], + "correct": 0, + "hint": "Dva procesy nesmí sdílet stejný port" + }, + { + "kind": "choice", + "prompt": "Well-known porty mají rozsah:", + "options": [ + "0–1023", + "1024–49151", + "49152–65535", + "Jen 80–443" + ], + "correct": 0, + "hint": "Well-known: 0–1023 (IANA)" + }, + { + "kind": "choice", + "prompt": "Dynamické (privátní) porty jsou:", + "options": [ + "49152–65535", + "0–1023", + "Jen 20–21", + "Jen 3306" + ], + "correct": 0, + "hint": "Dynamické porty: 49152–65535" + }, + { + "kind": "choice", + "prompt": "Aplikační spojení určuje:", + "options": [ + "Pětice (transport, IP1, port1, IP2, port2)", + "Jen MAC adresa", + "Jen název souboru", + "Jen VLAN ID" + ], + "correct": 0, + "hint": "Spojení = pětice hodnot" + }, + { + "kind": "choice", + "prompt": "HTTP a HTTPS používají porty:", + "options": [ + "80 a 443", + "22 a 23", + "25 a 110", + "53 a 67" + ], + "correct": 0, + "hint": "HTTP 80, HTTPS 443" + }, + { + "kind": "choice", + "prompt": "SSH a DNS mají porty:", + "options": [ + "22 a 53", + "80 a 443", + "3389 a 5900", + "20 a 21" + ], + "correct": 0, + "hint": "SSH 22, DNS 53" + }, + { + "kind": "choice", + "prompt": "MySQL a RDP jsou typicky na portech:", + "options": [ + "3306 a 3389", + "80 a 443", + "67 a 68", + "161 a 162" + ], + "correct": 0, + "hint": "MySQL 3306, RDP 3389" + } + ] + } + ] +} diff --git a/content/lessons/networks/unit-27.json b/content/lessons/networks/unit-27.json new file mode 100644 index 0000000..8f81dd4 --- /dev/null +++ b/content/lessons/networks/unit-27.json @@ -0,0 +1,196 @@ +{ + "id": "unit-27", + "subject": "networks", + "number": 27, + "titleKey": "net_unit27", + "subtitleKey": "net_unit27_sub", + "slides": [ + { + "kicker": "1 / 8 • Úvod", + "title": "Bezdrátové sítě", + "tip": null, + "lines": [ + "Patří sem hlavně: družicové, mikrovlnné a optické spoje.", + "Dále Wi-Fi (LAN), WiMAX/LTE (MAN/WAN) a další." + ] + }, + { + "kicker": "2 / 8 • Družice", + "title": "Geostacionární spoje", + "tip": null, + "lines": [ + "Geostacionární družice: ~36 000 km, stále nad stejným bodem.", + "Pasivní odrážejí; aktivní mají transpondéry (převod + zisk).", + "C-band ~6/4 GHz; KU-band 12–14 GHz (menší antény).", + "Nevýhoda: zpoždění ~250–300 ms (RTT až ~600 ms)." + ] + }, + { + "kicker": "3 / 8 • VSAT", + "title": "Přístup a topologie", + "tip": null, + "lines": [ + "Bod–bod, broadcast (TV) i multiple access.", + "VSAT: terminály + centrální hub.", + "Komunikace jen terminál ↔ hub (ne přímo mezi terminály)." + ] + }, + { + "kicker": "4 / 8 • Mikrovlny", + "title": "Pozemní spoje", + "tip": "Tip: přímá viditelnost", + "lines": [ + "Frekvence 1–12 GHz, směrování parabolou, malý rozptyl.", + "Dosah typicky do ~50 km; retranslační stanice.", + "Troposférické spoje: odraz ve ~16 km, dosah až ~500 km." + ] + }, + { + "kicker": "5 / 8 • Wi-Fi pojmy", + "title": "AP, BSS, ESS", + "tip": null, + "lines": [ + "AP = přístupový bod; STA komunikují přes AP (ne přímo).", + "BSS = stanice v buňce BSA; ESS = více buněk přes DS.", + "Roaming při překrytí; ad-hoc = P2P bez AP; hotspot = Wi-Fi.", + "ESSID identifikuje síť při přístupu k AP." + ] + }, + { + "kicker": "6 / 8 • Standardy", + "title": "802.11 a … ax", + "tip": null, + "lines": [ + "b: 11 Mb/s, 2,4 GHz; a/g: 54 Mb/s; n: MIMO, až 600 Mb/s.", + "ac (Wi-Fi 5): 256-QAM, široké kanály; ax (Wi-Fi 6): OFDMA.", + "OFDM: mnoho ortogonálních subnosných v kanálu." + ] + }, + { + "kicker": "7 / 8 • Zabezpečení", + "title": "WEP → WPA3", + "tip": null, + "lines": [ + "WEP: RC4, krátký IV – prolomeno (2001), nepoužívat.", + "WPA: TKIP; WPA2: AES (doporučený základ).", + "WPA3: SAE místo PSK, silnější ochrana hesla.", + "802.1X/EAP: ověření klienta přes AP (RADIUS)." + ] + }, + { + "kicker": "8 / 8 • Shrnutí", + "title": "Dosahy a další", + "tip": null, + "lines": [ + "PAN <10 m (Bluetooth); LAN = Wi-Fi; MAN = WiMAX.", + "WAN/mobilita: 802.16e, LTE; licencovaná pásma = méně rušení.", + "Používej WPA2/WPA3 + AES, ne WEP." + ] + } + ], + "tasks": [ + { + "number": 1, + "title": "Quiz", + "subtitleKey": "net_quiz27_head", + "items": [ + { + "kind": "choice", + "prompt": "Geostacionární družice létají asi:", + "options": [ + "36 000 km nad Zemí", + "16 km v troposféře", + "50 km nad povrchem", + "Jen v nízké orbitě LEO" + ], + "correct": 0, + "hint": "Geostacionární družice ~36 000 km" + }, + { + "kind": "choice", + "prompt": "Hlavní nevýhoda družicového spoje je:", + "options": [ + "Velké zpoždění (~250–300 ms)", + "Žádný broadcast", + "Jen kabelové médium", + "Absence portů" + ], + "correct": 0, + "hint": "Družice: zpoždění stovky ms" + }, + { + "kind": "choice", + "prompt": "V síti VSAT komunikace probíhá:", + "options": [ + "Jen mezi terminálem a hubem", + "Přímo mezi dvěma terminály", + "Jen přes ARP", + "Jen přes WEP" + ], + "correct": 0, + "hint": "VSAT: jen terminál ↔ hub" + }, + { + "kind": "choice", + "prompt": "Mikrovlnný spoj typicky vyžaduje:", + "options": [ + "Přímou viditelnost (dosah ~50 km)", + "Jen metalický kabel", + "Jen port 80", + "Jen WEP klíč" + ], + "correct": 0, + "hint": "Mikrovlny: přímá viditelnost ~50 km" + }, + { + "kind": "choice", + "prompt": "V infrastruktuře Wi-Fi stanice (STA):", + "options": [ + "Komunikují přes AP, ne přímo mezi sebou", + "Vždy jen ad-hoc bez AP", + "Nepoužívají ESSID", + "Běží jen na 36 000 km" + ], + "correct": 0, + "hint": "STA komunikují přes AP" + }, + { + "kind": "choice", + "prompt": "802.11ax (Wi-Fi 6) přináší zejména:", + "options": [ + "OFDMA a vysokou kapacitu", + "Jen WEP", + "Jen C-band 4/6 GHz", + "Jen troposférický odraz" + ], + "correct": 0, + "hint": "Wi-Fi 6 (ax): OFDMA" + }, + { + "kind": "choice", + "prompt": "WEP je dnes:", + "options": [ + "Prolomený a nevhodný", + "Nejbezpečnější volba", + "Totéž co WPA3-SAE", + "Povinný od roku 2006" + ], + "correct": 0, + "hint": "WEP prolomen – nepoužívat" + }, + { + "kind": "choice", + "prompt": "Doporučené zabezpečení Wi-Fi je:", + "options": [ + "WPA2/WPA3 s AES (ne WEP)", + "Jen Open system WEP", + "Jen Shared key WEP", + "Bez hesla vždy" + ], + "correct": 0, + "hint": "Používej WPA2/WPA3 + AES" + } + ] + } + ] +} diff --git a/content/manifest.json b/content/manifest.json new file mode 100644 index 0000000..4465664 --- /dev/null +++ b/content/manifest.json @@ -0,0 +1,63 @@ +{ + "subjects": [ + "deutsch", + "networks", + "hardware", + "czech", + "civics", + "english", + "math", + "physics", + "science", + "tech-graphics", + "presentation", + "programming", + "software" + ], + "lessons": { + "deutsch": [ + "unit-01", + "unit-02", + "unit-03" + ], + "networks": [ + "unit-01", + "unit-02", + "unit-03", + "unit-04", + "unit-05", + "unit-06", + "unit-07", + "unit-08", + "unit-09", + "unit-10", + "unit-11", + "unit-12", + "unit-13", + "unit-14", + "unit-15", + "unit-16", + "unit-17", + "unit-18", + "unit-19", + "unit-20", + "unit-21", + "unit-22", + "unit-23", + "unit-24", + "unit-25", + "unit-26", + "unit-27" + ], + "hardware": [ + "unit-01", + "unit-02", + "unit-03" + ], + "czech": [ + "mluvnice", + "orwell-1984", + "fuks-spalovac-mrtvol" + ] + } +} diff --git a/content/paths.json b/content/paths.json new file mode 100644 index 0000000..9cf70d8 --- /dev/null +++ b/content/paths.json @@ -0,0 +1,389 @@ +[ + { + "subject": "deutsch", + "units": [ + { + "number": 1, + "lesson": "unit-01", + "title": { + "cs": "Neue Freunde", + "en": "Neue Freunde" + }, + "unlocked": true + }, + { + "number": 2, + "lesson": "unit-02", + "title": { + "cs": "Aus aller Welt", + "en": "Aus aller Welt" + }, + "unlocked": true + }, + { + "number": 3, + "lesson": "unit-03", + "title": { + "cs": "Bei uns zu Hause", + "en": "Bei uns zu Hause" + }, + "unlocked": true + }, + { + "number": 4, + "lesson": null, + "title": { + "cs": "Schule und Freizeit", + "en": "Schule und Freizeit" + }, + "unlocked": false + }, + { + "number": 5, + "lesson": null, + "title": { + "cs": "Guten Appetit!", + "en": "Guten Appetit!" + }, + "unlocked": false + }, + { + "number": 6, + "lesson": null, + "title": { + "cs": "Mein Tagesablauf", + "en": "Mein Tagesablauf" + }, + "unlocked": false + }, + { + "number": 7, + "lesson": null, + "title": { + "cs": "Meine Freunde", + "en": "Meine Freunde" + }, + "unlocked": false + }, + { + "number": 8, + "lesson": null, + "title": { + "cs": "Wir treffen uns in Salzburg", + "en": "Wir treffen uns in Salzburg" + }, + "unlocked": false + }, + { + "number": 9, + "lesson": null, + "title": { + "cs": "Mein Haus ist meine Burg", + "en": "Mein Haus ist meine Burg" + }, + "unlocked": false + }, + { + "number": 10, + "lesson": null, + "title": { + "cs": "Urlaub in Österreich", + "en": "Urlaub in Österreich" + }, + "unlocked": false + } + ] + }, + { + "subject": "networks", + "year": 1, + "units": [ + { + "number": 1, + "lesson": "unit-01", + "titleKey": "net_unit1", + "unlocked": true + }, + { + "number": 2, + "lesson": "unit-02", + "titleKey": "net_unit2", + "unlocked": true + }, + { + "number": 3, + "lesson": "unit-03", + "titleKey": "net_unit3", + "unlocked": true + }, + { + "number": 4, + "lesson": "unit-04", + "titleKey": "net_unit4", + "unlocked": true + }, + { + "number": 5, + "lesson": "unit-05", + "titleKey": "net_unit5", + "unlocked": true + }, + { + "number": 6, + "lesson": "unit-06", + "titleKey": "net_unit6", + "unlocked": true + }, + { + "number": 7, + "lesson": "unit-07", + "titleKey": "net_unit7", + "unlocked": true + }, + { + "number": 8, + "lesson": "unit-08", + "titleKey": "net_unit8", + "unlocked": true + }, + { + "number": 9, + "lesson": "unit-09", + "titleKey": "net_unit9", + "unlocked": true + }, + { + "number": 10, + "lesson": "unit-10", + "titleKey": "net_unit10", + "unlocked": true + }, + { + "number": 11, + "lesson": "unit-11", + "titleKey": "net_unit11", + "unlocked": true + }, + { + "number": 12, + "lesson": "unit-12", + "titleKey": "net_unit12", + "unlocked": true + }, + { + "number": 13, + "lesson": "unit-13", + "titleKey": "net_unit13", + "unlocked": true + }, + { + "number": 14, + "lesson": "unit-14", + "titleKey": "net_unit14", + "unlocked": true + }, + { + "number": 15, + "lesson": "unit-15", + "titleKey": "net_unit15", + "unlocked": true + }, + { + "number": 16, + "lesson": "unit-16", + "titleKey": "net_unit16", + "unlocked": true + }, + { + "number": 17, + "lesson": "unit-17", + "titleKey": "net_unit17", + "unlocked": true + }, + { + "number": 18, + "lesson": "unit-18", + "titleKey": "net_unit18", + "unlocked": true + }, + { + "number": 19, + "lesson": "unit-19", + "titleKey": "net_unit19", + "unlocked": true + }, + { + "number": 20, + "lesson": "unit-20", + "titleKey": "net_unit20", + "unlocked": true + }, + { + "number": 21, + "lesson": "unit-21", + "titleKey": "net_unit21", + "unlocked": true + }, + { + "number": 22, + "lesson": "unit-22", + "titleKey": "net_unit22", + "unlocked": true + }, + { + "number": 23, + "lesson": "unit-23", + "titleKey": "net_unit23", + "unlocked": true + }, + { + "number": 24, + "lesson": "unit-24", + "titleKey": "net_unit24", + "unlocked": true + }, + { + "number": 25, + "lesson": "unit-25", + "titleKey": "net_unit25", + "unlocked": true + }, + { + "number": 26, + "lesson": "unit-26", + "titleKey": "net_unit26", + "unlocked": true + }, + { + "number": 27, + "lesson": "unit-27", + "titleKey": "net_unit27", + "unlocked": true + } + ] + }, + { + "subject": "hardware", + "units": [ + { + "number": 1, + "lesson": "unit-01", + "titleKey": "hw_unit1", + "unlocked": true + }, + { + "number": 2, + "lesson": "unit-02", + "titleKey": "hw_unit2", + "unlocked": true + }, + { + "number": 3, + "lesson": "unit-03", + "titleKey": "hw_unit3", + "unlocked": true + }, + { + "number": 4, + "lesson": null, + "titleKey": "hw_unit4", + "unlocked": false + }, + { + "number": 5, + "lesson": null, + "titleKey": "hw_unit5", + "unlocked": false + }, + { + "number": 6, + "lesson": null, + "titleKey": "hw_unit6", + "unlocked": false + }, + { + "number": 7, + "lesson": null, + "titleKey": "hw_unit7", + "unlocked": false + }, + { + "number": 8, + "lesson": null, + "titleKey": "hw_unit8", + "unlocked": false + }, + { + "number": 9, + "lesson": null, + "titleKey": "hw_unit9", + "unlocked": false + }, + { + "number": 10, + "lesson": null, + "titleKey": "hw_unit10", + "unlocked": false + } + ] + }, + { + "subject": "czech", + "units": [ + { + "number": 1, + "lesson": null, + "route": null, + "title": { + "cs": "Literatura", + "en": "Literatura" + }, + "unlocked": false + }, + { + "number": 2, + "lesson": null, + "route": "/czech/mluvnice", + "title": { + "cs": "Mluvnice", + "en": "Mluvnice" + }, + "unlocked": true + }, + { + "number": 3, + "lesson": null, + "route": "/czech/reading", + "title": { + "cs": "Maturitní četba", + "en": "Maturitní četba" + }, + "unlocked": true + } + ] + }, + { + "subject": "czech", + "branch": "reading", + "units": [ + { + "number": 1, + "lesson": "orwell-1984", + "title": { + "cs": "George Orwell – 1984", + "en": "George Orwell – 1984" + }, + "unlocked": true + }, + { + "number": 2, + "lesson": "fuks-spalovac-mrtvol", + "title": { + "cs": "Ladislav Fuks – Spalovač mrtvol", + "en": "Ladislav Fuks – Spalovač mrtvol" + }, + "unlocked": true + } + ] + } +] diff --git a/content/schema.ts b/content/schema.ts new file mode 100644 index 0000000..3d5165a --- /dev/null +++ b/content/schema.ts @@ -0,0 +1,337 @@ +/** + * Shared lesson content schema. + * + * This is the single description of everything under `content/`. Both the + * extractor in `tools/` and the Next.js app in `web/` type against it, so a + * shape change here surfaces as a type error on both sides. + */ + +export type Lang = 'cs' | 'en'; + +/** A short piece of text that may differ per UI language. */ +export interface Localized { + cs: string; + en?: string; +} + +/* ---------------------------------------------------------------- themes --- */ + +export interface ThemePalette { + crust: string; + base: string; + mantle: string; + surface0: string; + surface1: string; + surface2: string; + overlay: string; + text: string; + subtext: string; + accent: string; + accent2: string; + accent3: string; + success: string; + success2: string; + warning: string; + error: string; + onAccent: string; + node: string; + lockedBg: string; + lockedBorder: string; + rail: string; + finishDark: string; + finishLight: string; + finishStroke: string; +} + +export interface Theme { + id: string; + name: string; + dark: ThemePalette; + light: ThemePalette; +} + +/* -------------------------------------------------------------- subjects --- */ + +export interface Subject { + /** Stable slug used in URLs, e.g. `deutsch`, `networks`. */ + id: string; + /** i18n key holding the display name. */ + key: string; + icon: 'flag-de' | 'wifi' | 'chip' | 'book' | null; + unlocked: boolean; + /** Route the subject node opens, or null when it is a locked placeholder. */ + route: string | null; +} + +/* ----------------------------------------------------------------- units --- */ + +/** + * One node on a serpentine learning path. + * + * A node carries either a literal `title` (German unit names are the same in + * both languages) or a `titleKey` to look up in the translation tables. + */ +export interface UnitRef { + /** 1-based position on the path. */ + number: number; + /** Slug of the lesson file under `content/lessons//`, if any. */ + lesson: string | null; + title?: Localized; + titleKey?: string; + /** Destination for nodes that open another path rather than a lesson. */ + route?: string | null; + unlocked: boolean; +} + +export interface Path { + subject: string; + /** Optional school-year grouping, as the networks subject uses. */ + year?: number; + /** Set on secondary paths within a subject, e.g. the Czech reading list. */ + branch?: string; + units: UnitRef[]; +} + +/* ----------------------------------------------------------- theory slides - */ + +export interface Slide { + /** Small label above the title, e.g. `1 / 4 • VLSM`. */ + kicker: string; + title: string; + /** Highlighted aside shown under the title. */ + tip: string | null; + lines: string[]; +} + +/* -------------------------------------------------------------- exercises -- */ + +/** Multiple choice. `correct` indexes into `options`. */ +export interface ChoiceExercise { + kind: 'choice'; + prompt: string; + options: string[]; + correct: number; + hint?: string; + /** Czech gloss of the prompt, shown as a translation aid. */ + meaning?: string; +} + +/** + * A sentence split into literal segments with gaps between them. + * + * `segments.length === answers.length + 1`. Every gap variant in the desktop + * app (verb insertion, number words, sequences, possessives, letters) collapses + * into this one shape; `input` decides whether the gap is a dropdown fed from + * `pool` or a free text field. + */ +export interface FillExercise { + kind: 'fill'; + segments: string[]; + answers: string[]; + input: 'select' | 'text'; + /** Row label such as `1.` or `a)`. */ + label?: string; + /** Group heading rendered above this row, e.g. a speaker's name. */ + heading?: string; + /** Emoji or picture clue shown before the sentence. */ + emoji?: string; + /** Extra clue such as the digits to spell out. */ + clue?: string; + /** Czech translation revealed as a hint. */ + meaning?: string; + /** Per-gap glosses, aligned with `answers`. */ + glosses?: (string | null)[]; + /** + * Which of the task's word lists feeds each gap, aligned with `answers`. + * Defaults to the task `pool`; `alt` selects `altPool`. + */ + gapPool?: ('main' | 'alt')[]; + /** Gaps hold single letters rather than whole words, so render them narrow. */ + letters?: boolean; +} + +/** Free-form answer checked against a model answer rather than exactly. */ +export interface FreeExercise { + kind: 'free'; + question: string; + questionCs?: string; + sample: string; + sampleCs?: string; +} + +/** Type the answer; `answers` lists all accepted spellings. */ +export interface TypedExercise { + kind: 'typed'; + prompt: string; + answers: string[]; + meaning?: string; + /** Full model sentence revealed after checking, where one exists. */ + model?: string; + /** Accepted answers are substrings of a longer sentence, not the whole input. */ + substring?: boolean; +} + +/** + * A prompt answered through several labelled fields, as the Czech grammar + * exercises use ("determine gender, number and case"). + */ +export interface FieldsExercise { + kind: 'fields'; + prompt: string; + fields: { label: string; answers: string[] }[]; + /** The full correct answer, revealed after checking. */ + solution?: string; +} + +/** + * Self-assessed exercise: think of the answer, then reveal the model solution. + * Used where no automatic check is meaningful (morpheme analysis, punctuation, + * rewriting direct speech). + */ +export interface RevealExercise { + kind: 'reveal'; + prompt: string; + solution: string; +} + +/** Drag or click words into order to build a sentence. */ +export interface AssemblyExercise { + kind: 'assembly'; + prompt: string; + words: string[]; + meaning?: string; +} + +/** Sort labelled items into named groups. */ +export interface AssignExercise { + kind: 'assign'; + groups: string[]; + items: { emoji: string | null; label: string; group: number; meaning?: string }[]; +} + +/** + * A dialogue where some replies are missing. + * + * `answer` may list several accepted words separated by `|`, matching the + * desktop app's answer comparison. + */ +export interface DialogueExercise { + kind: 'dialogue'; + title: string; + rows: { + speaker: string; + before: string; + answer: string; + after: string; + meaning?: string; + }[]; +} + +/** Guess the word letter by letter. */ +export interface HangmanExercise { + kind: 'hangman'; + word: string; + hint: string; +} + +/** Open profile question with a model answer ("Steckbrief"). */ +export interface ProfileExercise { + kind: 'profile'; + stem: string; + sample: string; +} + +/** Editable grid, e.g. the possessive-pronoun table. */ +export interface TableExercise { + kind: 'table'; + columns: string[]; + rows: string[]; + /** `answers[row][col]`; a prefilled cell has `given: true`. */ + answers: { value: string; given?: boolean }[][]; +} + +/** VLSM subnetting: split a network into four blocks. */ +export interface SubnetExercise { + kind: 'subnet'; + scenario: string; + solution: string; + blocks: { + prefix: number; + network: string; + broadcast: string; + firstHost: string; + lastHost: string; + }[] | null; +} + +export type Exercise = + | ChoiceExercise + | FillExercise + | FreeExercise + | TypedExercise + | FieldsExercise + | RevealExercise + | AssemblyExercise + | AssignExercise + | DialogueExercise + | HangmanExercise + | ProfileExercise + | TableExercise + | SubnetExercise; + +/* ---------------------------------------------------------------- lessons -- */ + +/** A group of exercises presented as one task on the unit map. */ +export interface Task { + /** 1-based bubble number on the unit map. */ + number: number; + /** Short label for the map bubble. */ + title: string; + /** Longer heading for the exercise page, where it differs from `title`. */ + heading?: string; + /** i18n key for the instruction line. */ + subtitleKey: string | null; + /** Literal instruction, where the desktop app passes text instead of a key. */ + subtitle?: string; + /** Worked example shown above the items. */ + example?: string; + /** Extra note under the instruction. */ + note?: string; + /** Words offered to every `select` gap in this task. */ + pool?: string[]; + /** Second word list, selected per gap via `FillExercise.gapPool`. */ + altPool?: string[]; + items: Exercise[]; +} + +export interface VocabSection { + header: string; + items: { prompt: string; answers: string[]; meaning?: string }[]; +} + +export interface Lesson { + /** File slug, unique within the subject. */ + id: string; + subject: string; + /** Position on the subject path. */ + number: number; + /** Literal title, or `titleKey` when the text comes from the i18n tables. */ + title?: Localized; + titleKey?: string; + subtitle?: Localized; + subtitleKey?: string; + /** Theory shown before the exercises. */ + slides: Slide[]; + tasks: Task[]; + /** Optional vocabulary trainer branch. */ + vocab?: VocabSection[]; +} + +/* --------------------------------------------------------------- manifest -- */ + +export interface ContentManifest { + subjects: Subject[]; + paths: Path[]; + /** Lesson ids per subject, in path order. */ + lessons: Record; +} diff --git a/content/subjects.json b/content/subjects.json new file mode 100644 index 0000000..85a3f22 --- /dev/null +++ b/content/subjects.json @@ -0,0 +1,93 @@ +[ + { + "id": "deutsch", + "icon": "flag-de", + "route": "/deutsch", + "key": "Deutsch", + "unlocked": true + }, + { + "id": "networks", + "icon": "wifi", + "route": "/networks", + "key": "Správa počítačových sítí", + "unlocked": true + }, + { + "id": "hardware", + "icon": "chip", + "route": "/hardware", + "key": "Technické vybavení", + "unlocked": true + }, + { + "id": "czech", + "icon": "book", + "route": "/czech", + "key": "Český jazyk a literatura", + "unlocked": true + }, + { + "id": "civics", + "icon": null, + "route": null, + "key": "Občanská nauka", + "unlocked": false + }, + { + "id": "english", + "icon": null, + "route": null, + "key": "English", + "unlocked": false + }, + { + "id": "math", + "icon": null, + "route": null, + "key": "Matematika", + "unlocked": false + }, + { + "id": "physics", + "icon": null, + "route": null, + "key": "Fyzika", + "unlocked": false + }, + { + "id": "science", + "icon": null, + "route": null, + "key": "Základy Přírodopisných věd", + "unlocked": false + }, + { + "id": "tech-graphics", + "icon": null, + "route": null, + "key": "Technická grafika", + "unlocked": false + }, + { + "id": "presentation", + "icon": null, + "route": null, + "key": "Prezentační grafika", + "unlocked": false + }, + { + "id": "programming", + "icon": null, + "route": null, + "key": "Programování", + "unlocked": false + }, + { + "id": "software", + "icon": null, + "route": null, + "key": "Programové vybavení", + "unlocked": false + } +] diff --git a/content/themes.json b/content/themes.json new file mode 100644 index 0000000..00d1298 --- /dev/null +++ b/content/themes.json @@ -0,0 +1,562 @@ +[ + { + "id": "catppuccin", + "name": "Catppuccin", + "dark": { + "crust": "#11111b", + "base": "#1e1e2e", + "mantle": "#181825", + "surface0": "#313244", + "surface1": "#45475a", + "surface2": "#585b70", + "overlay": "#6c7086", + "text": "#cdd6f4", + "subtext": "#a6adc8", + "accent": "#cba6f7", + "accent2": "#b4befe", + "accent3": "#89b4fa", + "success": "#a6e3a1", + "success2": "#94e2d5", + "warning": "#f9e2af", + "error": "#f38ba8", + "onAccent": "#1e1e2e", + "node": "#2b2d40", + "lockedBg": "#24263a", + "lockedBorder": "#383b52", + "rail": "#27293c", + "finishDark": "#1f202e", + "finishLight": "#3b3e58", + "finishStroke": "#52556b" + }, + "light": { + "crust": "#dce0e8", + "base": "#eff1f5", + "mantle": "#e6e9ef", + "surface0": "#ccd0da", + "surface1": "#bcc0cc", + "surface2": "#acb0be", + "overlay": "#9ca0b0", + "text": "#4c4f69", + "subtext": "#6c6f85", + "accent": "#8839ef", + "accent2": "#7287fd", + "accent3": "#1e66f5", + "success": "#40a02b", + "success2": "#179299", + "warning": "#df8e1d", + "error": "#d20f39", + "onAccent": "#eff1f5", + "node": "#e6e9ef", + "lockedBg": "#dce0e8", + "lockedBorder": "#bcc0cc", + "rail": "#ccd0da", + "finishDark": "#dce0e8", + "finishLight": "#bcc0cc", + "finishStroke": "#9ca0b0" + } + }, + { + "id": "nord", + "name": "Nord", + "dark": { + "crust": "#2e3440", + "base": "#3b4252", + "mantle": "#2e3440", + "surface0": "#434c5e", + "surface1": "#4c566a", + "surface2": "#616e88", + "overlay": "#7b88a1", + "text": "#eceff4", + "subtext": "#d8dee9", + "accent": "#88c0d0", + "accent2": "#81a1c1", + "accent3": "#5e81ac", + "success": "#a3be8c", + "success2": "#8fbcbb", + "warning": "#ebcb8b", + "error": "#bf616a", + "onAccent": "#2e3440", + "node": "#434c5e", + "lockedBg": "#3b4252", + "lockedBorder": "#4c566a", + "rail": "#2e3440", + "finishDark": "#2e3440", + "finishLight": "#434c5e", + "finishStroke": "#4c566a" + }, + "light": { + "crust": "#d8dee9", + "base": "#eceff4", + "mantle": "#e5e9f0", + "surface0": "#d8dee9", + "surface1": "#c7ceda", + "surface2": "#b0b8c8", + "overlay": "#7b88a1", + "text": "#2e3440", + "subtext": "#4c566a", + "accent": "#5e81ac", + "accent2": "#81a1c1", + "accent3": "#5e81ac", + "success": "#a3be8c", + "success2": "#8fbcbb", + "warning": "#ebcb8b", + "error": "#bf616a", + "onAccent": "#eceff4", + "node": "#e5e9f0", + "lockedBg": "#d8dee9", + "lockedBorder": "#c7ceda", + "rail": "#d8dee9", + "finishDark": "#d8dee9", + "finishLight": "#c7ceda", + "finishStroke": "#7b88a1" + } + }, + { + "id": "dracula", + "name": "Dracula", + "dark": { + "crust": "#191a21", + "base": "#282a36", + "mantle": "#21222c", + "surface0": "#44475a", + "surface1": "#6272a4", + "surface2": "#707eb0", + "overlay": "#6272a4", + "text": "#f8f8f2", + "subtext": "#bfbfb2", + "accent": "#bd93f9", + "accent2": "#ff79c6", + "accent3": "#8be9fd", + "success": "#50fa7b", + "success2": "#8be9fd", + "warning": "#f1fa8c", + "error": "#ff5555", + "onAccent": "#282a36", + "node": "#383a4a", + "lockedBg": "#2f3240", + "lockedBorder": "#44475a", + "rail": "#21222c", + "finishDark": "#191a21", + "finishLight": "#383a4a", + "finishStroke": "#6272a4" + }, + "light": { + "crust": "#d5d7e0", + "base": "#f8f8f2", + "mantle": "#efefea", + "surface0": "#e2e2d8", + "surface1": "#d0d0c4", + "surface2": "#bfbfb2", + "overlay": "#9a9a8c", + "text": "#282a36", + "subtext": "#44475a", + "accent": "#7c3aed", + "accent2": "#d946a6", + "accent3": "#0891b2", + "success": "#16a34a", + "success2": "#0e7490", + "warning": "#ca8a04", + "error": "#dc2626", + "onAccent": "#f8f8f2", + "node": "#efefea", + "lockedBg": "#e2e2d8", + "lockedBorder": "#d0d0c4", + "rail": "#e2e2d8", + "finishDark": "#d5d7e0", + "finishLight": "#d0d0c4", + "finishStroke": "#9a9a8c" + } + }, + { + "id": "rose-pine", + "name": "Rose Pine", + "dark": { + "crust": "#191724", + "base": "#1f1d2e", + "mantle": "#1f1d2e", + "surface0": "#26233a", + "surface1": "#403d52", + "surface2": "#524f67", + "overlay": "#6e6a86", + "text": "#e0def4", + "subtext": "#908caa", + "accent": "#c4a7e7", + "accent2": "#ebbcba", + "accent3": "#9ccfd8", + "success": "#31748f", + "success2": "#9ccfd8", + "warning": "#f6c177", + "error": "#eb6f92", + "onAccent": "#191724", + "node": "#26233a", + "lockedBg": "#21202e", + "lockedBorder": "#403d52", + "rail": "#191724", + "finishDark": "#191724", + "finishLight": "#26233a", + "finishStroke": "#524f67" + }, + "light": { + "crust": "#f2e9e1", + "base": "#faf4ed", + "mantle": "#fffaf3", + "surface0": "#f2e9e1", + "surface1": "#dfdad9", + "surface2": "#cecacd", + "overlay": "#9893a5", + "text": "#575279", + "subtext": "#797593", + "accent": "#907aa9", + "accent2": "#d7827e", + "accent3": "#56949f", + "success": "#286983", + "success2": "#56949f", + "warning": "#ea9d34", + "error": "#b4637a", + "onAccent": "#faf4ed", + "node": "#fffaf3", + "lockedBg": "#f2e9e1", + "lockedBorder": "#dfdad9", + "rail": "#f2e9e1", + "finishDark": "#f2e9e1", + "finishLight": "#dfdad9", + "finishStroke": "#9893a5" + } + }, + { + "id": "ocean", + "name": "Ocean", + "dark": { + "crust": "#16161e", + "base": "#1a1b26", + "mantle": "#16161e", + "surface0": "#24283b", + "surface1": "#414868", + "surface2": "#565f89", + "overlay": "#565f89", + "text": "#c0caf5", + "subtext": "#a9b1d6", + "accent": "#7aa2f7", + "accent2": "#bb9af7", + "accent3": "#7dcfff", + "success": "#9ece6a", + "success2": "#73daca", + "warning": "#e0af68", + "error": "#f7768e", + "onAccent": "#1a1b26", + "node": "#24283b", + "lockedBg": "#1f2335", + "lockedBorder": "#3b4261", + "rail": "#16161e", + "finishDark": "#16161e", + "finishLight": "#24283b", + "finishStroke": "#414868" + }, + "light": { + "crust": "#d6dae8", + "base": "#e1e2ec", + "mantle": "#d5d6e2", + "surface0": "#c8c9d6", + "surface1": "#b4b6c5", + "surface2": "#9aa0b5", + "overlay": "#7a8199", + "text": "#2e3446", + "subtext": "#4a5168", + "accent": "#2e7de9", + "accent2": "#7847bd", + "accent3": "#007197", + "success": "#387068", + "success2": "#007197", + "warning": "#8c6c3e", + "error": "#c64343", + "onAccent": "#e1e2ec", + "node": "#d5d6e2", + "lockedBg": "#c8c9d6", + "lockedBorder": "#b4b6c5", + "rail": "#c8c9d6", + "finishDark": "#d6dae8", + "finishLight": "#b4b6c5", + "finishStroke": "#7a8199" + } + }, + { + "id": "gruvbox", + "name": "Gruvbox", + "dark": { + "crust": "#1d2021", + "base": "#282828", + "mantle": "#1d2021", + "surface0": "#3c3836", + "surface1": "#504945", + "surface2": "#665c54", + "overlay": "#928374", + "text": "#ebdbb2", + "subtext": "#a89984", + "accent": "#fe8019", + "accent2": "#d3869b", + "accent3": "#83a598", + "success": "#b8bb26", + "success2": "#8ec07c", + "warning": "#fabd2f", + "error": "#fb4934", + "onAccent": "#1d2021", + "node": "#3c3836", + "lockedBg": "#32302f", + "lockedBorder": "#504945", + "rail": "#1d2021", + "finishDark": "#1d2021", + "finishLight": "#3c3836", + "finishStroke": "#504945" + }, + "light": { + "crust": "#ebdbb2", + "base": "#fbf1c7", + "mantle": "#f2e5bc", + "surface0": "#ebdbb2", + "surface1": "#d5c4a1", + "surface2": "#bdae93", + "overlay": "#928374", + "text": "#3c3836", + "subtext": "#504945", + "accent": "#d65d0e", + "accent2": "#b16286", + "accent3": "#076678", + "success": "#79740e", + "success2": "#427b58", + "warning": "#b57614", + "error": "#9d0006", + "onAccent": "#fbf1c7", + "node": "#f2e5bc", + "lockedBg": "#ebdbb2", + "lockedBorder": "#d5c4a1", + "rail": "#ebdbb2", + "finishDark": "#ebdbb2", + "finishLight": "#d5c4a1", + "finishStroke": "#928374" + } + }, + { + "id": "solarized", + "name": "Solarized", + "dark": { + "crust": "#002b36", + "base": "#073642", + "mantle": "#002b36", + "surface0": "#586e75", + "surface1": "#657b83", + "surface2": "#839496", + "overlay": "#93a1a1", + "text": "#fdf6e3", + "subtext": "#93a1a1", + "accent": "#268bd2", + "accent2": "#6c71c4", + "accent3": "#2aa198", + "success": "#859900", + "success2": "#2aa198", + "warning": "#b58900", + "error": "#dc322f", + "onAccent": "#002b36", + "node": "#073642", + "lockedBg": "#002b36", + "lockedBorder": "#586e75", + "rail": "#002b36", + "finishDark": "#002b36", + "finishLight": "#073642", + "finishStroke": "#586e75" + }, + "light": { + "crust": "#eee8d5", + "base": "#fdf6e3", + "mantle": "#eee8d5", + "surface0": "#eee8d5", + "surface1": "#e2dbc6", + "surface2": "#c9c0a6", + "overlay": "#657b83", + "text": "#586e75", + "subtext": "#657b83", + "accent": "#268bd2", + "accent2": "#6c71c4", + "accent3": "#2aa198", + "success": "#859900", + "success2": "#2aa198", + "warning": "#b58900", + "error": "#dc322f", + "onAccent": "#fdf6e3", + "node": "#eee8d5", + "lockedBg": "#e6dfc8", + "lockedBorder": "#93a1a1", + "rail": "#eee8d5", + "finishDark": "#eee8d5", + "finishLight": "#93a1a1", + "finishStroke": "#586e75" + } + }, + { + "id": "everforest", + "name": "Everforest", + "dark": { + "crust": "#1e2326", + "base": "#272e33", + "mantle": "#2d353b", + "surface0": "#374145", + "surface1": "#4f5b58", + "surface2": "#7a8478", + "overlay": "#859289", + "text": "#d3c6aa", + "subtext": "#a7c080", + "accent": "#a7c080", + "accent2": "#d699b6", + "accent3": "#7fbbb3", + "success": "#a7c080", + "success2": "#83c092", + "warning": "#dbbc7f", + "error": "#e67e80", + "onAccent": "#272e33", + "node": "#374145", + "lockedBg": "#2d353b", + "lockedBorder": "#4f5b58", + "rail": "#1e2326", + "finishDark": "#1e2326", + "finishLight": "#374145", + "finishStroke": "#4f5b58" + }, + "light": { + "crust": "#e6e2cc", + "base": "#fdf6e3", + "mantle": "#f4f0d9", + "surface0": "#efebd4", + "surface1": "#e0dcc7", + "surface2": "#a6b0a0", + "overlay": "#939f91", + "text": "#5c6a72", + "subtext": "#829181", + "accent": "#8da101", + "accent2": "#df69ba", + "accent3": "#35a77c", + "success": "#8da101", + "success2": "#35a77c", + "warning": "#dfa000", + "error": "#f85552", + "onAccent": "#fdf6e3", + "node": "#f4f0d9", + "lockedBg": "#efebd4", + "lockedBorder": "#e0dcc7", + "rail": "#e6e2cc", + "finishDark": "#e6e2cc", + "finishLight": "#e0dcc7", + "finishStroke": "#939f91" + } + }, + { + "id": "monokai", + "name": "Monokai", + "dark": { + "crust": "#1d1e19", + "base": "#272822", + "mantle": "#1e1f1a", + "surface0": "#3e3d32", + "surface1": "#49483e", + "surface2": "#75715e", + "overlay": "#75715e", + "text": "#f8f8f2", + "subtext": "#a59f85", + "accent": "#f92672", + "accent2": "#ae81ff", + "accent3": "#66d9ef", + "success": "#a6e22e", + "success2": "#a1efe4", + "warning": "#e6db74", + "error": "#f92672", + "onAccent": "#272822", + "node": "#3e3d32", + "lockedBg": "#2e2f29", + "lockedBorder": "#49483e", + "rail": "#1d1e19", + "finishDark": "#1d1e19", + "finishLight": "#3e3d32", + "finishStroke": "#49483e" + }, + "light": { + "crust": "#e6e3d4", + "base": "#faf8f0", + "mantle": "#f3f0e4", + "surface0": "#e8e4d4", + "surface1": "#d6d2c0", + "surface2": "#b8b49e", + "overlay": "#8a8674", + "text": "#2d2a2e", + "subtext": "#5b5854", + "accent": "#e14775", + "accent2": "#7c5cbf", + "accent3": "#1c7d9b", + "success": "#5b8c2a", + "success2": "#1c7d9b", + "warning": "#b08900", + "error": "#e14775", + "onAccent": "#faf8f0", + "node": "#f3f0e4", + "lockedBg": "#e8e4d4", + "lockedBorder": "#d6d2c0", + "rail": "#e6e3d4", + "finishDark": "#e6e3d4", + "finishLight": "#d6d2c0", + "finishStroke": "#8a8674" + } + }, + { + "id": "one-dark", + "name": "One Dark", + "dark": { + "crust": "#21252b", + "base": "#282c34", + "mantle": "#21252b", + "surface0": "#3b4048", + "surface1": "#4b5263", + "surface2": "#5c6370", + "overlay": "#5c6370", + "text": "#abb2bf", + "subtext": "#7f848e", + "accent": "#c678dd", + "accent2": "#61afef", + "accent3": "#56b6c2", + "success": "#98c379", + "success2": "#56b6c2", + "warning": "#e5c07b", + "error": "#e06c75", + "onAccent": "#282c34", + "node": "#3b4048", + "lockedBg": "#2c313a", + "lockedBorder": "#4b5263", + "rail": "#21252b", + "finishDark": "#21252b", + "finishLight": "#3b4048", + "finishStroke": "#4b5263" + }, + "light": { + "crust": "#e5e5e6", + "base": "#fafafa", + "mantle": "#f0f0f0", + "surface0": "#e5e5e6", + "surface1": "#d0d0d2", + "surface2": "#a0a1a7", + "overlay": "#a0a1a7", + "text": "#383a42", + "subtext": "#696c77", + "accent": "#a626a4", + "accent2": "#4078f2", + "accent3": "#0184bc", + "success": "#50a14f", + "success2": "#0184bc", + "warning": "#c18401", + "error": "#e45649", + "onAccent": "#fafafa", + "node": "#f0f0f0", + "lockedBg": "#e5e5e6", + "lockedBorder": "#d0d0d2", + "rail": "#e5e5e6", + "finishDark": "#e5e5e6", + "finishLight": "#d0d0d2", + "finishStroke": "#a0a1a7" + } + } +] diff --git a/package.json b/package.json new file mode 100644 index 0000000..c568ab2 --- /dev/null +++ b/package.json @@ -0,0 +1,14 @@ +{ + "name": "maturita", + "version": "1.0.0", + "private": true, + "description": "Educational maturita app: GTK 4 desktop client, Next.js web client, shared lesson content.", + "scripts": { + "content": "node tools/build-content.mjs", + "web": "npm --prefix web run dev", + "web:build": "npm --prefix web run build", + "web:install": "npm --prefix web install", + "desktop": "make -C desktop run", + "desktop:build": "make -C desktop" + } +} diff --git a/tools/build-content.mjs b/tools/build-content.mjs new file mode 100644 index 0000000..6a011d6 --- /dev/null +++ b/tools/build-content.mjs @@ -0,0 +1,239 @@ +#!/usr/bin/env node +/** + * Regenerate `content/` from the desktop C sources. + * + * The C app remains the authoring surface for now, so this is a one-way + * export: run it after changing lesson data in `desktop/` to refresh the JSON + * the web app reads. It is deliberately strict — a shape it does not recognise + * throws rather than emitting a half-empty lesson. + */ + +import { mkdirSync, writeFileSync, rmSync } from 'node:fs'; +import { dirname, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +import { parseArray } from './lib/cparse.mjs'; +import { readFileSync } from 'node:fs'; +import { extractThemes } from './extract/themes.mjs'; +import { extractI18n } from './extract/i18n.mjs'; +import { extractNetworks } from './extract/networks.mjs'; +import { extractDeutschUnit1 } from './extract/deutsch.mjs'; +import { extractDeutschUnit2 } from './extract/deutsch-u2.mjs'; +import { extractDeutschUnit3 } from './extract/deutsch-u3.mjs'; +import { extractHardware } from './extract/hardware.mjs'; +import { extractMluvnice } from './extract/mluvnice.mjs'; +import { extractCetba } from './extract/cetba.mjs'; + +const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..'); +const DESKTOP = resolve(ROOT, 'desktop'); +const CONTENT = resolve(ROOT, 'content'); + +const write = (relPath, data) => { + const file = resolve(CONTENT, relPath); + mkdirSync(dirname(file), { recursive: true }); + writeFileSync(file, JSON.stringify(data, null, 2) + '\n'); + return relPath; +}; + +/* ------------------------------------------------------------- subjects --- */ + +/** Mirrors `sub_keys` in subjects.c; only four subjects have content today. */ +const SUBJECTS = [ + { id: 'deutsch', icon: 'flag-de', route: '/deutsch' }, + { id: 'networks', icon: 'wifi', route: '/networks' }, + { id: 'hardware', icon: 'chip', route: '/hardware' }, + { id: 'czech', icon: 'book', route: '/czech' }, + { id: 'civics', icon: null, route: null }, + { id: 'english', icon: null, route: null }, + { id: 'math', icon: null, route: null }, + { id: 'physics', icon: null, route: null }, + { id: 'science', icon: null, route: null }, + { id: 'tech-graphics', icon: null, route: null }, + { id: 'presentation', icon: null, route: null }, + { id: 'programming', icon: null, route: null }, + { id: 'software', icon: null, route: null }, +]; + +function extractSubjects() { + const keys = parseArray(readFileSync(`${DESKTOP}/subjects.c`, 'utf8'), 'sub_keys').map(String); + if (keys.length !== SUBJECTS.length) { + throw new Error(`subjects.c has ${keys.length} keys but the extractor knows ${SUBJECTS.length}`); + } + return SUBJECTS.map((s, i) => ({ ...s, key: keys[i], unlocked: s.route !== null })); +} + +/* ---------------------------------------------------------------- paths --- */ + +/** German unit titles from `unit_meta_init` in main.c. */ +const DEUTSCH_TITLES = [ + 'Neue Freunde', 'Aus aller Welt', 'Bei uns zu Hause', + 'Schule und Freizeit', 'Guten Appetit!', 'Mein Tagesablauf', + 'Meine Freunde', 'Wir treffen uns in Salzburg', + 'Mein Haus ist meine Burg', 'Urlaub in Österreich', +]; + +/** + * `HW_UNITS` bubbles are drawn but only `HW_LESSONS` of them are playable, so + * the trailing nodes stay locked placeholders as they do on the desktop map. + */ +const HW_UNITS = 10; + +/** `cz_keys` in czech.c; "Literatura" has no content yet. */ +const CZECH_NODES = [ + { number: 1, title: 'Literatura', route: null }, + { number: 2, title: 'Mluvnice', route: '/czech/mluvnice' }, + { number: 3, title: 'Maturitní četba', route: '/czech/reading' }, +]; + +function buildPaths({ networkLessons, deutschLessons, hardwareLessons, cetbaLessons }) { + const done = new Set(deutschLessons.map((l) => l.number)); + + const deutsch = { + subject: 'deutsch', + units: DEUTSCH_TITLES.map((title, i) => ({ + number: i + 1, + // Units 1-3 are playable in the desktop app; the rest are placeholders. + lesson: done.has(i + 1) ? `unit-${String(i + 1).padStart(2, '0')}` : null, + title: { cs: title, en: title }, + unlocked: i < 3 && done.has(i + 1), + })), + }; + + const networks = { + subject: 'networks', + year: 1, + units: networkLessons.map((l) => ({ + number: l.number, + lesson: l.id, + titleKey: l.titleKey, + unlocked: true, + })), + }; + + const byNumber = new Map(hardwareLessons.map((l) => [l.number, l])); + const hardware = { + subject: 'hardware', + units: Array.from({ length: HW_UNITS }, (_, i) => { + const lesson = byNumber.get(i + 1); + return { + number: i + 1, + lesson: lesson?.id ?? null, + titleKey: lesson?.titleKey ?? `hw_unit${i + 1}`, + unlocked: Boolean(lesson), + }; + }), + }; + + const czech = { + subject: 'czech', + units: CZECH_NODES.map((node) => ({ + number: node.number, + lesson: null, + route: node.route, + title: { cs: node.title, en: node.title }, + unlocked: node.route !== null, + })), + }; + + const reading = { + subject: 'czech', + branch: 'reading', + units: cetbaLessons.map((l, i) => ({ + number: i + 1, + lesson: l.id, + title: l.title, + unlocked: true, + })), + }; + + return [deutsch, networks, hardware, czech, reading]; +} + +/* ----------------------------------------------------------------- main --- */ + +function main() { + rmSync(resolve(CONTENT, 'lessons'), { recursive: true, force: true }); + + const written = []; + + written.push(write('themes.json', extractThemes(DESKTOP))); + + const i18n = extractI18n(DESKTOP); + written.push(write('i18n/ui.json', i18n.ui)); + written.push(write('i18n/content.json', i18n.content)); + + const subjects = extractSubjects(); + written.push(write('subjects.json', subjects)); + + const networkLessons = extractNetworks(DESKTOP); + for (const lesson of networkLessons) { + written.push(write(`lessons/networks/${lesson.id}.json`, lesson)); + } + + const deutschLessons = [ + extractDeutschUnit1(DESKTOP), + extractDeutschUnit2(DESKTOP), + extractDeutschUnit3(DESKTOP), + ]; + for (const lesson of deutschLessons) { + written.push(write(`lessons/deutsch/${lesson.id}.json`, lesson)); + } + + const hardwareLessons = extractHardware(DESKTOP); + for (const lesson of hardwareLessons) { + written.push(write(`lessons/hardware/${lesson.id}.json`, lesson)); + } + + const czechLessons = [extractMluvnice(DESKTOP), ...extractCetba(DESKTOP)]; + for (const lesson of czechLessons) { + written.push(write(`lessons/czech/${lesson.id}.json`, lesson)); + } + + const cetbaLessons = czechLessons.filter((l) => l.id !== 'mluvnice'); + + const paths = buildPaths({ + networkLessons, + deutschLessons, + hardwareLessons, + cetbaLessons, + }); + written.push(write('paths.json', paths)); + + written.push(write('manifest.json', { + subjects: subjects.map((s) => s.id), + lessons: { + deutsch: deutschLessons.map((l) => l.id), + networks: networkLessons.map((l) => l.id), + hardware: hardwareLessons.map((l) => l.id), + czech: czechLessons.map((l) => l.id), + }, + })); + + const stats = { + 'network lessons': networkLessons.length, + 'network slides': networkLessons.reduce((a, l) => a + l.slides.length, 0), + 'network items': networkLessons.reduce( + (a, l) => a + l.tasks.reduce((b, t) => b + t.items.length, 0), 0), + 'deutsch tasks': deutschLessons.reduce((a, l) => a + l.tasks.length, 0), + 'deutsch items': deutschLessons.reduce( + (a, l) => a + l.tasks.reduce((b, t) => b + t.items.length, 0), 0), + 'vocab words': deutschLessons.reduce( + (a, l) => a + (l.vocab ?? []).reduce((b, s) => b + s.items.length, 0), 0), + 'hardware lessons': hardwareLessons.length, + 'hardware slides': hardwareLessons.reduce((a, l) => a + l.slides.length, 0), + 'hardware items': hardwareLessons.reduce( + (a, l) => a + l.tasks.reduce((b, t) => b + t.items.length, 0), 0), + 'czech lessons': czechLessons.length, + 'czech tasks': czechLessons.reduce((a, l) => a + l.tasks.length, 0), + 'czech items': czechLessons.reduce( + (a, l) => a + l.tasks.reduce((b, t) => b + t.items.length, 0), 0), + 'ui strings': Object.keys(i18n.ui.cs).length, + 'content strings': Object.keys(i18n.content.cs).length, + themes: 10, + }; + + console.log(`wrote ${written.length} files to content/`); + for (const [k, v] of Object.entries(stats)) console.log(` ${k}: ${v}`); +} + +main(); diff --git a/tools/extract/cetba.mjs b/tools/extract/cetba.mjs new file mode 100644 index 0000000..0cace47 --- /dev/null +++ b/tools/extract/cetba.mjs @@ -0,0 +1,114 @@ +import { readFileSync } from 'node:fs'; +import { parseArray, parseArrayInFunction, trimNulls } from '../lib/cparse.mjs'; + +/** + * Maturita reading list ("Četba"): one lesson per book. + * + * Each book page shows four reference cards followed by two exercises, so the + * cards become the lesson's theory slides and the quiz and plot ordering + * become its two tasks. + */ + +/** + * Lesson numbers continue after Mluvnice, so every Czech lesson has a distinct + * number for the statistics page; the reading path numbers its own nodes. + */ +const BOOKS = [ + { + id: 'orwell-1984', + number: 2, + title: 'George Orwell – 1984', + page: 'build_cetba1984_page', + quiz: 'lit_qs', + plot: 'lit_plot_items', + plotMeaning: 'lit_plot_meaning', + cards: [ + ['about', 'O knize'], + ['world', 'Svět a strana'], + ['people', 'Postavy'], + ['terms', 'Klíčové pojmy'], + ], + }, + { + id: 'fuks-spalovac-mrtvol', + number: 3, + title: 'Ladislav Fuks – Spalovač mrtvol', + page: 'build_cetba_fuks_page', + quiz: 'fuks_qs', + plot: 'fuks_plot_items', + plotMeaning: 'fuks_plot_meaning', + cards: [ + ['about', 'O knize'], + ['world', 'Doba a svět'], + ['people', 'Postavy'], + ['terms', 'Klíčové motivy'], + ], + }, +]; + +/** `LitQ`: question, opts[4], correct, explanation. */ +function litChoice(row, label) { + const [prompt, options, correct, expl] = row; + const list = trimNulls(options ?? []).map(String); + + if (typeof correct !== 'number' || correct < 0 || correct >= list.length) { + throw new Error(`${label}: correct index ${correct} out of range for ${list.length} options`); + } + + return { + kind: 'choice', + prompt: String(prompt), + options: list, + correct, + ...(expl ? { hint: String(expl) } : {}), + }; +} + +export function extractCetba(desktopDir) { + const src = readFileSync(`${desktopDir}/cetba.c`, 'utf8'); + + return BOOKS.map((book) => { + const slides = book.cards.map(([arrayName, cardTitle]) => ({ + kicker: book.title, + title: cardTitle, + tip: null, + lines: trimNulls(parseArrayInFunction(src, book.page, arrayName)).map(String), + })); + + const plotMeanings = parseArray(src, book.plotMeaning).map(String); + + return { + id: book.id, + subject: 'czech', + number: book.number, + title: { cs: book.title, en: book.title }, + subtitle: { + cs: 'Projděte si přehled a pak si vyzkoušejte kvíz a řazení děje.', + en: 'Read the overview, then try the quiz and the plot ordering.', + }, + slides, + tasks: [ + { + number: 1, + title: 'Kvíz', + heading: 'Kvíz ke knize', + subtitleKey: 'lit_quiz_sub', + items: parseArray(src, book.quiz) + .map((row, i) => litChoice(row, `${book.id} q${i + 1}`)), + }, + { + number: 2, + title: 'Děj', + heading: 'Seřaďte děj', + subtitleKey: 'lit_plot_sub', + items: parseArray(src, book.plot).map(([prompt, words], i) => ({ + kind: 'assembly', + prompt: prompt ? String(prompt) : '', + words: trimNulls(words).map(String), + ...(plotMeanings[i] ? { meaning: plotMeanings[i] } : {}), + })), + }, + ], + }; + }); +} diff --git a/tools/extract/deutsch-helpers.mjs b/tools/extract/deutsch-helpers.mjs new file mode 100644 index 0000000..61a7bf6 --- /dev/null +++ b/tools/extract/deutsch-helpers.mjs @@ -0,0 +1,196 @@ +import { parseArray, trimNulls } from '../lib/cparse.mjs'; + +/** Shared conversions for the three Deutsch units. */ + +export const opt = (v) => (v === null || v === undefined || v === '' ? undefined : String(v)); + +/** Split the pipe-separated accepted-answer lists used by TypedQ and friends. */ +export const alternatives = (s) => + String(s ?? '').split('|').map((a) => a.trim()).filter(Boolean); + +/** `VerbQ`/`SeqQ` `{before, after, answer}` becomes a single-gap fill sentence. */ +export function verbFill(row, meaning, extra = {}) { + const [before, after, answer] = row; + return { + kind: 'fill', + segments: [before ?? '', after ?? ''], + answers: [String(answer)], + input: 'select', + ...(meaning ? { meaning: String(meaning) } : {}), + ...extra, + }; +} + +/** + * `U3Fill` alternates literal segments and answers: s0, a0, s1, a1, s2, a2, s3. + * Trailing NULLs mean the row uses fewer than three gaps. + */ +export function u3Fill(row, { gloss } = {}) { + const [num, ...rest] = row; + const mean = rest.pop(); + const parts = rest; + + const segments = []; + const answers = []; + for (let i = 0; i < parts.length; i++) { + if (i % 2 === 0) segments.push(parts[i] ?? ''); + else if (parts[i] !== null && parts[i] !== undefined) answers.push(String(parts[i])); + } + + // Drop segments that only exist to pad unused gaps. + while (segments.length > answers.length + 1) segments.pop(); + + return { + kind: 'fill', + segments, + answers, + input: 'select', + ...(opt(num) ? { label: String(num) } : {}), + ...(opt(mean) ? { meaning: String(mean) } : {}), + ...(gloss ? { glosses: [String(gloss)] } : {}), + }; +} + +/** `U3Let`: s0, a0, s1, a1, s2, a2, s3, a3, s4 — gaps hold missing letters. */ +export function u3Letters(row) { + const [num, s0, a0, s1, a1, s2, a2, s3, a3, s4, mean] = row; + const rawSegments = [s0, s1, s2, s3, s4]; + const rawAnswers = [a0, a1, a2, a3]; + + const answers = rawAnswers.filter((a) => a !== null && a !== undefined).map(String); + const segments = rawSegments.slice(0, answers.length + 1).map((s) => s ?? ''); + + return { + kind: 'fill', + segments, + answers, + input: 'text', + letters: true, + ...(opt(num) ? { label: String(num) } : {}), + ...(opt(mean) ? { meaning: String(mean) } : {}), + }; +} + +/** + * `Ex4Row`: seg[5], ans[4] (missing letters), czech, word[4], gmean[4], gaps. + * Each gap's gloss pairs the completed German word with its Czech meaning. + */ +export function ex4Letters(row) { + const [seg, ans, czech, word, gmean, gaps] = row; + const answers = ans.slice(0, gaps).map(String); + const segments = seg.slice(0, gaps + 1).map((s) => s ?? ''); + + const glosses = answers.map((_, i) => { + const w = opt(word?.[i]); + const m = opt(gmean?.[i]); + if (w && m) return `${w} — ${m}`; + return w ?? m ?? null; + }); + + return { + kind: 'fill', + segments, + answers, + input: 'text', + letters: true, + ...(opt(czech) ? { meaning: String(czech) } : {}), + glosses, + }; +} + +/** `Ex2Row`: num, seg[4], ans[3], gaps — grouped under an `Ex2Item`'s translation. */ +export function ex2Row(row, czech) { + const [num, seg, ans, gaps] = row; + return { + kind: 'fill', + segments: seg.slice(0, gaps + 1).map((s) => s ?? ''), + answers: ans.slice(0, gaps).map(String), + input: 'select', + ...(opt(num) ? { label: String(num) } : {}), + ...(opt(czech) ? { meaning: String(czech) } : {}), + }; +} + +/** `ChoiceQ`: prompt, options[5], n_options, correct. */ +export function choiceItem(row, meaning) { + const [prompt, options, n, correct] = row; + const list = trimNulls(options ?? []).map(String); + const count = typeof n === 'number' ? n : list.length; + + if (typeof correct !== 'number' || correct < 0 || correct >= count) { + throw new Error(`choice '${prompt}': correct index ${correct} out of range`); + } + + return { + kind: 'choice', + prompt: String(prompt), + options: list.slice(0, count), + correct, + ...(opt(meaning) ? { meaning: String(meaning) } : {}), + }; +} + +/** `TypedQ`: prompt, pipe-separated answers, Czech meaning. */ +export function typedItem(row) { + const [prompt, answers, meaning] = row; + return { + kind: 'typed', + prompt: String(prompt), + answers: alternatives(answers), + ...(opt(meaning) ? { meaning: String(meaning) } : {}), + }; +} + +/** `FreeQ`: question, Czech question, sample, Czech sample. */ +export function freeItem(row) { + const [question, questionCs, sample, sampleCs] = row; + return { + kind: 'free', + question: String(question), + ...(opt(questionCs) ? { questionCs: String(questionCs) } : {}), + sample: String(sample), + ...(opt(sampleCs) ? { sampleCs: String(sampleCs) } : {}), + }; +} + +/** `AssemblyItem`: prompt, words[6], n. */ +export function assemblyItem(row, meaning) { + const [prompt, words] = row; + return { + kind: 'assembly', + prompt: opt(prompt) ?? '', + words: trimNulls(words).map(String), + ...(opt(meaning) ? { meaning: String(meaning) } : {}), + }; +} + +/** One `assign` exercise built from `AssignItem[]`, group labels and meanings. */ +export function assignExercise(src, itemsName, groupsName, meaningName) { + const meanings = meaningName ? parseArray(src, meaningName) : []; + return { + kind: 'assign', + groups: parseArray(src, groupsName).map(String), + items: parseArray(src, itemsName).map(([emoji, label, group], i) => ({ + emoji: emoji ?? null, + label: String(label), + group, + ...(opt(meanings[i]) ? { meaning: String(meanings[i]) } : {}), + })), + }; +} + +/** Vocabulary trainer sections: `TransSection[]` referencing `TypedQ[]` arrays. */ +export function vocabSections(src, sectionsName) { + return parseArray(src, sectionsName).map(([header, arrayRef]) => { + const name = arrayRef?.__c; + if (!name) throw new Error(`vocab section '${header}' has no data array`); + return { + header: String(header), + items: parseArray(src, name).map(([prompt, answers, meaning]) => ({ + prompt: String(prompt), + answers: alternatives(answers), + ...(opt(meaning) ? { meaning: String(meaning) } : {}), + })), + }; + }); +} diff --git a/tools/extract/deutsch-u2.mjs b/tools/extract/deutsch-u2.mjs new file mode 100644 index 0000000..b8f3dc6 --- /dev/null +++ b/tools/extract/deutsch-u2.mjs @@ -0,0 +1,159 @@ +import { readFileSync } from 'node:fs'; +import { parseArray, parseString } from '../lib/cparse.mjs'; +import { + choiceItem, + freeItem, + opt, + typedItem, + verbFill, + vocabSections, +} from './deutsch-helpers.mjs'; + +/** + * Deutsch Unit 2 ("Familie und Freunde"). + * + * Task order, titles and instruction keys come from the `u2exN` builders at the + * bottom of exercise_u2.c; each one names the `const` arrays holding its data. + */ +export function extractDeutschUnit2(desktopDir) { + const src = readFileSync(`${desktopDir}/exercise_u2.c`, 'utf8'); + const tasks = []; + + /** `build_verb_ex`: one pool feeding single-gap sentences. */ + const verbTask = (number, title, subtitleKey, prefix, { gloss = false } = {}) => { + const meanings = parseArray(src, `${prefix}_mean`); + const glosses = gloss ? parseArray(src, `${prefix}_gloss`) : null; + return { + number, + title, + subtitleKey, + pool: parseArray(src, `${prefix}_pool`).map(String), + items: parseArray(src, `${prefix}_rows`).map((row, i) => + verbFill(row, meanings[i], glosses && opt(glosses[i]) + ? { glosses: [String(glosses[i])] } + : {})), + }; + }; + + const choiceTask = (number, title, subtitleKey, prefix) => { + const meanings = parseArray(src, `${prefix}_mean`); + return { + number, + title, + subtitleKey, + items: parseArray(src, `${prefix}_rows`).map((row, i) => choiceItem(row, meanings[i])), + }; + }; + + const typedTask = (number, title, subtitleKey, rowsName, bankName) => ({ + number, + title, + subtitleKey, + ...(bankName ? { note: parseString(src, bankName) } : {}), + items: parseArray(src, rowsName).map(typedItem), + }); + + /* 1 — Verben konjugieren: two people, each a headed group over one pool. */ + { + const pool = parseArray(src, 'g01_pool').map(String); + const groups = [ + ['Peter Fritsch:', 'g01_peter', 'g01_peter_mean'], + ['Jana Nová und Pavol Korčák:', 'g01_jana', 'g01_jana_mean'], + ]; + + const items = groups.flatMap(([heading, rowsName, meanName]) => { + const meanings = parseArray(src, meanName); + return parseArray(src, rowsName).map((row, i) => + verbFill(row, meanings[i], i === 0 ? { heading } : {})); + }); + + tasks.push({ + number: 1, + title: 'Verben konjugieren', + subtitleKey: 'sub_verben', + pool, + items, + }); + } + + tasks.push(choiceTask(2, 'aus oder in', 'sub_ausin', 'g02')); + tasks.push(choiceTask(3, 'Fragewörter', 'sub_wer', 'g03')); + tasks.push(verbTask(4, 'sprechen', 'sub_sprich', 'g04')); + tasks.push(typedTask(5, 'Nationalitäten', 'sub_nation', 'g05_rows', 'g05_bank')); + tasks.push(typedTask(6, 'Woher?', 'sub_woher', 'g06_rows')); + tasks.push(typedTask(7, 'Länder schreiben', 'sub_laender', 'g07_rows')); + tasks.push(verbTask(8, 'Verben einsetzen', 'sub_verb2', 'g08')); + + /* 9 — Freie Antwort */ + tasks.push({ + number: 9, + title: 'Freie Antwort', + subtitleKey: 'sub_free', + items: parseArray(src, 'ex9_free_qs').map(freeItem), + }); + + tasks.push(verbTask(10, 'Euro', 'sub_euro', 'g10')); + tasks.push(typedTask(11, 'Wörter suchen', 'sub_wortsuchen', 'g11_rows')); + tasks.push(choiceTask(12, 'Was ist richtig?', 'sub_verb2', 'g12')); + + /* 13 — Ordne zu: a Fragewort dropdown and an answer dropdown per row. */ + { + const meanings = parseArray(src, 'g13_mean'); + tasks.push({ + number: 13, + title: 'Ordne zu', + subtitleKey: 'sub_ordne', + pool: parseArray(src, 'g13_fw_pool').map(String), + altPool: parseArray(src, 'g13_ans_pool').map(String), + items: parseArray(src, 'g13_rows').map(([mid, fw, ans], i) => ({ + kind: 'fill', + segments: ['', ` ${mid} → `, ''], + answers: [String(fw), String(ans)], + input: 'select', + gapPool: ['main', 'alt'], + label: `${i + 1}.`, + ...(opt(meanings[i]) ? { meaning: String(meanings[i]) } : {}), + })), + }); + } + + tasks.push(verbTask(14, 'Lückentext', 'sub_luecke', 'g14', { gloss: true })); + tasks.push(verbTask(15, 'Verbinde', 'sub_verbinde', 'g15', { gloss: true })); + tasks.push(verbTask(16, 'Zahlen', 'sub_zahlpaar', 'g16')); + + /* 17 — Steckbrief */ + tasks.push({ + number: 17, + title: 'Steckbrief', + subtitleKey: 'sub_steckbrief', + items: parseArray(src, 's01_rows').map(([stem, sample]) => ({ + kind: 'profile', + stem: String(stem), + sample: String(sample), + })), + }); + + /* 18 — Berufe: hangman, one round per profession. */ + { + const words = parseArray(src, 'hm_words').map(String); + const tips = parseArray(src, 'hm_tips').map(String); + tasks.push({ + number: 18, + title: 'Berufe', + subtitleKey: 'sub_berufe', + items: words.map((word, i) => ({ kind: 'hangman', word, hint: tips[i] })), + }); + } + + tasks.push(typedTask(19, 'Nationalität', 'sub_bistdu', 's03_rows')); + + return { + id: 'unit-02', + subject: 'deutsch', + number: 2, + title: { cs: 'Aus aller Welt', en: 'Aus aller Welt' }, + slides: [], + tasks, + vocab: vocabSections(src, 'u2_trans_sections'), + }; +} diff --git a/tools/extract/deutsch-u3.mjs b/tools/extract/deutsch-u3.mjs new file mode 100644 index 0000000..de12c2b --- /dev/null +++ b/tools/extract/deutsch-u3.mjs @@ -0,0 +1,174 @@ +import { readFileSync } from 'node:fs'; +import { parseArray, parseString } from '../lib/cparse.mjs'; +import { + alternatives, + assemblyItem, + assignExercise, + ex2Row, + ex4Letters, + opt, + typedItem, + u3Fill, + u3Letters, + vocabSections, +} from './deutsch-helpers.mjs'; + +/** + * Deutsch Unit 3 ("Bei uns zu Hause"). + * + * Most tasks go through `u3_build_drop` (dropdown gaps over a shared pool); + * the rest are hand-built pages whose data arrays are read here directly. + */ +export function extractDeutschUnit3(desktopDir) { + const src = readFileSync(`${desktopDir}/exercise_u3.c`, 'utf8'); + const tasks = []; + + /** `u3_build_drop`: `U3Fill` rows sharing one dropdown pool. */ + const dropTask = (number, title, subtitleKey, prefix, { example, gloss } = {}) => { + const glosses = gloss ? parseArray(src, `${prefix}_gloss`) : null; + return { + number, + title, + subtitleKey, + ...(example ? { example } : {}), + pool: parseArray(src, `${prefix}_pool`).map(String), + items: parseArray(src, `${prefix}_rows`).map((row, i) => + u3Fill(row, { gloss: glosses ? opt(glosses[i]) : undefined })), + }; + }; + + tasks.push(dropTask(1, 'Familienpaare', 'sub3_pair', 'ex1_u3', { + example: 'Beispiel: der Vater ↔ die Mutter', + })); + + /* 2 — mein oder dein: rows grouped per item, each item has one translation. */ + tasks.push({ + number: 2, + title: 'mein oder dein', + subtitleKey: 'sub3_poss', + example: + 'Beispiel: Ist das dein Vater? – Nein, das ist nicht mein Vater. ' + + 'Das ist sein Onkel.', + pool: parseArray(src, 'ex2_u3_pool').map(String), + items: parseArray(src, 'ex2_u3_items').flatMap(([czech, rowsRef]) => { + const name = rowsRef?.__c; + if (!name) throw new Error(`ex2_u3_items row group for '${czech}' has no data array`); + return parseArray(src, name).map((row) => ex2Row(row, czech)); + }), + }); + + tasks.push(dropTask(3, 'ein / kein', 'sub3_haustier', 'ex3_u3', { + example: + 'Beispiel: Hast du eine Katze? – Nein, ich habe keine Katze. ' + + 'Ich habe einen Hund.', + })); + + /* 4 — Lückentext: missing letters inside words. */ + tasks.push({ + number: 4, + title: 'Lückentext', + subtitleKey: 'sub3_buchst', + items: parseArray(src, 'ex4_u3_rows').map(ex4Letters), + }); + + /* 5 — Marcos Familie */ + tasks.push({ + number: 5, + title: 'Marcos Familie', + subtitleKey: 'sub3_marco', + note: parseString(src, 'ex5_u3_bank'), + items: parseArray(src, 'ex5_u3_rows').map(typedItem), + }); + + /* 6 — Sortieren */ + tasks.push({ + number: 6, + title: 'Sortieren', + subtitleKey: 'sub3_sort', + items: [assignExercise(src, 'ex6_u3_items', 'ex6_u3_groups', 'ex6_u3_meaning')], + }); + + /* 7 — Possessivtabelle: nouns down the side, persons across the top. */ + { + const persons = ['ich', 'du', 'er', 'sie', 'es', 'wir', 'ihr', 'sie / Sie']; + const nouns = ['der Garten', 'die Idee', 'das Fest', 'die Geschwister']; + const forms = [ + ['mein', 'dein', 'sein', 'ihr', 'sein', 'unser', 'euer', 'ihr'], + ['meine', 'deine', 'seine', 'ihre', 'seine', 'unsere', 'eure', 'ihre'], + ['mein', 'dein', 'sein', 'ihr', 'sein', 'unser', 'euer', 'ihr'], + ['meine', 'deine', 'seine', 'ihre', 'seine', 'unsere', 'eure', 'ihre'], + ]; + + tasks.push({ + number: 7, + title: 'Possessivtabelle', + subtitleKey: 'sub3_tabelle', + items: [{ + kind: 'table', + columns: persons, + rows: nouns, + answers: forms.map((row) => row.map((value) => ({ value }))), + }], + }); + } + + tasks.push(dropTask(8, 'Akkusativ', 'sub3_akk', 'ex8_u3', { + example: 'Beispiel: die Inliner (ich) → Ich brauche meine Inliner.', + gloss: true, + })); + tasks.push(dropTask(9, 'kein / nicht', 'sub3_nicht', 'ex9_u3')); + + /* 10 — Sätze bauen */ + { + const meanings = parseArray(src, 'ex10_u3_meaning'); + tasks.push({ + number: 10, + title: 'Sätze bauen', + subtitleKey: 'sub3_satz', + items: parseArray(src, 'ex10_u3_items').map((row, i) => assemblyItem(row, meanings[i])), + }); + } + + /* 11 + 14 — `u3_build_kw`: free sentence checked for the required keywords. */ + const keywordTask = (number, title, subtitleKey, qsName, example) => ({ + number, + title, + subtitleKey, + example, + items: parseArray(src, qsName).map(([prompt, answers, mean, german]) => ({ + kind: 'typed', + prompt: String(prompt), + answers: alternatives(answers), + substring: true, + ...(opt(mean) ? { meaning: String(mean) } : {}), + ...(opt(german) ? { model: String(german) } : {}), + })), + }); + + tasks.push(keywordTask(11, 'Was siehst du?', 'sub3_sehen', 'ex11_u3_qs', + 'Beispiel: Ich sehe eine Burg. / Ich sehe ein Schloss.')); + + tasks.push(dropTask(12, 'Wem gehört das?', 'sub3_wem', 'ex12_u3')); + tasks.push(dropTask(13, 'Es gibt …', 'sub3_gibt', 'ex13_u3')); + + tasks.push(keywordTask(14, 'Beschreiben', 'sub3_saetze', 'ex14_u3_qs', + 'Beispiel: Ich sehe einen Jungen. Er liest ein Buch.')); + + /* 15 — Wochenende: missing letters again, but with no per-gap glosses. */ + tasks.push({ + number: 15, + title: 'Wochenende', + subtitleKey: 'sub3_wochen', + items: parseArray(src, 'ex15_u3_rows').map(u3Letters), + }); + + return { + id: 'unit-03', + subject: 'deutsch', + number: 3, + title: { cs: 'Bei uns zu Hause', en: 'Bei uns zu Hause' }, + slides: [], + tasks, + vocab: vocabSections(src, 'u3_trans_sections'), + }; +} diff --git a/tools/extract/deutsch.mjs b/tools/extract/deutsch.mjs new file mode 100644 index 0000000..897be4a --- /dev/null +++ b/tools/extract/deutsch.mjs @@ -0,0 +1,249 @@ +import { readFileSync } from 'node:fs'; +import { parseArray, trimNulls } from '../lib/cparse.mjs'; + +/** + * Deutsch Unit 1 ("Neue Freunde"). + * + * The desktop app defines each exercise's data as a `const` array next to its + * `build_*` function; the task order and titles come from + * `build_exercise_page` in main.c and `u1_ex_names` in globals.c. + */ + +const opt = (v) => (v === null || v === undefined || v === '' ? undefined : String(v)); + +/** Split the pipe-separated accepted-answer lists used by TypedQ. */ +const alternatives = (s) => String(s).split('|').map((a) => a.trim()).filter(Boolean); + +/** `{before, after, answer}` becomes a single-gap fill sentence. */ +function verbFill(row, meaning, extra = {}) { + const [before, after, answer] = row; + return { + kind: 'fill', + segments: [before ?? '', after ?? ''], + answers: [String(answer)], + input: 'select', + ...(meaning ? { meaning: String(meaning) } : {}), + ...extra, + }; +} + +export function extractDeutschUnit1(desktopDir) { + const u1 = readFileSync(`${desktopDir}/exercise_u1.c`, 'utf8'); + const common = readFileSync(`${desktopDir}/exercise_common.c`, 'utf8'); + + const tasks = []; + + /* 1 — Dialog: three dialogues sharing one word pool, one gap per line. */ + { + const meanings = parseArray(common, 'ex1_meaning'); + const pool = parseArray(common, 'ex1_pool'); + const dialogues = [ + ['Sich vorstellen', parseArray(common, 'ex1_d1')], + ['Begrüßung', parseArray(common, 'ex1_d2')], + ['Verabschiedung', parseArray(common, 'ex1_d3')], + ]; + + let i = 0; + const items = dialogues.map(([title, rows]) => ({ + kind: 'dialogue', + title, + rows: rows.map(([speaker, before, answer, after]) => ({ + speaker: speaker ?? '', + before: before ?? '', + answer: String(answer), + after: after ?? '', + meaning: opt(meanings[i++]), + })), + })); + + tasks.push({ number: 1, title: 'Dialog', subtitleKey: 'sub_dialog', pool, items }); + } + + /* 2 — Sätze bilden */ + { + const meanings = parseArray(common, 'ex2_meaning'); + tasks.push({ + number: 2, + title: 'Sätze bilden', + subtitleKey: 'sub_assembly', + items: parseArray(common, 'ex2_items').map(([prompt, words], i) => ({ + kind: 'assembly', + prompt: opt(prompt) ?? '', + words: trimNulls(words).map(String), + meaning: opt(meanings[i]), + })), + }); + } + + /* 3 + 9 — multiple choice */ + const choiceTask = (number, title, subtitleKey, qsName, meanName) => { + const meanings = parseArray(u1, meanName); + return { + number, + title, + subtitleKey, + items: parseArray(u1, qsName).map(([prompt, options, n, correct], i) => ({ + kind: 'choice', + prompt: String(prompt), + options: trimNulls(options).map(String).slice(0, n), + correct, + meaning: opt(meanings[i]), + })), + }; + }; + tasks.push(choiceTask(3, 'Was ist richtig?', 'sub_choice_num', 'ex3_questions', 'ex3_meaning')); + + /* 4 — Freie Antwort */ + tasks.push({ + number: 4, + title: 'Freie Antwort', + subtitleKey: 'sub_free', + items: parseArray(u1, 'ex4_questions').map(([question, questionCs, sample, sampleCs]) => ({ + kind: 'free', + question: String(question), + questionCs: opt(questionCs), + sample: String(sample), + sampleCs: opt(sampleCs), + })), + }); + + /* 5 — Zahlen: digits shown as the clue, pick the German word. */ + { + const meanings = parseArray(u1, 'ex5_meaning'); + tasks.push({ + number: 5, + title: 'Zahlen', + subtitleKey: 'sub_zahlen', + pool: parseArray(u1, 'ex5_pool'), + items: parseArray(u1, 'ex5_data').map(([digits, answer], i) => ({ + kind: 'fill', + segments: ['', ''], + answers: [String(answer)], + input: 'select', + clue: String(digits), + meaning: opt(meanings[i]), + })), + }); + } + + /* 6 — Wie viel?: the emoji is repeated `count` times as the clue. */ + { + const meanings = parseArray(u1, 'ex6_meaning'); + tasks.push({ + number: 6, + title: 'Wie viel?', + subtitleKey: 'sub_wieviel', + pool: parseArray(u1, 'ex6_pool'), + items: parseArray(u1, 'ex6_data').map(([emoji, count, noun, answer], i) => ({ + kind: 'fill', + segments: ['', ` ${noun}`], + answers: [String(answer)], + input: 'select', + emoji: Array.from({ length: count }, () => emoji).join(' '), + meaning: opt(meanings[i]), + })), + }); + } + + /* 7 — Zahlenreihe */ + { + const meanings = parseArray(u1, 'ex7_meaning'); + tasks.push({ + number: 7, + title: 'Zahlenreihe', + subtitleKey: 'sub_reihe', + pool: parseArray(u1, 'ex7_pool'), + items: parseArray(u1, 'ex7_data').map((row, i) => verbFill(row, meanings[i])), + }); + } + + /* 8 — Verb einsetzen */ + { + const meanings = parseArray(u1, 'ex8_meaning'); + tasks.push({ + number: 8, + title: 'Verb einsetzen', + subtitleKey: 'sub_verb', + pool: parseArray(u1, 'ex8_pool'), + items: parseArray(u1, 'ex8_data').map((row, i) => verbFill(row, meanings[i])), + }); + } + + tasks.push(choiceTask(9, 'Wer? Wie? Wo?', 'sub_wer', 'ex9_questions', 'ex9_meaning')); + + /* 10 — Wörter trennen: split a run-together string into words. */ + { + const meanings = parseArray(u1, 'ex10_meaning'); + tasks.push({ + number: 10, + title: 'Wörter trennen', + subtitleKey: 'sub_assembly', + items: parseArray(u1, 'ex10_items').map(([prompt, words], i) => ({ + kind: 'assembly', + prompt: opt(prompt) ?? '', + words: trimNulls(words).map(String), + meaning: opt(meanings[i]), + })), + }); + } + + /* 11 + 13 — sort items into groups */ + const assignTask = (number, title, subtitleKey, itemsName, groupsName, meanName) => { + const meanings = parseArray(u1, meanName); + return { + number, + title, + subtitleKey, + items: [{ + kind: 'assign', + groups: parseArray(u1, groupsName).map(String), + items: parseArray(u1, itemsName).map(([emoji, label, group], i) => ({ + emoji: emoji ?? null, + label: String(label), + group, + meaning: opt(meanings[i]), + })), + }], + }; + }; + tasks.push(assignTask(11, 'Grußformen', 'sub_gruss', 'ex11_items', 'ex11_groups', 'ex11_meaning')); + + /* 12 — Was macht er/sie? */ + { + const meanings = parseArray(u1, 'ex12_meaning'); + tasks.push({ + number: 12, + title: 'Was macht er/sie?', + subtitleKey: 'sub_bild', + pool: parseArray(u1, 'ex12_pool'), + items: parseArray(u1, 'ex12_data').map(([emoji, before, after, answer], i) => + verbFill([before, after, answer], meanings[i], { emoji: String(emoji) })), + }); + } + + tasks.push(assignTask(13, 'Länder', 'sub_land', 'ex13_items', 'ex13_groups', 'ex13_meaning')); + + /* Vocabulary trainer branch: one section per textbook page. */ + const vocab = parseArray(u1, 'u1_trans_sections').map(([header, arrayRef]) => { + const name = arrayRef?.__c; + if (!name) throw new Error(`vocab section '${header}' has no data array`); + return { + header: String(header), + items: parseArray(u1, name).map(([prompt, answers, meaning]) => ({ + prompt: String(prompt), + answers: alternatives(answers), + meaning: opt(meaning), + })), + }; + }); + + return { + id: 'unit-01', + subject: 'deutsch', + number: 1, + title: { cs: 'Neue Freunde', en: 'Neue Freunde' }, + slides: [], + tasks, + vocab, + }; +} diff --git a/tools/extract/hardware.mjs b/tools/extract/hardware.mjs new file mode 100644 index 0000000..92b8099 --- /dev/null +++ b/tools/extract/hardware.mjs @@ -0,0 +1,73 @@ +import { readFileSync } from 'node:fs'; +import { parseArrayInFunction, trimNulls } from '../lib/cparse.mjs'; + +/** + * Hardware ("Technické vybavení"). + * + * Structurally identical to the network lessons: each `build_hw_unitN_page` + * holds a local `NetSlide slides[]` and each `build_hw_unitN_exercise_page` + * holds a local `ChoiceQ qs[]` with a parallel `hints[]`. + */ + +const HW_LESSONS = 3; + +function toSlide(row, label) { + if (!Array.isArray(row)) throw new Error(`${label}: slide is not a braced list`); + const [kicker, title, tip, lines] = row; + return { + kicker: kicker ?? '', + title: title ?? '', + tip: tip ?? null, + lines: trimNulls(lines ?? []).map(String), + }; +} + +function toChoice(row, hint, label) { + if (!Array.isArray(row)) throw new Error(`${label}: question is not a braced list`); + const [prompt, options, nOptions, correct] = row; + const list = trimNulls(options ?? []).map(String); + const n = typeof nOptions === 'number' ? nOptions : list.length; + + if (typeof correct !== 'number' || correct < 0 || correct >= n) { + throw new Error(`${label}: correct index ${correct} out of range for ${n} options`); + } + + return { + kind: 'choice', + prompt: String(prompt), + options: list.slice(0, n), + correct, + ...(hint ? { hint: String(hint) } : {}), + }; +} + +export function extractHardware(desktopDir) { + const src = readFileSync(`${desktopDir}/hw.c`, 'utf8'); + const lessons = []; + + for (let n = 1; n <= HW_LESSONS; n++) { + const slides = parseArrayInFunction(src, `build_hw_unit${n}_page`, 'slides') + .map((row, i) => toSlide(row, `hw unit ${n} slide ${i + 1}`)); + + const exFn = `build_hw_unit${n}_exercise_page`; + const qs = parseArrayInFunction(src, exFn, 'qs'); + const hints = parseArrayInFunction(src, exFn, 'hints'); + + lessons.push({ + id: `unit-${String(n).padStart(2, '0')}`, + subject: 'hardware', + number: n, + titleKey: `hw_unit${n}`, + subtitleKey: `hw_unit${n}_sub`, + slides, + tasks: [{ + number: 1, + title: 'Quiz', + subtitleKey: `hw_quiz${n}_head`, + items: qs.map((row, i) => toChoice(row, hints[i], `hw unit ${n} q${i + 1}`)), + }], + }); + } + + return lessons; +} diff --git a/tools/extract/i18n.mjs b/tools/extract/i18n.mjs new file mode 100644 index 0000000..7eafcfa --- /dev/null +++ b/tools/extract/i18n.mjs @@ -0,0 +1,35 @@ +import { readFileSync } from 'node:fs'; +import { parseArray } from '../lib/cparse.mjs'; + +/** + * `tr_ui` holds UI chrome keyed by short identifiers; `tr_content` holds + * lesson text keyed by the Czech string itself (its `cs` column is usually + * NULL, meaning "the key already is the Czech text"). + */ +function toTable(entries, { keyIsCzech }) { + const cs = {}; + const en = {}; + + for (const row of entries) { + if (!Array.isArray(row)) continue; + const [key, csText, enText] = row; + if (key === null || key === undefined) continue; // terminator + + cs[key] = csText ?? (keyIsCzech ? key : null); + if (enText !== null && enText !== undefined) en[key] = enText; + } + + // A null Czech value in tr_ui would render as an empty label; drop it. + for (const k of Object.keys(cs)) if (cs[k] === null) delete cs[k]; + + return { cs, en }; +} + +export function extractI18n(desktopDir) { + const src = readFileSync(`${desktopDir}/i18n.c`, 'utf8'); + + return { + ui: toTable(parseArray(src, 'tr_ui'), { keyIsCzech: false }), + content: toTable(parseArray(src, 'tr_content'), { keyIsCzech: true }), + }; +} diff --git a/tools/extract/mluvnice.mjs b/tools/extract/mluvnice.mjs new file mode 100644 index 0000000..debf65f --- /dev/null +++ b/tools/extract/mluvnice.mjs @@ -0,0 +1,145 @@ +import { readFileSync } from 'node:fs'; +import { parseArray, trimNulls } from '../lib/cparse.mjs'; + +/** + * Czech grammar ("Mluvnice"), 20 exercises in one lesson. + * + * Unlike the other subjects, mluvnice.c passes its instructions as literal + * Czech strings rather than i18n keys, so they are copied verbatim from the + * `build_mluvnice_exercise_page` switch below. + */ + +/** One row per `case` in `build_mluvnice_exercise_page`, in the same order. */ +const EXERCISES = [ + ['typed', 'Pravopis – i/y po obojetných souhláskách', 'Doplňte i/í nebo y/ý.', null], + ['choice', 'Pravopis – velká/malá písmena', 'Vyberte správnou variantu.', null], + ['typed', 'Slovní druhy', 'Určete slovní druh podtržených slov.', + 'Do pole napište název slovního druhu.'], + ['typed', 'Mluvnické kategorie – podstatná jména', + 'Určete rod, číslo a pád podtržených slov.', + 'Vyplňte tři pole: rod, číslo a pád.'], + ['typed', 'Mluvnické kategorie – slovesa', + 'Určete osobu, číslo, čas a způsob u těchto sloves.', + 'U rozkazovacího a podmiňovacího způsobu napište do pole čas „neurčitý“.'], + ['reveal', 'Slovotvorba', 'Rozeberte slova na morfémy.', + 'Určete předponu, kořen, příponu a koncovku.'], + ['typed', 'Větné členy', 'Určete větný člen podtržených výrazů.', null], + ['typed', 'Druhy vedlejších vět', 'Určete druh vedlejší věty.', null], + ['typed', 'Synonyma', 'Ke každému slovu napište synonymum.', null], + ['typed', 'Antonyma', 'Napište opak.', null], + ['typed', 'Pravopis – s/z na začátku slova', 'Vyberte správnou předponu s-/z-.', null], + ['reveal', 'Skladba – najděte chybu', + 'Každá věta obsahuje jednu chybu. Najděte ji a opravte.', null], + ['typed', 'Tvarosloví – správný tvar', 'Dejte slovo do správného tvaru.', null], + ['choice', 'Výběr ze čtyř možností', 'Vyberte správnou odpověď.', null], + ['reveal', 'Přímá a nepřímá řeč', 'Přepište přímou řeč na nepřímou.', null], + ['reveal', 'Slovní zásoba – rozdíly', 'Vysvětlete rozdíl mezi těmito dvojicemi slov.', null], + ['reveal', 'Interpunkce', 'Doplňte čárky tam, kde patří.', null], + ['typed', 'Obrazná pojmenování', + 'Určete, o jaký druh obrazného pojmenování jde.', null], + ['typed', 'Stylistika – slohové útvary', + 'Přiřaďte ukázku ke správnému slohovému útvaru.', null], + ['choice', 'Souhrnné opakování', 'Vyberte správnou odpověď.', null], +]; + +/** Only exercise 14 ships per-question explanations. */ +const CHOICE_EXPLANATIONS = { 14: 'e14_expl' }; + +/** `MluvItem`: prompt, shown, nblank, hint[5], answers[5]. */ +function fieldsItem(row, label) { + const [prompt, shown, nblank, hints, answers] = row; + if (typeof nblank !== 'number' || nblank < 1) { + throw new Error(`${label}: expected at least one blank, got ${nblank}`); + } + + return { + kind: 'fields', + prompt: String(prompt), + fields: Array.from({ length: nblank }, (_, i) => ({ + label: String(hints[i] ?? ''), + answers: String(answers[i] ?? '').split('|').map((a) => a.trim()).filter(Boolean), + })), + ...(shown ? { solution: String(shown) } : {}), + }; +} + +function choiceItem(row, expl, label) { + const [prompt, options, nOptions, correct] = row; + const list = trimNulls(options ?? []).map(String); + const n = typeof nOptions === 'number' ? nOptions : list.length; + + if (typeof correct !== 'number' || correct < 0 || correct >= n) { + throw new Error(`${label}: correct index ${correct} out of range for ${n} options`); + } + + return { + kind: 'choice', + prompt: String(prompt), + options: list.slice(0, n), + correct, + ...(expl ? { hint: String(expl) } : {}), + }; +} + +export function extractMluvnice(desktopDir) { + const src = readFileSync(`${desktopDir}/mluvnice.c`, 'utf8'); + const names = parseArray(src, 'mluv_names').map(String); + + if (names.length !== EXERCISES.length) { + throw new Error(`mluv_names has ${names.length} entries but the extractor knows ${EXERCISES.length}`); + } + + const tasks = EXERCISES.map(([type, heading, subtitle, note], index) => { + const number = index + 1; + const label = `mluvnice ex${number}`; + const base = { + number, + // Short label for the map bubble; the page shows the full heading. + title: names[index], + heading, + subtitleKey: null, + subtitle, + ...(note ? { note } : {}), + }; + + if (type === 'choice') { + const explName = CHOICE_EXPLANATIONS[number]; + const expls = explName ? parseArray(src, explName).map(String) : []; + return { + ...base, + items: parseArray(src, `e${number}_qs`) + .map((row, i) => choiceItem(row, expls[i], `${label} q${i + 1}`)), + }; + } + + if (type === 'reveal') { + return { + ...base, + items: parseArray(src, `e${number}_items`).map(([prompt, solution]) => ({ + kind: 'reveal', + prompt: String(prompt), + solution: String(solution), + })), + }; + } + + return { + ...base, + items: parseArray(src, `e${number}_items`) + .map((row, i) => fieldsItem(row, `${label} item ${i + 1}`)), + }; + }); + + return { + id: 'mluvnice', + subject: 'czech', + number: 1, + title: { cs: 'Mluvnice', en: 'Czech grammar' }, + subtitle: { + cs: 'Vyberte cvičení a dokončete je.', + en: 'Pick an exercise and complete it.', + }, + slides: [], + tasks, + }; +} diff --git a/tools/extract/networks.mjs b/tools/extract/networks.mjs new file mode 100644 index 0000000..650411f --- /dev/null +++ b/tools/extract/networks.mjs @@ -0,0 +1,97 @@ +import { readFileSync } from 'node:fs'; +import { parseArray, parseArrayInFunction, trimNulls } from '../lib/cparse.mjs'; + +const NET_LESSONS = 27; + +/** `NetSlide` is positional: kicker, title, tip, line[8]. */ +function toSlide(row, label) { + if (!Array.isArray(row)) throw new Error(`${label}: slide is not a braced list`); + const [kicker, title, tip, lines] = row; + return { + kicker: kicker ?? '', + title: title ?? '', + tip: tip ?? null, + lines: trimNulls(lines ?? []).map((l) => String(l)), + }; +} + +/** `ChoiceQ` is positional: prompt, options[5], n_options, correct. */ +function toChoice(row, hint, label) { + if (!Array.isArray(row)) throw new Error(`${label}: question is not a braced list`); + const [prompt, options, nOptions, correct] = row; + const list = trimNulls(options ?? []).map((o) => String(o)); + const n = typeof nOptions === 'number' ? nOptions : list.length; + + if (typeof correct !== 'number' || correct < 0 || correct >= n) { + throw new Error(`${label}: correct index ${correct} out of range for ${n} options`); + } + + const out = { kind: 'choice', prompt: String(prompt), options: list.slice(0, n), correct }; + if (hint) out.hint = String(hint); + return out; +} + +/** Unit 1 is the VLSM walkthrough: four scenarios plus a per-block answer key. */ +function subnetTasks(src) { + const tasks = parseArray(src, 'net_tasks'); + const answers = parseArray(src, 'net_ans'); + + return tasks.map(([scenario, solution], i) => { + const rows = answers[i] ?? []; + const blocks = rows + .map(([prefix, network, broadcast, firstHost, lastHost]) => ({ + prefix, network, broadcast, firstHost, lastHost, + })) + // A prefix of -1 marks a scenario that has no valid allocation. + .filter((b) => typeof b.prefix === 'number' && b.prefix > 0); + + return { + kind: 'subnet', + scenario: String(scenario), + solution: String(solution), + blocks: blocks.length ? blocks : null, + }; + }); +} + +export function extractNetworks(desktopDir) { + const src = readFileSync(`${desktopDir}/net.c`, 'utf8'); + const lessons = []; + + for (let n = 1; n <= NET_LESSONS; n++) { + const slides = parseArrayInFunction(src, `build_net_unit${n}_page`, 'slides') + .map((row, i) => toSlide(row, `net unit ${n} slide ${i + 1}`)); + + let tasks; + if (n === 1) { + tasks = [{ + number: 1, + title: 'VLSM', + subtitleKey: 'net_ex1_title', + items: subnetTasks(src), + }]; + } else { + const qs = parseArray(src, `net${n}_qs`); + const hints = parseArray(src, `net${n}_hints`); + tasks = [{ + number: 1, + title: 'Quiz', + subtitleKey: `net_quiz${n}_head`, + items: qs.map((row, i) => toChoice(row, hints[i], `net unit ${n} q${i + 1}`)), + }]; + } + + lessons.push({ + id: `unit-${String(n).padStart(2, '0')}`, + subject: 'networks', + number: n, + // Titles live in the i18n tables; the web app resolves these keys. + titleKey: `net_unit${n}`, + subtitleKey: `net_unit${n}_sub`, + slides, + tasks, + }); + } + + return lessons; +} diff --git a/tools/extract/themes.mjs b/tools/extract/themes.mjs new file mode 100644 index 0000000..716f803 --- /dev/null +++ b/tools/extract/themes.mjs @@ -0,0 +1,48 @@ +import { readFileSync } from 'node:fs'; +import { parseStruct } from '../lib/cparse.mjs'; + +/** Field order of `ThemePalette` in maturita.h, as the C initializers are positional. */ +const FIELDS = [ + 'crust', 'base', 'mantle', 'surface0', 'surface1', 'surface2', + 'overlay', 'text', 'subtext', 'accent', 'accent2', 'accent3', + 'success', 'success2', 'warning', 'error', 'onAccent', + 'node', 'lockedBg', 'lockedBorder', 'rail', + 'finishDark', 'finishLight', 'finishStroke', +]; + +/** slug, display name, and the C variable prefix used in theme.c. */ +const THEMES = [ + ['catppuccin', 'Catppuccin', 'cat'], + ['nord', 'Nord', 'nord'], + ['dracula', 'Dracula', 'dra'], + ['rose-pine', 'Rose Pine', 'rose'], + ['ocean', 'Ocean', 'ocean'], + ['gruvbox', 'Gruvbox', 'gruv'], + ['solarized', 'Solarized', 'sol'], + ['everforest', 'Everforest', 'ever'], + ['monokai', 'Monokai', 'mono'], + ['one-dark', 'One Dark', 'one'], +]; + +function toPalette(values, label) { + if (values.length !== FIELDS.length) { + throw new Error(`${label}: expected ${FIELDS.length} colors, got ${values.length}`); + } + const out = {}; + values.forEach((v, i) => { + if (typeof v !== 'number') throw new Error(`${label}: field ${FIELDS[i]} is not a hex literal`); + out[FIELDS[i]] = '#' + v.toString(16).padStart(6, '0'); + }); + return out; +} + +export function extractThemes(desktopDir) { + const src = readFileSync(`${desktopDir}/theme.c`, 'utf8'); + + return THEMES.map(([id, name, prefix]) => ({ + id, + name, + dark: toPalette(parseStruct(src, `${prefix}_dark`), `${id} dark`), + light: toPalette(parseStruct(src, `${prefix}_light`), `${id} light`), + })); +} diff --git a/tools/lib/cparse.mjs b/tools/lib/cparse.mjs new file mode 100644 index 0000000..a9f06c5 --- /dev/null +++ b/tools/lib/cparse.mjs @@ -0,0 +1,354 @@ +/** + * Minimal reader for the C initializer syntax used by the desktop sources. + * + * It understands only what the lesson data actually uses: string literals with + * adjacent concatenation, char literals, integers, `NULL`, identifiers, + * designated initializers and nested braces. Anything else throws so a bad + * extraction fails loudly instead of silently producing empty lessons. + */ + +const IDENT_START = /[A-Za-z_]/; +const IDENT_PART = /[A-Za-z0-9_]/; + +/** Strip comments while preserving string/char literals verbatim. */ +export function stripComments(src) { + let out = ''; + let i = 0; + + while (i < src.length) { + const c = src[i]; + + if (c === '"' || c === "'") { + const quote = c; + out += c; + i++; + while (i < src.length) { + if (src[i] === '\\') { + out += src[i] + (src[i + 1] ?? ''); + i += 2; + continue; + } + out += src[i]; + if (src[i] === quote) { + i++; + break; + } + i++; + } + continue; + } + + if (c === '/' && src[i + 1] === '*') { + const end = src.indexOf('*/', i + 2); + i = end === -1 ? src.length : end + 2; + out += ' '; + continue; + } + + if (c === '/' && src[i + 1] === '/') { + const end = src.indexOf('\n', i); + i = end === -1 ? src.length : end; + out += ' '; + continue; + } + + out += c; + i++; + } + + return out; +} + +const ESCAPES = { + n: '\n', + t: '\t', + r: '\r', + '0': '\0', + '\\': '\\', + '"': '"', + "'": "'", + a: '\x07', + b: '\b', + f: '\f', + v: '\v', +}; + +class Reader { + constructor(src, label) { + this.src = src; + this.label = label; + this.i = 0; + } + + fail(msg) { + const at = this.src.slice(Math.max(0, this.i - 60), this.i + 60); + throw new Error(`${this.label}: ${msg} near\n...${at}...`); + } + + ws() { + while (this.i < this.src.length && /\s/.test(this.src[this.i])) this.i++; + } + + peek() { + this.ws(); + return this.src[this.i]; + } + + eat(ch) { + this.ws(); + if (this.src[this.i] !== ch) this.fail(`expected '${ch}', got '${this.src[this.i]}'`); + this.i++; + } + + tryEat(ch) { + this.ws(); + if (this.src[this.i] === ch) { + this.i++; + return true; + } + return false; + } + + /** One string literal, honouring C's adjacent-literal concatenation. */ + readString() { + let value = ''; + let first = true; + + for (;;) { + this.ws(); + if (this.src[this.i] !== '"') { + if (first) this.fail('expected string literal'); + return value; + } + first = false; + this.i++; + while (this.i < this.src.length && this.src[this.i] !== '"') { + if (this.src[this.i] === '\\') { + const esc = this.src[this.i + 1]; + if (esc in ESCAPES) { + value += ESCAPES[esc]; + this.i += 2; + continue; + } + if (esc === 'u' || esc === 'x') { + const m = /^\\(u[0-9a-fA-F]{4}|x[0-9a-fA-F]+)/.exec(this.src.slice(this.i)); + if (!m) this.fail('bad escape'); + const hex = m[1].slice(1); + value += String.fromCodePoint(parseInt(hex, 16)); + this.i += m[0].length; + continue; + } + value += esc; + this.i += 2; + continue; + } + value += this.src[this.i]; + this.i++; + } + if (this.src[this.i] !== '"') this.fail('unterminated string'); + this.i++; + } + } + + readIdent() { + this.ws(); + if (!IDENT_START.test(this.src[this.i] ?? '')) this.fail('expected identifier'); + let start = this.i; + while (this.i < this.src.length && IDENT_PART.test(this.src[this.i])) this.i++; + return this.src.slice(start, this.i); + } + + /** + * A single initializer value. Braces become arrays, or plain objects when the + * body uses designated initializers. + */ + readValue() { + this.ws(); + const c = this.src[this.i]; + + if (c === undefined) this.fail('unexpected end of input'); + if (c === '"') return this.readString(); + if (c === '{') return this.readBraced(); + + // Cast prefix such as `(int)` or `(const char *)`: skip it and read on. + if (c === '(') { + const cast = /^\(\s*(?:const\s+|unsigned\s+|signed\s+)*[A-Za-z_]\w*\s*\**\s*\)/.exec( + this.src.slice(this.i) + ); + if (cast) { + this.i += cast[0].length; + return this.readValue(); + } + } + + if (c === "'") { + this.i++; + let ch; + if (this.src[this.i] === '\\') { + const esc = this.src[this.i + 1]; + ch = esc in ESCAPES ? ESCAPES[esc] : esc; + this.i += 2; + } else { + ch = this.src[this.i]; + this.i++; + } + this.eat("'"); + return ch; + } + + // Numeric or simple arithmetic/negation, e.g. `-1`, `4`, `G_N_ELEMENTS(x)`. + const numMatch = /^[+-]?(?:0[xX][0-9a-fA-F]+|\d+)(?![\w.])/.exec(this.src.slice(this.i)); + if (numMatch) { + this.i += numMatch[0].length; + return Number(numMatch[0]); + } + + if (IDENT_START.test(c)) { + const name = this.readIdent(); + if (name === 'NULL') return null; + if (name === 'TRUE') return true; + if (name === 'FALSE') return false; + // Macro call or bare constant: keep the source text for the caller. + if (this.peek() === '(') { + let depth = 0; + const start = this.i; + while (this.i < this.src.length) { + if (this.src[this.i] === '(') depth++; + else if (this.src[this.i] === ')') { + depth--; + if (depth === 0) { + this.i++; + break; + } + } + this.i++; + } + return { __c: name + this.src.slice(start, this.i) }; + } + return { __c: name }; + } + + this.fail(`unexpected character '${c}'`); + } + + readBraced() { + this.eat('{'); + const list = []; + const obj = {}; + let designated = false; + + for (;;) { + if (this.tryEat('}')) break; + + if (this.peek() === '.') { + this.i++; + const field = this.readIdent(); + this.eat('='); + obj[field] = this.readValue(); + designated = true; + } else { + list.push(this.readValue()); + } + + if (this.tryEat(',')) continue; + this.eat('}'); + break; + } + + return designated ? obj : list; + } +} + +/** + * Find an array/struct definition by name and parse its initializer. + * Matches e.g. `static const ChoiceQ net2_qs[] = { ... };` + */ +export function parseArray(src, name, { label = name } = {}) { + const clean = stripComments(src); + const re = new RegExp( + `\\b${name}\\s*(?:\\[[^\\]]*\\]\\s*)+=\\s*(?=\\{)`, + 'g' + ); + const m = re.exec(clean); + if (!m) throw new Error(`${label}: array '${name}' not found`); + + const reader = new Reader(clean, label); + reader.i = m.index + m[0].length; + const value = reader.readValue(); + if (!Array.isArray(value)) throw new Error(`${label}: '${name}' is not a braced list`); + return value; +} + +/** Parse a scalar struct definition, e.g. `static const ThemePalette nord_dark = {...};` */ +export function parseStruct(src, name, { label = name } = {}) { + const clean = stripComments(src); + const re = new RegExp(`\\b${name}\\s*=\\s*(?=\\{)`, 'g'); + const m = re.exec(clean); + if (!m) throw new Error(`${label}: struct '${name}' not found`); + + const reader = new Reader(clean, label); + reader.i = m.index + m[0].length; + return reader.readValue(); +} + +/** + * Same as parseArray but scoped to the body of a single function, so the many + * identically-named `static const NetSlide slides[]` locals stay distinct. + */ +export function parseArrayInFunction(src, fnName, arrayName) { + const clean = stripComments(src); + const fnRe = new RegExp(`\\b${fnName}\\s*\\([^)]*\\)\\s*\\{`, 'g'); + const m = fnRe.exec(clean); + if (!m) throw new Error(`function '${fnName}' not found`); + + // Walk to the matching closing brace so we only search this body. + let depth = 0; + let i = m.index + m[0].length - 1; + const start = i; + for (; i < clean.length; i++) { + if (clean[i] === '"' || clean[i] === "'") { + const q = clean[i++]; + while (i < clean.length && clean[i] !== q) i += clean[i] === '\\' ? 2 : 1; + continue; + } + if (clean[i] === '{') depth++; + else if (clean[i] === '}') { + depth--; + if (depth === 0) break; + } + } + + const body = clean.slice(start, i + 1); + return parseArray(body, arrayName, { label: `${fnName}/${arrayName}` }); +} + +/** Parse a scalar string definition, e.g. `const char *g05_bank = "a, b, c";` */ +export function parseString(src, name, { label = name } = {}) { + const clean = stripComments(src); + const re = new RegExp(`\\b${name}\\s*=\\s*(?=")`, 'g'); + const m = re.exec(clean); + if (!m) throw new Error(`${label}: string '${name}' not found`); + + const reader = new Reader(clean, label); + reader.i = m.index + m[0].length; + return reader.readString(); +} + +/** Resolve `#define NAME value` integer macros. */ +export function parseDefines(src) { + const out = {}; + const re = /^[ \t]*#[ \t]*define[ \t]+([A-Za-z_]\w*)[ \t]+([^\n/]+)/gm; + let m; + while ((m = re.exec(src))) { + const raw = m[2].trim(); + if (/^-?\d+$/.test(raw)) out[m[1]] = Number(raw); + } + return out; +} + +/** Trailing NULLs are array terminators in the C data, not content. */ +export function trimNulls(list) { + const out = [...list]; + while (out.length && (out.at(-1) === null || out.at(-1) === undefined)) out.pop(); + return out; +} diff --git a/web/next-env.d.ts b/web/next-env.d.ts new file mode 100644 index 0000000..ce4e94a --- /dev/null +++ b/web/next-env.d.ts @@ -0,0 +1,7 @@ +/// +/// +import "./.next/types/routes.d.ts"; +import "./.next/types/root-params.d.ts"; + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/web/next.config.ts b/web/next.config.ts new file mode 100644 index 0000000..5b61ffd --- /dev/null +++ b/web/next.config.ts @@ -0,0 +1,10 @@ +import type { NextConfig } from 'next'; + +const config: NextConfig = { + // `content/` lives outside web/, so allow tracing files from the repo root. + outputFileTracingRoot: __dirname + '/..', + // Routes are built from content ids at runtime, so they cannot be statically typed. + typedRoutes: false, +}; + +export default config; diff --git a/web/package-lock.json b/web/package-lock.json new file mode 100644 index 0000000..be50766 --- /dev/null +++ b/web/package-lock.json @@ -0,0 +1,1076 @@ +{ + "name": "maturita-web", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "maturita-web", + "version": "1.0.0", + "dependencies": { + "next": "^16.3.5", + "react": "^19.1.1", + "react-dom": "^19.1.1" + }, + "devDependencies": { + "@types/node": "^22.10.2", + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "typescript": "^5.7.2" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz", + "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.4.tgz", + "integrity": "sha512-Uhfl4V4lhP2nbUVF9+hyH1+luj86f1gUFeo8ALYxFoULoU+G87D43BfeMP8XHsk9boxAnCY/bf2EHwhA7MuGsA==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.3.3" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.4.tgz", + "integrity": "sha512-hWniXY3bG5qKpkKrAwPe4y+VTPmf086YQAnkxWh7uA1YrlRouWGa0M0Mxj3ZjnXFkv7/TD1bTy9lGUK26vRvWw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.3.3" + } + }, + "node_modules/@img/sharp-freebsd-wasm32": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.4.tgz", + "integrity": "sha512-lIsKw/BU+kjB4eZjxrYrZmwOJYi3Ajrv66iAlBmUPyKc3HpnloevB1g3wxGD9P/5BbQ1brBGl65VRRrCvQDEqA==", + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "dependencies": { + "@img/sharp-wasm32": "0.35.4" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.3.tgz", + "integrity": "sha512-suTBPTDGrI9WodccaDdwZItTSaBYASlBk1NSfElSHrUfzu3szG6lvIF58+WiFvnfzuK8ZBFS5zE00PxqxnRiPg==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.3.tgz", + "integrity": "sha512-FVJZ5mITMobmXIz/hPDTw0EintTW5H3WfrxwLqEqjiIihlu+hVRyGrFQ60xl0Lxn7Bt3zdpevPaQi0HEzqz9fw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.3.tgz", + "integrity": "sha512-3rbU4vqXXc3hY/OiXdl52xZvT0F1yEngWfvqudtPJg/KkyiaQw2DRsFrNzpmLvfavbwOq3qXn36GP8obHRULQA==", + "cpu": [ + "arm" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.3.tgz", + "integrity": "sha512-0DaL0A6Xu6sQSQFwe4iVCrKWU2cCTItnRsYsCdxAMm9NF6twAA9BKnoqy4hqz4+azQ0JHuA26qiUKsf1XJ/v5A==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.3.tgz", + "integrity": "sha512-cdn1OvUBwsXhbC0zSzJnNzf5MZ/mTrobawDvNXBTxe8VtqKAm0sRuEY2Evzovb/w9JMk4TvRxqt1mekSuJz64w==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.3.tgz", + "integrity": "sha512-HjPVx7yKz+0lqdhDlTw1tt90wamBoxhiXpvl1XZpJLiHH4RCJ5yDTqH+VlYPv2fwFs89JFw4c1IexYOcQUi4IQ==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.3.tgz", + "integrity": "sha512-neWLh+3yCNThxnfy3c4BbVBeGgt9aftno+XbT56iK28RgeDs3UOFWviLWlUu0bArYVYJaFDK+RRohbicUNCm8Q==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.3.tgz", + "integrity": "sha512-4vKmvAst9nrowcqquKFAyZJUDolUaIp8uRiN0mWFguJ1IplC9/pitXtlnnlU4aa/eJw3J7i67V+pwUL+wZGdsA==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.3.tgz", + "integrity": "sha512-Y9kQaLMuNoB0bPYOOdcZMaseNrFpPodIWWMrx+CZyydf2xn68j9WYc6sWWRrDwNkzCQjKYfc68L7jKjGlHMibw==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.3.tgz", + "integrity": "sha512-fj8Mv0HHfD1Rr+4I68+3agJynxDWtBFgicTbSOb9Bke6pIwzGcJ+RX/yHjmiEGFMCavY/dxvem7MyNaJF+wDiw==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.4.tgz", + "integrity": "sha512-7OAS8gI0EReKGVN2HssHlM6umJgxF5VI3xN0p9FA91p/YO+ou5hiNghLdZ5BEHztwaaK5+bLKRf8x/o2L2nk9A==", + "cpu": [ + "arm" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.3.3" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.4.tgz", + "integrity": "sha512-De4jpEnAU8Hd5oT0j1G3uL4ZvTuipVMn7YC6vPaJhy6/7EwEae0SVAoBrUMYQbkLGDm85taVWwuPc1a44LTzCQ==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.3.3" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.4.tgz", + "integrity": "sha512-2oYZJeIl4kCcMGk4ouZVjnkCtFrpQFlNEtJ6GbxzhHQchwH0NH/qEb9ykmOl29dqwMq+JhFdZn+1ak2FKhI9fQ==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.3.3" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.4.tgz", + "integrity": "sha512-cPbNChoRURAWdebDIHSenxRpgEdy7JkPydSnUxRm9VvKD7m0/xVaR/8Fzlu81pk5nHEvHH87UZUA7cTtwnbJSA==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.3.3" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.4.tgz", + "integrity": "sha512-RY0JFY8Fd6RonCBtHz+DvadaPkXDSI1AUn6yWL9TipqkZ1vY8w8evqdgyDFnkm4/K1ve1TvZiaePP5oSd4+WVQ==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.3.3" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.4.tgz", + "integrity": "sha512-9qvvEAuk8k89TfWUoX2htWjbAMX8p+NxCppjpcg5k6xMsjhBQPTsoIh36h9Qde4WRuGpJeYnOjdosDn/cnv+OA==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.3.3" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.4.tgz", + "integrity": "sha512-KB5jxpfWQTr0nc3xdHtWChdbifHrBGsd2SM62Eyxrl8afikm+f5qGBU75SJIZBT/S1MC8XyacdlXBMSWq6OURA==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.3.3" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.4.tgz", + "integrity": "sha512-f+eZJZIQNEEd26RPSW+76chwOf1XtA2Y/O+5ocVyLliHkeih3e+jhLVBdNTd2rS3IbNXK8+ug93Vf5ZXtF5Lxg==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.3.3" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.4.tgz", + "integrity": "sha512-zQnl4Kwp7Q6NHsENtU2T/00Zi+w3AQNwz3+UaTyVBy2FpXrzXzGjndpK61onhZjRtRpQXxCTeqw19bVyXOh7jA==", + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.11.3" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-webcontainers-wasm32": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.4.tgz", + "integrity": "sha512-ESfNkywmCfPNyaZjxooddJQiQ+l/nTpGEOGthxiLnIHXC/CmcBixnfwUleX9mCz9ovrUUvKMap/pm8RYbzfwaA==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/sharp-wasm32": "0.35.4" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.4.tgz", + "integrity": "sha512-iNdlBX9gLVvqe2I3uIJSIKTq6wckP/DYxZtcqxm09x5Gi24DnFBmPAWZmr60ZyYMG0xlzo6goG3670ar+RXvRw==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.4.tgz", + "integrity": "sha512-kqRsbaa5CS6KHlpxnN7WhE6vAAugXyZButpRdvDWetlv6Qv4N9WTcrWzF7tXfB9T7MsoadqdI8hmwLq6UlLvtw==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.4.tgz", + "integrity": "sha512-XtmnYhBcrORsJ4XJngyzr/EWP0hRZLAZRFaApdKuviyqF78+ylxh2y06ZmtULAMOnObJ3ucpN0AcwSWnMowTRg==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@next/env": { + "version": "16.3.5", + "resolved": "https://registry.npmjs.org/@next/env/-/env-16.3.5.tgz", + "integrity": "sha512-NWEXVDMqoEo0ktmU6u0sE2Vg0LOcsD7NnOTJNo3/fEaTfsg+F1bMIxuDmQbda4e3yTIQwVdUREF2yIuMOusKtg==", + "license": "MIT" + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "16.3.5", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.3.5.tgz", + "integrity": "sha512-pMmGgETfKvElucLHtVaeiMRbp2zUbvKx7b1yGko0liBz3cw1mKSggWN/Rp/wPz8z+E1O82u3r4L1Co+ZS5hokQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "16.3.5", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.3.5.tgz", + "integrity": "sha512-76VaGYvf6HPa5/w12yLkE3dXTn9AfdEviI79oEL3aZoAmRLc9rWitjWqyjViVysK/ht/y9YKzFkBrUdi/wGkow==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "16.3.5", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.3.5.tgz", + "integrity": "sha512-zKDELJ5jSQMHeO/hmXUQsAzagX4bQD4OiMi3pQ5FbUj+yK506oLVHnKA2YXMlbg1EHHqJYtyePOgByIDXD1lqw==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "16.3.5", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.3.5.tgz", + "integrity": "sha512-7Vql0pgzCoHagv6+FNOZoqmJqA52c6zeVbhtS/47qFozO1MSx4ms7x7GHiciY8R5CDsSMKMQjJEryoJLcsBIbA==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "16.3.5", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.3.5.tgz", + "integrity": "sha512-NH/xzehyHEFWE2nlcZon7TB/0+H4shfWCi7S1zka815XCOhJDYZhoeJtOYy0dh0WVRWACVXSyGNFFytoMxUhRg==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "16.3.5", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.3.5.tgz", + "integrity": "sha512-lV4+EhWMfS8jcC+EH2nn/Cm5cn6XsgbE07bU9tMH8fCo0tNAqhyzi1b5wQ/Tn6NGFTvKDY65w3ZH95EjwBRAnQ==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "16.3.5", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.3.5.tgz", + "integrity": "sha512-/wKzAREX2RF++MhicjDbg8tGn2AiBIM0+EFeTFKoUEUbW5D6amCJehd5Z5G1H5/gxNdgnwoXMcHz24H/c2tGkQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "16.3.5", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.3.5.tgz", + "integrity": "sha512-LNdCHzgLFc+UeqMS84LzXPaeBRKyqDN9OMyFAr1OrB0XrNw78IRrEVtZvvA7245W/HsaoeVOQX9jPjPk8jojwA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@swc/helpers": { + "version": "0.5.23", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz", + "integrity": "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@types/node": { + "version": "22.20.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.3.tgz", + "integrity": "sha512-DZmzkmwHzXrLPAXPyKNDzlIwMMUZCVacoD25ywdy5YTKGbOx/2ld+Q38Im2zJ0vBuZP5Prd3VZutKZyXwkOS8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/react": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.3.0.tgz", + "integrity": "sha512-N0rFCuH9YoxG9/m61l9MfpJKfmLOVU0em7ipIz6TRgSSkvReLB9vL85GB+yr8Bs5leqpvg96JSwF4ZS1s4viQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.3.0.tgz", + "integrity": "sha512-ZI7bU42mZXXKHn/qNLEw2IrbiINU7X5+vfgdixBHkCNpYWXjKgfQ/P+uyGb5CjOLB9UcnTeg3rylQtV2hym44Q==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.3.0" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.11.24", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.24.tgz", + "integrity": "sha512-hYrgxie335U08WqICoGqKRzV1HFXv6zdxwJE4ekCb80CM9a0SVVsN4QPwT67RraRo+9h8IATk6uxHJw7QSkdOg==", + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001810", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001810.tgz", + "integrity": "sha512-TITQPUkaz+aVk5GL6NhOdwk1aEaNTSDPsGFWrTuhKGtjTF70jL/Oht2W4c6rXUe5fu7Ie19VIahAXHIIiWWNeg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/nanoid": { + "version": "3.3.19", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.19.tgz", + "integrity": "sha512-Y2tUNy4ouw6tq5oDSKeQYGOyhkUBhNOcGV/02KC+6kd9eDGqdZd++mjMiIDilrBYvjEnCYvVtsuHCuP+okSfug==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/next": { + "version": "16.3.5", + "resolved": "https://registry.npmjs.org/next/-/next-16.3.5.tgz", + "integrity": "sha512-MdtsTgzyfCPRLC6uJ1mN8ao7lyJ4BB0U6Inhnx3gta1UcCIdHK3yxLG0E8OWQteWD8/Q0qb8A5o7wJaL8M9y2w==", + "license": "MIT", + "dependencies": { + "@next/env": "16.3.5", + "@swc/helpers": "0.5.23", + "baseline-browser-mapping": "^2.9.19", + "caniuse-lite": "^1.0.30001579", + "postcss": "8.5.23", + "styled-jsx": "5.1.6" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=20.9.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "16.3.5", + "@next/swc-darwin-x64": "16.3.5", + "@next/swc-linux-arm64-gnu": "16.3.5", + "@next/swc-linux-arm64-musl": "16.3.5", + "@next/swc-linux-x64-gnu": "16.3.5", + "@next/swc-linux-x64-musl": "16.3.5", + "@next/swc-win32-arm64-msvc": "16.3.5", + "@next/swc-win32-x64-msvc": "16.3.5", + "sharp": "^0.35.4" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.51.1", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/postcss": { + "version": "8.5.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.23.tgz", + "integrity": "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.16", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/react": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.3.0.tgz", + "integrity": "sha512-E8LUcbtBWt20bbl2YoHfx4ZDBdxVTfOKtCZn9cDSJ4l6/nuoApcpIBcj47t2wZoVX8g2ZHuMHbiShgCR1T5Sog==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.3.0.tgz", + "integrity": "sha512-JDk8dgif51OjFoDE70+OT9ICyYr+69HlmihNwp1+Nsfbna3t5sIiCa9ZJktDmQ4/1b/rn26hIAR2uYXDMr5r0Q==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.28.0" + }, + "peerDependencies": { + "react": "^19.3.0" + } + }, + "node_modules/scheduler": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.28.0.tgz", + "integrity": "sha512-juorfCmIkIw8tT+p5BXSm6PJjQF/ycEYmKyzURCIt/RaZIhL+PulbQ9Yu2z1HdOJDdqDTlxA1+xKBmHXJsczAw==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sharp": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.4.tgz", + "integrity": "sha512-n++8XWcj+jCOr2IOl7h8LbKnGBDY4aPbmprMONBNFdn0ImXqpGVv5zliDs0V9HbmbCQLpbuo2ej9rAoOQTvMDA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/colour": "^1.1.0", + "detect-libc": "^2.1.2", + "semver": "^7.8.5" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.35.4", + "@img/sharp-darwin-x64": "0.35.4", + "@img/sharp-freebsd-wasm32": "0.35.4", + "@img/sharp-libvips-darwin-arm64": "1.3.3", + "@img/sharp-libvips-darwin-x64": "1.3.3", + "@img/sharp-libvips-linux-arm": "1.3.3", + "@img/sharp-libvips-linux-arm64": "1.3.3", + "@img/sharp-libvips-linux-ppc64": "1.3.3", + "@img/sharp-libvips-linux-riscv64": "1.3.3", + "@img/sharp-libvips-linux-s390x": "1.3.3", + "@img/sharp-libvips-linux-x64": "1.3.3", + "@img/sharp-libvips-linuxmusl-arm64": "1.3.3", + "@img/sharp-libvips-linuxmusl-x64": "1.3.3", + "@img/sharp-linux-arm": "0.35.4", + "@img/sharp-linux-arm64": "0.35.4", + "@img/sharp-linux-ppc64": "0.35.4", + "@img/sharp-linux-riscv64": "0.35.4", + "@img/sharp-linux-s390x": "0.35.4", + "@img/sharp-linux-x64": "0.35.4", + "@img/sharp-linuxmusl-arm64": "0.35.4", + "@img/sharp-linuxmusl-x64": "0.35.4", + "@img/sharp-webcontainers-wasm32": "0.35.4", + "@img/sharp-win32-arm64": "0.35.4", + "@img/sharp-win32-ia32": "0.35.4", + "@img/sharp-win32-x64": "0.35.4" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", + "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", + "license": "MIT", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + } + } +} diff --git a/web/package.json b/web/package.json new file mode 100644 index 0000000..020acab --- /dev/null +++ b/web/package.json @@ -0,0 +1,24 @@ +{ + "name": "maturita-web", + "version": "1.0.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint", + "typecheck": "tsc --noEmit", + "content": "node ../tools/build-content.mjs" + }, + "dependencies": { + "next": "^16.3.5", + "react": "^19.1.1", + "react-dom": "^19.1.1" + }, + "devDependencies": { + "@types/node": "^22.10.2", + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "typescript": "^5.7.2" + } +} diff --git a/web/src/app/ThemeScript.tsx b/web/src/app/ThemeScript.tsx new file mode 100644 index 0000000..4cc77fe --- /dev/null +++ b/web/src/app/ThemeScript.tsx @@ -0,0 +1,38 @@ +import type { Theme } from '../../../content/schema'; + +/** + * Applies the stored palette before the first paint. + * + * Without this the page renders with the dark fallback from `globals.css` and + * only recolours once 's effect runs, which shows as a dark flash + * for anyone using a light theme. + */ +export function ThemeScript({ themes }: { themes: Theme[] }) { + const palettes = Object.fromEntries( + themes.map((theme) => [theme.id, { dark: theme.dark, light: theme.light }]) + ); + + const source = ` +(function () { + try { + var palettes = ${JSON.stringify(palettes)}; + var stored = JSON.parse(localStorage.getItem('maturita.settings') || '{}'); + var theme = palettes[stored.themeId] || palettes['catppuccin']; + var mode = stored.mode === 'light' ? 'light' : 'dark'; + var palette = theme[mode]; + var root = document.documentElement; + + for (var key in palette) { + root.style.setProperty('--' + key.replace(/[A-Z]/g, function (c) { + return '-' + c.toLowerCase(); + }), palette[key]); + } + + root.dataset.mode = mode; + root.style.colorScheme = mode; + if (stored.lang === 'en' || stored.lang === 'cs') root.lang = stored.lang; + } catch (e) {} +})();`; + + return