mirror of
https://github.com/pepaskopec-blip/Graduately.git
synced 2026-10-27 07:04:35 +00:00
Build all apps from Markdown content; Compose Desktop replaces GTK on Linux and Windows
- content/ + scripts/build-content.py produce content.json for every app - stable lesson IDs with one-time progress migration (Swift, Kotlin) - shared answer-check tests (tests/answers.json) for Kotlin and Swift - android/desktop: Compose app with updater, speech and GTK progress import - CI packages AppImage and Windows zip with ProGuard, runs the tests Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
b324496334
commit
c3bc32113b
964 changed files with 57285 additions and 1156 deletions
72
.github/workflows/build.yml
vendored
72
.github/workflows/build.yml
vendored
|
|
@ -24,19 +24,27 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install dependencies
|
||||
# ProGuard and jlink need a JDK that ships jmods; Temurin 21 does.
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 21
|
||||
|
||||
- uses: gradle/actions/setup-gradle@v4
|
||||
with:
|
||||
build-root-directory: android
|
||||
|
||||
- name: Answer checks
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y \
|
||||
build-essential pkg-config curl \
|
||||
libgtk-4-dev librsvg2-dev \
|
||||
desktop-file-utils \
|
||||
appstream
|
||||
chmod +x android/gradlew
|
||||
cd android
|
||||
./gradlew :desktop:test --no-daemon
|
||||
|
||||
- name: Build AppImage
|
||||
env:
|
||||
COMMIT: ${{ github.sha }}
|
||||
run: |
|
||||
export PACKAGE_JDK="$JAVA_HOME"
|
||||
chmod +x scripts/bundle-linux.sh
|
||||
./scripts/bundle-linux.sh
|
||||
|
||||
|
|
@ -51,38 +59,35 @@ jobs:
|
|||
runs-on: windows-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
shell: bash
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: msys2/setup-msys2@v2
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
msystem: UCRT64
|
||||
update: true
|
||||
install: >-
|
||||
make
|
||||
zip
|
||||
mingw-w64-ucrt-x86_64-gcc
|
||||
mingw-w64-ucrt-x86_64-gtk4
|
||||
mingw-w64-ucrt-x86_64-pkg-config
|
||||
mingw-w64-ucrt-x86_64-make
|
||||
distribution: temurin
|
||||
java-version: 21
|
||||
|
||||
- name: Build and bundle
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
- uses: gradle/actions/setup-gradle@v4
|
||||
with:
|
||||
build-root-directory: android
|
||||
|
||||
- name: Build zip
|
||||
env:
|
||||
COMMIT: ${{ github.sha }}
|
||||
run: |
|
||||
make bundle
|
||||
cd dist
|
||||
zip -qry ../graduately-windows-x64.zip .
|
||||
cd ..
|
||||
mkdir -p dist-out
|
||||
mv graduately-windows-x64.zip dist-out/
|
||||
export PACKAGE_JDK="$JAVA_HOME"
|
||||
bash scripts/bundle-windows.sh
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: graduately-windows
|
||||
path: dist-out/graduately-windows-x64.zip
|
||||
path: dist/graduately-windows-x64.zip
|
||||
|
||||
macos:
|
||||
name: macOS app
|
||||
|
|
@ -173,11 +178,11 @@ jobs:
|
|||
with:
|
||||
build-root-directory: android
|
||||
|
||||
- name: Extract content and build APK
|
||||
- name: Build content and APK
|
||||
env:
|
||||
COMMIT: ${{ github.sha }}
|
||||
run: |
|
||||
python3 scripts/extract-android-content.py
|
||||
python3 scripts/build-content.py
|
||||
chmod +x android/gradlew
|
||||
cd android
|
||||
./gradlew :app:assembleRelease --no-daemon
|
||||
|
|
@ -198,7 +203,14 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Extract content and build IPA
|
||||
- name: Answer checks
|
||||
env:
|
||||
DEVELOPER_DIR: /Applications/Xcode.app/Contents/Developer
|
||||
run: |
|
||||
chmod +x scripts/test-answers-swift.sh
|
||||
./scripts/test-answers-swift.sh
|
||||
|
||||
- name: Build content and IPA
|
||||
env:
|
||||
COMMIT: ${{ github.sha }}
|
||||
DEVELOPER_DIR: /Applications/Xcode.app/Contents/Developer
|
||||
|
|
@ -253,6 +265,8 @@ jobs:
|
|||
[ -f fresh/graduately-android.apk ] && echo "${{ github.sha }}" > staged/VERSION-android
|
||||
[ -f fresh/graduately-ios.ipa ] && echo "${{ github.sha }}" > staged/VERSION-ios
|
||||
ls fresh/graduately-macos-*.zip >/dev/null 2>&1 && echo "${{ github.sha }}" > staged/VERSION-macos
|
||||
[ -f fresh/graduately-windows-x64.zip ] && echo "${{ github.sha }}" > staged/VERSION-windows
|
||||
[ -f fresh/graduately-linux-x86_64.AppImage ] && echo "${{ github.sha }}" > staged/VERSION-linux
|
||||
# Compatibility aliases so older installers/updaters still find packages.
|
||||
[ -f staged/graduately-macos-arm64.zip ] && cp -f staged/graduately-macos-arm64.zip staged/maturita-macos-arm64.zip
|
||||
[ -f staged/graduately-macos-x86_64.zip ] && cp -f staged/graduately-macos-x86_64.zip staged/maturita-macos-x86_64.zip
|
||||
|
|
|
|||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -30,6 +30,7 @@ CLAUDE.md
|
|||
android/.gradle/
|
||||
android/build/
|
||||
android/app/build/
|
||||
android/desktop/build/
|
||||
android/local.properties
|
||||
android/.idea/
|
||||
android/*.iml
|
||||
|
|
|
|||
152
Makefile
152
Makefile
|
|
@ -1,111 +1,49 @@
|
|||
CC = gcc
|
||||
# Every app reads the lessons from content/ (built into content.json).
|
||||
# Android, Linux, Windows: Kotlin + Compose in android/ (shared code in android/shared)
|
||||
# iOS, macOS: Swift + SwiftUI in ios/ and macos/
|
||||
#
|
||||
# Published builds pass COMMIT (the CI workflow exports it); the updaters
|
||||
# compare it against the build in the repository. Without it a build stays
|
||||
# "dev" and never offers an update.
|
||||
|
||||
# Make sure pkg-config is found even when make runs with a minimal PATH
|
||||
# (e.g. launched from an IDE such as CLion on macOS).
|
||||
PKG_CONFIG ?= $(firstword $(wildcard \
|
||||
$(addsuffix /pkg-config,$(subst :, ,$(PATH)) /opt/homebrew/bin /usr/local/bin)))
|
||||
ifeq ($(PKG_CONFIG),)
|
||||
PKG_CONFIG := pkg-config
|
||||
endif
|
||||
GRADLE = cd android && ./gradlew
|
||||
|
||||
GTK_CFLAGS := $(shell $(PKG_CONFIG) --cflags gtk4)
|
||||
GTK_LIBS := $(shell $(PKG_CONFIG) --libs gtk4)
|
||||
all: content
|
||||
|
||||
SRC_DIR := src
|
||||
DATA_DIR := data
|
||||
BUILD_DIR := build
|
||||
content:
|
||||
python3 scripts/build-content.py
|
||||
|
||||
CFLAGS = -Wall -Wextra -Wno-deprecated-declarations -I$(SRC_DIR) \
|
||||
-MMD -MP $(GTK_CFLAGS)
|
||||
LIBS = $(GTK_LIBS) -lm
|
||||
# Runs the desktop app from source on this machine (Linux, Windows or macOS).
|
||||
run:
|
||||
$(GRADLE) :desktop:run
|
||||
|
||||
# Published builds pass the commit they were made from (the CI workflow
|
||||
# exports it), which the updater compares against the build in the repository.
|
||||
# Without it the build keeps the "dev" default and never offers an update.
|
||||
COMMIT ?=
|
||||
ifneq ($(COMMIT),)
|
||||
CFLAGS += -DAPP_COMMIT='"$(COMMIT)"'
|
||||
endif
|
||||
# Answer checks shared by Kotlin and Swift (tests/answers.json), plus
|
||||
# progress migration and import of GTK progress.
|
||||
test:
|
||||
$(GRADLE) :desktop:test
|
||||
@if command -v xcrun >/dev/null 2>&1; then \
|
||||
chmod +x scripts/test-answers-swift.sh && ./scripts/test-answers-swift.sh; \
|
||||
else \
|
||||
echo "Swift checks skipped (no Xcode)"; \
|
||||
fi
|
||||
|
||||
ifeq ($(OS),Windows_NT)
|
||||
TARGET = graduately.exe
|
||||
LIBS += -mwindows
|
||||
WINDRES ?= windres
|
||||
RC_SRC = $(DATA_DIR)/windows/maturita.rc
|
||||
RC_OBJ = $(BUILD_DIR)/maturita_rc.o
|
||||
UNAME_S :=
|
||||
else
|
||||
TARGET = graduately
|
||||
RC_SRC =
|
||||
RC_OBJ =
|
||||
UNAME_S := $(shell uname -s 2>/dev/null)
|
||||
ifeq ($(UNAME_S),Darwin)
|
||||
LIBS += -framework AppKit -framework Foundation
|
||||
endif
|
||||
endif
|
||||
android:
|
||||
$(GRADLE) :app:assembleRelease
|
||||
|
||||
SRC = $(wildcard $(SRC_DIR)/*.c)
|
||||
OBJ = $(patsubst $(SRC_DIR)/%.c,$(BUILD_DIR)/%.o,$(SRC))
|
||||
DEP = $(OBJ:.o=.d)
|
||||
linux:
|
||||
chmod +x scripts/bundle-linux.sh
|
||||
./scripts/bundle-linux.sh
|
||||
|
||||
ICON_DST = $(DATA_DIR)/share/icons/hicolor/512x512/apps/maturita.png
|
||||
ICON_ICO = assets/app-icon.ico
|
||||
windows:
|
||||
bash scripts/bundle-windows.sh
|
||||
|
||||
all: $(TARGET)
|
||||
ios:
|
||||
chmod +x scripts/bundle-ios.sh
|
||||
./scripts/bundle-ios.sh
|
||||
|
||||
$(BUILD_DIR):
|
||||
mkdir -p $(BUILD_DIR)
|
||||
|
||||
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c | $(BUILD_DIR)
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
ifeq ($(OS),Windows_NT)
|
||||
$(RC_OBJ): $(RC_SRC) $(ICON_ICO) | $(BUILD_DIR)
|
||||
$(WINDRES) -I. -o $@ $<
|
||||
|
||||
$(TARGET): $(OBJ) $(RC_OBJ)
|
||||
$(CC) $(CFLAGS) -o $@ $(OBJ) $(RC_OBJ) $(LIBS)
|
||||
else
|
||||
$(TARGET): $(OBJ)
|
||||
$(CC) $(CFLAGS) -o $@ $(OBJ) $(LIBS)
|
||||
endif
|
||||
|
||||
clean:
|
||||
rm -f $(TARGET) graduately.exe maturita.exe maturita
|
||||
rm -rf $(BUILD_DIR)
|
||||
|
||||
run: $(TARGET)
|
||||
./$(TARGET)
|
||||
|
||||
ifeq ($(OS),Windows_NT)
|
||||
bundle: $(TARGET)
|
||||
@rm -rf dist
|
||||
@mkdir -p dist
|
||||
@cp $(TARGET) dist/
|
||||
@cp $(DATA_DIR)/style.css dist/
|
||||
@cp $(DATA_DIR)/changelog.txt dist/
|
||||
@mkdir -p dist/icons/hicolor/512x512/apps
|
||||
@cp "$(ICON_DST)" dist/icons/hicolor/512x512/apps/
|
||||
@cp -R $(DATA_DIR)/share dist/
|
||||
@ldd $(TARGET) | grep -Ei '/(ucrt64|mingw64)/bin/' | awk '{print $$3}' \
|
||||
| xargs -r -I{} cp -f {} dist/
|
||||
@GTK_PREFIX="$$($(PKG_CONFIG) --variable=prefix gtk4)"; \
|
||||
if [ -d "$$GTK_PREFIX/share/glib-2.0" ]; then \
|
||||
mkdir -p dist/share && cp -R "$$GTK_PREFIX/share/glib-2.0" dist/share/; \
|
||||
fi; \
|
||||
if [ -d "$$GTK_PREFIX/lib/gdk-pixbuf-2.0" ]; then \
|
||||
mkdir -p dist/lib && cp -R "$$GTK_PREFIX/lib/gdk-pixbuf-2.0" dist/lib/; \
|
||||
fi
|
||||
@echo "Bundled into dist/ - run dist/$(TARGET)"
|
||||
else ifeq ($(UNAME_S),Darwin)
|
||||
bundle:
|
||||
@chmod +x scripts/bundle-macos-swift.sh
|
||||
@./scripts/bundle-macos-swift.sh
|
||||
else
|
||||
bundle:
|
||||
@chmod +x scripts/bundle-linux.sh
|
||||
@./scripts/bundle-linux.sh
|
||||
endif
|
||||
macos:
|
||||
chmod +x scripts/bundle-macos-swift.sh
|
||||
./scripts/bundle-macos-swift.sh
|
||||
|
||||
# Browsers render .command/.sh/.cmd as text/plain. Rebuild these zips after
|
||||
# changing a script so the README download links stay in sync. The macOS zip
|
||||
|
|
@ -118,18 +56,8 @@ smoke:
|
|||
chmod +x scripts/smoke-platforms.sh
|
||||
./scripts/smoke-platforms.sh
|
||||
|
||||
-include $(DEP)
|
||||
clean:
|
||||
rm -rf build dist dist-android dist-ios
|
||||
$(GRADLE) clean
|
||||
|
||||
android:
|
||||
python3 scripts/extract-android-content.py
|
||||
cd android && ./gradlew :app:assembleRelease
|
||||
|
||||
ios:
|
||||
chmod +x scripts/bundle-ios.sh
|
||||
./scripts/bundle-ios.sh
|
||||
|
||||
macos:
|
||||
chmod +x scripts/bundle-macos-swift.sh
|
||||
./scripts/bundle-macos-swift.sh
|
||||
|
||||
.PHONY: all clean run bundle installer-zips smoke android ios macos
|
||||
.PHONY: all content run test android linux windows ios macos installer-zips smoke clean
|
||||
|
|
|
|||
196
README.md
196
README.md
|
|
@ -54,8 +54,10 @@ spolehlivější instalátor výše, nebo stažení přímo z té stránky větv
|
|||
- [graduately-android.apk](https://github.com/pepaskopec-blip/Graduately/raw/refs/heads/builds/graduately-android.apk)
|
||||
- [graduately-ios.ipa](https://github.com/pepaskopec-blip/Graduately/raw/refs/heads/builds/graduately-ios.ipa)
|
||||
|
||||
Postup a nastavení se ukládají vedle `.app` / složky / AppImage do `progress/`.
|
||||
Na Androidu, iOS a macOS do úložiště aplikace (stejné statistiky, témata a jazyk).
|
||||
Na Linuxu a Windows se postup a nastavení ukládají do `progress/` vedle
|
||||
AppImage / ve složce aplikace; postup ze starší GTK verze se při prvním
|
||||
spuštění převezme. Na Androidu, iOS a macOS do úložiště aplikace (stejné
|
||||
statistiky, témata a jazyk).
|
||||
|
||||
Intel Mac, jiná architektura nebo úpravy kódu → [sestavení ze zdroje](#sestavení-ze-zdroje).
|
||||
|
||||
|
|
@ -84,7 +86,7 @@ Intel Mac, jiná architektura nebo úpravy kódu → [sestavení ze zdroje](#ses
|
|||
- **Angličtina** — 4 ročníky, 32 lekcí podle osnov gymnázia (A2 až maturita):
|
||||
poslech, čtení, psaní, doplňování, kvízy a ročníkové testy
|
||||
- statistiky, hledání (lupa nebo `Cmd/Ctrl+K`), 10 témat, tmavý/světlý režim, čeština/angličtina
|
||||
- ukončení: `Cmd/Super+Q` nebo `Alt+F4`
|
||||
- ukončení: `Ctrl/Cmd+Q` nebo `Alt+F4`, zpět: `Esc`
|
||||
|
||||
### Použití
|
||||
|
||||
|
|
@ -95,49 +97,42 @@ Intel Mac, jiná architektura nebo úpravy kódu → [sestavení ze zdroje](#ses
|
|||
|
||||
### Sestavení ze zdroje
|
||||
|
||||
macOS je nativní SwiftUI aplikace (Xcode 26, macOS 26+). Linux a Windows
|
||||
zůstávají GTK 4.
|
||||
Dvě kódové základny, jeden obsah (`content/`) a společné testy (`tests/`):
|
||||
|
||||
```bash
|
||||
# macOS
|
||||
# Xcode 26 z App Storu; žádné GTK
|
||||
|
||||
# Debian / Ubuntu
|
||||
sudo apt install build-essential pkg-config libgtk-4-dev
|
||||
|
||||
# Fedora
|
||||
sudo dnf install gcc make pkgconf-pkg-config gtk4-devel
|
||||
|
||||
# Arch
|
||||
sudo pacman -S base-devel pkgconf gtk4
|
||||
```
|
||||
- **Kotlin + Compose** (`android/`): Android, Linux a Windows. Obrazovky,
|
||||
cvičení a kontrola odpovědí jsou v `android/shared/`, platformy se liší jen
|
||||
vstupním bodem (`android/app`, `android/desktop`).
|
||||
- **Swift + SwiftUI** (`ios/`, `macos/`): iPhone a Mac (Xcode 26, macOS 26+).
|
||||
|
||||
```bash
|
||||
git clone https://github.com/pepaskopec-blip/Graduately.git
|
||||
cd Graduately
|
||||
make test # kontrola odpovědí v Kotlinu (a ve Swiftu, je-li Xcode)
|
||||
```
|
||||
|
||||
Linux, Windows (i Mac pro vývoj) — stačí JDK 17+ a Python 3:
|
||||
|
||||
```bash
|
||||
make run # spustí desktopovou aplikaci ze zdroje
|
||||
make linux # dist/graduately-linux-x86_64.AppImage
|
||||
make windows # dist/graduately-windows-x64.zip (v Git Bash)
|
||||
make smoke # instalátory, obsah, testy, dostupnost builds
|
||||
```
|
||||
|
||||
Na balení (`make linux` / `make windows`) je potřeba JDK s `jmods`, např.
|
||||
Temurin 21; cestu k němu předejte v `PACKAGE_JDK`. ProGuard zmenší balíček
|
||||
pod limit GitHubu 100 MB.
|
||||
|
||||
Na Macu:
|
||||
|
||||
```bash
|
||||
open Graduately.xcworkspace # scheme Graduately z macos/Graduately.xcodeproj
|
||||
# nebo: make bundle # zip v dist/graduately-macos-arm64.zip
|
||||
# nebo: make macos # zip v dist/graduately-macos-arm64.zip
|
||||
```
|
||||
|
||||
Na Linuxu a Windows:
|
||||
|
||||
```bash
|
||||
make
|
||||
make run # nebo ./graduately
|
||||
make bundle # AppImage / Windows složka s DLL
|
||||
make smoke # instalátory, content packs, dostupnost builds
|
||||
```
|
||||
|
||||
Volitelně CMake (GTK): `cmake -S . -B build && cmake --build build`.
|
||||
|
||||
Na macOS `make bundle` automaticky vloží aktuální Git commit, aby fungovala
|
||||
Na macOS `make macos` automaticky vloží aktuální Git commit, aby fungovala
|
||||
kontrola aktualizací. Při balení ze zdrojů bez `.git` zadejte
|
||||
`COMMIT=<zdrojový-commit> make bundle`.
|
||||
`COMMIT=<zdrojový-commit> make macos`.
|
||||
|
||||
Aby stažená aplikace na macOS šla otevřít bez potvrzení v Nastavení, CI
|
||||
potřebuje **Apple Developer Program** a GitHub Secrets:
|
||||
|
|
@ -149,43 +144,28 @@ potřebuje **Apple Developer Program** a GitHub Secrets:
|
|||
|
||||
Bez toho zůstane jen ad-hoc podpis a Gatekeeper stažený build zablokuje.
|
||||
|
||||
#### Windows (MSYS2 UCRT64, bez Visual Studia)
|
||||
|
||||
```cmd
|
||||
winget install --id MSYS2.MSYS2 -e --source winget
|
||||
C:\msys64\ucrt64.exe pacman -S --noconfirm mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-gtk4 mingw-w64-ucrt-x86_64-pkg-config make
|
||||
```
|
||||
|
||||
V terminálu **MSYS2 UCRT64**:
|
||||
|
||||
```bash
|
||||
cd /c/Users/<jméno>/Graduately # C:\Users\<jméno>\Graduately v MSYS2
|
||||
make
|
||||
./graduately.exe
|
||||
make bundle # dist/graduately.exe jde spustit i z Průzkumníka
|
||||
```
|
||||
|
||||
### Struktura
|
||||
|
||||
```
|
||||
src/ C zdroje (GTK přehrávač pro Linux a Windows)
|
||||
android/ Jetpack Compose přehrávač (stejný obsah)
|
||||
ios/ SwiftUI přehrávač (stejný obsah)
|
||||
macos/ nativní SwiftUI aplikace pro Mac (stejný obsah)
|
||||
data/ style.css, changelog.txt, share/, cetba/*.json
|
||||
content/ texty lekcí, cvičení a knih v Markdownu (viz content/README.md)
|
||||
android/shared/ společný Kotlin: obrazovky, cvičení, kontrola odpovědí, postup
|
||||
android/app/ Android (vstupní bod, aktualizace APK, předčítání)
|
||||
android/desktop/ Linux a Windows (okno, aktualizace, předčítání, import z GTK)
|
||||
ios/ SwiftUI pro iPhone
|
||||
macos/ SwiftUI pro Mac (sdílí kód s ios/)
|
||||
tests/ společné testy kontroly odpovědí (answers.json) + Swift harness
|
||||
data/share/ ikony a .desktop soubor
|
||||
assets/ zdrojová ikona a screenshoty
|
||||
installers/ instalátory, které stáhnou aktuální build
|
||||
scripts/ balení AppImage, .app, IPA, extract a smoke test
|
||||
scripts/ build-content.py, balení AppImage, zip, .app, IPA a smoke test
|
||||
.github/workflows/ CI: push na main → větev builds
|
||||
progress/ vzniká za běhu (cvičení, nastavení)
|
||||
```
|
||||
|
||||
Android ze zdroje (JDK 17 + Android SDK):
|
||||
|
||||
```bash
|
||||
python3 scripts/extract-android-content.py
|
||||
cd android
|
||||
./gradlew :app:assembleRelease
|
||||
./gradlew :app:assembleRelease # obsah z content/ se sestaví sám
|
||||
# APK: android/app/build/outputs/apk/release/app-release.apk
|
||||
```
|
||||
|
||||
|
|
@ -202,12 +182,12 @@ iOS ze zdroje (Xcode 26, iOS 26+ / Liquid Glass):
|
|||
```bash
|
||||
open Graduately.xcworkspace # v kořeni repozitáře
|
||||
# Simulátor: vyber iPhone a Run, nic dalšího není potřeba (obsah se
|
||||
# vytáhne z C zdrojů při buildu). Na iPhone: v Signing vyber svůj Team.
|
||||
# sestaví z content/ při buildu). Na iPhone: v Signing vyber svůj Team.
|
||||
# nebo: make ios # unsigned IPA v dist-ios/graduately-ios.ipa
|
||||
```
|
||||
|
||||
Workspace odkazuje na `ios/Graduately.xcodeproj` a `macos/Graduately.xcodeproj`.
|
||||
Projekty nepřesouvejte – build čte `../src` a `../scripts`.
|
||||
Projekty nepřesouvejte – build čte `../content` a `../scripts`.
|
||||
|
||||
Licence: [GPL-3.0](LICENSE).
|
||||
|
||||
|
|
@ -261,8 +241,10 @@ above, or download from that branch page:
|
|||
- [graduately-android.apk](https://github.com/pepaskopec-blip/Graduately/raw/refs/heads/builds/graduately-android.apk)
|
||||
- [graduately-ios.ipa](https://github.com/pepaskopec-blip/Graduately/raw/refs/heads/builds/graduately-ios.ipa)
|
||||
|
||||
Progress and settings live in `progress/` next to the `.app` / folder /
|
||||
AppImage. On Android, iOS and macOS they stay in app storage (same stats, themes, language).
|
||||
On Linux and Windows, progress and settings live in `progress/` next to the
|
||||
AppImage / in the app folder; progress from the older GTK build is taken over
|
||||
on first launch. On Android, iOS and macOS they stay in app storage (same
|
||||
stats, themes, language).
|
||||
|
||||
Intel Mac, another architecture, or hacking on the code →
|
||||
[build from source](#build-from-source).
|
||||
|
|
@ -293,7 +275,7 @@ Intel Mac, another architecture, or hacking on the code →
|
|||
- **English** — 4 years, 32 lessons from the gymnasium syllabus (A2 through
|
||||
the maturita): listening, reading, writing, gap-fill, quizzes and year tests
|
||||
- statistics, search (magnifier or `Cmd/Ctrl+K`), 10 palettes, dark/light mode, Czech/English
|
||||
- quit with `Cmd/Super+Q` or `Alt+F4`
|
||||
- quit with `Ctrl/Cmd+Q` or `Alt+F4`, back with `Esc`
|
||||
|
||||
### Usage
|
||||
|
||||
|
|
@ -304,49 +286,42 @@ Intel Mac, another architecture, or hacking on the code →
|
|||
|
||||
### Build from source
|
||||
|
||||
macOS is a native SwiftUI app (Xcode 26, macOS 26+). Linux and Windows
|
||||
stay on GTK 4.
|
||||
Two code bases, one content tree (`content/`) and shared tests (`tests/`):
|
||||
|
||||
```bash
|
||||
# macOS
|
||||
# Xcode 26 from the App Store; no GTK
|
||||
|
||||
# Debian / Ubuntu
|
||||
sudo apt install build-essential pkg-config libgtk-4-dev
|
||||
|
||||
# Fedora
|
||||
sudo dnf install gcc make pkgconf-pkg-config gtk4-devel
|
||||
|
||||
# Arch
|
||||
sudo pacman -S base-devel pkgconf gtk4
|
||||
```
|
||||
- **Kotlin + Compose** (`android/`): Android, Linux and Windows. Screens,
|
||||
exercises and answer checking live in `android/shared/`; the platforms only
|
||||
differ in their entry point (`android/app`, `android/desktop`).
|
||||
- **Swift + SwiftUI** (`ios/`, `macos/`): iPhone and Mac (Xcode 26, macOS 26+).
|
||||
|
||||
```bash
|
||||
git clone https://github.com/pepaskopec-blip/Graduately.git
|
||||
cd Graduately
|
||||
make test # answer checks in Kotlin (and Swift when Xcode is there)
|
||||
```
|
||||
|
||||
Linux, Windows (and a Mac for development) need JDK 17+ and Python 3:
|
||||
|
||||
```bash
|
||||
make run # run the desktop app from source
|
||||
make linux # dist/graduately-linux-x86_64.AppImage
|
||||
make windows # dist/graduately-windows-x64.zip (in Git Bash)
|
||||
make smoke # installers, content, tests, builds availability
|
||||
```
|
||||
|
||||
Packaging (`make linux` / `make windows`) needs a JDK that ships `jmods`,
|
||||
such as Temurin 21; pass its path in `PACKAGE_JDK`. ProGuard keeps the
|
||||
package under GitHub's 100 MB limit.
|
||||
|
||||
On a Mac:
|
||||
|
||||
```bash
|
||||
open Graduately.xcworkspace # scheme Graduately from macos/Graduately.xcodeproj
|
||||
# or: make bundle # zip at dist/graduately-macos-arm64.zip
|
||||
# or: make macos # zip at dist/graduately-macos-arm64.zip
|
||||
```
|
||||
|
||||
On Linux and Windows:
|
||||
|
||||
```bash
|
||||
make
|
||||
make run # or ./graduately
|
||||
make bundle # AppImage / Windows DLL folder
|
||||
make smoke # installers, content packs, builds availability
|
||||
```
|
||||
|
||||
Optional CMake (GTK): `cmake -S . -B build && cmake --build build`.
|
||||
|
||||
On macOS, `make bundle` embeds the current Git commit so the installed app
|
||||
On macOS, `make macos` embeds the current Git commit so the installed app
|
||||
can check for updates. When packaging a source export without `.git`, use
|
||||
`COMMIT=<source-commit> make bundle`.
|
||||
`COMMIT=<source-commit> make macos`.
|
||||
|
||||
Skipping Gatekeeper on a downloaded macOS build needs an
|
||||
**Apple Developer Program** membership and these GitHub Secrets:
|
||||
|
|
@ -358,43 +333,28 @@ Skipping Gatekeeper on a downloaded macOS build needs an
|
|||
|
||||
Without them the bundle stays ad-hoc signed and Gatekeeper still blocks it.
|
||||
|
||||
#### Windows (MSYS2 UCRT64, no Visual Studio)
|
||||
|
||||
```cmd
|
||||
winget install --id MSYS2.MSYS2 -e --source winget
|
||||
C:\msys64\ucrt64.exe pacman -S --noconfirm mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-gtk4 mingw-w64-ucrt-x86_64-pkg-config make
|
||||
```
|
||||
|
||||
In an **MSYS2 UCRT64** terminal:
|
||||
|
||||
```bash
|
||||
cd /c/Users/<name>/Graduately # C:\Users\<name>\Graduately in MSYS2
|
||||
make
|
||||
./graduately.exe
|
||||
make bundle # dist/graduately.exe can be double-clicked
|
||||
```
|
||||
|
||||
### Layout
|
||||
|
||||
```
|
||||
src/ C sources (GTK player for Linux and Windows)
|
||||
android/ Jetpack Compose player (same content)
|
||||
ios/ SwiftUI player (same content)
|
||||
macos/ native SwiftUI Mac app (same content)
|
||||
data/ style.css, changelog.txt, share/, cetba/*.json
|
||||
content/ lesson, exercise and book texts in Markdown (see content/README.md)
|
||||
android/shared/ shared Kotlin: screens, exercises, answer checking, progress
|
||||
android/app/ Android (entry point, APK updates, speech)
|
||||
android/desktop/ Linux and Windows (window, updates, speech, GTK progress import)
|
||||
ios/ SwiftUI for iPhone
|
||||
macos/ SwiftUI for Mac (shares code with ios/)
|
||||
tests/ shared answer-check cases (answers.json) + Swift harness
|
||||
data/share/ icons and the .desktop file
|
||||
assets/ source icon and screenshots
|
||||
installers/ fetch-the-latest installers
|
||||
scripts/ AppImage / .app / IPA bundlers, extract, smoke test
|
||||
scripts/ build-content.py, AppImage / zip / .app / IPA bundlers, smoke test
|
||||
.github/workflows/ CI: push to main → builds branch
|
||||
progress/ created at runtime (exercises, settings)
|
||||
```
|
||||
|
||||
Android from source (JDK 17 + Android SDK):
|
||||
|
||||
```bash
|
||||
python3 scripts/extract-android-content.py
|
||||
cd android
|
||||
./gradlew :app:assembleRelease
|
||||
./gradlew :app:assembleRelease # content/ is built automatically
|
||||
# APK: android/app/build/outputs/apk/release/app-release.apk
|
||||
```
|
||||
|
||||
|
|
@ -411,11 +371,11 @@ iOS from source (Xcode 26, iOS 26+ / Liquid Glass):
|
|||
```bash
|
||||
open Graduately.xcworkspace # at the repo root
|
||||
# Simulator: pick an iPhone and Run, nothing else needed (content is
|
||||
# extracted from the C sources during the build). Device: pick your Team.
|
||||
# built from content/ during the build). Device: pick your Team.
|
||||
# or: make ios # unsigned IPA at dist-ios/graduately-ios.ipa
|
||||
```
|
||||
|
||||
The workspace points at `ios/Graduately.xcodeproj` and `macos/Graduately.xcodeproj`.
|
||||
Do not move the projects – the build reads `../src` and `../scripts`.
|
||||
Do not move the projects – the build reads `../content` and `../scripts`.
|
||||
|
||||
License: [GPL-3.0](LICENSE).
|
||||
|
|
|
|||
|
|
@ -66,6 +66,9 @@ android {
|
|||
compose = true
|
||||
buildConfig = true
|
||||
}
|
||||
|
||||
// UI, data and navigation shared with the desktop app (../desktop).
|
||||
sourceSets.getByName("main").kotlin.directories.add("../shared/src")
|
||||
}
|
||||
|
||||
kotlin {
|
||||
|
|
@ -88,13 +91,14 @@ dependencies {
|
|||
debugImplementation("androidx.compose.ui:ui-tooling")
|
||||
}
|
||||
|
||||
val extractContent = tasks.register<Exec>("extractContent") {
|
||||
val buildContent = tasks.register<Exec>("buildContent") {
|
||||
workingDir = rootProject.projectDir.parentFile
|
||||
commandLine("python3", "scripts/extract-android-content.py")
|
||||
inputs.dir(rootProject.projectDir.parentFile.resolve("src"))
|
||||
commandLine("python3", "scripts/build-content.py")
|
||||
inputs.dir(rootProject.projectDir.parentFile.resolve("content"))
|
||||
inputs.file(rootProject.projectDir.parentFile.resolve("scripts/build-content.py"))
|
||||
outputs.file(file("src/main/assets/content.json"))
|
||||
}
|
||||
|
||||
tasks.named("preBuild").configure {
|
||||
dependsOn(extractContent)
|
||||
dependsOn(buildContent)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,88 @@
|
|||
package org.maturita.maturita
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.speech.tts.TextToSpeech
|
||||
import android.speech.tts.UtteranceProgressListener
|
||||
import org.maturita.maturita.platform.Platform
|
||||
import org.maturita.maturita.platform.Prefs
|
||||
import org.maturita.maturita.platform.Speaker
|
||||
import org.maturita.maturita.update.Updater
|
||||
import java.util.Locale
|
||||
|
||||
class AndroidPlatform(private val app: Application) : Platform {
|
||||
override val commit: String = BuildConfig.COMMIT
|
||||
override val versionName: String = BuildConfig.VERSION_NAME
|
||||
override val welcomeKey = "welcome_body_android"
|
||||
override val prefs: Prefs = AndroidPrefs(app.getSharedPreferences("maturita", Context.MODE_PRIVATE))
|
||||
override val updater = Updater(app)
|
||||
|
||||
override fun speaker(): Speaker = AndroidSpeaker(app)
|
||||
}
|
||||
|
||||
private class AndroidPrefs(private val sp: SharedPreferences) : Prefs {
|
||||
override fun getBoolean(key: String, fallback: Boolean) = sp.getBoolean(key, fallback)
|
||||
override fun getInt(key: String, fallback: Int) = sp.getInt(key, fallback)
|
||||
override fun getString(key: String, fallback: String?): String? = sp.getString(key, fallback)
|
||||
override fun edit(): Prefs.Editor = Editor(sp.edit())
|
||||
|
||||
private class Editor(private val e: SharedPreferences.Editor) : Prefs.Editor {
|
||||
override fun putBoolean(key: String, value: Boolean) = apply { e.putBoolean(key, value) }
|
||||
override fun putInt(key: String, value: Int) = apply { e.putInt(key, value) }
|
||||
override fun putString(key: String, value: String) = apply { e.putString(key, value) }
|
||||
override fun apply() = e.apply()
|
||||
}
|
||||
}
|
||||
|
||||
private class AndroidSpeaker(context: Context) : Speaker {
|
||||
private val main = Handler(Looper.getMainLooper())
|
||||
private var ready = false
|
||||
private val tts: TextToSpeech = TextToSpeech(context) { status ->
|
||||
ready = status == TextToSpeech.SUCCESS
|
||||
}
|
||||
|
||||
override fun speak(
|
||||
text: String,
|
||||
locale: Locale,
|
||||
rate: Float,
|
||||
volume: Float,
|
||||
onRange: (Int) -> Unit,
|
||||
onEnd: (Boolean) -> Unit,
|
||||
) {
|
||||
if (!ready) {
|
||||
main.post { onEnd(false) }
|
||||
return
|
||||
}
|
||||
val id = "en-${System.nanoTime()}"
|
||||
tts.language = locale
|
||||
tts.setSpeechRate(rate)
|
||||
tts.setOnUtteranceProgressListener(object : UtteranceProgressListener() {
|
||||
override fun onStart(utteranceId: String?) {}
|
||||
override fun onRangeStart(utteranceId: String?, rangeStart: Int, rangeEnd: Int, frame: Int) {
|
||||
if (utteranceId == id) main.post { onRange(rangeStart) }
|
||||
}
|
||||
override fun onDone(utteranceId: String?) {
|
||||
if (utteranceId == id) main.post { onEnd(true) }
|
||||
}
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun onError(utteranceId: String?) {
|
||||
if (utteranceId == id) main.post { onEnd(false) }
|
||||
}
|
||||
})
|
||||
val params = Bundle().apply { putFloat(TextToSpeech.Engine.KEY_PARAM_VOLUME, volume) }
|
||||
tts.speak(text, TextToSpeech.QUEUE_FLUSH, params, id)
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
tts.stop()
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
tts.stop()
|
||||
tts.shutdown()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +1,7 @@
|
|||
package org.maturita.maturita
|
||||
|
||||
import android.app.Application
|
||||
import android.os.Bundle
|
||||
import java.util.Locale
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.slideInHorizontally
|
||||
import androidx.compose.animation.slideOutHorizontally
|
||||
import androidx.compose.animation.togetherWith
|
||||
import android.util.TypedValue
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
|
|
@ -21,60 +13,19 @@ import androidx.activity.compose.BackHandler
|
|||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.activity.viewModels
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.darkColorScheme
|
||||
import androidx.compose.material3.lightColorScheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import org.maturita.maturita.data.ColorMode
|
||||
import org.maturita.maturita.data.Palette
|
||||
import org.maturita.maturita.ui.BookListScreen
|
||||
import org.maturita.maturita.ui.BookScreen
|
||||
import org.maturita.maturita.ui.CzechMapScreen
|
||||
import org.maturita.maturita.ui.GermanExercise
|
||||
import org.maturita.maturita.ui.HomeScreen
|
||||
import org.maturita.maturita.ui.HwQuizScreen
|
||||
import org.maturita.maturita.ui.HwYearsScreen
|
||||
import org.maturita.maturita.ui.LessonListScreen
|
||||
import org.maturita.maturita.ui.FyzQuizScreen
|
||||
import org.maturita.maturita.ui.MathPracticeScreen
|
||||
import org.maturita.maturita.ui.MatYearsScreen
|
||||
import org.maturita.maturita.ui.FyzYearsScreen
|
||||
import org.maturita.maturita.ui.LitYearsScreen
|
||||
import org.maturita.maturita.ui.LessonRow
|
||||
import org.maturita.maturita.ui.LitQuizScreen
|
||||
import org.maturita.maturita.ui.SciMapScreen
|
||||
import org.maturita.maturita.ui.SciQuizScreen
|
||||
import org.maturita.maturita.ui.MluvExercise
|
||||
import org.maturita.maturita.ui.NetQuizScreen
|
||||
import org.maturita.maturita.ui.NetYearsScreen
|
||||
import org.maturita.maturita.ui.On2QuizScreen
|
||||
import org.maturita.maturita.ui.On3QuizScreen
|
||||
import org.maturita.maturita.ui.On4QuizScreen
|
||||
import org.maturita.maturita.ui.OnQuizScreen
|
||||
import org.maturita.maturita.ui.OnYearsScreen
|
||||
import org.maturita.maturita.ui.EnYearsScreen
|
||||
import org.maturita.maturita.ui.ChoiceLessonScreen
|
||||
import org.maturita.maturita.ui.DeHomeScreen
|
||||
import org.maturita.maturita.ui.ItYearScreen
|
||||
import org.maturita.maturita.ui.EngExScreen
|
||||
import org.maturita.maturita.ui.PlotScreen
|
||||
import org.maturita.maturita.ui.RoadmapScreen
|
||||
import org.maturita.maturita.ui.SearchScreen
|
||||
import org.maturita.maturita.ui.SettingsScreen
|
||||
import org.maturita.maturita.ui.SlidesScreen
|
||||
import org.maturita.maturita.ui.StatsScreen
|
||||
import org.maturita.maturita.ui.UnitMapScreen
|
||||
import org.maturita.maturita.ui.VocabExercise
|
||||
import org.maturita.maturita.ui.appTypography
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import org.maturita.maturita.data.Content
|
||||
|
||||
/** Keeps the shared app state alive across rotation and other config changes. */
|
||||
class AppHolder(app: Application) : AndroidViewModel(app) {
|
||||
val vm = AppViewModel(
|
||||
Content.parse(runCatching { app.assets.open("content.json").bufferedReader().use { it.readText() } }.getOrNull()),
|
||||
AndroidPlatform(app),
|
||||
)
|
||||
}
|
||||
|
||||
class MainActivity : ComponentActivity() {
|
||||
private val vm: AppViewModel by viewModels()
|
||||
private val holder: AppHolder by viewModels()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
|
@ -96,7 +47,11 @@ class MainActivity : ComponentActivity() {
|
|||
return
|
||||
}
|
||||
enableEdgeToEdge()
|
||||
setContent { MaturitaApp(vm) }
|
||||
val vm = holder.vm
|
||||
setContent {
|
||||
BackHandler(vm.canGoBack || vm.searchOpen) { vm.handleBack() }
|
||||
MaturitaApp(vm)
|
||||
}
|
||||
}
|
||||
|
||||
private fun crashView(dump: String, retry: () -> Unit): LinearLayout {
|
||||
|
|
@ -135,512 +90,3 @@ class MainActivity : ComponentActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
/** Material 3 colour roles from the shared theme palette. */
|
||||
private fun schemeFor(p: Palette, dark: Boolean) = if (dark) {
|
||||
darkColorScheme(
|
||||
primary = p.tint,
|
||||
onPrimary = p.onTint,
|
||||
primaryContainer = p.accent,
|
||||
onPrimaryContainer = p.onAccent,
|
||||
secondary = p.accent2,
|
||||
onSecondary = p.onAccent,
|
||||
secondaryContainer = p.surface1,
|
||||
onSecondaryContainer = p.text,
|
||||
tertiary = p.warning,
|
||||
onTertiary = p.crust,
|
||||
background = p.base,
|
||||
onBackground = p.text,
|
||||
surface = p.base,
|
||||
onSurface = p.text,
|
||||
surfaceVariant = p.surface0,
|
||||
onSurfaceVariant = p.subtext,
|
||||
surfaceContainerLowest = p.crust,
|
||||
surfaceContainerLow = p.mantle,
|
||||
surfaceContainer = p.mantle,
|
||||
surfaceContainerHigh = p.surface0,
|
||||
surfaceContainerHighest = p.surface1,
|
||||
outline = p.overlay,
|
||||
outlineVariant = p.surface1,
|
||||
error = p.error,
|
||||
onError = Color.White,
|
||||
errorContainer = p.error.copy(alpha = 0.22f),
|
||||
onErrorContainer = p.text,
|
||||
)
|
||||
} else {
|
||||
lightColorScheme(
|
||||
primary = p.tint,
|
||||
onPrimary = p.onTint,
|
||||
primaryContainer = p.accent,
|
||||
onPrimaryContainer = p.onAccent,
|
||||
secondary = p.accent2,
|
||||
onSecondary = Color.White,
|
||||
secondaryContainer = p.surface1,
|
||||
onSecondaryContainer = p.text,
|
||||
tertiary = p.warning,
|
||||
onTertiary = Color.White,
|
||||
background = p.base,
|
||||
onBackground = p.text,
|
||||
surface = p.base,
|
||||
onSurface = p.text,
|
||||
surfaceVariant = p.surface1,
|
||||
onSurfaceVariant = p.subtext,
|
||||
surfaceContainerLowest = p.mantle,
|
||||
surfaceContainerLow = p.mantle,
|
||||
surfaceContainer = p.mantle,
|
||||
surfaceContainerHigh = p.surface1,
|
||||
surfaceContainerHighest = p.surface2,
|
||||
outline = p.overlay,
|
||||
outlineVariant = p.surface2,
|
||||
error = p.error,
|
||||
onError = Color.White,
|
||||
errorContainer = p.error.copy(alpha = 0.14f),
|
||||
onErrorContainer = p.text,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun MaturitaApp(vm: AppViewModel) {
|
||||
MaterialTheme(colorScheme = schemeFor(vm.palette, vm.mode == ColorMode.Dark), typography = appTypography()) {
|
||||
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
|
||||
MaturitaAppBody(vm)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MaturitaAppBody(vm: AppViewModel) {
|
||||
LaunchedEffect(Unit) { vm.checkUpdate(false) }
|
||||
BackHandler(vm.canGoBack || vm.searchOpen) {
|
||||
if (vm.searchOpen) vm.searchOpen = false else vm.back()
|
||||
}
|
||||
Box(Modifier.fillMaxSize()) {
|
||||
AnimatedContent(
|
||||
targetState = vm.route,
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
transitionSpec = {
|
||||
val tabs = targetState.isRoot && initialState.isRoot
|
||||
if (tabs) {
|
||||
fadeIn(tween(180)) togetherWith fadeOut(tween(140))
|
||||
} else if (vm.navigatingForward) {
|
||||
(fadeIn(tween(220)) + slideInHorizontally(tween(220)) { it / 5 })
|
||||
.togetherWith(fadeOut(tween(150)) + slideOutHorizontally(tween(150)) { -it / 8 })
|
||||
} else {
|
||||
(fadeIn(tween(220)) + slideInHorizontally(tween(220)) { -it / 8 })
|
||||
.togetherWith(fadeOut(tween(150)) + slideOutHorizontally(tween(150)) { it / 5 })
|
||||
}
|
||||
},
|
||||
label = "screen",
|
||||
) { route ->
|
||||
when (val r = route) {
|
||||
Route.Welcome, Route.Subjects -> HomeScreen(vm)
|
||||
Route.Stats -> StatsScreen(vm)
|
||||
Route.Settings -> SettingsScreen(vm)
|
||||
Route.DeHome -> DeHomeScreen(vm)
|
||||
is Route.DeMap -> LessonListScreen(
|
||||
vm, vm.tr("de_year${r.year}"), vm.tr("de_y${r.year}_sub"),
|
||||
vm.content.deYear(r.year).map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.deDone(r.year, id), Route.DeLesson(r.year, id))
|
||||
},
|
||||
)
|
||||
is Route.DeLesson -> {
|
||||
val l = vm.content.deLesson(r.year, r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.DeEx(r.year, r.id))
|
||||
}
|
||||
}
|
||||
is Route.DeEx -> EngExScreen(
|
||||
vm, r.year, r.id, Locale.GERMANY, vm.content.deLesson(r.year, r.id),
|
||||
) { vm.markDe(r.year, r.id) }
|
||||
Route.Roadmap -> RoadmapScreen(vm)
|
||||
is Route.UnitMap -> UnitMapScreen(vm, r.unitId)
|
||||
is Route.GermanEx -> GermanExercise(vm, r.unitId, r.ex)
|
||||
is Route.Vocab -> VocabExercise(vm, r.unitId)
|
||||
Route.NetYears -> NetYearsScreen(vm)
|
||||
Route.NetMap -> LessonListScreen(
|
||||
vm, vm.tr("net_year1"), vm.tr("net_sub"),
|
||||
vm.content.netLessons.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.netDone(id), Route.NetLesson(id))
|
||||
},
|
||||
)
|
||||
is Route.NetLesson -> {
|
||||
val l = vm.content.netLesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.NetEx(r.id))
|
||||
}
|
||||
}
|
||||
is Route.NetEx -> NetQuizScreen(vm, r.id)
|
||||
Route.Net2Map -> ItYearScreen(vm, "net2", "net_year2", "net2_sub") { Route.Net2Lesson(it) }
|
||||
is Route.Net2Lesson -> {
|
||||
val l = vm.content.itLesson("net2", r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.Net2Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.Net2Ex -> ChoiceLessonScreen(vm, vm.content.itLesson("net2", r.id)) { vm.markCourse("net2", r.id) }
|
||||
Route.Net3Map -> ItYearScreen(vm, "net3", "net_year3", "net3_sub") { Route.Net3Lesson(it) }
|
||||
is Route.Net3Lesson -> {
|
||||
val l = vm.content.itLesson("net3", r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.Net3Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.Net3Ex -> ChoiceLessonScreen(vm, vm.content.itLesson("net3", r.id)) { vm.markCourse("net3", r.id) }
|
||||
Route.Net4Map -> ItYearScreen(vm, "net4", "net_year4", "net4_sub") { Route.Net4Lesson(it) }
|
||||
is Route.Net4Lesson -> {
|
||||
val l = vm.content.itLesson("net4", r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.Net4Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.Net4Ex -> ChoiceLessonScreen(vm, vm.content.itLesson("net4", r.id)) { vm.markCourse("net4", r.id) }
|
||||
Route.HwYears -> HwYearsScreen(vm)
|
||||
Route.HwMap -> LessonListScreen(
|
||||
vm, vm.tr("hw_year1"), vm.tr("hw_sub"),
|
||||
vm.content.hw.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.hwDone(id), Route.HwLesson(id))
|
||||
},
|
||||
)
|
||||
is Route.HwLesson -> {
|
||||
val l = vm.content.hwLesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.HwEx(r.id))
|
||||
}
|
||||
}
|
||||
is Route.HwEx -> HwQuizScreen(vm, r.id)
|
||||
Route.Hw2Map -> ItYearScreen(vm, "hw2", "hw_year2", "hw2_sub") { Route.Hw2Lesson(it) }
|
||||
is Route.Hw2Lesson -> {
|
||||
val l = vm.content.itLesson("hw2", r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.Hw2Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.Hw2Ex -> ChoiceLessonScreen(vm, vm.content.itLesson("hw2", r.id)) { vm.markCourse("hw2", r.id) }
|
||||
Route.Hw3Map -> ItYearScreen(vm, "hw3", "hw_year3", "hw3_sub") { Route.Hw3Lesson(it) }
|
||||
is Route.Hw3Lesson -> {
|
||||
val l = vm.content.itLesson("hw3", r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.Hw3Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.Hw3Ex -> ChoiceLessonScreen(vm, vm.content.itLesson("hw3", r.id)) { vm.markCourse("hw3", r.id) }
|
||||
Route.Hw4Map -> ItYearScreen(vm, "hw4", "hw_year4", "hw4_sub") { Route.Hw4Lesson(it) }
|
||||
is Route.Hw4Lesson -> {
|
||||
val l = vm.content.itLesson("hw4", r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.Hw4Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.Hw4Ex -> ChoiceLessonScreen(vm, vm.content.itLesson("hw4", r.id)) { vm.markCourse("hw4", r.id) }
|
||||
Route.EnYears -> EnYearsScreen(vm)
|
||||
is Route.EnMap -> LessonListScreen(
|
||||
vm, vm.tr("en_year${r.year}"), vm.tr("en_y${r.year}_sub"),
|
||||
vm.content.enYear(r.year).map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.enDone(r.year, id), Route.EnLesson(r.year, id))
|
||||
},
|
||||
)
|
||||
is Route.EnLesson -> {
|
||||
val l = vm.content.enLesson(r.year, r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.EnEx(r.year, r.id))
|
||||
}
|
||||
}
|
||||
is Route.EnEx -> EngExScreen(vm, r.year, r.id)
|
||||
Route.OnYears -> OnYearsScreen(vm)
|
||||
Route.OnMap -> LessonListScreen(
|
||||
vm, vm.tr("on_year1"), vm.tr("on_sub"),
|
||||
vm.content.on.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.onDone(id), Route.OnLesson(id))
|
||||
},
|
||||
)
|
||||
is Route.OnLesson -> {
|
||||
val l = vm.content.onLesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.OnEx(r.id))
|
||||
}
|
||||
}
|
||||
is Route.OnEx -> OnQuizScreen(vm, r.id)
|
||||
Route.On2Map -> LessonListScreen(
|
||||
vm, vm.tr("on_year2"), vm.tr("on2_sub"),
|
||||
vm.content.on2.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.on2Done(id), Route.On2Lesson(id))
|
||||
},
|
||||
)
|
||||
is Route.On2Lesson -> {
|
||||
val l = vm.content.on2Lesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.On2Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.On2Ex -> On2QuizScreen(vm, r.id)
|
||||
Route.On3Map -> LessonListScreen(
|
||||
vm, vm.tr("on_year3"), vm.tr("on3_sub"),
|
||||
vm.content.on3.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.on3Done(id), Route.On3Lesson(id))
|
||||
},
|
||||
)
|
||||
is Route.On3Lesson -> {
|
||||
val l = vm.content.on3Lesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.On3Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.On3Ex -> On3QuizScreen(vm, r.id)
|
||||
Route.On4Map -> LessonListScreen(
|
||||
vm, vm.tr("on_year4"), vm.tr("on4_sub"),
|
||||
vm.content.on4.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.on4Done(id), Route.On4Lesson(id))
|
||||
},
|
||||
)
|
||||
is Route.On4Lesson -> {
|
||||
val l = vm.content.on4Lesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.On4Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.On4Ex -> On4QuizScreen(vm, r.id)
|
||||
Route.LitYears -> LitYearsScreen(vm)
|
||||
Route.LitMap -> LessonListScreen(
|
||||
vm, vm.tr("lit_year1"), vm.tr("lit_sub"),
|
||||
vm.content.lit.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.litDone(id), Route.LitLesson(id))
|
||||
},
|
||||
)
|
||||
is Route.LitLesson -> {
|
||||
val l = vm.content.litLesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.LitEx(r.id))
|
||||
}
|
||||
}
|
||||
is Route.LitEx -> LitQuizScreen(vm, 1, r.id)
|
||||
Route.Lit2Map -> LessonListScreen(
|
||||
vm, vm.tr("lit_year2"), vm.tr("lit2_sub"),
|
||||
vm.content.lit2.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.lit2Done(id), Route.Lit2Lesson(id))
|
||||
},
|
||||
)
|
||||
is Route.Lit2Lesson -> {
|
||||
val l = vm.content.lit2Lesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.Lit2Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.Lit2Ex -> LitQuizScreen(vm, 2, r.id)
|
||||
Route.Lit3Map -> LessonListScreen(
|
||||
vm, vm.tr("lit_year3"), vm.tr("lit3_sub"),
|
||||
vm.content.lit3.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.lit3Done(id), Route.Lit3Lesson(id))
|
||||
},
|
||||
)
|
||||
is Route.Lit3Lesson -> {
|
||||
val l = vm.content.lit3Lesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.Lit3Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.Lit3Ex -> LitQuizScreen(vm, 3, r.id)
|
||||
Route.Lit4Map -> LessonListScreen(
|
||||
vm, vm.tr("lit_year4"), vm.tr("lit4_sub"),
|
||||
vm.content.lit4.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.lit4Done(id), Route.Lit4Lesson(id))
|
||||
},
|
||||
)
|
||||
is Route.Lit4Lesson -> {
|
||||
val l = vm.content.lit4Lesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.Lit4Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.Lit4Ex -> LitQuizScreen(vm, 4, r.id)
|
||||
Route.MatYears -> MatYearsScreen(vm)
|
||||
Route.Mat0Map -> LessonListScreen(
|
||||
vm, vm.tr("mat0_year"), vm.tr("mat0_sub"),
|
||||
vm.content.mat0.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.mat0Done(id), Route.Mat0Lesson(id))
|
||||
},
|
||||
)
|
||||
is Route.Mat0Lesson -> {
|
||||
val l = vm.content.mat0Lesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.Mat0Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.Mat0Ex -> MathPracticeScreen(vm, 0, r.id)
|
||||
Route.MatMap -> LessonListScreen(
|
||||
vm, vm.tr("mat_year1"), vm.tr("mat_sub"),
|
||||
vm.content.mat.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.matDone(id), Route.MatLesson(id))
|
||||
},
|
||||
)
|
||||
is Route.MatLesson -> {
|
||||
val l = vm.content.matLesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.MatEx(r.id))
|
||||
}
|
||||
}
|
||||
is Route.MatEx -> MathPracticeScreen(vm, 1, r.id)
|
||||
Route.Mat2Map -> LessonListScreen(
|
||||
vm, vm.tr("mat_year2"), vm.tr("mat2_sub"),
|
||||
vm.content.mat2.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.mat2Done(id), Route.Mat2Lesson(id))
|
||||
},
|
||||
)
|
||||
is Route.Mat2Lesson -> {
|
||||
val l = vm.content.mat2Lesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.Mat2Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.Mat2Ex -> MathPracticeScreen(vm, 2, r.id)
|
||||
Route.Mat3Map -> LessonListScreen(
|
||||
vm, vm.tr("mat_year3"), vm.tr("mat3_sub"),
|
||||
vm.content.mat3.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.mat3Done(id), Route.Mat3Lesson(id))
|
||||
},
|
||||
)
|
||||
is Route.Mat3Lesson -> {
|
||||
val l = vm.content.mat3Lesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.Mat3Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.Mat3Ex -> MathPracticeScreen(vm, 3, r.id)
|
||||
Route.Mat4Map -> LessonListScreen(
|
||||
vm, vm.tr("mat_year4"), vm.tr("mat4_sub"),
|
||||
vm.content.mat4.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.mat4Done(id), Route.Mat4Lesson(id))
|
||||
},
|
||||
)
|
||||
is Route.Mat4Lesson -> {
|
||||
val l = vm.content.mat4Lesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.Mat4Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.Mat4Ex -> MathPracticeScreen(vm, 4, r.id)
|
||||
Route.FyzYears -> FyzYearsScreen(vm)
|
||||
Route.FyzMap -> LessonListScreen(
|
||||
vm, vm.tr("fyz_year1"), vm.tr("fyz_sub"),
|
||||
vm.content.fyz.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.fyzDone(id), Route.FyzLesson(id))
|
||||
},
|
||||
)
|
||||
is Route.FyzLesson -> {
|
||||
val l = vm.content.fyzLesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.FyzEx(r.id))
|
||||
}
|
||||
}
|
||||
is Route.FyzEx -> FyzQuizScreen(vm, 1, r.id)
|
||||
Route.Fyz2Map -> LessonListScreen(
|
||||
vm, vm.tr("fyz_year2"), vm.tr("fyz2_sub"),
|
||||
vm.content.fyz2.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.fyz2Done(id), Route.Fyz2Lesson(id))
|
||||
},
|
||||
)
|
||||
is Route.Fyz2Lesson -> {
|
||||
val l = vm.content.fyz2Lesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.Fyz2Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.Fyz2Ex -> FyzQuizScreen(vm, 2, r.id)
|
||||
Route.Fyz3Map -> LessonListScreen(
|
||||
vm, vm.tr("fyz_year3"), vm.tr("fyz3_sub"),
|
||||
vm.content.fyz3.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.fyz3Done(id), Route.Fyz3Lesson(id))
|
||||
},
|
||||
)
|
||||
is Route.Fyz3Lesson -> {
|
||||
val l = vm.content.fyz3Lesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.Fyz3Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.Fyz3Ex -> FyzQuizScreen(vm, 3, r.id)
|
||||
Route.Fyz4Map -> LessonListScreen(
|
||||
vm, vm.tr("fyz_year4"), vm.tr("fyz4_sub"),
|
||||
vm.content.fyz4.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.fyz4Done(id), Route.Fyz4Lesson(id))
|
||||
},
|
||||
)
|
||||
is Route.Fyz4Lesson -> {
|
||||
val l = vm.content.fyz4Lesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.Fyz4Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.Fyz4Ex -> FyzQuizScreen(vm, 4, r.id)
|
||||
Route.SciMap -> SciMapScreen(vm)
|
||||
Route.ChemMap -> LessonListScreen(
|
||||
vm, vm.tr("Chemie"), vm.tr("chem_sub"),
|
||||
vm.content.chem.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.chemDone(id), Route.ChemLesson(id))
|
||||
},
|
||||
)
|
||||
is Route.ChemLesson -> {
|
||||
val l = vm.content.chemLesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.ChemEx(r.id))
|
||||
}
|
||||
}
|
||||
is Route.ChemEx -> SciQuizScreen(vm, "chem", r.id)
|
||||
Route.BioMap -> LessonListScreen(
|
||||
vm, vm.tr("Biologie"), vm.tr("bio_sub"),
|
||||
vm.content.bio.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.bioDone(id), Route.BioLesson(id))
|
||||
},
|
||||
)
|
||||
is Route.BioLesson -> {
|
||||
val l = vm.content.bioLesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.BioEx(r.id))
|
||||
}
|
||||
}
|
||||
is Route.BioEx -> SciQuizScreen(vm, "bio", r.id)
|
||||
Route.CzechMap -> CzechMapScreen(vm)
|
||||
Route.Mluvnice -> LessonListScreen(
|
||||
vm, vm.tr("Mluvnice"), vm.tr("mluv_sub"),
|
||||
vm.content.mluvnice.map { m ->
|
||||
val n = m.int("id")
|
||||
LessonRow(m.str("name"), vm.progress.mluvDone(n), Route.MluvEx(n))
|
||||
},
|
||||
)
|
||||
is Route.MluvEx -> MluvExercise(vm, r.n)
|
||||
Route.ReadingList -> BookListScreen(vm)
|
||||
is Route.Book -> BookScreen(vm, r.id)
|
||||
is Route.BookQuiz -> LitQuizScreen(vm, r.id)
|
||||
is Route.BookPlot -> PlotScreen(vm, r.id)
|
||||
}
|
||||
}
|
||||
AnimatedVisibility(
|
||||
visible = vm.searchOpen,
|
||||
enter = fadeIn(tween(160)),
|
||||
exit = fadeOut(tween(120)),
|
||||
) {
|
||||
Box(Modifier.fillMaxSize()) { SearchScreen(vm) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,26 +9,20 @@ import android.os.Looper
|
|||
import android.provider.Settings
|
||||
import androidx.core.content.FileProvider
|
||||
import org.maturita.maturita.BuildConfig
|
||||
import org.maturita.maturita.platform.AppUpdater
|
||||
import org.maturita.maturita.platform.UpdateState
|
||||
import java.io.File
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.URL
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
data class UpdateState(
|
||||
val status: String = "idle",
|
||||
val remote: String? = null,
|
||||
val messageKey: String = "update_current",
|
||||
val messageArg: String? = BuildConfig.COMMIT.take(7),
|
||||
val canInstall: Boolean = false,
|
||||
)
|
||||
|
||||
/**
|
||||
* Self-update from the `builds` branch. CI rewrites that branch on every
|
||||
* push to main with a commit titled "Build from <sha>"; the APK there is
|
||||
* signed with the repository's sideload key, so Android accepts it as an
|
||||
* update over any earlier build signed the same way.
|
||||
*/
|
||||
class Updater(private val app: Application) {
|
||||
class Updater(private val app: Application) : AppUpdater {
|
||||
private val io = Executors.newSingleThreadExecutor()
|
||||
private val main = Handler(Looper.getMainLooper())
|
||||
private val repo = BuildConfig.UPDATE_REPO
|
||||
|
|
@ -38,7 +32,7 @@ class Updater(private val app: Application) {
|
|||
main.post { cb(state) }
|
||||
}
|
||||
|
||||
fun check(interactive: Boolean, cb: (UpdateState) -> Unit) {
|
||||
override fun check(interactive: Boolean, cb: (UpdateState) -> Unit) {
|
||||
if (BuildConfig.COMMIT == "dev") {
|
||||
emit(cb, UpdateState(status = "dev", messageKey = "update_err_devbuild", messageArg = null))
|
||||
return
|
||||
|
|
@ -63,7 +57,7 @@ class Updater(private val app: Application) {
|
|||
}
|
||||
}
|
||||
|
||||
fun install(cb: (UpdateState) -> Unit) {
|
||||
override fun install(cb: (UpdateState) -> Unit) {
|
||||
// Android 8+ needs a per-app opt-in before we may hand an APK to the
|
||||
// package installer. Send the user there and keep the Update button
|
||||
// so the second tap goes straight to the download.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
plugins {
|
||||
id("com.android.application") version "9.1.1" apply false
|
||||
id("org.jetbrains.kotlin.plugin.compose") version "2.2.10" apply false
|
||||
id("org.jetbrains.kotlin.jvm") version "2.2.10" apply false
|
||||
id("org.jetbrains.compose") version "1.9.3" apply false
|
||||
}
|
||||
|
|
|
|||
103
android/desktop/build.gradle.kts
Normal file
103
android/desktop/build.gradle.kts
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
// Linux and Windows app: the same Compose UI as Android (../shared), packaged
|
||||
// with its own Java runtime by jpackage.
|
||||
plugins {
|
||||
id("org.jetbrains.kotlin.jvm")
|
||||
id("org.jetbrains.kotlin.plugin.compose")
|
||||
id("org.jetbrains.compose")
|
||||
}
|
||||
|
||||
val commit: String = System.getenv("COMMIT")?.takeIf { it.isNotBlank() } ?: "dev"
|
||||
val repoRoot: File = rootProject.projectDir.parentFile
|
||||
val generated = layout.buildDirectory.dir("generated/resources")
|
||||
|
||||
kotlin {
|
||||
compilerOptions {
|
||||
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17)
|
||||
}
|
||||
sourceSets.named("main") {
|
||||
kotlin.srcDir("../shared/src")
|
||||
}
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
sourceSets.named("main") {
|
||||
resources.srcDir(generated)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(compose.desktop.currentOs)
|
||||
implementation(compose.material3)
|
||||
implementation("org.jetbrains.compose.material:material-icons-extended:1.7.3")
|
||||
implementation("org.json:json:20250517")
|
||||
testImplementation(kotlin("test"))
|
||||
}
|
||||
|
||||
val buildContent = tasks.register<Exec>("buildContent") {
|
||||
val out = generated.get().file("content.json").asFile
|
||||
workingDir = repoRoot
|
||||
val python = System.getenv("PYTHON")?.takeIf { it.isNotBlank() }
|
||||
?: if (System.getProperty("os.name").startsWith("Windows")) "python" else "python3"
|
||||
commandLine(python, "scripts/build-content.py", "--out", out.path)
|
||||
inputs.dir(repoRoot.resolve("content"))
|
||||
inputs.file(repoRoot.resolve("scripts/build-content.py"))
|
||||
outputs.file(out)
|
||||
}
|
||||
|
||||
val buildInfo = tasks.register("buildInfo") {
|
||||
val out = generated.get().file("build-info.properties").asFile
|
||||
inputs.property("commit", commit)
|
||||
outputs.file(out)
|
||||
doLast {
|
||||
out.parentFile.mkdirs()
|
||||
out.writeText("commit=$commit\n")
|
||||
}
|
||||
}
|
||||
|
||||
val appIcon = tasks.register<Copy>("appIcon") {
|
||||
from(repoRoot.resolve("data/share/icons/hicolor/256x256/apps/maturita.png"))
|
||||
into(generated)
|
||||
rename { "icon.png" }
|
||||
}
|
||||
|
||||
tasks.named("processResources") {
|
||||
dependsOn(buildContent, buildInfo, appIcon)
|
||||
}
|
||||
|
||||
tasks.withType<Test>().configureEach {
|
||||
useJUnitPlatform()
|
||||
systemProperty("graduately.repo", repoRoot.path)
|
||||
}
|
||||
|
||||
compose.desktop {
|
||||
application {
|
||||
mainClass = "org.maturita.maturita.desktop.MainKt"
|
||||
// jpackage and ProGuard need a JDK with jmods (Temurin 21 has them, 24+ may not).
|
||||
System.getenv("PACKAGE_JDK")?.takeIf { it.isNotBlank() }?.let { javaHome = it }
|
||||
// Shrinking drops the thousands of unused icons and keeps the
|
||||
// packages under GitHub's 100 MB file limit.
|
||||
buildTypes.release.proguard {
|
||||
version.set("7.10.0")
|
||||
obfuscate.set(false)
|
||||
configurationFiles.from(project.file("proguard-rules.pro"))
|
||||
}
|
||||
nativeDistributions {
|
||||
// The launcher must stay graduately(.exe): installers and the
|
||||
// updater of older builds start it by that name.
|
||||
packageName = "graduately"
|
||||
packageVersion = "1.0.0"
|
||||
description = "Graduately"
|
||||
vendor = "Graduately"
|
||||
modules("java.naming", "jdk.crypto.ec", "jdk.unsupported")
|
||||
linux {
|
||||
iconFile.set(repoRoot.resolve("data/share/icons/hicolor/512x512/apps/maturita.png"))
|
||||
}
|
||||
windows {
|
||||
iconFile.set(repoRoot.resolve("assets/app-icon.ico"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2
android/desktop/proguard-rules.pro
vendored
Normal file
2
android/desktop/proguard-rules.pro
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
-dontwarn org.slf4j.**
|
||||
-dontnote **
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package org.maturita.maturita.desktop
|
||||
|
||||
import org.maturita.maturita.platform.Platform
|
||||
import org.maturita.maturita.platform.Prefs
|
||||
import org.maturita.maturita.platform.Speaker
|
||||
|
||||
class DesktopPlatform(
|
||||
override val commit: String,
|
||||
override val prefs: Prefs,
|
||||
install: Install,
|
||||
) : Platform {
|
||||
override val versionName: String = if (Install.isWindows) "windows" else "linux"
|
||||
override val welcomeKey = "welcome_body_desktop"
|
||||
override val updater = DesktopUpdater(commit, install)
|
||||
|
||||
override fun speaker(): Speaker? = DesktopSpeaker.create()
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
package org.maturita.maturita.desktop
|
||||
|
||||
import org.maturita.maturita.platform.Speaker
|
||||
import java.io.File
|
||||
import java.util.Locale
|
||||
import javax.swing.SwingUtilities
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
/**
|
||||
* Speech through whatever the system already has: SAPI via PowerShell on
|
||||
* Windows, espeak-ng / espeak / spd-say on Linux, `say` on a Mac. None of them
|
||||
* report word positions, so pause and resume start the passage again.
|
||||
*/
|
||||
class DesktopSpeaker private constructor(private val command: (String, Locale, Float, Float) -> List<String>) : Speaker {
|
||||
@Volatile private var process: Process? = null
|
||||
|
||||
override fun speak(
|
||||
text: String,
|
||||
locale: Locale,
|
||||
rate: Float,
|
||||
volume: Float,
|
||||
onRange: (Int) -> Unit,
|
||||
onEnd: (Boolean) -> Unit,
|
||||
) {
|
||||
stop()
|
||||
val argv = command(text, locale, rate, volume)
|
||||
val stdin = argv.lastOrNull() == STDIN
|
||||
val p = runCatching {
|
||||
ProcessBuilder(if (stdin) argv.dropLast(1) else argv)
|
||||
.redirectErrorStream(true)
|
||||
.redirectOutput(ProcessBuilder.Redirect.DISCARD)
|
||||
.start()
|
||||
}.getOrElse {
|
||||
SwingUtilities.invokeLater { onEnd(false) }
|
||||
return
|
||||
}
|
||||
process = p
|
||||
thread(isDaemon = true, name = "speech") {
|
||||
if (stdin) runCatching { p.outputStream.writer(Charsets.UTF_8).use { it.write(text) } }
|
||||
val ok = p.waitFor() == 0
|
||||
if (process === p) {
|
||||
process = null
|
||||
SwingUtilities.invokeLater { onEnd(ok) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
process?.let {
|
||||
process = null
|
||||
it.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
override fun close() = stop()
|
||||
|
||||
companion object {
|
||||
/** Marks a command that reads the text from standard input. */
|
||||
private const val STDIN = "\u0000stdin"
|
||||
|
||||
private fun onPath(name: String): Boolean =
|
||||
System.getenv("PATH").orEmpty().split(File.pathSeparator).any { File(it, name).canExecute() }
|
||||
|
||||
fun create(): DesktopSpeaker? {
|
||||
val os = System.getProperty("os.name").orEmpty()
|
||||
return when {
|
||||
os.startsWith("Windows") -> DesktopSpeaker { _, locale, rate, volume ->
|
||||
val sapiRate = ((rate - 1f) * 10f).toInt().coerceIn(-10, 10)
|
||||
val script = "[Console]::InputEncoding=[Text.Encoding]::UTF8;" +
|
||||
"Add-Type -AssemblyName System.Speech;" +
|
||||
"\$s=New-Object System.Speech.Synthesis.SpeechSynthesizer;" +
|
||||
"try{\$s.SelectVoiceByHints('NotSet','NotSet',0,[Globalization.CultureInfo]'${locale.toLanguageTag()}')}catch{};" +
|
||||
"\$s.Rate=$sapiRate;\$s.Volume=${(volume * 100).toInt()};" +
|
||||
"\$s.Speak([Console]::In.ReadToEnd())"
|
||||
listOf("powershell", "-NoProfile", "-NonInteractive", "-Command", script, STDIN)
|
||||
}
|
||||
os.startsWith("Mac") -> DesktopSpeaker { text, _, rate, _ ->
|
||||
listOf("say", "-r", (180 * rate).toInt().toString(), text)
|
||||
}
|
||||
onPath("espeak-ng") || onPath("espeak") -> {
|
||||
val bin = if (onPath("espeak-ng")) "espeak-ng" else "espeak"
|
||||
DesktopSpeaker { _, locale, rate, volume ->
|
||||
val voice = if (locale.language == "de") "de" else "en-gb"
|
||||
listOf(bin, "-v", voice, "-s", (165 * rate).toInt().toString(), "-a", (volume * 150).toInt().toString(), "--stdin", STDIN)
|
||||
}
|
||||
}
|
||||
onPath("spd-say") -> DesktopSpeaker { text, locale, rate, volume ->
|
||||
listOf(
|
||||
"spd-say", "-w", "-l", locale.language,
|
||||
"-r", ((rate - 1f) * 100f).toInt().coerceIn(-100, 100).toString(),
|
||||
"-i", ((volume - 1f) * 100f).toInt().coerceIn(-100, 100).toString(),
|
||||
text,
|
||||
)
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,220 @@
|
|||
package org.maturita.maturita.desktop
|
||||
|
||||
import org.maturita.maturita.platform.AppUpdater
|
||||
import org.maturita.maturita.platform.UpdateState
|
||||
import java.io.File
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.URI
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.zip.ZipInputStream
|
||||
import javax.swing.SwingUtilities
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
/**
|
||||
* Self-update from the `builds` branch, the same scheme the GTK builds used,
|
||||
* so their updater and this one hand over cleanly: the asset names stay, and
|
||||
* progress/ next to the app survives the swap.
|
||||
*
|
||||
* raw.githubusercontent.com caches branch-named URLs, so the branch tip is
|
||||
* read from the Atom feed and every file is fetched from that commit. A running
|
||||
* app cannot replace itself; a small script waits for this process to exit,
|
||||
* swaps the new version in and starts it.
|
||||
*/
|
||||
class DesktopUpdater(private val commit: String, private val install: Install) : AppUpdater {
|
||||
private val io = Executors.newSingleThreadExecutor { r -> Thread(r, "updater").apply { isDaemon = true } }
|
||||
private val repo = "pepaskopec-blip/Graduately"
|
||||
private val branch = "builds"
|
||||
private val platform = if (Install.isWindows) "windows" else "linux"
|
||||
private val asset = if (Install.isWindows) "graduately-windows-x64.zip" else "graduately-linux-x86_64.AppImage"
|
||||
|
||||
private fun emit(cb: (UpdateState) -> Unit, state: UpdateState) = SwingUtilities.invokeLater { cb(state) }
|
||||
|
||||
override fun check(interactive: Boolean, cb: (UpdateState) -> Unit) {
|
||||
if (!commit.matches(Regex("[0-9a-fA-F]{7,40}"))) {
|
||||
emit(cb, UpdateState("dev", messageKey = "update_err_devbuild"))
|
||||
return
|
||||
}
|
||||
if (interactive) emit(cb, UpdateState("checking", messageKey = "update_checking"))
|
||||
io.execute {
|
||||
try {
|
||||
val atom = get("https://github.com/$repo/commits/$branch.atom")
|
||||
val tip = atomTip(atom) ?: error("no tip")
|
||||
val remote = remoteCommit(atom, tip)
|
||||
emit(cb, when {
|
||||
sameCommit(remote, commit) -> UpdateState("ok", remote, "update_uptodate", remote.take(7))
|
||||
install.kind == Install.Kind.Unsupported ->
|
||||
UpdateState("unsupported", remote, if (interactive) "update_err_unsupported" else "update_current", commit.take(7))
|
||||
else -> UpdateState("available", remote, "update_available", remote.take(7), canInstall = true)
|
||||
})
|
||||
} catch (_: Exception) {
|
||||
emit(cb, if (interactive) UpdateState("error", messageKey = "update_err_network")
|
||||
else UpdateState(messageArg = commit.take(7)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun install(cb: (UpdateState) -> Unit) {
|
||||
val target = install.target
|
||||
if (install.kind == Install.Kind.Unsupported || target == null) {
|
||||
emit(cb, UpdateState("error", messageKey = "update_err_unsupported"))
|
||||
return
|
||||
}
|
||||
emit(cb, UpdateState("downloading", messageKey = "update_downloading"))
|
||||
io.execute {
|
||||
val staging = File(System.getProperty("java.io.tmpdir"), "graduately-update")
|
||||
val source: File
|
||||
try {
|
||||
val tip = atomTip(get("https://github.com/$repo/commits/$branch.atom")) ?: error("no tip")
|
||||
staging.deleteRecursively()
|
||||
staging.mkdirs()
|
||||
val file = File(staging, asset)
|
||||
download("https://raw.githubusercontent.com/$repo/$tip/$asset", file)
|
||||
source = if (install.kind == Install.Kind.WindowsDir) {
|
||||
File(staging, "new").also { unzip(file, it) }
|
||||
.takeIf { File(it, "graduately.exe").isFile } ?: error("bad zip")
|
||||
} else {
|
||||
file.takeIf { isElf(it) }?.also { it.setExecutable(true) } ?: error("bad AppImage")
|
||||
}
|
||||
} catch (_: Exception) {
|
||||
staging.deleteRecursively()
|
||||
emit(cb, UpdateState("error", messageKey = "update_err_download", canInstall = true))
|
||||
return@execute
|
||||
}
|
||||
try {
|
||||
startSwap(target, source, staging)
|
||||
} catch (_: Exception) {
|
||||
emit(cb, UpdateState("error", messageKey = "update_err_stage", canInstall = true))
|
||||
return@execute
|
||||
}
|
||||
emit(cb, UpdateState("staged", messageKey = "update_staged"))
|
||||
SwingUtilities.invokeLater { exitProcess(0) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun startSwap(target: File, source: File, staging: File) {
|
||||
val pid = ProcessHandle.current().pid().toString()
|
||||
val windows = install.kind == Install.Kind.WindowsDir
|
||||
val script = File(System.getProperty("java.io.tmpdir"), if (windows) "graduately-update.cmd" else "graduately-update.sh")
|
||||
script.writeText(if (windows) WINDOWS_SWAP else UNIX_SWAP)
|
||||
script.setExecutable(true)
|
||||
val argv = if (windows) listOf("cmd", "/c", script.path) else listOf("/bin/sh", script.path)
|
||||
val pb = ProcessBuilder(argv + listOf(pid, target.path, source.path, staging.path))
|
||||
// The new AppImage must get its own mount, not inherit this one.
|
||||
pb.environment().keys.removeAll(setOf("APPIMAGE", "APPDIR", "ARGV0", "OWD"))
|
||||
val p = pb.redirectErrorStream(true).redirectOutput(ProcessBuilder.Redirect.DISCARD).start()
|
||||
// The script detaches itself and exits; wait so we do not quit first.
|
||||
p.waitFor()
|
||||
}
|
||||
|
||||
/** Commit whose package for this platform sits on the branch. */
|
||||
private fun remoteCommit(atom: String, tip: String): String {
|
||||
val marker = runCatching { get("https://raw.githubusercontent.com/$repo/$tip/VERSION-$platform").trim() }.getOrNull()
|
||||
if (marker != null && marker.length >= 7) return marker
|
||||
return atomMainSha(atom) ?: get("https://raw.githubusercontent.com/$repo/$tip/VERSION").trim()
|
||||
}
|
||||
|
||||
private fun atomTip(atom: String): String? =
|
||||
Regex("""Commit/([0-9a-f]{40})""", RegexOption.IGNORE_CASE).find(atom)?.groupValues?.get(1)
|
||||
|
||||
private fun atomMainSha(atom: String): String? =
|
||||
Regex("""Build from ([0-9a-f]{7,40})""", RegexOption.IGNORE_CASE).find(atom)?.groupValues?.get(1)
|
||||
|
||||
private fun sameCommit(a: String, b: String): Boolean {
|
||||
val n = minOf(a.length, b.length)
|
||||
return n >= 7 && a.take(n).equals(b.take(n), ignoreCase = true)
|
||||
}
|
||||
|
||||
private fun isElf(f: File): Boolean = f.length() > 1_000_000L &&
|
||||
f.inputStream().use { val h = ByteArray(4); it.read(h) == 4 && h.contentEquals(byteArrayOf(0x7f, 'E'.code.toByte(), 'L'.code.toByte(), 'F'.code.toByte())) }
|
||||
|
||||
private fun unzip(zip: File, dest: File) {
|
||||
val root = dest.canonicalFile
|
||||
ZipInputStream(zip.inputStream().buffered()).use { z ->
|
||||
while (true) {
|
||||
val e = z.nextEntry ?: break
|
||||
val out = File(root, e.name).canonicalFile
|
||||
if (!out.path.startsWith(root.path + File.separator)) error("zip slip")
|
||||
if (e.isDirectory) out.mkdirs() else {
|
||||
out.parentFile.mkdirs()
|
||||
out.outputStream().use { z.copyTo(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun open(url: String, readMs: Int): HttpURLConnection =
|
||||
(URI(url).toURL().openConnection() as HttpURLConnection).apply {
|
||||
connectTimeout = 15000
|
||||
readTimeout = readMs
|
||||
instanceFollowRedirects = true
|
||||
setRequestProperty("User-Agent", "Graduately-desktop")
|
||||
}
|
||||
|
||||
private fun get(url: String): String {
|
||||
val c = open(url, 15000)
|
||||
try {
|
||||
if (c.responseCode !in 200..299) error("http ${c.responseCode}")
|
||||
return c.inputStream.bufferedReader().use { it.readText() }
|
||||
} finally {
|
||||
c.disconnect()
|
||||
}
|
||||
}
|
||||
|
||||
private fun download(url: String, dest: File) {
|
||||
val c = open(url, 60000)
|
||||
try {
|
||||
if (c.responseCode !in 200..299) error("http ${c.responseCode}")
|
||||
c.inputStream.use { input -> dest.outputStream().use { input.copyTo(it) } }
|
||||
} finally {
|
||||
c.disconnect()
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
// Arguments: pid target source staging.
|
||||
const val UNIX_SWAP = """#!/bin/sh
|
||||
if [ -z "${'$'}GRADUATELY_UPDATE_DETACHED" ]; then
|
||||
GRADUATELY_UPDATE_DETACHED=1
|
||||
export GRADUATELY_UPDATE_DETACHED
|
||||
nohup /bin/sh "${'$'}0" "${'$'}@" >/dev/null 2>&1 &
|
||||
exit 0
|
||||
fi
|
||||
pid=${'$'}1; target=${'$'}2; source=${'$'}3; staging=${'$'}4
|
||||
n=0
|
||||
while kill -0 "${'$'}pid" 2>/dev/null && [ ${'$'}n -lt 600 ]; do
|
||||
sleep 0.2; n=${'$'}((n+1))
|
||||
done
|
||||
if mv -f "${'$'}source" "${'$'}target" 2>/dev/null; then
|
||||
chmod +x "${'$'}target"
|
||||
fi
|
||||
"${'$'}target" >/dev/null 2>&1 &
|
||||
rm -rf "${'$'}staging"
|
||||
rm -f "${'$'}0"
|
||||
"""
|
||||
|
||||
// robocopy mirrors the new build over the old one (so nothing stale is
|
||||
// left behind) but never touches progress/. ping is a sleep without a
|
||||
// console window.
|
||||
val WINDOWS_SWAP = """@echo off
|
||||
if not defined GRADUATELY_UPDATE_DETACHED (
|
||||
set GRADUATELY_UPDATE_DETACHED=1
|
||||
start "" /b cmd /c "%~f0" %*
|
||||
exit /b 0
|
||||
)
|
||||
set "PID=%~1"
|
||||
set "TARGET=%~2"
|
||||
set "SOURCE=%~3"
|
||||
set "STAGING=%~4"
|
||||
:wait
|
||||
tasklist /FI "PID eq %PID%" 2>nul | find "%PID%" >nul
|
||||
if not errorlevel 1 (
|
||||
ping -n 2 127.0.0.1 >nul
|
||||
goto wait
|
||||
)
|
||||
robocopy "%SOURCE%" "%TARGET%" /MIR /XD progress /R:5 /W:1 /NFL /NDL /NJH /NJS /NP >nul
|
||||
start "" "%TARGET%\graduately.exe"
|
||||
rmdir /s /q "%STAGING%"
|
||||
(goto) 2>nul & del "%~f0"
|
||||
""".replace("\n", "\r\n")
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package org.maturita.maturita.desktop
|
||||
|
||||
import org.maturita.maturita.platform.Prefs
|
||||
import java.io.File
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.StandardCopyOption
|
||||
import java.util.Properties
|
||||
|
||||
/** Settings and progress in one properties file, rewritten atomically on every change. */
|
||||
class FilePrefs(private val file: File) : Prefs {
|
||||
private val values = Properties()
|
||||
|
||||
init {
|
||||
runCatching { file.inputStream().use { values.load(it.reader(Charsets.UTF_8)) } }
|
||||
}
|
||||
|
||||
override fun getBoolean(key: String, fallback: Boolean) =
|
||||
values.getProperty(key)?.toBooleanStrictOrNull() ?: fallback
|
||||
|
||||
override fun getInt(key: String, fallback: Int) =
|
||||
values.getProperty(key)?.toIntOrNull() ?: fallback
|
||||
|
||||
override fun getString(key: String, fallback: String?): String? =
|
||||
values.getProperty(key) ?: fallback
|
||||
|
||||
override fun edit(): Prefs.Editor = Editor()
|
||||
|
||||
@Synchronized
|
||||
private fun save(changes: Map<String, String>) {
|
||||
values.putAll(changes)
|
||||
runCatching {
|
||||
file.parentFile?.mkdirs()
|
||||
val tmp = File(file.path + ".tmp")
|
||||
tmp.writer(Charsets.UTF_8).use { values.store(it, null) }
|
||||
Files.move(tmp.toPath(), file.toPath(), StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE)
|
||||
}
|
||||
}
|
||||
|
||||
private inner class Editor : Prefs.Editor {
|
||||
private val changes = LinkedHashMap<String, String>()
|
||||
override fun putBoolean(key: String, value: Boolean) = apply { changes[key] = value.toString() }
|
||||
override fun putInt(key: String, value: Int) = apply { changes[key] = value.toString() }
|
||||
override fun putString(key: String, value: String) = apply { changes[key] = value }
|
||||
override fun apply() = save(changes)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
package org.maturita.maturita.desktop
|
||||
|
||||
import org.maturita.maturita.data.ThemeId
|
||||
import org.maturita.maturita.data.themeNames
|
||||
import org.maturita.maturita.platform.Prefs
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* The GTK builds kept progress in `progress/<course>.conf` key files. Copy it
|
||||
* once into the shared progress keys (`net.3`, `en.2.5`, `g.0.vocab` …); the
|
||||
* shared ProgressStore then moves those onto lesson ids like on every
|
||||
* platform. The .conf files stay, so nothing is lost if the import misreads.
|
||||
*/
|
||||
fun importGtkProgress(dir: File, prefs: Prefs) {
|
||||
if (prefs.getBoolean("gtk_imported", false)) return
|
||||
val edit = prefs.edit()
|
||||
for (file in dir.listFiles { f -> f.name.endsWith(".conf") }.orEmpty()) {
|
||||
val course = file.name.removeSuffix(".conf")
|
||||
val groups = readKeyFile(file)
|
||||
if (course == "settings") {
|
||||
groups["ui"]?.let { importSettings(it, edit) }
|
||||
continue
|
||||
}
|
||||
for ((key, value) in groups["done"].orEmpty()) {
|
||||
if (value != "true") continue
|
||||
gtkAddress(course, key)?.let { edit.putBoolean(it, true) }
|
||||
}
|
||||
}
|
||||
edit.putBoolean("gtk_imported", true).apply()
|
||||
}
|
||||
|
||||
/** GTK file and key to the address the apps use, or null for what has no equivalent. */
|
||||
internal fun gtkAddress(course: String, key: String): String? {
|
||||
val unit = Regex("""unit(\d)""").matchEntire(course)?.groupValues?.get(1)?.toInt()
|
||||
return when {
|
||||
// The vocabulary branch used the last slot of the unit.
|
||||
unit != null -> key.toIntOrNull()?.let { if (it == 20) "g.${unit - 1}.vocab" else "g.${unit - 1}.$it" }
|
||||
course == "english" -> yearKey("en", key)
|
||||
course == "german-course" -> yearKey("de", key)
|
||||
course == "mluvnice" -> key.toIntOrNull()?.let { "mluv.$it" }
|
||||
// Book progress was one shared slot, not per book.
|
||||
course == "cetba" -> null
|
||||
else -> key.toIntOrNull()?.let { "$course.$it" }
|
||||
}
|
||||
}
|
||||
|
||||
private fun yearKey(prefix: String, key: String): String? {
|
||||
val (year, lesson) = key.split("-").takeIf { it.size == 2 } ?: return null
|
||||
if (year.toIntOrNull() == null || lesson.toIntOrNull() == null) return null
|
||||
return "$prefix.$year.$lesson"
|
||||
}
|
||||
|
||||
private fun importSettings(ui: Map<String, String>, edit: Prefs.Editor) {
|
||||
ui["theme"]?.let { name ->
|
||||
val i = themeNames.indexOfFirst { it.equals(name, ignoreCase = true) }
|
||||
if (i >= 0) edit.putInt("theme", ThemeId.entries[i].ordinal)
|
||||
}
|
||||
ui["mode"]?.let { edit.putString("mode", if (it.lowercase() in setOf("light", "white")) "light" else "dark") }
|
||||
ui["lang"]?.let { edit.putString("lang", if (it.lowercase() in setOf("en", "english")) "en" else "cs") }
|
||||
ui["seen_commit"]?.takeIf { it.isNotBlank() }?.let { edit.putString("seen_commit", it) }
|
||||
}
|
||||
|
||||
internal fun readKeyFile(file: File): Map<String, Map<String, String>> {
|
||||
val groups = LinkedHashMap<String, MutableMap<String, String>>()
|
||||
var current: MutableMap<String, String>? = null
|
||||
runCatching { file.readLines() }.getOrDefault(emptyList()).forEach { raw ->
|
||||
val line = raw.trim()
|
||||
when {
|
||||
line.isEmpty() || line.startsWith("#") -> {}
|
||||
line.startsWith("[") && line.endsWith("]") ->
|
||||
current = groups.getOrPut(line.substring(1, line.length - 1)) { LinkedHashMap() }
|
||||
'=' in line -> current?.put(line.substringBefore('=').trim(), line.substringAfter('=').trim())
|
||||
}
|
||||
}
|
||||
return groups
|
||||
}
|
||||
|
||||
/**
|
||||
* The GTK updater copied new packages over the install without deleting
|
||||
* anything, so a Windows folder updated from GTK still carries its DLLs and
|
||||
* data. style.css marks such a folder; jpackage never writes one.
|
||||
*/
|
||||
fun removeGtkLeftovers(install: Install) {
|
||||
if (install.kind != Install.Kind.WindowsDir) return
|
||||
val dir = install.target ?: return
|
||||
val marker = File(dir, "style.css")
|
||||
if (!marker.isFile) return
|
||||
dir.listFiles().orEmpty().forEach { f ->
|
||||
val name = f.name.lowercase()
|
||||
val gtkDll = name.endsWith(".dll") && (name.startsWith("lib") || name == "zlib1.dll")
|
||||
val stale = (f.isFile && (gtkDll || name == "changelog.txt")) ||
|
||||
(f.isDirectory && name in setOf("lib", "share", "icons"))
|
||||
if (stale) f.deleteRecursively()
|
||||
}
|
||||
marker.delete()
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
package org.maturita.maturita.desktop
|
||||
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* How this copy runs, which decides where progress lives and what an update
|
||||
* replaces. Progress sits next to the app, as it did in the GTK builds, so
|
||||
* existing students keep it: beside the AppImage on Linux, inside the install
|
||||
* directory on Windows.
|
||||
*/
|
||||
class Install(
|
||||
val kind: Kind,
|
||||
/** The AppImage file, or the Windows directory holding graduately.exe. */
|
||||
val target: File?,
|
||||
val progressDir: File,
|
||||
) {
|
||||
enum class Kind { AppImage, WindowsDir, Unsupported }
|
||||
|
||||
companion object {
|
||||
val isWindows = System.getProperty("os.name").orEmpty().startsWith("Windows")
|
||||
|
||||
fun detect(): Install {
|
||||
val appImage = System.getenv("APPIMAGE")?.takeIf { it.isNotBlank() }?.let(::File)
|
||||
val launcher = System.getProperty("jpackage.app-path")?.let(::File)
|
||||
val windowsDir = launcher?.parentFile?.takeIf {
|
||||
isWindows && launcher.name.equals("graduately.exe", ignoreCase = true) &&
|
||||
File(it, "app").isDirectory && File(it, "runtime").isDirectory
|
||||
}
|
||||
val (kind, target) = when {
|
||||
appImage != null && !isWindows -> Kind.AppImage to appImage
|
||||
windowsDir != null -> Kind.WindowsDir to windowsDir
|
||||
else -> Kind.Unsupported to null
|
||||
}
|
||||
val beside = target?.let { if (kind == Kind.AppImage) it.parentFile else it }
|
||||
val home = File(System.getProperty("user.home"), ".graduately")
|
||||
val root = beside?.takeIf { it.canWrite() } ?: home
|
||||
return Install(kind, target, File(root, "progress"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
package org.maturita.maturita.desktop
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.painter.BitmapPainter
|
||||
import androidx.compose.ui.graphics.toComposeImageBitmap
|
||||
import androidx.compose.ui.input.key.Key
|
||||
import androidx.compose.ui.input.key.KeyEventType
|
||||
import androidx.compose.ui.input.key.isCtrlPressed
|
||||
import androidx.compose.ui.input.key.isMetaPressed
|
||||
import androidx.compose.ui.input.key.key
|
||||
import androidx.compose.ui.input.key.type
|
||||
import androidx.compose.ui.input.pointer.PointerButton
|
||||
import androidx.compose.ui.input.pointer.PointerEventType
|
||||
import androidx.compose.ui.input.pointer.onPointerEvent
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Window
|
||||
import androidx.compose.ui.window.application
|
||||
import androidx.compose.ui.window.rememberWindowState
|
||||
import org.maturita.maturita.AppViewModel
|
||||
import org.maturita.maturita.MaturitaApp
|
||||
import org.maturita.maturita.data.Content
|
||||
import org.maturita.maturita.handleBack
|
||||
import java.io.File
|
||||
import java.util.Properties
|
||||
import javax.imageio.ImageIO
|
||||
|
||||
private fun resourceText(name: String): String? =
|
||||
Thread.currentThread().contextClassLoader.getResourceAsStream(name)?.bufferedReader()?.use { it.readText() }
|
||||
|
||||
@OptIn(ExperimentalComposeUiApi::class)
|
||||
fun main() {
|
||||
val install = Install.detect()
|
||||
val prefs = FilePrefs(File(install.progressDir, "graduately.properties"))
|
||||
importGtkProgress(install.progressDir, prefs)
|
||||
removeGtkLeftovers(install)
|
||||
|
||||
val info = Properties().apply { resourceText("build-info.properties")?.let { load(it.reader()) } }
|
||||
val platform = DesktopPlatform(info.getProperty("commit") ?: "dev", prefs, install)
|
||||
val vm = AppViewModel(Content.parse(resourceText("content.json")), platform)
|
||||
val icon = Thread.currentThread().contextClassLoader.getResourceAsStream("icon.png")
|
||||
?.use { ImageIO.read(it) }?.let { BitmapPainter(it.toComposeImageBitmap()) }
|
||||
|
||||
application {
|
||||
Window(
|
||||
onCloseRequest = ::exitApplication,
|
||||
title = "Graduately",
|
||||
icon = icon,
|
||||
state = rememberWindowState(width = 1100.dp, height = 780.dp),
|
||||
onPreviewKeyEvent = { e ->
|
||||
if (e.type != KeyEventType.KeyDown) return@Window false
|
||||
val cmd = e.isCtrlPressed || e.isMetaPressed
|
||||
when {
|
||||
e.key == Key.Escape -> vm.handleBack()
|
||||
cmd && e.key == Key.K -> { vm.searchOpen = true; true }
|
||||
cmd && e.key == Key.Q -> { exitApplication(); true }
|
||||
else -> false
|
||||
}
|
||||
},
|
||||
) {
|
||||
Box(
|
||||
Modifier.fillMaxSize().onPointerEvent(PointerEventType.Press) { e ->
|
||||
if (e.button == PointerButton.Back) vm.handleBack()
|
||||
},
|
||||
) {
|
||||
MaturitaApp(vm)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
package org.maturita.maturita
|
||||
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import org.maturita.maturita.data.answerAccepts
|
||||
import org.maturita.maturita.data.answerIncomplete
|
||||
import org.maturita.maturita.data.hasUmlaut
|
||||
import org.maturita.maturita.data.mathAnswerOk
|
||||
import org.maturita.maturita.data.mathDrawGiven
|
||||
import org.maturita.maturita.data.mathDrawNeed
|
||||
import org.maturita.maturita.data.mathDrawOk
|
||||
import org.maturita.maturita.data.mathIsDraw
|
||||
import org.maturita.maturita.data.netTxtEq
|
||||
import org.maturita.maturita.data.normalizeAnswer
|
||||
import java.io.File
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
/** Runs tests/answers.json, the cases the Swift apps check too (tests/swift). */
|
||||
class AnswersTest {
|
||||
private val cases = JSONObject(File(System.getProperty("graduately.repo"), "tests/answers.json").readText())
|
||||
|
||||
private fun rows(name: String): List<JSONArray> =
|
||||
cases.getJSONArray(name).let { a -> (0 until a.length()).map { a.getJSONArray(it) } }
|
||||
|
||||
private fun JSONArray.str(i: Int): String? = if (isNull(i)) null else getString(i)
|
||||
|
||||
private fun JSONArray.points(i: Int): List<Pair<Int, Int>> =
|
||||
getJSONArray(i).let { a -> (0 until a.length()).map { a.getJSONArray(it).let { p -> p.getInt(0) to p.getInt(1) } } }
|
||||
|
||||
@Test
|
||||
fun normalize() = rows("normalize").forEach { assertEquals(it.str(1), normalizeAnswer(it.str(0)), "normalize ${it.str(0)}") }
|
||||
|
||||
@Test
|
||||
fun accepts() = rows("accepts").forEach {
|
||||
assertEquals(it.getBoolean(2), answerAccepts(normalizeAnswer(it.str(0)), it.str(1)), "accepts $it")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun incomplete() = rows("incomplete").forEach {
|
||||
assertEquals(it.getBoolean(2), answerIncomplete(normalizeAnswer(it.str(0)), it.str(1)), "incomplete $it")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun netText() = rows("netTxtEq").forEach { assertEquals(it.getBoolean(2), netTxtEq(it.str(0), it.str(1)), "netTxtEq $it") }
|
||||
|
||||
@Test
|
||||
fun umlaut() = rows("hasUmlaut").forEach { assertEquals(it.getBoolean(1), hasUmlaut(it.str(0)), "hasUmlaut $it") }
|
||||
|
||||
@Test
|
||||
fun math() = rows("math").forEach { assertEquals(it.getBoolean(2), mathAnswerOk(it.str(0), it.str(1)), "math $it") }
|
||||
|
||||
@Test
|
||||
fun draw() {
|
||||
rows("drawNeed").forEach { assertEquals(it.getInt(1), mathDrawNeed(it.str(0)), "drawNeed $it") }
|
||||
rows("drawGiven").forEach { assertEquals(it.points(1), mathDrawGiven(it.str(0)), "drawGiven $it") }
|
||||
rows("draw").forEach { assertEquals(it.getBoolean(2), mathDrawOk(it.str(0), it.points(1)), "draw $it") }
|
||||
}
|
||||
|
||||
/** Every worked answer in content/ must pass its own check, or students could never solve it. */
|
||||
@Test
|
||||
fun contentAnswersSolveThemselves() {
|
||||
val root = JSONObject(javaClass.classLoader.getResource("content.json")!!.readText())
|
||||
var checked = 0
|
||||
for (section in listOf("mat0", "mat", "mat2", "mat3", "mat4")) {
|
||||
val lessons = root.getJSONArray(section)
|
||||
for (l in 0 until lessons.length()) {
|
||||
val lesson = lessons.getJSONObject(l)
|
||||
val problems = lesson.getJSONArray("problems")
|
||||
for (p in 0 until problems.length()) {
|
||||
val spec = problems.getJSONObject(p).getString("answer")
|
||||
val where = "$section ${lesson.getString("key")}: $spec"
|
||||
if (mathIsDraw(spec)) {
|
||||
assertTrue(mathDrawNeed(spec) > 0, where)
|
||||
} else {
|
||||
val body = spec.substringAfter(':').substringBefore('|')
|
||||
assertTrue(mathAnswerOk(spec, body), where)
|
||||
}
|
||||
checked++
|
||||
}
|
||||
}
|
||||
}
|
||||
assertTrue(checked > 100, "only $checked problems found")
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
package org.maturita.maturita
|
||||
|
||||
import org.json.JSONObject
|
||||
import org.maturita.maturita.data.ColorMode
|
||||
import org.maturita.maturita.data.Content
|
||||
import org.maturita.maturita.data.ProgressStore
|
||||
import org.maturita.maturita.data.ThemeId
|
||||
import org.maturita.maturita.desktop.FilePrefs
|
||||
import org.maturita.maturita.desktop.gtkAddress
|
||||
import org.maturita.maturita.desktop.importGtkProgress
|
||||
import java.nio.file.Files
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class ProgressTest {
|
||||
private val content = Content.parse(javaClass.classLoader.getResource("content.json")!!.readText())
|
||||
|
||||
@Test
|
||||
fun everyLegacyAddressHasALesson() {
|
||||
val root = JSONObject(javaClass.classLoader.getResource("content.json")!!.readText())
|
||||
val keys = root.getJSONObject("progress").getJSONObject("keys")
|
||||
assertTrue(content.progressLegacy.isNotEmpty())
|
||||
for ((old, id) in content.progressLegacy) {
|
||||
assertTrue(keys.keySet().any { keys.getString(it) == id }, "$old -> $id has no lesson")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun oldProgressMovesToLessonIds() {
|
||||
val dir = Files.createTempDirectory("progress").toFile()
|
||||
val prefs = FilePrefs(dir.resolve("p.properties"))
|
||||
prefs.edit().putBoolean("fyz.1", true).putBoolean("g.0.vocab", true).putBoolean("en.2.3", true).apply()
|
||||
|
||||
val store = ProgressStore(prefs, content)
|
||||
assertTrue(store.fyzDone(1))
|
||||
assertTrue(store.vocabDone(0))
|
||||
assertTrue(store.enDone(2, 3))
|
||||
assertFalse(store.fyzDone(2))
|
||||
assertTrue(prefs.getBoolean("done.fyzika-1-fyzikalni-veliciny", false))
|
||||
|
||||
store.markMat(1)
|
||||
assertTrue(FilePrefs(dir.resolve("p.properties")).getBoolean("done.matematika-1-delitelnost-a-prvocisla", false))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun gtkProgressIsImported() {
|
||||
val dir = Files.createTempDirectory("gtk").toFile()
|
||||
dir.resolve("net.conf").writeText("[done]\n1=true\n2=false\n")
|
||||
dir.resolve("unit1.conf").writeText("[done]\n1=true\n20=true\n")
|
||||
dir.resolve("english.conf").writeText("[done]\n2-3=true\n")
|
||||
dir.resolve("settings.conf").writeText("[ui]\ntheme=Nord\nmode=dark\nlang=en\nseen_commit=abcdef1\n")
|
||||
val prefs = FilePrefs(dir.resolve("graduately.properties"))
|
||||
|
||||
importGtkProgress(dir, prefs)
|
||||
val store = ProgressStore(prefs, content)
|
||||
|
||||
assertTrue(store.netDone(1))
|
||||
assertFalse(store.netDone(2))
|
||||
assertTrue(store.germanDone(0, 1))
|
||||
assertTrue(store.vocabDone(0))
|
||||
assertTrue(store.enDone(2, 3))
|
||||
assertEquals(ThemeId.Nord, store.themeId)
|
||||
assertEquals(ColorMode.Dark, store.mode)
|
||||
assertEquals("abcdef1", store.seenCommit)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun gtkAddresses() {
|
||||
assertEquals("g.2.5", gtkAddress("unit3", "5"))
|
||||
assertEquals("de.4.6", gtkAddress("german-course", "4-6"))
|
||||
assertEquals("mluv.7", gtkAddress("mluvnice", "7"))
|
||||
assertEquals("hw3.2", gtkAddress("hw3", "2"))
|
||||
assertEquals(null, gtkAddress("cetba", "1"))
|
||||
}
|
||||
}
|
||||
|
|
@ -16,3 +16,4 @@ dependencyResolutionManagement {
|
|||
|
||||
rootProject.name = "maturita"
|
||||
include(":app")
|
||||
include(":desktop")
|
||||
|
|
|
|||
580
android/shared/src/org/maturita/maturita/App.kt
Normal file
580
android/shared/src/org/maturita/maturita/App.kt
Normal file
|
|
@ -0,0 +1,580 @@
|
|||
package org.maturita.maturita
|
||||
|
||||
import java.util.Locale
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.slideInHorizontally
|
||||
import androidx.compose.animation.slideOutHorizontally
|
||||
import androidx.compose.animation.togetherWith
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.darkColorScheme
|
||||
import androidx.compose.material3.lightColorScheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import org.maturita.maturita.data.ColorMode
|
||||
import org.maturita.maturita.data.Palette
|
||||
import org.maturita.maturita.ui.BookListScreen
|
||||
import org.maturita.maturita.ui.BookScreen
|
||||
import org.maturita.maturita.ui.CzechMapScreen
|
||||
import org.maturita.maturita.ui.GermanExercise
|
||||
import org.maturita.maturita.ui.HomeScreen
|
||||
import org.maturita.maturita.ui.HwQuizScreen
|
||||
import org.maturita.maturita.ui.HwYearsScreen
|
||||
import org.maturita.maturita.ui.LessonListScreen
|
||||
import org.maturita.maturita.ui.FyzQuizScreen
|
||||
import org.maturita.maturita.ui.MathPracticeScreen
|
||||
import org.maturita.maturita.ui.MatYearsScreen
|
||||
import org.maturita.maturita.ui.FyzYearsScreen
|
||||
import org.maturita.maturita.ui.LitYearsScreen
|
||||
import org.maturita.maturita.ui.LessonRow
|
||||
import org.maturita.maturita.ui.LitQuizScreen
|
||||
import org.maturita.maturita.ui.SciMapScreen
|
||||
import org.maturita.maturita.ui.SciQuizScreen
|
||||
import org.maturita.maturita.ui.MluvExercise
|
||||
import org.maturita.maturita.ui.NetQuizScreen
|
||||
import org.maturita.maturita.ui.NetYearsScreen
|
||||
import org.maturita.maturita.ui.On2QuizScreen
|
||||
import org.maturita.maturita.ui.On3QuizScreen
|
||||
import org.maturita.maturita.ui.On4QuizScreen
|
||||
import org.maturita.maturita.ui.OnQuizScreen
|
||||
import org.maturita.maturita.ui.OnYearsScreen
|
||||
import org.maturita.maturita.ui.EnYearsScreen
|
||||
import org.maturita.maturita.ui.ChoiceLessonScreen
|
||||
import org.maturita.maturita.ui.DeHomeScreen
|
||||
import org.maturita.maturita.ui.ItYearScreen
|
||||
import org.maturita.maturita.ui.EngExScreen
|
||||
import org.maturita.maturita.ui.PlotScreen
|
||||
import org.maturita.maturita.ui.RoadmapScreen
|
||||
import org.maturita.maturita.ui.SearchScreen
|
||||
import org.maturita.maturita.ui.SettingsScreen
|
||||
import org.maturita.maturita.ui.SlidesScreen
|
||||
import org.maturita.maturita.ui.StatsScreen
|
||||
import org.maturita.maturita.ui.UnitMapScreen
|
||||
import org.maturita.maturita.ui.VocabExercise
|
||||
import org.maturita.maturita.ui.appTypography
|
||||
|
||||
/** Material 3 colour roles from the shared theme palette. */
|
||||
private fun schemeFor(p: Palette, dark: Boolean) = if (dark) {
|
||||
darkColorScheme(
|
||||
primary = p.tint,
|
||||
onPrimary = p.onTint,
|
||||
primaryContainer = p.accent,
|
||||
onPrimaryContainer = p.onAccent,
|
||||
secondary = p.accent2,
|
||||
onSecondary = p.onAccent,
|
||||
secondaryContainer = p.surface1,
|
||||
onSecondaryContainer = p.text,
|
||||
tertiary = p.warning,
|
||||
onTertiary = p.crust,
|
||||
background = p.base,
|
||||
onBackground = p.text,
|
||||
surface = p.base,
|
||||
onSurface = p.text,
|
||||
surfaceVariant = p.surface0,
|
||||
onSurfaceVariant = p.subtext,
|
||||
surfaceContainerLowest = p.crust,
|
||||
surfaceContainerLow = p.mantle,
|
||||
surfaceContainer = p.mantle,
|
||||
surfaceContainerHigh = p.surface0,
|
||||
surfaceContainerHighest = p.surface1,
|
||||
outline = p.overlay,
|
||||
outlineVariant = p.surface1,
|
||||
error = p.error,
|
||||
onError = Color.White,
|
||||
errorContainer = p.error.copy(alpha = 0.22f),
|
||||
onErrorContainer = p.text,
|
||||
)
|
||||
} else {
|
||||
lightColorScheme(
|
||||
primary = p.tint,
|
||||
onPrimary = p.onTint,
|
||||
primaryContainer = p.accent,
|
||||
onPrimaryContainer = p.onAccent,
|
||||
secondary = p.accent2,
|
||||
onSecondary = Color.White,
|
||||
secondaryContainer = p.surface1,
|
||||
onSecondaryContainer = p.text,
|
||||
tertiary = p.warning,
|
||||
onTertiary = Color.White,
|
||||
background = p.base,
|
||||
onBackground = p.text,
|
||||
surface = p.base,
|
||||
onSurface = p.text,
|
||||
surfaceVariant = p.surface1,
|
||||
onSurfaceVariant = p.subtext,
|
||||
surfaceContainerLowest = p.mantle,
|
||||
surfaceContainerLow = p.mantle,
|
||||
surfaceContainer = p.mantle,
|
||||
surfaceContainerHigh = p.surface1,
|
||||
surfaceContainerHighest = p.surface2,
|
||||
outline = p.overlay,
|
||||
outlineVariant = p.surface2,
|
||||
error = p.error,
|
||||
onError = Color.White,
|
||||
errorContainer = p.error.copy(alpha = 0.14f),
|
||||
onErrorContainer = p.text,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun MaturitaApp(vm: AppViewModel) {
|
||||
MaterialTheme(colorScheme = schemeFor(vm.palette, vm.mode == ColorMode.Dark), typography = appTypography()) {
|
||||
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
|
||||
MaturitaAppBody(vm)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Back gesture, Escape or the mouse back button: close search first, then walk up. */
|
||||
fun AppViewModel.handleBack(): Boolean {
|
||||
if (searchOpen) {
|
||||
searchOpen = false
|
||||
return true
|
||||
}
|
||||
if (!canGoBack) return false
|
||||
back()
|
||||
return true
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MaturitaAppBody(vm: AppViewModel) {
|
||||
LaunchedEffect(Unit) { vm.checkUpdate(false) }
|
||||
Box(Modifier.fillMaxSize()) {
|
||||
AnimatedContent(
|
||||
targetState = vm.route,
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
transitionSpec = {
|
||||
val tabs = targetState.isRoot && initialState.isRoot
|
||||
if (tabs) {
|
||||
fadeIn(tween(180)) togetherWith fadeOut(tween(140))
|
||||
} else if (vm.navigatingForward) {
|
||||
(fadeIn(tween(220)) + slideInHorizontally(tween(220)) { it / 5 })
|
||||
.togetherWith(fadeOut(tween(150)) + slideOutHorizontally(tween(150)) { -it / 8 })
|
||||
} else {
|
||||
(fadeIn(tween(220)) + slideInHorizontally(tween(220)) { -it / 8 })
|
||||
.togetherWith(fadeOut(tween(150)) + slideOutHorizontally(tween(150)) { it / 5 })
|
||||
}
|
||||
},
|
||||
label = "screen",
|
||||
) { route ->
|
||||
when (val r = route) {
|
||||
Route.Welcome, Route.Subjects -> HomeScreen(vm)
|
||||
Route.Stats -> StatsScreen(vm)
|
||||
Route.Settings -> SettingsScreen(vm)
|
||||
Route.DeHome -> DeHomeScreen(vm)
|
||||
is Route.DeMap -> LessonListScreen(
|
||||
vm, vm.tr("de_year${r.year}"), vm.tr("de_y${r.year}_sub"),
|
||||
vm.content.deYear(r.year).map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.deDone(r.year, id), Route.DeLesson(r.year, id))
|
||||
},
|
||||
)
|
||||
is Route.DeLesson -> {
|
||||
val l = vm.content.deLesson(r.year, r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.DeEx(r.year, r.id))
|
||||
}
|
||||
}
|
||||
is Route.DeEx -> EngExScreen(
|
||||
vm, r.year, r.id, Locale.GERMANY, vm.content.deLesson(r.year, r.id),
|
||||
) { vm.markDe(r.year, r.id) }
|
||||
Route.Roadmap -> RoadmapScreen(vm)
|
||||
is Route.UnitMap -> UnitMapScreen(vm, r.unitId)
|
||||
is Route.GermanEx -> GermanExercise(vm, r.unitId, r.ex)
|
||||
is Route.Vocab -> VocabExercise(vm, r.unitId)
|
||||
Route.NetYears -> NetYearsScreen(vm)
|
||||
Route.NetMap -> LessonListScreen(
|
||||
vm, vm.tr("net_year1"), vm.tr("net_sub"),
|
||||
vm.content.netLessons.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.netDone(id), Route.NetLesson(id))
|
||||
},
|
||||
)
|
||||
is Route.NetLesson -> {
|
||||
val l = vm.content.netLesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.NetEx(r.id))
|
||||
}
|
||||
}
|
||||
is Route.NetEx -> NetQuizScreen(vm, r.id)
|
||||
Route.Net2Map -> ItYearScreen(vm, "net2", "net_year2", "net2_sub") { Route.Net2Lesson(it) }
|
||||
is Route.Net2Lesson -> {
|
||||
val l = vm.content.itLesson("net2", r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.Net2Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.Net2Ex -> ChoiceLessonScreen(vm, vm.content.itLesson("net2", r.id)) { vm.markCourse("net2", r.id) }
|
||||
Route.Net3Map -> ItYearScreen(vm, "net3", "net_year3", "net3_sub") { Route.Net3Lesson(it) }
|
||||
is Route.Net3Lesson -> {
|
||||
val l = vm.content.itLesson("net3", r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.Net3Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.Net3Ex -> ChoiceLessonScreen(vm, vm.content.itLesson("net3", r.id)) { vm.markCourse("net3", r.id) }
|
||||
Route.Net4Map -> ItYearScreen(vm, "net4", "net_year4", "net4_sub") { Route.Net4Lesson(it) }
|
||||
is Route.Net4Lesson -> {
|
||||
val l = vm.content.itLesson("net4", r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.Net4Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.Net4Ex -> ChoiceLessonScreen(vm, vm.content.itLesson("net4", r.id)) { vm.markCourse("net4", r.id) }
|
||||
Route.HwYears -> HwYearsScreen(vm)
|
||||
Route.HwMap -> LessonListScreen(
|
||||
vm, vm.tr("hw_year1"), vm.tr("hw_sub"),
|
||||
vm.content.hw.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.hwDone(id), Route.HwLesson(id))
|
||||
},
|
||||
)
|
||||
is Route.HwLesson -> {
|
||||
val l = vm.content.hwLesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.HwEx(r.id))
|
||||
}
|
||||
}
|
||||
is Route.HwEx -> HwQuizScreen(vm, r.id)
|
||||
Route.Hw2Map -> ItYearScreen(vm, "hw2", "hw_year2", "hw2_sub") { Route.Hw2Lesson(it) }
|
||||
is Route.Hw2Lesson -> {
|
||||
val l = vm.content.itLesson("hw2", r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.Hw2Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.Hw2Ex -> ChoiceLessonScreen(vm, vm.content.itLesson("hw2", r.id)) { vm.markCourse("hw2", r.id) }
|
||||
Route.Hw3Map -> ItYearScreen(vm, "hw3", "hw_year3", "hw3_sub") { Route.Hw3Lesson(it) }
|
||||
is Route.Hw3Lesson -> {
|
||||
val l = vm.content.itLesson("hw3", r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.Hw3Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.Hw3Ex -> ChoiceLessonScreen(vm, vm.content.itLesson("hw3", r.id)) { vm.markCourse("hw3", r.id) }
|
||||
Route.Hw4Map -> ItYearScreen(vm, "hw4", "hw_year4", "hw4_sub") { Route.Hw4Lesson(it) }
|
||||
is Route.Hw4Lesson -> {
|
||||
val l = vm.content.itLesson("hw4", r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.Hw4Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.Hw4Ex -> ChoiceLessonScreen(vm, vm.content.itLesson("hw4", r.id)) { vm.markCourse("hw4", r.id) }
|
||||
Route.EnYears -> EnYearsScreen(vm)
|
||||
is Route.EnMap -> LessonListScreen(
|
||||
vm, vm.tr("en_year${r.year}"), vm.tr("en_y${r.year}_sub"),
|
||||
vm.content.enYear(r.year).map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.enDone(r.year, id), Route.EnLesson(r.year, id))
|
||||
},
|
||||
)
|
||||
is Route.EnLesson -> {
|
||||
val l = vm.content.enLesson(r.year, r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.EnEx(r.year, r.id))
|
||||
}
|
||||
}
|
||||
is Route.EnEx -> EngExScreen(vm, r.year, r.id)
|
||||
Route.OnYears -> OnYearsScreen(vm)
|
||||
Route.OnMap -> LessonListScreen(
|
||||
vm, vm.tr("on_year1"), vm.tr("on_sub"),
|
||||
vm.content.on.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.onDone(id), Route.OnLesson(id))
|
||||
},
|
||||
)
|
||||
is Route.OnLesson -> {
|
||||
val l = vm.content.onLesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.OnEx(r.id))
|
||||
}
|
||||
}
|
||||
is Route.OnEx -> OnQuizScreen(vm, r.id)
|
||||
Route.On2Map -> LessonListScreen(
|
||||
vm, vm.tr("on_year2"), vm.tr("on2_sub"),
|
||||
vm.content.on2.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.on2Done(id), Route.On2Lesson(id))
|
||||
},
|
||||
)
|
||||
is Route.On2Lesson -> {
|
||||
val l = vm.content.on2Lesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.On2Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.On2Ex -> On2QuizScreen(vm, r.id)
|
||||
Route.On3Map -> LessonListScreen(
|
||||
vm, vm.tr("on_year3"), vm.tr("on3_sub"),
|
||||
vm.content.on3.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.on3Done(id), Route.On3Lesson(id))
|
||||
},
|
||||
)
|
||||
is Route.On3Lesson -> {
|
||||
val l = vm.content.on3Lesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.On3Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.On3Ex -> On3QuizScreen(vm, r.id)
|
||||
Route.On4Map -> LessonListScreen(
|
||||
vm, vm.tr("on_year4"), vm.tr("on4_sub"),
|
||||
vm.content.on4.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.on4Done(id), Route.On4Lesson(id))
|
||||
},
|
||||
)
|
||||
is Route.On4Lesson -> {
|
||||
val l = vm.content.on4Lesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.On4Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.On4Ex -> On4QuizScreen(vm, r.id)
|
||||
Route.LitYears -> LitYearsScreen(vm)
|
||||
Route.LitMap -> LessonListScreen(
|
||||
vm, vm.tr("lit_year1"), vm.tr("lit_sub"),
|
||||
vm.content.lit.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.litDone(id), Route.LitLesson(id))
|
||||
},
|
||||
)
|
||||
is Route.LitLesson -> {
|
||||
val l = vm.content.litLesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.LitEx(r.id))
|
||||
}
|
||||
}
|
||||
is Route.LitEx -> LitQuizScreen(vm, 1, r.id)
|
||||
Route.Lit2Map -> LessonListScreen(
|
||||
vm, vm.tr("lit_year2"), vm.tr("lit2_sub"),
|
||||
vm.content.lit2.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.lit2Done(id), Route.Lit2Lesson(id))
|
||||
},
|
||||
)
|
||||
is Route.Lit2Lesson -> {
|
||||
val l = vm.content.lit2Lesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.Lit2Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.Lit2Ex -> LitQuizScreen(vm, 2, r.id)
|
||||
Route.Lit3Map -> LessonListScreen(
|
||||
vm, vm.tr("lit_year3"), vm.tr("lit3_sub"),
|
||||
vm.content.lit3.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.lit3Done(id), Route.Lit3Lesson(id))
|
||||
},
|
||||
)
|
||||
is Route.Lit3Lesson -> {
|
||||
val l = vm.content.lit3Lesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.Lit3Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.Lit3Ex -> LitQuizScreen(vm, 3, r.id)
|
||||
Route.Lit4Map -> LessonListScreen(
|
||||
vm, vm.tr("lit_year4"), vm.tr("lit4_sub"),
|
||||
vm.content.lit4.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.lit4Done(id), Route.Lit4Lesson(id))
|
||||
},
|
||||
)
|
||||
is Route.Lit4Lesson -> {
|
||||
val l = vm.content.lit4Lesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.Lit4Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.Lit4Ex -> LitQuizScreen(vm, 4, r.id)
|
||||
Route.MatYears -> MatYearsScreen(vm)
|
||||
Route.Mat0Map -> LessonListScreen(
|
||||
vm, vm.tr("mat0_year"), vm.tr("mat0_sub"),
|
||||
vm.content.mat0.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.mat0Done(id), Route.Mat0Lesson(id))
|
||||
},
|
||||
)
|
||||
is Route.Mat0Lesson -> {
|
||||
val l = vm.content.mat0Lesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.Mat0Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.Mat0Ex -> MathPracticeScreen(vm, 0, r.id)
|
||||
Route.MatMap -> LessonListScreen(
|
||||
vm, vm.tr("mat_year1"), vm.tr("mat_sub"),
|
||||
vm.content.mat.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.matDone(id), Route.MatLesson(id))
|
||||
},
|
||||
)
|
||||
is Route.MatLesson -> {
|
||||
val l = vm.content.matLesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.MatEx(r.id))
|
||||
}
|
||||
}
|
||||
is Route.MatEx -> MathPracticeScreen(vm, 1, r.id)
|
||||
Route.Mat2Map -> LessonListScreen(
|
||||
vm, vm.tr("mat_year2"), vm.tr("mat2_sub"),
|
||||
vm.content.mat2.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.mat2Done(id), Route.Mat2Lesson(id))
|
||||
},
|
||||
)
|
||||
is Route.Mat2Lesson -> {
|
||||
val l = vm.content.mat2Lesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.Mat2Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.Mat2Ex -> MathPracticeScreen(vm, 2, r.id)
|
||||
Route.Mat3Map -> LessonListScreen(
|
||||
vm, vm.tr("mat_year3"), vm.tr("mat3_sub"),
|
||||
vm.content.mat3.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.mat3Done(id), Route.Mat3Lesson(id))
|
||||
},
|
||||
)
|
||||
is Route.Mat3Lesson -> {
|
||||
val l = vm.content.mat3Lesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.Mat3Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.Mat3Ex -> MathPracticeScreen(vm, 3, r.id)
|
||||
Route.Mat4Map -> LessonListScreen(
|
||||
vm, vm.tr("mat_year4"), vm.tr("mat4_sub"),
|
||||
vm.content.mat4.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.mat4Done(id), Route.Mat4Lesson(id))
|
||||
},
|
||||
)
|
||||
is Route.Mat4Lesson -> {
|
||||
val l = vm.content.mat4Lesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.Mat4Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.Mat4Ex -> MathPracticeScreen(vm, 4, r.id)
|
||||
Route.FyzYears -> FyzYearsScreen(vm)
|
||||
Route.FyzMap -> LessonListScreen(
|
||||
vm, vm.tr("fyz_year1"), vm.tr("fyz_sub"),
|
||||
vm.content.fyz.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.fyzDone(id), Route.FyzLesson(id))
|
||||
},
|
||||
)
|
||||
is Route.FyzLesson -> {
|
||||
val l = vm.content.fyzLesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.FyzEx(r.id))
|
||||
}
|
||||
}
|
||||
is Route.FyzEx -> FyzQuizScreen(vm, 1, r.id)
|
||||
Route.Fyz2Map -> LessonListScreen(
|
||||
vm, vm.tr("fyz_year2"), vm.tr("fyz2_sub"),
|
||||
vm.content.fyz2.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.fyz2Done(id), Route.Fyz2Lesson(id))
|
||||
},
|
||||
)
|
||||
is Route.Fyz2Lesson -> {
|
||||
val l = vm.content.fyz2Lesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.Fyz2Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.Fyz2Ex -> FyzQuizScreen(vm, 2, r.id)
|
||||
Route.Fyz3Map -> LessonListScreen(
|
||||
vm, vm.tr("fyz_year3"), vm.tr("fyz3_sub"),
|
||||
vm.content.fyz3.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.fyz3Done(id), Route.Fyz3Lesson(id))
|
||||
},
|
||||
)
|
||||
is Route.Fyz3Lesson -> {
|
||||
val l = vm.content.fyz3Lesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.Fyz3Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.Fyz3Ex -> FyzQuizScreen(vm, 3, r.id)
|
||||
Route.Fyz4Map -> LessonListScreen(
|
||||
vm, vm.tr("fyz_year4"), vm.tr("fyz4_sub"),
|
||||
vm.content.fyz4.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.fyz4Done(id), Route.Fyz4Lesson(id))
|
||||
},
|
||||
)
|
||||
is Route.Fyz4Lesson -> {
|
||||
val l = vm.content.fyz4Lesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.Fyz4Ex(r.id))
|
||||
}
|
||||
}
|
||||
is Route.Fyz4Ex -> FyzQuizScreen(vm, 4, r.id)
|
||||
Route.SciMap -> SciMapScreen(vm)
|
||||
Route.ChemMap -> LessonListScreen(
|
||||
vm, vm.tr("Chemie"), vm.tr("chem_sub"),
|
||||
vm.content.chem.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.chemDone(id), Route.ChemLesson(id))
|
||||
},
|
||||
)
|
||||
is Route.ChemLesson -> {
|
||||
val l = vm.content.chemLesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.ChemEx(r.id))
|
||||
}
|
||||
}
|
||||
is Route.ChemEx -> SciQuizScreen(vm, "chem", r.id)
|
||||
Route.BioMap -> LessonListScreen(
|
||||
vm, vm.tr("Biologie"), vm.tr("bio_sub"),
|
||||
vm.content.bio.map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.bioDone(id), Route.BioLesson(id))
|
||||
},
|
||||
)
|
||||
is Route.BioLesson -> {
|
||||
val l = vm.content.bioLesson(r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.BioEx(r.id))
|
||||
}
|
||||
}
|
||||
is Route.BioEx -> SciQuizScreen(vm, "bio", r.id)
|
||||
Route.CzechMap -> CzechMapScreen(vm)
|
||||
Route.Mluvnice -> LessonListScreen(
|
||||
vm, vm.tr("Mluvnice"), vm.tr("mluv_sub"),
|
||||
vm.content.mluvnice.map { m ->
|
||||
val n = m.int("id")
|
||||
LessonRow(m.str("name"), vm.progress.mluvDone(n), Route.MluvEx(n))
|
||||
},
|
||||
)
|
||||
is Route.MluvEx -> MluvExercise(vm, r.n)
|
||||
Route.ReadingList -> BookListScreen(vm)
|
||||
is Route.Book -> BookScreen(vm, r.id)
|
||||
is Route.BookQuiz -> LitQuizScreen(vm, r.id)
|
||||
is Route.BookPlot -> PlotScreen(vm, r.id)
|
||||
}
|
||||
}
|
||||
AnimatedVisibility(
|
||||
visible = vm.searchOpen,
|
||||
enter = fadeIn(tween(160)),
|
||||
exit = fadeOut(tween(120)),
|
||||
) {
|
||||
Box(Modifier.fillMaxSize()) { SearchScreen(vm) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,24 +1,22 @@
|
|||
package org.maturita.maturita
|
||||
|
||||
import android.app.Application
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import org.maturita.maturita.data.ColorMode
|
||||
import org.maturita.maturita.data.Content
|
||||
import org.maturita.maturita.data.ProgressStore
|
||||
import org.maturita.maturita.data.ThemeId
|
||||
import org.maturita.maturita.data.UiLang
|
||||
import org.maturita.maturita.data.themePalette
|
||||
import org.maturita.maturita.update.UpdateState
|
||||
import org.maturita.maturita.update.Updater
|
||||
import org.maturita.maturita.platform.Platform
|
||||
import org.maturita.maturita.platform.UpdateState
|
||||
|
||||
class AppViewModel(app: Application) : AndroidViewModel(app) {
|
||||
val content = Content.load(app)
|
||||
val progress = ProgressStore(app)
|
||||
val updater = Updater(app)
|
||||
/** App state shared by every platform; the platform only supplies [Platform]. */
|
||||
class AppViewModel(val content: Content, val platform: Platform) {
|
||||
val progress = ProgressStore(platform.prefs, content)
|
||||
private val updater = platform.updater
|
||||
|
||||
var themeId by mutableStateOf(progress.themeId)
|
||||
private set
|
||||
|
|
@ -30,7 +28,7 @@ class AppViewModel(app: Application) : AndroidViewModel(app) {
|
|||
var searchQuery by mutableStateOf("")
|
||||
var tick by mutableStateOf(0)
|
||||
private set
|
||||
var update by mutableStateOf(UpdateState())
|
||||
var update by mutableStateOf(UpdateState(messageArg = platform.commit.take(7)))
|
||||
private set
|
||||
var showChangelog by mutableStateOf(shouldShowChangelog())
|
||||
private set
|
||||
|
|
@ -268,13 +266,13 @@ class AppViewModel(app: Application) : AndroidViewModel(app) {
|
|||
}
|
||||
|
||||
fun dismissChangelog() {
|
||||
progress.seenCommit = BuildConfig.COMMIT
|
||||
progress.seenCommit = platform.commit
|
||||
showChangelog = false
|
||||
}
|
||||
|
||||
private fun shouldShowChangelog(): Boolean {
|
||||
if (content.changelog.isEmpty()) return false
|
||||
return !sameBuild(BuildConfig.COMMIT, progress.seenCommit)
|
||||
return !sameBuild(platform.commit, progress.seenCommit)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package org.maturita.maturita.data
|
||||
|
||||
import android.content.Context
|
||||
import org.json.JSONObject
|
||||
|
||||
class Content(root: JSONObject) {
|
||||
|
|
@ -65,6 +64,8 @@ class Content(root: JSONObject) {
|
|||
val mluvnice = raw.arr("mluvnice")
|
||||
val books = raw.arr("books")
|
||||
val changelog = raw.arr("changelog")
|
||||
val progressKeys = stringMap(root.optJSONObject("progress")?.optJSONObject("keys"))
|
||||
val progressLegacy = stringMap(root.optJSONObject("progress")?.optJSONObject("legacy"))
|
||||
|
||||
fun germanUnit(id: Int) = german.firstOrNull { it.int("id") == id }
|
||||
fun netLesson(id: Int) = netLessons.firstOrNull { it.int("id") == id }
|
||||
|
|
@ -135,13 +136,13 @@ class Content(root: JSONObject) {
|
|||
}
|
||||
|
||||
companion object {
|
||||
fun load(context: Context): Content {
|
||||
return try {
|
||||
val text = context.assets.open("content.json").bufferedReader().use { it.readText() }
|
||||
Content(JSONObject(text))
|
||||
} catch (_: Exception) {
|
||||
Content(JSONObject())
|
||||
}
|
||||
private fun stringMap(o: JSONObject?): Map<String, String> =
|
||||
o?.keys()?.asSequence()?.associateWith { o.optString(it) } ?: emptyMap()
|
||||
|
||||
fun parse(text: String?): Content = try {
|
||||
Content(JSONObject(text ?: "{}"))
|
||||
} catch (_: Exception) {
|
||||
Content(JSONObject())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,28 @@
|
|||
package org.maturita.maturita.data
|
||||
|
||||
import android.content.Context
|
||||
import org.maturita.maturita.platform.Prefs
|
||||
|
||||
class ProgressStore(context: Context) {
|
||||
private val prefs = context.getSharedPreferences("maturita", Context.MODE_PRIVATE)
|
||||
class ProgressStore(private val prefs: Prefs, content: Content) {
|
||||
private val ids = content.progressKeys
|
||||
|
||||
init {
|
||||
migrate(content.progressLegacy)
|
||||
}
|
||||
|
||||
/** Progress is stored under each lesson's id from content/, so lessons can be
|
||||
* reordered or renamed without losing it. `address` is the in-app position. */
|
||||
private fun key(address: String) = "done." + (ids[address] ?: address)
|
||||
private fun done(address: String) = prefs.getBoolean(key(address), false)
|
||||
private fun mark(address: String) { prefs.edit().putBoolean(key(address), true).apply() }
|
||||
|
||||
private fun migrate(legacy: Map<String, String>) {
|
||||
if (prefs.getBoolean("progress_ids_v2", false)) return
|
||||
val edit = prefs.edit()
|
||||
for ((old, id) in legacy) {
|
||||
if (prefs.getBoolean(old, false)) edit.putBoolean("done.$id", true)
|
||||
}
|
||||
edit.putBoolean("progress_ids_v2", true).apply()
|
||||
}
|
||||
|
||||
var themeId: ThemeId
|
||||
get() = ThemeId.entries.getOrElse(prefs.getInt("theme", 0)) { ThemeId.Catppuccin }
|
||||
|
|
@ -21,75 +40,75 @@ class ProgressStore(context: Context) {
|
|||
get() = prefs.getString("seen_commit", "") ?: ""
|
||||
set(v) { prefs.edit().putString("seen_commit", v).apply() }
|
||||
|
||||
fun germanDone(unit: Int, ex: Int) = prefs.getBoolean("g.$unit.$ex", false)
|
||||
fun markGerman(unit: Int, ex: Int) { prefs.edit().putBoolean("g.$unit.$ex", true).apply() }
|
||||
fun vocabDone(unit: Int) = prefs.getBoolean("g.$unit.vocab", false)
|
||||
fun markVocab(unit: Int) { prefs.edit().putBoolean("g.$unit.vocab", true).apply() }
|
||||
fun germanDone(unit: Int, ex: Int) = done("g.$unit.$ex")
|
||||
fun markGerman(unit: Int, ex: Int) { mark("g.$unit.$ex") }
|
||||
fun vocabDone(unit: Int) = done("g.$unit.vocab")
|
||||
fun markVocab(unit: Int) { mark("g.$unit.vocab") }
|
||||
|
||||
fun netDone(id: Int) = prefs.getBoolean("net.$id", false)
|
||||
fun markNet(id: Int) { prefs.edit().putBoolean("net.$id", true).apply() }
|
||||
fun netDone(id: Int) = done("net.$id")
|
||||
fun markNet(id: Int) { mark("net.$id") }
|
||||
|
||||
fun hwDone(id: Int) = prefs.getBoolean("hw.$id", false)
|
||||
fun markHw(id: Int) { prefs.edit().putBoolean("hw.$id", true).apply() }
|
||||
fun hwDone(id: Int) = done("hw.$id")
|
||||
fun markHw(id: Int) { mark("hw.$id") }
|
||||
|
||||
fun onDone(id: Int) = prefs.getBoolean("on.$id", false)
|
||||
fun markOn(id: Int) { prefs.edit().putBoolean("on.$id", true).apply() }
|
||||
fun onDone(id: Int) = done("on.$id")
|
||||
fun markOn(id: Int) { mark("on.$id") }
|
||||
|
||||
fun on2Done(id: Int) = prefs.getBoolean("on2.$id", false)
|
||||
fun markOn2(id: Int) { prefs.edit().putBoolean("on2.$id", true).apply() }
|
||||
fun on2Done(id: Int) = done("on2.$id")
|
||||
fun markOn2(id: Int) { mark("on2.$id") }
|
||||
|
||||
fun on3Done(id: Int) = prefs.getBoolean("on3.$id", false)
|
||||
fun markOn3(id: Int) { prefs.edit().putBoolean("on3.$id", true).apply() }
|
||||
fun on3Done(id: Int) = done("on3.$id")
|
||||
fun markOn3(id: Int) { mark("on3.$id") }
|
||||
|
||||
fun on4Done(id: Int) = prefs.getBoolean("on4.$id", false)
|
||||
fun markOn4(id: Int) { prefs.edit().putBoolean("on4.$id", true).apply() }
|
||||
fun on4Done(id: Int) = done("on4.$id")
|
||||
fun markOn4(id: Int) { mark("on4.$id") }
|
||||
|
||||
fun enDone(year: Int, id: Int) = prefs.getBoolean("en.$year.$id", false)
|
||||
fun markEn(year: Int, id: Int) { prefs.edit().putBoolean("en.$year.$id", true).apply() }
|
||||
fun deDone(year: Int, id: Int) = prefs.getBoolean("de.$year.$id", false)
|
||||
fun markDe(year: Int, id: Int) { prefs.edit().putBoolean("de.$year.$id", true).apply() }
|
||||
fun courseDone(course: String, id: Int) = prefs.getBoolean("$course.$id", false)
|
||||
fun markCourse(course: String, id: Int) { prefs.edit().putBoolean("$course.$id", true).apply() }
|
||||
fun enDone(year: Int, id: Int) = done("en.$year.$id")
|
||||
fun markEn(year: Int, id: Int) { mark("en.$year.$id") }
|
||||
fun deDone(year: Int, id: Int) = done("de.$year.$id")
|
||||
fun markDe(year: Int, id: Int) { mark("de.$year.$id") }
|
||||
fun courseDone(course: String, id: Int) = done("$course.$id")
|
||||
fun markCourse(course: String, id: Int) { mark("$course.$id") }
|
||||
|
||||
fun litDone(id: Int) = prefs.getBoolean("lit.$id", false)
|
||||
fun markLit(id: Int) { prefs.edit().putBoolean("lit.$id", true).apply() }
|
||||
fun lit2Done(id: Int) = prefs.getBoolean("lit2.$id", false)
|
||||
fun markLit2(id: Int) { prefs.edit().putBoolean("lit2.$id", true).apply() }
|
||||
fun lit3Done(id: Int) = prefs.getBoolean("lit3.$id", false)
|
||||
fun markLit3(id: Int) { prefs.edit().putBoolean("lit3.$id", true).apply() }
|
||||
fun lit4Done(id: Int) = prefs.getBoolean("lit4.$id", false)
|
||||
fun markLit4(id: Int) { prefs.edit().putBoolean("lit4.$id", true).apply() }
|
||||
fun litDone(id: Int) = done("lit.$id")
|
||||
fun markLit(id: Int) { mark("lit.$id") }
|
||||
fun lit2Done(id: Int) = done("lit2.$id")
|
||||
fun markLit2(id: Int) { mark("lit2.$id") }
|
||||
fun lit3Done(id: Int) = done("lit3.$id")
|
||||
fun markLit3(id: Int) { mark("lit3.$id") }
|
||||
fun lit4Done(id: Int) = done("lit4.$id")
|
||||
fun markLit4(id: Int) { mark("lit4.$id") }
|
||||
|
||||
fun chemDone(id: Int) = prefs.getBoolean("chem.$id", false)
|
||||
fun markChem(id: Int) { prefs.edit().putBoolean("chem.$id", true).apply() }
|
||||
fun bioDone(id: Int) = prefs.getBoolean("bio.$id", false)
|
||||
fun markBio(id: Int) { prefs.edit().putBoolean("bio.$id", true).apply() }
|
||||
fun fyzDone(id: Int) = prefs.getBoolean("fyz.$id", false)
|
||||
fun markFyz(id: Int) { prefs.edit().putBoolean("fyz.$id", true).apply() }
|
||||
fun fyz2Done(id: Int) = prefs.getBoolean("fyz2.$id", false)
|
||||
fun markFyz2(id: Int) { prefs.edit().putBoolean("fyz2.$id", true).apply() }
|
||||
fun fyz3Done(id: Int) = prefs.getBoolean("fyz3.$id", false)
|
||||
fun markFyz3(id: Int) { prefs.edit().putBoolean("fyz3.$id", true).apply() }
|
||||
fun fyz4Done(id: Int) = prefs.getBoolean("fyz4.$id", false)
|
||||
fun markFyz4(id: Int) { prefs.edit().putBoolean("fyz4.$id", true).apply() }
|
||||
fun mat0Done(id: Int) = prefs.getBoolean("mat0.$id", false)
|
||||
fun markMat0(id: Int) { prefs.edit().putBoolean("mat0.$id", true).apply() }
|
||||
fun matDone(id: Int) = prefs.getBoolean("mat.$id", false)
|
||||
fun markMat(id: Int) { prefs.edit().putBoolean("mat.$id", true).apply() }
|
||||
fun mat2Done(id: Int) = prefs.getBoolean("mat2.$id", false)
|
||||
fun markMat2(id: Int) { prefs.edit().putBoolean("mat2.$id", true).apply() }
|
||||
fun mat3Done(id: Int) = prefs.getBoolean("mat3.$id", false)
|
||||
fun markMat3(id: Int) { prefs.edit().putBoolean("mat3.$id", true).apply() }
|
||||
fun mat4Done(id: Int) = prefs.getBoolean("mat4.$id", false)
|
||||
fun markMat4(id: Int) { prefs.edit().putBoolean("mat4.$id", true).apply() }
|
||||
fun chemDone(id: Int) = done("chem.$id")
|
||||
fun markChem(id: Int) { mark("chem.$id") }
|
||||
fun bioDone(id: Int) = done("bio.$id")
|
||||
fun markBio(id: Int) { mark("bio.$id") }
|
||||
fun fyzDone(id: Int) = done("fyz.$id")
|
||||
fun markFyz(id: Int) { mark("fyz.$id") }
|
||||
fun fyz2Done(id: Int) = done("fyz2.$id")
|
||||
fun markFyz2(id: Int) { mark("fyz2.$id") }
|
||||
fun fyz3Done(id: Int) = done("fyz3.$id")
|
||||
fun markFyz3(id: Int) { mark("fyz3.$id") }
|
||||
fun fyz4Done(id: Int) = done("fyz4.$id")
|
||||
fun markFyz4(id: Int) { mark("fyz4.$id") }
|
||||
fun mat0Done(id: Int) = done("mat0.$id")
|
||||
fun markMat0(id: Int) { mark("mat0.$id") }
|
||||
fun matDone(id: Int) = done("mat.$id")
|
||||
fun markMat(id: Int) { mark("mat.$id") }
|
||||
fun mat2Done(id: Int) = done("mat2.$id")
|
||||
fun markMat2(id: Int) { mark("mat2.$id") }
|
||||
fun mat3Done(id: Int) = done("mat3.$id")
|
||||
fun markMat3(id: Int) { mark("mat3.$id") }
|
||||
fun mat4Done(id: Int) = done("mat4.$id")
|
||||
fun markMat4(id: Int) { mark("mat4.$id") }
|
||||
|
||||
fun mluvDone(n: Int) = prefs.getBoolean("mluv.$n", false)
|
||||
fun markMluv(n: Int) { prefs.edit().putBoolean("mluv.$n", true).apply() }
|
||||
fun mluvDone(n: Int) = done("mluv.$n")
|
||||
fun markMluv(n: Int) { mark("mluv.$n") }
|
||||
|
||||
fun bookQuiz(id: String) = prefs.getBoolean("book.$id.quiz", false)
|
||||
fun markBookQuiz(id: String) { prefs.edit().putBoolean("book.$id.quiz", true).apply() }
|
||||
fun bookPlot(id: String) = prefs.getBoolean("book.$id.plot", false)
|
||||
fun markBookPlot(id: String) { prefs.edit().putBoolean("book.$id.plot", true).apply() }
|
||||
fun bookQuiz(id: String) = done("book.$id.quiz")
|
||||
fun markBookQuiz(id: String) { mark("book.$id.quiz") }
|
||||
fun bookPlot(id: String) = done("book.$id.plot")
|
||||
fun markBookPlot(id: String) { mark("book.$id.plot") }
|
||||
}
|
||||
|
||||
data class ProgressSum(var doneEx: Int = 0, var totalEx: Int = 0, var doneUnits: Int = 0, var openUnits: Int = 0)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
package org.maturita.maturita.platform
|
||||
|
||||
import java.util.Locale
|
||||
|
||||
/**
|
||||
* Everything the shared app needs from the system it runs on. Android and the
|
||||
* desktop (Linux, Windows) each provide one; the screens never touch platform
|
||||
* APIs directly.
|
||||
*/
|
||||
interface Platform {
|
||||
/** Source commit baked into the build, or "dev" for local builds. */
|
||||
val commit: String
|
||||
val versionName: String
|
||||
/** Text key of the welcome card blurb, which names the device. */
|
||||
val welcomeKey: String
|
||||
val prefs: Prefs
|
||||
val updater: AppUpdater
|
||||
|
||||
/** A speech engine for listening exercises, or null when there is none. */
|
||||
fun speaker(): Speaker?
|
||||
}
|
||||
|
||||
/** The subset of Android's SharedPreferences the app uses. */
|
||||
interface Prefs {
|
||||
fun getBoolean(key: String, fallback: Boolean): Boolean
|
||||
fun getInt(key: String, fallback: Int): Int
|
||||
fun getString(key: String, fallback: String?): String?
|
||||
fun edit(): Editor
|
||||
|
||||
interface Editor {
|
||||
fun putBoolean(key: String, value: Boolean): Editor
|
||||
fun putInt(key: String, value: Int): Editor
|
||||
fun putString(key: String, value: String): Editor
|
||||
fun apply()
|
||||
}
|
||||
}
|
||||
|
||||
data class UpdateState(
|
||||
val status: String = "idle",
|
||||
val remote: String? = null,
|
||||
val messageKey: String = "update_current",
|
||||
val messageArg: String? = null,
|
||||
val canInstall: Boolean = false,
|
||||
)
|
||||
|
||||
/** Callbacks always arrive on the UI thread. */
|
||||
interface AppUpdater {
|
||||
fun check(interactive: Boolean, cb: (UpdateState) -> Unit)
|
||||
fun install(cb: (UpdateState) -> Unit)
|
||||
}
|
||||
|
||||
interface Speaker {
|
||||
/**
|
||||
* Reads [text] aloud. [onRange] gets the offset of the word being spoken
|
||||
* where the engine reports it; [onEnd] gets false when speaking failed.
|
||||
* Both run on the UI thread.
|
||||
*/
|
||||
fun speak(
|
||||
text: String,
|
||||
locale: Locale,
|
||||
rate: Float,
|
||||
volume: Float,
|
||||
onRange: (Int) -> Unit,
|
||||
onEnd: (Boolean) -> Unit,
|
||||
)
|
||||
|
||||
fun stop()
|
||||
fun close()
|
||||
}
|
||||
|
|
@ -37,16 +37,10 @@ import androidx.compose.material3.MaterialTheme
|
|||
import androidx.compose.material3.OutlinedButton
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Text
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.speech.tts.TextToSpeech
|
||||
import android.speech.tts.UtteranceProgressListener
|
||||
import androidx.compose.material3.Slider
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.SideEffect
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import java.util.Locale
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
|
|
@ -1423,18 +1417,9 @@ fun EngExScreen(
|
|||
var revealed by remember(year, id) { mutableStateOf(false) }
|
||||
var showModel by remember(year, id) { mutableStateOf(false) }
|
||||
var fb by remember(year, id) { mutableStateOf("" to "") }
|
||||
val context = LocalContext.current
|
||||
var tts by remember { mutableStateOf<TextToSpeech?>(null) }
|
||||
DisposableEffect(context) {
|
||||
var engine: TextToSpeech? = null
|
||||
engine = TextToSpeech(context) { status ->
|
||||
if (status == TextToSpeech.SUCCESS) engine?.language = locale
|
||||
}
|
||||
tts = engine
|
||||
onDispose {
|
||||
engine?.stop()
|
||||
engine?.shutdown()
|
||||
}
|
||||
val tts = remember { vm.platform.speaker() }
|
||||
DisposableEffect(tts) {
|
||||
onDispose { tts?.close() }
|
||||
}
|
||||
|
||||
fun picksOk(questions: List<J>, picks: List<Int>) =
|
||||
|
|
@ -1490,32 +1475,18 @@ fun EngExScreen(
|
|||
val start = index.coerceIn(0, listening.length)
|
||||
val id = "en-${System.nanoTime()}"
|
||||
utterance = id
|
||||
engine.language = locale
|
||||
engine.setSpeechRate(speed)
|
||||
engine.setOnUtteranceProgressListener(object : UtteranceProgressListener() {
|
||||
override fun onStart(utteranceId: String?) {}
|
||||
override fun onRangeStart(utteranceId: String?, rangeStart: Int, rangeEnd: Int, frame: Int) {
|
||||
if (utteranceId == id) cursor = start + rangeStart
|
||||
}
|
||||
override fun onDone(utteranceId: String?) {
|
||||
if (utteranceId != utterance) return
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
val rest = listening.substring(start).ifEmpty { listening }
|
||||
engine.speak(
|
||||
rest, locale, speed, volume.coerceIn(0f, 1f),
|
||||
onRange = { offset -> if (utterance == id) cursor = start + offset },
|
||||
onEnd = { ok ->
|
||||
if (utterance == id) {
|
||||
phase = 0
|
||||
cursor = 0
|
||||
if (ok) cursor = 0
|
||||
showScript = true
|
||||
}
|
||||
}
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun onError(utteranceId: String?) {
|
||||
if (utteranceId != utterance) return
|
||||
Handler(Looper.getMainLooper()).post { showScript = true; phase = 0 }
|
||||
}
|
||||
})
|
||||
val params = Bundle().apply {
|
||||
putFloat(TextToSpeech.Engine.KEY_PARAM_VOLUME, volume.coerceIn(0f, 1f))
|
||||
}
|
||||
val rest = listening.substring(start).ifEmpty { listening }
|
||||
engine.speak(rest, TextToSpeech.QUEUE_FLUSH, params, id)
|
||||
},
|
||||
)
|
||||
phase = 1
|
||||
}
|
||||
Text(vm.tr("en_sec_listen"), style = MaterialTheme.typography.titleMedium, modifier = Modifier.padding(top = 8.dp))
|
||||
|
|
|
|||
|
|
@ -74,7 +74,6 @@ import androidx.compose.ui.text.style.TextOverflow
|
|||
import androidx.compose.ui.unit.dp
|
||||
import kotlinx.coroutines.launch
|
||||
import org.maturita.maturita.AppViewModel
|
||||
import org.maturita.maturita.BuildConfig
|
||||
import org.maturita.maturita.Route
|
||||
import org.maturita.maturita.data.ColorMode
|
||||
import org.maturita.maturita.data.J
|
||||
|
|
@ -110,7 +109,7 @@ fun HomeScreen(vm: AppViewModel) {
|
|||
)
|
||||
Spacer(Modifier.height(8.dp))
|
||||
Text(
|
||||
vm.tr("welcome_body_android"),
|
||||
vm.tr(vm.platform.welcomeKey),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onPrimaryContainer.copy(alpha = 0.8f),
|
||||
)
|
||||
|
|
@ -433,7 +432,7 @@ fun SettingsScreen(vm: AppViewModel) {
|
|||
item {
|
||||
ListItem(
|
||||
headlineContent = { Text("Build") },
|
||||
supportingContent = { Text("${BuildConfig.VERSION_NAME} · ${BuildConfig.COMMIT.take(7)}") },
|
||||
supportingContent = { Text("${vm.platform.versionName} · ${vm.platform.commit.take(7)}") },
|
||||
colors = ListItemDefaults.colors(containerColor = Color.Transparent),
|
||||
modifier = Modifier.padding(top = 8.dp),
|
||||
)
|
||||
|
|
|
|||
319
content/README.md
Normal file
319
content/README.md
Normal file
|
|
@ -0,0 +1,319 @@
|
|||
# Obsah aplikace
|
||||
|
||||
Všechny texty lekcí, cvičení, kvízů a knih jsou tady v Markdownu. Aplikace pro
|
||||
Android, iOS, macOS, Linux i Windows z nich při sestavení vyrobí jeden soubor
|
||||
`content.json` (skript `scripts/build-content.py`). Na kód se kvůli obsahu sahat
|
||||
nemusí.
|
||||
|
||||
Kontrola po úpravě:
|
||||
|
||||
```sh
|
||||
python3 scripts/build-content.py
|
||||
```
|
||||
|
||||
Skript vypíše počet lekcí, nebo chyby s cestou a číslem řádku
|
||||
(`content/fyzika/1-rocnik/02-pohyb.md:41: …`). Při chybě se aplikace nesestaví.
|
||||
|
||||
## Kde co je
|
||||
|
||||
| Složka | Obsah |
|
||||
|---|---|
|
||||
| `pocitacove-site/`, `technicke-vybaveni/`, `obcanska-nauka/`, `fyzika/` | `N-rocnik/`, v nich lekce |
|
||||
| `prirodni-vedy/chemie`, `prirodni-vedy/biologie` | lekce |
|
||||
| `cestina/literatura/N-rocnik` | lekce literatury |
|
||||
| `cestina/mluvnice` | cvičení z mluvnice |
|
||||
| `cestina/cetba` | knihy k maturitní četbě |
|
||||
| `matematika/0-opakovani`, `matematika/N-rocnik` | lekce s příklady |
|
||||
| `anglictina/N-rocnik`, `nemcina/N-rocnik` | lekce s výkladem, čtením, poslechem, psaním |
|
||||
| `nemcina/ucebnice` | učebnice němčiny po kapitolách |
|
||||
| `aplikace/texty.md` | texty rozhraní (tlačítka, nadpisy obrazovek) |
|
||||
| `aplikace/predmety.md` | dlaždice předmětů na úvodní obrazovce |
|
||||
| `aplikace/novinky.txt` | seznam změn zobrazovaný v aplikaci |
|
||||
|
||||
Jedna lekce je jeden soubor `NN-nazev.md`. Pořadí v aplikaci určuje číslo na
|
||||
začátku názvu. Soubory, které začínají `_`, nejsou lekce (např. `_lekce.md`
|
||||
v učebnici popisuje kapitolu).
|
||||
|
||||
## Angličtina
|
||||
|
||||
Anglická verze leží vedle české jako `NN-nazev.en.md`. Co v ní chybí, zobrazí
|
||||
se česky. Obsahuje:
|
||||
|
||||
- hlavičku se stejnými poli jako česká (`nazev`, `popis`, …), ale anglicky,
|
||||
- volitelně tabulku `# Překlady`, kde je každý český text z lekce přeložený:
|
||||
|
||||
```md
|
||||
---
|
||||
nazev: Physical quantities
|
||||
popis: SI, scalar and vector, measurement error.
|
||||
---
|
||||
|
||||
# Překlady
|
||||
|
||||
| Česky | Anglicky |
|
||||
|---|---|
|
||||
| Fyzikální veličina má číselnou hodnotu a jednotku. | A physical quantity has a value and a unit. |
|
||||
```
|
||||
|
||||
Český text musí v tabulce sedět přesně (včetně interpunkce). Pole `id`
|
||||
a `puvodni` do `.en.md` nepatří.
|
||||
|
||||
## Společná pravidla zápisu
|
||||
|
||||
Hlavička mezi `---` obsahuje pole `klíč: hodnota`. Pak následují oddíly `#`,
|
||||
položky `##` a podle potřeby `###`.
|
||||
|
||||
| Zápis | Význam |
|
||||
|---|---|
|
||||
| `- text` | odrážka; v kvízu možnost |
|
||||
| `- [x] text` | správná možnost |
|
||||
| `1. text` | číslovaná položka (např. části děje) |
|
||||
| `> text` | vysvětlení, nápověda, tip nebo význam (podle oddílu) |
|
||||
| `= odpověď` | správná odpověď; více variant odděluje `\|`: `= hasn't\|has not` |
|
||||
| `[odpověď]` | mezera k doplnění uvnitř věty: `Ich [bin\|heiße] Anna.` |
|
||||
| `\| a \| b \|` | tabulka; v buňce se píše `\|` jako `\\|` a nový řádek jako `\n` |
|
||||
| `<!-- … -->` | poznámka, do aplikace se nedostane |
|
||||
|
||||
Hranaté závorky, které nemají být mezerou, se píšou `\[` a `\]`. Řádek, který
|
||||
by jinak vypadal jako značka (začíná `-`, `>`, `=` …), se uvede zpětným
|
||||
lomítkem: `\- tohle je obyčejný text`.
|
||||
|
||||
## ID a postup žáků
|
||||
|
||||
```md
|
||||
id: fyzika-1-fyzikalni-veliciny
|
||||
puvodni: fyz.1
|
||||
```
|
||||
|
||||
- **`id`** je trvalé jméno lekce. Pod ním se ukládá, co má žák hotové. Musí být
|
||||
v celém obsahu jedinečné. **Po vydání ho neměňte**, jinak se žákům postup
|
||||
v lekci ztratí. Název souboru, číslo pořadí i nadpis měnit lze.
|
||||
- **`puvodni`** je adresa lekce ze starších verzí aplikace. Podle ní se při
|
||||
prvním spuštění nové verze převede starý postup. Neměňte ji a u nových lekcí
|
||||
ji nepište.
|
||||
|
||||
Nová lekce: zkopírujte podobný soubor, dejte mu číslo podle pořadí, nové `id`
|
||||
a smažte `puvodni`.
|
||||
|
||||
## Běžná lekce
|
||||
|
||||
Sítě, hardware, občanka, literatura, chemie, biologie, fyzika.
|
||||
|
||||
```md
|
||||
---
|
||||
id: fyzika-1-fyzikalni-veliciny
|
||||
nazev: Fyzikální veličiny
|
||||
popis: SI, skalár a vektor, chyba měření.
|
||||
nazev_cviceni: Kvíz: veličiny
|
||||
nadpis_kvizu: Ověřte si jednotky a chyby
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## Veličina a jednotka
|
||||
*Měření*
|
||||
|
||||
- Fyzikální veličina má číselnou hodnotu a jednotku.
|
||||
- Soustava SI má sedm základních jednotek.
|
||||
|
||||
> Tip: základní jednotka hmotnosti je kilogram, ne gram.
|
||||
|
||||
# Kvíz
|
||||
|
||||
## Která jednotka je základní jednotka SI pro hmotnost?
|
||||
- Gram
|
||||
- [x] Kilogram
|
||||
- Newton
|
||||
> Gram je tisícina kilogramu. Newton je jednotka síly.
|
||||
```
|
||||
|
||||
Každá `##` ve výkladu je jeden snímek. Řádek `*Měření*` je štítek snímku,
|
||||
počítadlo „1 / 3“ doplní aplikace sama.
|
||||
|
||||
V první lekci sítí je navíc oddíl `# Úlohy na podsítě`: `## Úloha N` se
|
||||
zadáním, `### Řešení` s textem řešení a `### Kontrola` s tabulkou
|
||||
`Prefix | Síť | Broadcast | První adresa | Poslední adresa`.
|
||||
|
||||
## Matematika
|
||||
|
||||
Stejná hlavička a `# Výklad` jako běžná lekce, místo kvízu `# Příklady`:
|
||||
|
||||
```md
|
||||
# Příklady
|
||||
|
||||
## Jaký je největší společný dělitel čísel 24 a 36?
|
||||
= num:12
|
||||
> Společní dělitelé jsou 1, 2, 3, 4, 6 a 12.
|
||||
```
|
||||
|
||||
Druhy odpovědí:
|
||||
|
||||
| Odpověď | Kdy je správně |
|
||||
|---|---|
|
||||
| `num:12`, `num:1/2` | číslo nebo výraz (zlomek, odmocnina, π); stačí stejná hodnota v jakémkoli tvaru |
|
||||
| `set:2;3` | všechna čísla v libovolném pořadí |
|
||||
| `pair:2;-1` | čísla v daném pořadí (např. x; y) |
|
||||
| `word:ano\|yes` | jedno ze slov |
|
||||
| `square:2,3;5,3`, `right:…`, `mid:…`, `para:…`, `points:1,4;fix:1,1` | rýsování do mřížky 10 × 8; `fix:` jsou body předem zakreslené |
|
||||
|
||||
## Angličtina a němčina po ročnících
|
||||
|
||||
```md
|
||||
---
|
||||
id: anglictina-1-ja-a-moje-rodina
|
||||
nazev: Já a moje rodina
|
||||
popis: Sloveso be, have got. Doplňování a kvíz.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
(snímky jako u běžné lekce)
|
||||
|
||||
# Čtení
|
||||
Text článku jedním odstavcem.
|
||||
|
||||
## The bus is ___ than the train.
|
||||
- faster
|
||||
- [x] slower
|
||||
> cheaper, but slower.
|
||||
|
||||
# Poslech
|
||||
Přepis nahrávky, pak otázky stejně jako u čtení.
|
||||
|
||||
# Doplňování
|
||||
|
||||
## My sister ___ sixteen.
|
||||
= is
|
||||
> Věk: be, ne have.
|
||||
|
||||
# Psaní
|
||||
Zadání.
|
||||
|
||||
## Vzorová odpověď
|
||||
Text.
|
||||
|
||||
## Musí obsahovat
|
||||
- would
|
||||
- because
|
||||
|
||||
## Minimum slov
|
||||
35
|
||||
|
||||
# Kvíz
|
||||
(jako u běžné lekce)
|
||||
```
|
||||
|
||||
Oddíly, které lekce nepotřebuje, se vynechají.
|
||||
|
||||
## Mluvnice (`cestina/mluvnice`)
|
||||
|
||||
Hlavička: `id`, `typ`, `zkratka` (krátký název na mapě), `nazev`, `popis`,
|
||||
volitelně `poznamka`. Úlohy jsou v oddílu `# Úlohy`, podle typu:
|
||||
|
||||
```md
|
||||
typ: doplnovani
|
||||
|
||||
## Stará bab_čka sed_la na lav_čce.
|
||||
- i/í/y/ý = babička
|
||||
- i/í/y/ý = seděla|sedla
|
||||
> babička, seděla, lavičce
|
||||
```
|
||||
|
||||
Každá odrážka je jedno políčko: vlevo nápověda, za `=` správné odpovědi.
|
||||
|
||||
```md
|
||||
typ: vyber
|
||||
|
||||
## Narodil se v ______ v malé vesnici.
|
||||
- [x] Čechách
|
||||
- čechách
|
||||
```
|
||||
|
||||
```md
|
||||
typ: reseni
|
||||
|
||||
## napsali
|
||||
= na- / ps- / -a- / -li
|
||||
```
|
||||
|
||||
U `reseni` si žák řešení jen odkryje.
|
||||
|
||||
## Četba (`cestina/cetba`)
|
||||
|
||||
```md
|
||||
---
|
||||
id: 1984
|
||||
autor: George Orwell
|
||||
nazev: 1984
|
||||
zanr: Próza
|
||||
preklad: Šimečková
|
||||
---
|
||||
|
||||
# O knize
|
||||
- Autor: George Orwell
|
||||
|
||||
# Postavy
|
||||
- Winston Smith – hlavní hrdina.
|
||||
|
||||
# Kvíz
|
||||
## Kdo je hlavní hrdina?
|
||||
- [x] Winston Smith
|
||||
- O'Brien
|
||||
> Vysvětlení.
|
||||
|
||||
# Děj
|
||||
## Přetáhněte části příběhu do správného pořadí:
|
||||
1. První část děje.
|
||||
2. Druhá část děje.
|
||||
> Volitelně význam celého děje.
|
||||
```
|
||||
|
||||
Všechny oddíly kromě `Kvíz` a `Děj` jsou poznámky ke knize, zobrazí se
|
||||
v uvedeném pořadí. Kvíz i děj jsou nepovinné. Volitelná pole v hlavičce:
|
||||
`popis`, `kviz_nadpis`, `kviz_popis`, `dej_nadpis`, `dej_popis` (jinak se
|
||||
použijí obecné texty) a `stranka`/`plna` pro knihy s vlastní obrazovkou.
|
||||
|
||||
## Učebnice němčiny (`nemcina/ucebnice`)
|
||||
|
||||
Každá kapitola je složka `NN-nazev/` se souborem `_lekce.md`:
|
||||
|
||||
```md
|
||||
---
|
||||
id: ucebnice-1
|
||||
nazev: Neue Freunde
|
||||
popis: Vyberte cvičení a dokončete je.
|
||||
zamceno: ano
|
||||
---
|
||||
```
|
||||
|
||||
(`zamceno: ano` kapitolu v aplikaci zamkne.) V kapitole jsou cvičení
|
||||
`NN-nazev.md` a slovíčka `slovicka.md`. Každé cvičení má v hlavičce `typ`.
|
||||
Nejčastější typy:
|
||||
|
||||
| Typ | Oddíly |
|
||||
|---|---|
|
||||
| `choice` | `# Otázky` jako kvíz |
|
||||
| `typed` | `# Úlohy`: tabulka `Zadání \| Odpověď \| Význam` |
|
||||
| `verb`, `fill` | `# Nabídka` (odrážky slov), `# Úlohy`: tabulka s větami a mezerami `[…]` |
|
||||
| `dialog` | `# Nabídka`, `# Rozhovory` s `## názvem` a tabulkou `Kdo \| Věta` |
|
||||
| `assign` | `# Skupiny` (odrážky), `# Slova`: tabulka `Obrázek \| Slovo \| Skupina` |
|
||||
| `free` | `# Otázky`: tabulka `Otázka \| Překlad otázky \| Vzorová odpověď \| Překlad odpovědi` |
|
||||
| `vocab` | `# Slovíčka`, `## Strana N` a tabulka `Německy \| Odpověď \| Význam` |
|
||||
|
||||
Další typy (`assembly`, `number`, `count`, `seq`, `verbclue`, `profile`,
|
||||
`hangman`, `ordne`, `letters`, `ex2`, `table`, `kw` …) mají vždy aspoň jeden
|
||||
vzor v existujících kapitolách; nejjednodušší je zkopírovat ho. Oddíl
|
||||
`# Překlad` obsahuje české překlady položek ve stejném pořadí.
|
||||
|
||||
Volitelná pole hlavičky cvičení: `tip`, `ukazka` (vzorový příklad),
|
||||
`vyznam_predem`, `preklad_predem`, `odhalit_nemcinu`, `ukazat_nemcinu`
|
||||
(`ano`/`ne`) a `poznamka_k_odpovedim`.
|
||||
|
||||
## Texty rozhraní a předměty
|
||||
|
||||
`aplikace/texty.md` obsahuje tabulky `Klíč | Česky | Anglicky`. Klíč používá
|
||||
kód aplikace, neměňte ho; texty ve sloupcích měnit lze. `%s` a `%d` jsou místa,
|
||||
kam aplikace doplní hodnotu.
|
||||
|
||||
`aplikace/predmety.md` má tabulku
|
||||
`Klíč | Česky | Anglicky | Ikona | Cíl | Otevřeno`. `Cíl` je obrazovka, která se
|
||||
otevře, `Otevřeno: ne` dlaždici zamkne.
|
||||
4
content/anglictina/1-rocnik/01-ja-a-moje-rodina.en.md
Normal file
4
content/anglictina/1-rocnik/01-ja-a-moje-rodina.en.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
nazev: Me and my family
|
||||
popis: The verb be, have got and possessives. Gaps and a quiz.
|
||||
---
|
||||
82
content/anglictina/1-rocnik/01-ja-a-moje-rodina.md
Normal file
82
content/anglictina/1-rocnik/01-ja-a-moje-rodina.md
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
---
|
||||
id: anglictina-1-ja-a-moje-rodina
|
||||
puvodni: en.1.1
|
||||
nazev: Já a moje rodina
|
||||
popis: Sloveso be, have got a přivlastňovací zájmena. Doplňování a kvíz.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## Kdo jsem
|
||||
*Be*
|
||||
|
||||
- I am, you are, he/she/it is, we/you/they are.
|
||||
- Zápor a otázka: She isn't tall. Are you from Prague?
|
||||
- Věk, povolání i nálada: I am 16. My mum is a nurse. I am fine.
|
||||
- Přivlastňovací zájmena: my, your, his, her, its, our, their.
|
||||
|
||||
> Tip: věk se říká slovesem be. „She has 16 years“ je čechismus.
|
||||
|
||||
## Co mám
|
||||
*Have got*
|
||||
|
||||
- I've got a younger brother. She hasn't got a pet.
|
||||
- Have you got any cousins? — Yes, I have. / No, I haven't.
|
||||
- V americké angličtině stačí have: I have a brother.
|
||||
- Rodina: parents, siblings, only child, get on well, look like.
|
||||
|
||||
> Tip: have got je britská hovorová vazba pro vlastnictví, ne pro věk.
|
||||
|
||||
|
||||
# Doplňování
|
||||
|
||||
## My sister ___ sixteen.
|
||||
= is
|
||||
> Věk: be, ne have.
|
||||
|
||||
## ___ you got a bike?
|
||||
= Have
|
||||
> Otázka s have got.
|
||||
|
||||
## This is ___ grandmother. She lives with us.
|
||||
= our
|
||||
> Přivlastňovací zájmeno.
|
||||
|
||||
## They ___ not from Brno. They are from Olomouc.
|
||||
= are
|
||||
> They + are.
|
||||
|
||||
## He ___ got a dog, but he has got two cats.
|
||||
= hasn't|has not
|
||||
> Zápor have got.
|
||||
|
||||
|
||||
# Kvíz
|
||||
|
||||
## Which sentence is correct?
|
||||
- She has 16 years.
|
||||
- [x] She is 16 years old.
|
||||
- She is 16 years.
|
||||
- She has 16 years old.
|
||||
> Věk: be + years old.
|
||||
|
||||
## I ___ two cousins and one aunt.
|
||||
- am
|
||||
- [x] have got
|
||||
- has got
|
||||
- is
|
||||
> Vlastnictví v 1. osobě: have got.
|
||||
|
||||
## Eva is my sister. ___ room is next to mine.
|
||||
- She
|
||||
- [x] Her
|
||||
- His
|
||||
- Hers
|
||||
> Před podstatným jménem je her, ne she.
|
||||
|
||||
## ___ your parents at home?
|
||||
- Is
|
||||
- [x] Are
|
||||
- Have
|
||||
- Do
|
||||
> Parents je množné číslo: Are.
|
||||
4
content/anglictina/1-rocnik/02-skolni-den.en.md
Normal file
4
content/anglictina/1-rocnik/02-skolni-den.en.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
nazev: A school day
|
||||
popis: The present simple. Reading and gaps.
|
||||
---
|
||||
80
content/anglictina/1-rocnik/02-skolni-den.md
Normal file
80
content/anglictina/1-rocnik/02-skolni-den.md
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
---
|
||||
id: anglictina-1-skolni-den
|
||||
puvodni: en.1.2
|
||||
nazev: Školní den
|
||||
popis: Přítomný čas prostý. Čtení a doplňování.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## Co dělám pravidelně
|
||||
*Present simple*
|
||||
|
||||
- I get up at seven. He gets up at six.
|
||||
- Zápor: I don't like maths. She doesn't eat meat.
|
||||
- Otázka: Do you walk to school? Does she play the piano?
|
||||
- Příslovce četnosti stojí před slovesem: I usually walk. She is always late.
|
||||
|
||||
> Tip: ve 3. osobě jednotného čísla přibývá -s/-es: she watches.
|
||||
|
||||
## Rozvrh a přestávky
|
||||
*Škola*
|
||||
|
||||
- lessons, break, canteen, homework, timetable, subject.
|
||||
- Čas: at eight, at half past twelve, in the morning, on Monday.
|
||||
- because vysvětluje důvod: I like biology because we do experiments.
|
||||
- never / sometimes / often / usually / always.
|
||||
|
||||
> Tip: předmět ve škole je bez členu, když mluvíme obecně: I like biology.
|
||||
|
||||
|
||||
# Čtení
|
||||
|
||||
My school day starts early. I get up at half past six, have breakfast and catch the tram. Lessons begin at eight. On Monday we have maths, English and biology. I like biology because we do experiments, but I don't like maths. We have lunch at half past twelve in the canteen. After school I do my homework or meet friends. I never go to bed after ten on a school night.
|
||||
|
||||
## What time do lessons begin?
|
||||
- At half past six
|
||||
- [x] At eight
|
||||
- At half past twelve
|
||||
- At ten
|
||||
> Lessons begin at eight.
|
||||
|
||||
## Why does the writer like biology?
|
||||
- Because it is easy
|
||||
- [x] Because they do experiments
|
||||
- Because the teacher is funny
|
||||
- Because there is no homework
|
||||
> because we do experiments.
|
||||
|
||||
## Where do they have lunch?
|
||||
- At home
|
||||
- On the tram
|
||||
- [x] In the canteen
|
||||
- In the park
|
||||
> in the canteen.
|
||||
|
||||
## On a school night the writer goes to bed…
|
||||
- after eleven
|
||||
- at midnight
|
||||
- [x] never after ten
|
||||
- before six
|
||||
> never go to bed after ten.
|
||||
|
||||
|
||||
# Doplňování
|
||||
|
||||
## She ___ (watch) a series every evening.
|
||||
= watches
|
||||
> 3. osoba: watches.
|
||||
|
||||
## We ___ (not go) to school on Sunday.
|
||||
= don't go|do not go
|
||||
> Zápor v 1. osobě množného čísla.
|
||||
|
||||
## ___ he play football on Fridays?
|
||||
= Does
|
||||
> Otázka ve 3. osobě.
|
||||
|
||||
## I usually ___ (get) up at seven.
|
||||
= get
|
||||
> Usually nemění tvar slovesa.
|
||||
4
content/anglictina/1-rocnik/03-vikend-ve-meste.en.md
Normal file
4
content/anglictina/1-rocnik/03-vikend-ve-meste.en.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
nazev: A weekend in town
|
||||
popis: The present continuous for arrangements. Listening.
|
||||
---
|
||||
80
content/anglictina/1-rocnik/03-vikend-ve-meste.md
Normal file
80
content/anglictina/1-rocnik/03-vikend-ve-meste.md
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
---
|
||||
id: anglictina-1-vikend-ve-meste
|
||||
puvodni: en.1.3
|
||||
nazev: Víkend ve městě
|
||||
popis: Přítomný čas průběhový pro domluvené plány. Poslech.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## Co právě probíhá a co je domluvené
|
||||
*Continuous*
|
||||
|
||||
- Tvar: am/is/are + -ing. I'm waiting. She isn't coming.
|
||||
- Teď: Look, it is raining. Please be quiet, the baby is sleeping.
|
||||
- Blízký plán: We're having lunch on Saturday. I'm playing volleyball.
|
||||
- Stavová slovesa obvykle průběhový čas nemají: I know, I like, I want.
|
||||
|
||||
> Tip: I'm meeting Eva at ten je plán, ne jen „potkávám“.
|
||||
|
||||
## Jak poslouchat vzkaz
|
||||
*Poslech*
|
||||
|
||||
- Chyťte jména, časy a místa. Ta se v otázkách opakují.
|
||||
- Nenechte se zastavit jedním slovem. Poslouchejte dál.
|
||||
- I'm meeting, we're going, I'm playing jsou v tomhle vzkazu klíčové.
|
||||
- Na konci bývá prosba: Call me back.
|
||||
|
||||
> Tip: nejdřív si přečtěte otázky, pak teprve pusťte nahrávku.
|
||||
|
||||
|
||||
# Poslech
|
||||
|
||||
Hi Tom, it's Anna. Are you free on Saturday? I'm meeting Eva at the station at ten. We're going to the market first, and then we're having lunch in that new café by the river. In the afternoon I'm playing volleyball with my class in the park. Do you want to come to the café? Call me back tonight.
|
||||
|
||||
## Who is Anna meeting?
|
||||
- Tom
|
||||
- [x] Eva
|
||||
- Her class
|
||||
- Her mum
|
||||
> I'm meeting Eva.
|
||||
|
||||
## Where are they meeting?
|
||||
- At school
|
||||
- [x] At the station
|
||||
- In the park
|
||||
- By the river only
|
||||
> at the station at ten.
|
||||
|
||||
## What is Anna doing in the afternoon?
|
||||
- Going to the market
|
||||
- Having lunch
|
||||
- [x] Playing volleyball
|
||||
- Sleeping
|
||||
> I'm playing volleyball.
|
||||
|
||||
## What should Tom do?
|
||||
- Buy tickets
|
||||
- [x] Call her back
|
||||
- Come to school
|
||||
- Bring a map
|
||||
> Call me back tonight.
|
||||
|
||||
|
||||
# Doplňování
|
||||
|
||||
## Listen, the phone ___.
|
||||
= is ringing
|
||||
> Děje se to teď.
|
||||
|
||||
## We ___ lunch with Eva on Saturday.
|
||||
= are having|'re having
|
||||
> Domluvený plán.
|
||||
|
||||
## I ___ not coming to the match.
|
||||
= am|'m
|
||||
> Zápor: am not.
|
||||
|
||||
## She ___ volleyball this afternoon.
|
||||
= is playing|'s playing
|
||||
> Domluvená aktivita.
|
||||
10
content/anglictina/1-rocnik/04-muj-pokoj.en.md
Normal file
10
content/anglictina/1-rocnik/04-muj-pokoj.en.md
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
nazev: My room
|
||||
popis: There is / there are and prepositions. A short description and a quiz.
|
||||
---
|
||||
|
||||
# Překlady
|
||||
|
||||
| Česky | Anglicky |
|
||||
|---|---|
|
||||
| on | he |
|
||||
78
content/anglictina/1-rocnik/04-muj-pokoj.md
Normal file
78
content/anglictina/1-rocnik/04-muj-pokoj.md
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
---
|
||||
id: anglictina-1-muj-pokoj
|
||||
puvodni: en.1.4
|
||||
nazev: Můj pokoj
|
||||
popis: There is / there are a předložky místa. Krátký popis a kvíz.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## Co v pokoji je
|
||||
*There is*
|
||||
|
||||
- There is a desk under the window. There are two chairs.
|
||||
- Zápor: There isn't a TV. There aren't any posters.
|
||||
- Otázka: Is there a lamp? Are there any books?
|
||||
- Předložky: in, on, under, next to, between, behind, in front of.
|
||||
|
||||
> Tip: there is pro jedno, there are pro více. There je formální podmět.
|
||||
|
||||
## Popis místa
|
||||
*Psaní*
|
||||
|
||||
- Začněte velikostí a světlem: small but bright.
|
||||
- Každá věta ať má věc a místo: The bag is under the chair.
|
||||
- Střídejte there is a there are, ať text není seznam.
|
||||
- Na konci jedna osobní věta: I like it because it is quiet.
|
||||
|
||||
> Tip: jděte od velkého k malému, od dveří k oknu.
|
||||
|
||||
|
||||
# Psaní
|
||||
|
||||
Describe your room in at least 30 words. Say what is in it and where things are. Use on and a piece of furniture such as a bed, and mention a window.
|
||||
|
||||
## Vzorová odpověď
|
||||
|
||||
My room is small but bright. There is a bed next to the window and a wooden desk under a shelf. My books are on the desk and my school bag is under the chair. There are two posters on the wall. I like the room because it is quiet in the evening.
|
||||
|
||||
## Musí obsahovat
|
||||
|
||||
- bed
|
||||
- window
|
||||
- on
|
||||
|
||||
## Minimum slov
|
||||
|
||||
30
|
||||
|
||||
|
||||
# Kvíz
|
||||
|
||||
## The lamp is ___ the desk.
|
||||
- under
|
||||
- [x] on
|
||||
- between
|
||||
- at
|
||||
> Lampa stojí na desce: on.
|
||||
|
||||
## There ___ a big window.
|
||||
- are
|
||||
- [x] is
|
||||
- be
|
||||
- have
|
||||
> Jedno okno: there is.
|
||||
|
||||
## There ___ two posters on the wall.
|
||||
- is
|
||||
- [x] are
|
||||
- has
|
||||
- been
|
||||
> Dva plakáty: there are.
|
||||
|
||||
## The cat is sleeping ___ the bed.
|
||||
- [x] under
|
||||
- next
|
||||
- between to
|
||||
- at to
|
||||
> Pod postelí: under the bed.
|
||||
4
content/anglictina/1-rocnik/05-na-trhu.en.md
Normal file
4
content/anglictina/1-rocnik/05-na-trhu.en.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
nazev: At the market
|
||||
popis: Countability, some and any, how much and how many. Reading and gaps.
|
||||
---
|
||||
80
content/anglictina/1-rocnik/05-na-trhu.md
Normal file
80
content/anglictina/1-rocnik/05-na-trhu.md
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
---
|
||||
id: anglictina-1-na-trhu
|
||||
puvodni: en.1.5
|
||||
nazev: Na trhu
|
||||
popis: Počitatelnost, some a any, how much a how many. Čtení a doplňování.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## Počitatelné a nepočitatelné
|
||||
*Množství*
|
||||
|
||||
- Počitatelné: an apple, some apples. Nepočitatelné: some bread, some milk.
|
||||
- How many apples? How much milk?
|
||||
- a little milk, a few rolls, a lot of cheese.
|
||||
- V obchodě: How much is it? It's four euros a kilo.
|
||||
|
||||
> Tip: some v kladné větě, any v otázce a záporu. Nabídka je výjimka: Would you like some tea?
|
||||
|
||||
## Zdvořilá žádost
|
||||
*Dialog*
|
||||
|
||||
- Have you got any bread? — Sorry, we haven't got any today.
|
||||
- We've got some rolls instead.
|
||||
- How many would you like? — Six, please.
|
||||
- Anything else? — No, that's all. Thank you.
|
||||
|
||||
> Tip: Can I have… a I'd like… zní v obchodě přirozeně.
|
||||
|
||||
|
||||
# Čtení
|
||||
|
||||
On Saturday morning the market by the river is busy. A woman asks, "How much is this cheese?" The seller says, "It's four euros a kilo." Then she asks, "Have you got any bread?" He answers, "Sorry, we haven't got any bread today, but we've got some fresh rolls." "How many rolls do you want?" "Six, please, and a little milk." She also buys a few apples. "Anything else?" "No, that's all."
|
||||
|
||||
## How much is the cheese?
|
||||
- Four euros a piece
|
||||
- [x] Four euros a kilo
|
||||
- Six euros
|
||||
- A little
|
||||
> four euros a kilo.
|
||||
|
||||
## What hasn't the seller got?
|
||||
- Rolls
|
||||
- Milk
|
||||
- [x] Bread
|
||||
- Apples
|
||||
> haven't got any bread today.
|
||||
|
||||
## How many rolls does the woman want?
|
||||
- Four
|
||||
- A few
|
||||
- [x] Six
|
||||
- A kilo
|
||||
> Six, please.
|
||||
|
||||
## Which phrase is an offer of more shopping?
|
||||
- That's all.
|
||||
- [x] Anything else?
|
||||
- How much is it?
|
||||
- A little milk.
|
||||
> Anything else? nabízí další nákup.
|
||||
|
||||
|
||||
# Doplňování
|
||||
|
||||
## We haven't got ___ bread today.
|
||||
= any
|
||||
> Zápor: any.
|
||||
|
||||
## There are ___ rolls in the bag.
|
||||
= some
|
||||
> Kladná věta: some.
|
||||
|
||||
## How ___ apples do you want?
|
||||
= many
|
||||
> Apples se dají počítat.
|
||||
|
||||
## How ___ milk is in the bottle?
|
||||
= much
|
||||
> Milk je nepočitatelné.
|
||||
4
content/anglictina/1-rocnik/06-minule-leto.en.md
Normal file
4
content/anglictina/1-rocnik/06-minule-leto.en.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
nazev: Last summer
|
||||
popis: The past simple, regular and irregular verbs. Listening and a quiz.
|
||||
---
|
||||
92
content/anglictina/1-rocnik/06-minule-leto.md
Normal file
92
content/anglictina/1-rocnik/06-minule-leto.md
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
---
|
||||
id: anglictina-1-minule-leto
|
||||
puvodni: en.1.6
|
||||
nazev: Minulé léto
|
||||
popis: Minulý čas prostý, pravidelná i nepravidelná slovesa. Poslech a kvíz.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## Co se stalo a je dokončené
|
||||
*Past simple*
|
||||
|
||||
- Pravidelná: play → played, visit → visited, try → tried, stop → stopped.
|
||||
- Nepravidelná: go → went, take → took, swim → swam, buy → bought.
|
||||
- I didn't stay in a hotel. Did you visit the island?
|
||||
- Signály: yesterday, last July, ago, in 2019, when I was ten.
|
||||
|
||||
> Tip: zápor a otázka používají did, sloveso zůstává v základním tvaru.
|
||||
|
||||
## Jedna událost za druhou
|
||||
*Vyprávění*
|
||||
|
||||
- Začněte kdy a kam: Last July we went to Croatia.
|
||||
- Pak doprava, počasí a jedna konkrétní příhoda.
|
||||
- Nepravidelná slovesa se neučí po jednom u testu, ale ve větě.
|
||||
- Na konci dojem: It was the best week of the year.
|
||||
|
||||
> Tip: then, after that a one day drží příběh pohromadě.
|
||||
|
||||
|
||||
# Poslech
|
||||
|
||||
Last July we went to Croatia. We travelled by train and then by bus because the flight was too expensive. The weather was hot every day. I swam in the morning and my brother tried surfing. He fell off the board a lot, but he loved it. One day we visited a small island. We didn't stay in a hotel. We stayed with our uncle near the beach. I took hundreds of photos.
|
||||
|
||||
## Where did they go?
|
||||
- Italy
|
||||
- [x] Croatia
|
||||
- Greece
|
||||
- Spain
|
||||
> went to Croatia.
|
||||
|
||||
## How did they travel?
|
||||
- By plane
|
||||
- [x] By train and bus
|
||||
- By car
|
||||
- By ferry only
|
||||
> by train and then by bus.
|
||||
|
||||
## What did the brother try?
|
||||
- Swimming
|
||||
- [x] Surfing
|
||||
- Cooking
|
||||
- Driving
|
||||
> tried surfing.
|
||||
|
||||
## Where did they stay?
|
||||
- In a hotel
|
||||
- On the island
|
||||
- [x] With their uncle
|
||||
- On the train
|
||||
> stayed with our uncle.
|
||||
|
||||
|
||||
# Kvíz
|
||||
|
||||
## go → ___
|
||||
- goed
|
||||
- [x] went
|
||||
- gone
|
||||
- going
|
||||
> go, went, gone.
|
||||
|
||||
## I ___ a lot of photos.
|
||||
- taked
|
||||
- [x] took
|
||||
- taken
|
||||
- token
|
||||
> take, took, taken.
|
||||
|
||||
## She ___ in the sea every morning.
|
||||
- swimmed
|
||||
- [x] swam
|
||||
- swum
|
||||
- swims
|
||||
> Minulý tvar swim je swam.
|
||||
|
||||
## We ___ stay in a hotel.
|
||||
- don't
|
||||
- [x] didn't
|
||||
- wasn't
|
||||
- haven't
|
||||
> Zápor minulého času: didn't + sloveso.
|
||||
4
content/anglictina/1-rocnik/07-zprava-kamaradovi.en.md
Normal file
4
content/anglictina/1-rocnik/07-zprava-kamaradovi.en.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
nazev: A message to a friend
|
||||
popis: Will and going to. A short informal message and gaps.
|
||||
---
|
||||
66
content/anglictina/1-rocnik/07-zprava-kamaradovi.md
Normal file
66
content/anglictina/1-rocnik/07-zprava-kamaradovi.md
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
---
|
||||
id: anglictina-1-zprava-kamaradovi
|
||||
puvodni: en.1.7
|
||||
nazev: Zpráva kamarádovi
|
||||
popis: Will a going to. Krátká neformální zpráva a doplňování.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## Plán, nebo rozhodnutí teď
|
||||
*Budoucnost*
|
||||
|
||||
- We've got tickets. We're going to leave at six. To je plán.
|
||||
- Look at those clouds. It's going to rain. To je důkaz.
|
||||
- The phone is ringing. I'll answer it. Rozhodnutí teď.
|
||||
- I think I'll stay at home. Will jako názor, ne jistý plán.
|
||||
|
||||
> Tip: going to má důkaz nebo plán. Will je rozhodnutí v tu chvíli nebo odhad.
|
||||
|
||||
## Neformální styl
|
||||
*Zpráva*
|
||||
|
||||
- Začněte Hi a jménem, ne Dear Sir.
|
||||
- Napište kdy, co a proč. Jedna věta s because stačí.
|
||||
- I'm going to… je v takové zprávě přirozené.
|
||||
- Konec: Want to come? Write back.
|
||||
|
||||
> Tip: Hi, kontraktované tvary a na konci otázka kamarádovi.
|
||||
|
||||
|
||||
# Doplňování
|
||||
|
||||
## Look at those clouds. It ___ rain.
|
||||
= is going to|'s going to
|
||||
> Je vidět důkaz: going to.
|
||||
|
||||
## I think I ___ stay at home tonight.
|
||||
= will|'ll
|
||||
> Názor v tu chvíli: will.
|
||||
|
||||
## The tickets are in my bag. We ___ leave at six.
|
||||
= are going to|'re going to
|
||||
> Už je to domluvené.
|
||||
|
||||
## Don't worry. I ___ help you with the bags.
|
||||
= will|'ll
|
||||
> Rozhodnutí teď: will.
|
||||
|
||||
|
||||
# Psaní
|
||||
|
||||
Write a short message to a friend about next weekend. Use at least 25 words. Say what you are going to do, mention the weekend, and give a reason with because.
|
||||
|
||||
## Vzorová odpověď
|
||||
|
||||
Hi Lena, next weekend I am going to visit my cousins in Pilsen. We are going to the cinema on Saturday because a new film is on. On Sunday we are going to cook lunch together. Do you want to come with me? Write back soon.
|
||||
|
||||
## Musí obsahovat
|
||||
|
||||
- going
|
||||
- weekend
|
||||
- because
|
||||
|
||||
## Minimum slov
|
||||
|
||||
25
|
||||
4
content/anglictina/1-rocnik/08-test-1-rocniku.en.md
Normal file
4
content/anglictina/1-rocnik/08-test-1-rocniku.en.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
nazev: Year 1 test
|
||||
popis: Reading, listening, grammar and a short piece of writing. Level A2.
|
||||
---
|
||||
129
content/anglictina/1-rocnik/08-test-1-rocniku.md
Normal file
129
content/anglictina/1-rocnik/08-test-1-rocniku.md
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
---
|
||||
id: anglictina-1-test-1-rocniku
|
||||
puvodni: en.1.8
|
||||
nazev: Test 1. ročníku
|
||||
popis: Čtení, poslech, gramatika a krátké psaní. Úroveň A2.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## A2 v jedné sadě
|
||||
*Co test bere*
|
||||
|
||||
- Čtení: najděte v textu čas, místo a důvod, nehádejte z jednoho slova.
|
||||
- Poslech: jména a čísla si poznamenejte hned.
|
||||
- Gramatika: be, přítomné časy, some/any, minulý čas, will a going to.
|
||||
- Psaní: krátký souvislý text, ne jen odrážky.
|
||||
|
||||
> Tip: nejdřív otázky, pak text nebo nahrávku. U psaní počítejte slova.
|
||||
|
||||
## Nejčastější čechismy
|
||||
*Jak opravovat*
|
||||
|
||||
- I am 16, ne I have 16 years.
|
||||
- She likes, ne she like.
|
||||
- Did you went je špatně. Did you go.
|
||||
- There is a book, ne It is a book on the table, když věc uvádíte.
|
||||
|
||||
> Tip: po kontrole si přečtěte nápovědy, i když je věta správně.
|
||||
|
||||
|
||||
# Čtení
|
||||
|
||||
Klara lives in a flat with her parents and a small dog. On weekdays she walks to school because it is only ten minutes away. She loves art. Last Friday her class visited a gallery and she bought a poster. This Saturday she is meeting her cousin at the station. They are going to a concert in the evening.
|
||||
|
||||
## How does Klara get to school?
|
||||
- By tram
|
||||
- [x] She walks
|
||||
- Her dad drives
|
||||
- By train
|
||||
> she walks to school.
|
||||
|
||||
## What did she buy at the gallery?
|
||||
- A dog
|
||||
- A ticket
|
||||
- [x] A poster
|
||||
- A flat
|
||||
> she bought a poster.
|
||||
|
||||
## Who is she meeting on Saturday?
|
||||
- Her parents
|
||||
- Her art teacher
|
||||
- [x] Her cousin
|
||||
- The singer
|
||||
> meeting her cousin.
|
||||
|
||||
|
||||
# Poslech
|
||||
|
||||
Hi, it's Marek. I missed you after school. I'm at the sports centre. The match starts at four, not at three, so don't hurry. Can you bring my blue jacket? It's on the chair in the kitchen. See you there.
|
||||
|
||||
## Where is Marek?
|
||||
- At school
|
||||
- [x] At the sports centre
|
||||
- In the kitchen
|
||||
- On the tram
|
||||
> at the sports centre.
|
||||
|
||||
## What time does the match start?
|
||||
- At three
|
||||
- [x] At four
|
||||
- At five
|
||||
- At ten
|
||||
> starts at four, not at three.
|
||||
|
||||
## What should his friend bring?
|
||||
- A ticket
|
||||
- [x] A blue jacket
|
||||
- Lunch
|
||||
- A poster
|
||||
> bring my blue jacket.
|
||||
|
||||
|
||||
# Psaní
|
||||
|
||||
Write at least 30 words about your family. Use is or are, and the words family and because.
|
||||
|
||||
## Vzorová odpověď
|
||||
|
||||
My family is not very big. I live with my parents and my younger sister. She is twelve and she is funny. We get on well because we both like films. My dad is a driver and my mum is a nurse. I am happy at home.
|
||||
|
||||
## Musí obsahovat
|
||||
|
||||
- family
|
||||
- because
|
||||
|
||||
## Minimum slov
|
||||
|
||||
30
|
||||
|
||||
|
||||
# Kvíz
|
||||
|
||||
## She ___ coffee.
|
||||
- don't like
|
||||
- [x] doesn't like
|
||||
- not like
|
||||
- isn't like
|
||||
> 3. osoba: doesn't like.
|
||||
|
||||
## There ___ any milk.
|
||||
- [x] isn't
|
||||
- aren't
|
||||
- hasn't
|
||||
- don't
|
||||
> Milk je jednotné: there isn't.
|
||||
|
||||
## Yesterday we ___ to the lake.
|
||||
- go
|
||||
- [x] went
|
||||
- gone
|
||||
- going
|
||||
> Minulý tvar go je went.
|
||||
|
||||
## I've got the tickets. We ___ leave at noon.
|
||||
- will
|
||||
- [x] are going to
|
||||
- did
|
||||
- are
|
||||
> Plán s důkazem: going to.
|
||||
4
content/anglictina/2-rocnik/01-na-cestach.en.md
Normal file
4
content/anglictina/2-rocnik/01-na-cestach.en.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
nazev: On the road
|
||||
popis: Comparison and the past continuous. Gaps and a quiz.
|
||||
---
|
||||
82
content/anglictina/2-rocnik/01-na-cestach.md
Normal file
82
content/anglictina/2-rocnik/01-na-cestach.md
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
---
|
||||
id: anglictina-2-na-cestach
|
||||
puvodni: en.2.1
|
||||
nazev: Na cestách
|
||||
popis: Stupňování a minulý čas průběhový. Doplňování a kvíz.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## Porovnat dvě věci i celou skupinu
|
||||
*Stupňování*
|
||||
|
||||
- cheap → cheaper → the cheapest. Expensive → more expensive → the most expensive.
|
||||
- Nepravidelné: good → better → the best, bad → worse → the worst, far → further → the furthest.
|
||||
- as … as: The bus is as fast as the train today.
|
||||
- than stojí po komparativu: This hostel is cheaper than the hotel.
|
||||
|
||||
> Tip: kratší přídavná jména berou -er/-est, delší more/most.
|
||||
|
||||
## Děje, který probíhal, když se stalo něco jiného
|
||||
*Past continuous*
|
||||
|
||||
- I was reading when the train stopped.
|
||||
- While we were waiting, it started to rain.
|
||||
- Zápor: We weren't sleeping. Otázka: Were you driving?
|
||||
- Nepleťte si ho s minulým prostým: I walked home popisuje celou cestu.
|
||||
|
||||
> Tip: průběhový čas je pozadí, prostý je krátká událost.
|
||||
|
||||
|
||||
# Doplňování
|
||||
|
||||
## This ticket is ___ (cheap) than the night train.
|
||||
= cheaper
|
||||
> Krátké přídavné jméno: -er.
|
||||
|
||||
## It was the ___ (bad) hotel in the town.
|
||||
= worst
|
||||
> bad, worse, the worst.
|
||||
|
||||
## Prague is not as ___ as London.
|
||||
= big
|
||||
> as + základní tvar + as.
|
||||
|
||||
## I ___ (read) when the bus suddenly stopped.
|
||||
= was reading
|
||||
> Pozadí: past continuous.
|
||||
|
||||
## While we ___ (wait), a street musician started to play.
|
||||
= were waiting
|
||||
> While + průběhový děj.
|
||||
|
||||
|
||||
# Kvíz
|
||||
|
||||
## far → ___ → the furthest
|
||||
- farer
|
||||
- [x] further
|
||||
- more far
|
||||
- farthest only
|
||||
> far, further, the furthest. Farthest je taky možné, ale further je v učebnici první.
|
||||
|
||||
## Which sentence is correct?
|
||||
- This café is more cheap than that one.
|
||||
- [x] This café is cheaper than that one.
|
||||
- This café is the cheaper than that one.
|
||||
- This café is cheap than that one.
|
||||
> cheap → cheaper than.
|
||||
|
||||
## She ___ a map when she missed the stop.
|
||||
- looked
|
||||
- [x] was looking
|
||||
- looks
|
||||
- is looking
|
||||
> Dělo se to v okamžiku, kdy zmeškala zastávku.
|
||||
|
||||
## good → better → ___
|
||||
- the goodest
|
||||
- the better
|
||||
- [x] the best
|
||||
- the most good
|
||||
> the best.
|
||||
4
content/anglictina/2-rocnik/02-u-lekare.en.md
Normal file
4
content/anglictina/2-rocnik/02-u-lekare.en.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
nazev: At the clinic
|
||||
popis: Should, must and have to. A leaflet and a quiz.
|
||||
---
|
||||
92
content/anglictina/2-rocnik/02-u-lekare.md
Normal file
92
content/anglictina/2-rocnik/02-u-lekare.md
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
---
|
||||
id: anglictina-2-u-lekare
|
||||
puvodni: en.2.2
|
||||
nazev: U lékaře
|
||||
popis: Should, must a have to. Čtení letáku a kvíz.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## Rada, povinnost, zákaz
|
||||
*Modální slovesa*
|
||||
|
||||
- You should rest. You shouldn't go to school tomorrow. To je rada.
|
||||
- I must call the doctor. Mluvčí cítí, že to je nutné.
|
||||
- You have to show your insurance card. To chce ordinace.
|
||||
- Mustn't je zákaz. Don't have to znamená, že to není nutné.
|
||||
|
||||
> Tip: must je silný pocit mluvčího, have to je pravidlo zvenku.
|
||||
|
||||
## Jak to říct u přepážky
|
||||
*Tělo a příznaky*
|
||||
|
||||
- a headache, a sore throat, a cough, a temperature, a rash.
|
||||
- It hurts when I swallow. I feel dizzy.
|
||||
- How long have you had it? — Since Monday. / For three days.
|
||||
- Take these tablets twice a day. Drink plenty of water.
|
||||
|
||||
> Tip: I've got a sore throat zní přirozeněji než I have pain in throat.
|
||||
|
||||
|
||||
# Čtení
|
||||
|
||||
The school clinic is open from seven to three. If you feel ill, you should tell your teacher first. You have to bring your insurance card. You must not come to school with a high temperature. Students with a cough should wear a mask in the waiting room. You don't have to make an appointment for a small cut, but you should come before noon. The nurse can give you a painkiller. She can't give you antibiotics.
|
||||
|
||||
## What do you have to bring?
|
||||
- A mask
|
||||
- [x] An insurance card
|
||||
- Antibiotics
|
||||
- An appointment
|
||||
> have to bring your insurance card.
|
||||
|
||||
## What is forbidden?
|
||||
- [x] Coming with a high temperature
|
||||
- Telling the teacher
|
||||
- Wearing a mask
|
||||
- Coming before noon
|
||||
> must not come with a high temperature.
|
||||
|
||||
## You don't have to make an appointment if…
|
||||
- you need antibiotics
|
||||
- [x] you have a small cut
|
||||
- you have a temperature
|
||||
- you arrive at four
|
||||
> for a small cut.
|
||||
|
||||
## What can't the nurse give you?
|
||||
- Water
|
||||
- A painkiller
|
||||
- [x] Antibiotics
|
||||
- A mask
|
||||
> She can't give you antibiotics.
|
||||
|
||||
|
||||
# Kvíz
|
||||
|
||||
## You ___ shout in the waiting room. It's a rule.
|
||||
- don't have to
|
||||
- [x] mustn't
|
||||
- shouldn't to
|
||||
- haven't
|
||||
> Zákaz: mustn't.
|
||||
|
||||
## You ___ wear a tie. Nobody minds.
|
||||
- mustn't
|
||||
- [x] don't have to
|
||||
- must
|
||||
- should to
|
||||
> Není to nutné: don't have to.
|
||||
|
||||
## I've got a headache. You ___ drink some water and rest.
|
||||
- [x] should
|
||||
- must to
|
||||
- have
|
||||
- are
|
||||
> Rada: should.
|
||||
|
||||
## Visitors ___ show a card. The clinic asks for it.
|
||||
- [x] have to
|
||||
- should to
|
||||
- don't must
|
||||
- are have
|
||||
> Pravidlo zvenku: have to.
|
||||
4
content/anglictina/2-rocnik/03-prvni-brigada.en.md
Normal file
4
content/anglictina/2-rocnik/03-prvni-brigada.en.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
nazev: A first job
|
||||
popis: The present perfect, for and since. A job interview and gaps.
|
||||
---
|
||||
84
content/anglictina/2-rocnik/03-prvni-brigada.md
Normal file
84
content/anglictina/2-rocnik/03-prvni-brigada.md
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
---
|
||||
id: anglictina-2-prvni-brigada
|
||||
puvodni: en.2.3
|
||||
nazev: První brigáda
|
||||
popis: Předpřítomný čas, for a since. Poslech pohovoru a doplňování.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## Zkušenost a děj až do teď
|
||||
*Present perfect*
|
||||
|
||||
- I have worked in a café. She has never had a paid job.
|
||||
- Ever v otázce, never v záporném významu: Have you ever used a till?
|
||||
- For three months = jak dlouho. Since May = od kdy.
|
||||
- Just, already, yet: I've just finished. I haven't finished yet.
|
||||
|
||||
> Tip: have/has + příčestí. Otázka na zkušenost začíná Have you ever…?
|
||||
|
||||
## Krátké odpovědi
|
||||
*Pohovor*
|
||||
|
||||
- I'm reliable and I get on well with people.
|
||||
- I have looked after my neighbours' children.
|
||||
- I can work on Saturdays, but I can't work on Sunday mornings.
|
||||
- Could you tell me what the shift is?
|
||||
|
||||
> Tip: odpovězte a přidejte jednu konkrétní větu, ať to není jen yes.
|
||||
|
||||
|
||||
# Poslech
|
||||
|
||||
Manager: Have you ever worked in a shop? Tereza: Not in a shop, but I have helped in my uncle's bakery since May. Manager: What do you do there? Tereza: I have served customers and I have learned to use the till. I haven't baked bread yet. Manager: Can you start next Saturday? Tereza: Yes. I have already asked my uncle, and he says it's fine. I can't work on Sunday mornings because I have a match.
|
||||
|
||||
## Where has Tereza helped?
|
||||
- In a supermarket
|
||||
- [x] In her uncle's bakery
|
||||
- In a hotel
|
||||
- At school
|
||||
> in my uncle's bakery.
|
||||
|
||||
## Since when?
|
||||
- Since March
|
||||
- [x] Since May
|
||||
- Since Saturday
|
||||
- For a year
|
||||
> since May.
|
||||
|
||||
## What hasn't she done yet?
|
||||
- Served customers
|
||||
- Used the till
|
||||
- [x] Baked bread
|
||||
- Asked her uncle
|
||||
> I haven't baked bread yet.
|
||||
|
||||
## Why can't she work on Sunday mornings?
|
||||
- The bakery is closed
|
||||
- [x] She has a match
|
||||
- She is ill
|
||||
- She has no till
|
||||
> because I have a match.
|
||||
|
||||
|
||||
# Doplňování
|
||||
|
||||
## She ___ (live) here since 2019.
|
||||
= has lived|'s lived
|
||||
> Since + předpřítomný čas.
|
||||
|
||||
## I have known him ___ three years.
|
||||
= for
|
||||
> For + délka.
|
||||
|
||||
## Have you ___ (be) to London?
|
||||
= been
|
||||
> Been to = mít zkušenost.
|
||||
|
||||
## We haven't finished ___.
|
||||
= yet
|
||||
> Yet v záporu na konci.
|
||||
|
||||
## He has ___ eaten, so he isn't hungry.
|
||||
= already|just
|
||||
> Already nebo just.
|
||||
4
content/anglictina/2-rocnik/04-recenze-filmu.en.md
Normal file
4
content/anglictina/2-rocnik/04-recenze-filmu.en.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
nazev: A film review
|
||||
popis: Relative clauses with who, which and that. A short review and a quiz.
|
||||
---
|
||||
78
content/anglictina/2-rocnik/04-recenze-filmu.md
Normal file
78
content/anglictina/2-rocnik/04-recenze-filmu.md
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
---
|
||||
id: anglictina-2-recenze-filmu
|
||||
puvodni: en.2.4
|
||||
nazev: Recenze filmu
|
||||
popis: Vztažné věty who, which a that. Krátká recenze a kvíz.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## Která osoba, která věc
|
||||
*Vztažné věty*
|
||||
|
||||
- The actor who plays the captain is brilliant.
|
||||
- A lighthouse which stands on a black rock.
|
||||
- V definující větě se čárka nepíše: The boy who lives next door.
|
||||
- Nedefinující věta čárku má a that se v ní nepoužívá: Prague, which I love, …
|
||||
|
||||
> Tip: who pro lidi, which pro věci. That jde často pro obojí v definující větě.
|
||||
|
||||
## Názor, ne jen děj
|
||||
*Recenze*
|
||||
|
||||
- Jedna věta o ději, jedna o postavě, jedna o tom, co se povedlo.
|
||||
- I would recommend it to anyone who likes quiet films.
|
||||
- The ending, which I will not describe, stays with you.
|
||||
- Hodnocení ať je konkrétní: the music is too loud, the script is sharp.
|
||||
|
||||
> Tip: neprozrazujte konec. Napište, pro koho film je.
|
||||
|
||||
|
||||
# Psaní
|
||||
|
||||
Write a short review of a film or a book in at least 40 words. Use who once and which once, and say who you would recommend it to.
|
||||
|
||||
## Vzorová odpověď
|
||||
|
||||
The Lighthouse Keeper is a quiet film which follows a woman on a small island. The actor who plays her hardly speaks, but her face tells the story. The sea, which is almost a character, is beautiful and dangerous. I would recommend it to anyone who likes slow films. The ending is sad but honest.
|
||||
|
||||
## Musí obsahovat
|
||||
|
||||
- who
|
||||
- which
|
||||
- recommend
|
||||
|
||||
## Minimum slov
|
||||
|
||||
40
|
||||
|
||||
|
||||
# Kvíz
|
||||
|
||||
## The nurse ___ helped me was very calm.
|
||||
- which
|
||||
- [x] who
|
||||
- where
|
||||
- whose it
|
||||
> Člověk: who.
|
||||
|
||||
## The app ___ crashed is useless.
|
||||
- who
|
||||
- [x] which
|
||||
- where
|
||||
- whom
|
||||
> Věc: which.
|
||||
|
||||
## Prague, ___ is my home city, is full of tourists in July.
|
||||
- that
|
||||
- [x] which
|
||||
- who
|
||||
- what
|
||||
> S čárkou that nepatří. Which.
|
||||
|
||||
## That's the boy ___ dog ran into the road.
|
||||
- who
|
||||
- which
|
||||
- [x] whose
|
||||
- that his
|
||||
> Čí: whose.
|
||||
4
content/anglictina/2-rocnik/05-pocasi-a-vylet.en.md
Normal file
4
content/anglictina/2-rocnik/05-pocasi-a-vylet.en.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
nazev: Weather and a trip
|
||||
popis: Too and enough, will and going to in a forecast. Reading and gaps.
|
||||
---
|
||||
80
content/anglictina/2-rocnik/05-pocasi-a-vylet.md
Normal file
80
content/anglictina/2-rocnik/05-pocasi-a-vylet.md
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
---
|
||||
id: anglictina-2-pocasi-a-vylet
|
||||
puvodni: en.2.5
|
||||
nazev: Počasí a výlet
|
||||
popis: Too a enough, will a going to v předpovědi. Čtení a doplňování.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## Příliš a dost
|
||||
*Too / enough*
|
||||
|
||||
- It's too cold to swim. The water isn't warm enough.
|
||||
- Too many people, too much rain.
|
||||
- Enough + podstatné jméno: enough water. Nebo za přídavným jménem: old enough.
|
||||
- Not enough time je častější než too little time.
|
||||
|
||||
> Tip: too stojí před přídavným jménem, enough za ním.
|
||||
|
||||
## Co říct, když se díváte z okna
|
||||
*Předpověď*
|
||||
|
||||
- Those clouds are black. It's going to storm.
|
||||
- I think it will be sunny on Sunday. To je jen odhad.
|
||||
- If it rains, we'll stay in the cabin.
|
||||
- Slovník: foggy, chilly, pouring, a heatwave, a breeze.
|
||||
|
||||
> Tip: mraky, které vidíte, vedou k going to. Odhad bez důkazu k will.
|
||||
|
||||
|
||||
# Čtení
|
||||
|
||||
We wanted to cycle to the lake, but the morning was too foggy to start. By ten the sun was out and the path was dry enough. There were too many cyclists near the dam, so we took a quieter road. We didn't have enough water, which was a mistake. At the lake a guard said, "Look at that cloud. It's going to pour. I think the storm will last an hour." We were not fast enough. We got soaked.
|
||||
|
||||
## Why didn't they start early?
|
||||
- The bikes were broken
|
||||
- [x] It was too foggy
|
||||
- The lake was closed
|
||||
- They had no map
|
||||
> too foggy to start.
|
||||
|
||||
## Why did they change the road?
|
||||
- [x] There were too many cyclists
|
||||
- They were lost
|
||||
- It was pouring
|
||||
- The guard sent them back
|
||||
> too many cyclists near the dam.
|
||||
|
||||
## What mistake did they make?
|
||||
- They forgot the bikes
|
||||
- [x] They didn't have enough water
|
||||
- They started at night
|
||||
- They swam
|
||||
> didn't have enough water.
|
||||
|
||||
## What did the guard predict from the cloud?
|
||||
- Fog
|
||||
- A heatwave
|
||||
- [x] Rain
|
||||
- Snow
|
||||
> It's going to pour.
|
||||
|
||||
|
||||
# Doplňování
|
||||
|
||||
## The rucksack is ___ heavy to carry.
|
||||
= too
|
||||
> Too + přídavné jméno.
|
||||
|
||||
## She isn't tall ___ to reach the shelf.
|
||||
= enough
|
||||
> Enough za přídavným jménem.
|
||||
|
||||
## There is too ___ sugar in this tea.
|
||||
= much
|
||||
> Nepočitatelné: too much.
|
||||
|
||||
## Look at the sky. It ___ snow.
|
||||
= is going to|'s going to
|
||||
> Viditelný důkaz.
|
||||
4
content/anglictina/2-rocnik/06-festival.en.md
Normal file
4
content/anglictina/2-rocnik/06-festival.en.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
nazev: A festival
|
||||
popis: Present perfect versus past simple. Listening and a quiz.
|
||||
---
|
||||
92
content/anglictina/2-rocnik/06-festival.md
Normal file
92
content/anglictina/2-rocnik/06-festival.md
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
---
|
||||
id: anglictina-2-festival
|
||||
puvodni: en.2.6
|
||||
nazev: Festival
|
||||
popis: Předpřítomný čas proti minulému. Poslech a kvíz.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## Kdy je děj uzavřený
|
||||
*Dva časy*
|
||||
|
||||
- I have been to the festival three times. Neříkám kdy.
|
||||
- I went in 2023. Tehdy pršelo. To už je uzavřené.
|
||||
- Have you ever slept in a tent? — Yes. I slept in one last June.
|
||||
- Been to znamená, že už je člověk zpátky. Gone to znamená, že je pořád pryč.
|
||||
|
||||
> Tip: jakmile zazní yesterday, last year nebo in 2019, patří minulý čas.
|
||||
|
||||
## Co se děje na místě
|
||||
*Reportáž*
|
||||
|
||||
- The gates have just opened.
|
||||
- Last night the main band played for two hours.
|
||||
- Have you seen the lanterns yet?
|
||||
- A local baker has made a cake in the shape of a violin.
|
||||
|
||||
> Tip: reportér míchá „už se stalo“ a „bylo to včera večer“.
|
||||
|
||||
|
||||
# Poslech
|
||||
|
||||
This is Nora at the river festival. The gates have just opened and hundreds of people have already come in. I have never seen so many lanterns. Last night the main band played for two hours, but tonight's singer hasn't arrived yet. A local baker has made a cake in the shape of a violin. I tried a piece yesterday. It was delicious. Have you ever been here? I came for the first time in 2022, and I have come back every summer since then.
|
||||
|
||||
## What has just happened?
|
||||
- The band has left
|
||||
- [x] The gates have opened
|
||||
- It has started to snow
|
||||
- The baker has closed
|
||||
> The gates have just opened.
|
||||
|
||||
## When did the main band play?
|
||||
- Just now
|
||||
- [x] Last night
|
||||
- In 2022
|
||||
- Every summer
|
||||
> Last night the main band played.
|
||||
|
||||
## What hasn't happened yet?
|
||||
- People have come in
|
||||
- [x] Tonight's singer has arrived
|
||||
- Nora tried the cake
|
||||
- The gates opened
|
||||
> hasn't arrived yet.
|
||||
|
||||
## When did Nora come for the first time?
|
||||
- Yesterday
|
||||
- Last night
|
||||
- [x] In 2022
|
||||
- This morning
|
||||
> for the first time in 2022.
|
||||
|
||||
|
||||
# Kvíz
|
||||
|
||||
## I ___ this play in 2019.
|
||||
- have seen
|
||||
- [x] saw
|
||||
- seen
|
||||
- have saw
|
||||
> Rok uzavírá děj: saw.
|
||||
|
||||
## She has ___ to Paris. She is still there.
|
||||
- been
|
||||
- [x] gone
|
||||
- went
|
||||
- going
|
||||
> Pořád je pryč: gone.
|
||||
|
||||
## ___ you ever slept in a tent?
|
||||
- Did
|
||||
- [x] Have
|
||||
- Do
|
||||
- Were
|
||||
> Ever + present perfect: Have you ever…?
|
||||
|
||||
## We ___ the lanterns yesterday.
|
||||
- have seen
|
||||
- [x] saw
|
||||
- seen
|
||||
- have watch
|
||||
> Yesterday → past simple.
|
||||
4
content/anglictina/2-rocnik/07-kdyby.en.md
Normal file
4
content/anglictina/2-rocnik/07-kdyby.en.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
nazev: If I could
|
||||
popis: First and second conditionals. Writing and gaps.
|
||||
---
|
||||
66
content/anglictina/2-rocnik/07-kdyby.md
Normal file
66
content/anglictina/2-rocnik/07-kdyby.md
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
---
|
||||
id: anglictina-2-kdyby
|
||||
puvodni: en.2.7
|
||||
nazev: Kdyby
|
||||
popis: První a druhá podmínková věta. Psaní a doplňování.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## Reálná a hypotetická
|
||||
*Podmínky*
|
||||
|
||||
- 1. kondicionál: If I finish early, I will call you. Je to možné.
|
||||
- 2. kondicionál: If I had a car, I would drive. Teď auto nemám.
|
||||
- V formální druhé podmínce je were: If I were you, I would apologise.
|
||||
- Unless = if not: We'll miss the bus unless we leave now.
|
||||
|
||||
> Tip: v if větě není will. If it rains, we will stay in.
|
||||
|
||||
## Jedna reálná, jedna vysněná
|
||||
*Vlastní věta*
|
||||
|
||||
- Napište situaci, která se může stát tento týden.
|
||||
- Pak situaci, která teď pravda není.
|
||||
- Would like není druhá podmínka. To je jen přání: I'd like a tea.
|
||||
- Krátký text ať má oba typy, ať je rozdíl vidět.
|
||||
|
||||
> Tip: would se v if větě druhé podmínky neopakuje na obou stranách špatně. If I would have je chyba.
|
||||
|
||||
|
||||
# Doplňování
|
||||
|
||||
## If it ___ (rain), we will stay in the tent.
|
||||
= rains
|
||||
> 1. podmínka: přítomný čas v if.
|
||||
|
||||
## If I ___ (be) you, I would tell the truth.
|
||||
= were|was
|
||||
> Were je přesnější, was se taky slyší.
|
||||
|
||||
## She would travel more if she ___ (have) time.
|
||||
= had
|
||||
> 2. podmínka: minulý tvar.
|
||||
|
||||
## We'll be late ___ we hurry.
|
||||
= unless
|
||||
> Unless = if not.
|
||||
|
||||
|
||||
# Psaní
|
||||
|
||||
Write at least 35 words. Include one real plan with if and will, and one unreal dream with would. Use the word if twice.
|
||||
|
||||
## Vzorová odpověď
|
||||
|
||||
If I finish my project tonight, I will go climbing with Eva on Saturday. We will take the early bus if the weather is fine. If I had more free time, I would learn the guitar. I would also travel by night train if tickets were cheaper. If is a small word with two very different lives.
|
||||
|
||||
## Musí obsahovat
|
||||
|
||||
- if
|
||||
- will
|
||||
- would
|
||||
|
||||
## Minimum slov
|
||||
|
||||
35
|
||||
4
content/anglictina/2-rocnik/08-test-2-rocniku.en.md
Normal file
4
content/anglictina/2-rocnik/08-test-2-rocniku.en.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
nazev: Year 2 test
|
||||
popis: Reading, listening, B1 grammar and a short piece of writing.
|
||||
---
|
||||
129
content/anglictina/2-rocnik/08-test-2-rocniku.md
Normal file
129
content/anglictina/2-rocnik/08-test-2-rocniku.md
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
---
|
||||
id: anglictina-2-test-2-rocniku
|
||||
puvodni: en.2.8
|
||||
nazev: Test 2. ročníku
|
||||
popis: Čtení, poslech, gramatika B1 a krátké psaní.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## Co už má držet pohromadě
|
||||
*B1*
|
||||
|
||||
- Stupňování, past continuous, modální slovesa rady a povinnosti.
|
||||
- Present perfect proti past simple.
|
||||
- Who a which, too a enough, první a druhá podmínka.
|
||||
- Psaní: krátký souvislý názor, ne odrážkový seznam.
|
||||
|
||||
> Tip: u předpřítomného času hledejte ever, yet, since. U minulého yesterday a rok.
|
||||
|
||||
## Jedna věta navíc
|
||||
*Strategie*
|
||||
|
||||
- U čtení škrtněte odpověď, která v textu vůbec není.
|
||||
- U poslechu si čísla zapište číslicí.
|
||||
- Mustn't není don't have to.
|
||||
- If I would have time je chyba. If I had time, I would…
|
||||
|
||||
> Tip: v psaní ať je důvod. Because nebo so text zvedne.
|
||||
|
||||
|
||||
# Čtení
|
||||
|
||||
The night bus to Brno is cheaper than the train, but it is also slower. Last Friday I was sleeping when the driver stopped at a dark petrol station. A woman who had missed her connection asked if she could sit next to me. She has travelled this route since March because her new job starts at six. If the bus is late, she has to run. She says she would move closer if flats were cheaper.
|
||||
|
||||
## The bus is ___ than the train.
|
||||
- faster and cheaper
|
||||
- [x] cheaper and slower
|
||||
- the best
|
||||
- as fast
|
||||
> cheaper, but slower.
|
||||
|
||||
## What was the writer doing when the bus stopped?
|
||||
- Reading
|
||||
- [x] Sleeping
|
||||
- Running
|
||||
- Driving
|
||||
> I was sleeping when the driver stopped.
|
||||
|
||||
## Why has the woman travelled this route since March?
|
||||
- She likes petrol stations
|
||||
- [x] Her job starts early
|
||||
- Flats are cheap
|
||||
- She missed a concert
|
||||
> her new job starts at six.
|
||||
|
||||
|
||||
# Poslech
|
||||
|
||||
Doctor: How long have you had this cough? Adam: Since Sunday. I have also had a sore throat for two days. Doctor: You should rest and drink water. You don't have to stay in bed all day, but you mustn't play football this week. If you still feel ill on Friday, come back.
|
||||
|
||||
## Since when has Adam had the cough?
|
||||
- Since Friday
|
||||
- [x] Since Sunday
|
||||
- For a month
|
||||
- Since March
|
||||
> Since Sunday.
|
||||
|
||||
## What mustn't he do?
|
||||
- Drink water
|
||||
- Rest
|
||||
- [x] Play football
|
||||
- Come back
|
||||
> mustn't play football.
|
||||
|
||||
## When should he come back?
|
||||
- [x] If he is still ill on Friday
|
||||
- Every day
|
||||
- Never
|
||||
- On Sunday morning
|
||||
> If you still feel ill on Friday.
|
||||
|
||||
|
||||
# Psaní
|
||||
|
||||
Write at least 35 words about a trip or a job you would like. Use would and because.
|
||||
|
||||
## Vzorová odpověď
|
||||
|
||||
I would like to work in a small bookshop by the station because I love quiet mornings. I would talk to customers and I would also read in the breaks. If I had the job, I would cycle there. I have never worked in a shop, but I have helped at school events.
|
||||
|
||||
## Musí obsahovat
|
||||
|
||||
- would
|
||||
- because
|
||||
|
||||
## Minimum slov
|
||||
|
||||
35
|
||||
|
||||
|
||||
# Kvíz
|
||||
|
||||
## This hostel is ___ than the hotel.
|
||||
- [x] cheaper
|
||||
- more cheap
|
||||
- the cheapest
|
||||
- cheap
|
||||
> cheap → cheaper.
|
||||
|
||||
## I have lived here ___ 2020.
|
||||
- for
|
||||
- [x] since
|
||||
- ago
|
||||
- during
|
||||
> Since + bod v čase.
|
||||
|
||||
## You ___ wear a helmet. It's the law.
|
||||
- must to
|
||||
- [x] have to
|
||||
- don't have
|
||||
- should to
|
||||
> Pravidlo: have to.
|
||||
|
||||
## If I ___ richer, I would take the train.
|
||||
- am
|
||||
- will be
|
||||
- [x] were
|
||||
- would be
|
||||
> 2. podmínka: were.
|
||||
4
content/anglictina/3-rocnik/01-jak-se-to-vyrabi.en.md
Normal file
4
content/anglictina/3-rocnik/01-jak-se-to-vyrabi.en.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
nazev: How things are made
|
||||
popis: The present and past passive. Gaps and a quiz.
|
||||
---
|
||||
82
content/anglictina/3-rocnik/01-jak-se-to-vyrabi.md
Normal file
82
content/anglictina/3-rocnik/01-jak-se-to-vyrabi.md
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
---
|
||||
id: anglictina-3-jak-se-to-vyrabi
|
||||
puvodni: en.3.1
|
||||
nazev: Jak se to vyrábí
|
||||
popis: Trpný rod v přítomnosti a minulosti. Doplňování a kvíz.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## Když je důležitější děj než původce
|
||||
*Passive*
|
||||
|
||||
- English is spoken here. The window was broken last night.
|
||||
- Původce s by, jen když na něm záleží: The book was written by a nurse.
|
||||
- Modální trpný rod: The form must be signed. It can be recycled.
|
||||
- Nelze trpně vyjádřit každé sloveso. Happen trpný rod nemá.
|
||||
|
||||
> Tip: be + příčestí. Čas nese sloveso be, ne příčestí.
|
||||
|
||||
## Od suroviny k věci
|
||||
*Popis procesu*
|
||||
|
||||
- The beans are picked by hand. They are dried in the sun.
|
||||
- The jars were labelled yesterday.
|
||||
- Waste paper is collected every Thursday.
|
||||
- A new bridge is being built. To už je průběhový trpný rod, zatím stačí ho poznat.
|
||||
|
||||
> Tip: first, then, after that, finally. Původce často chybí, protože je obecný.
|
||||
|
||||
|
||||
# Doplňování
|
||||
|
||||
## This bread ___ (bake) every morning.
|
||||
= is baked
|
||||
> Přítomný trpný rod.
|
||||
|
||||
## The letters ___ (send) yesterday.
|
||||
= were sent
|
||||
> Minulý trpný rod, množné číslo.
|
||||
|
||||
## The poem ___ (write) by a student.
|
||||
= was written
|
||||
> Write → written.
|
||||
|
||||
## These bottles can ___ (recycle).
|
||||
= be recycled
|
||||
> Modální sloveso + be + příčestí.
|
||||
|
||||
## The window ___ (not break) by the wind. Someone hit it.
|
||||
= wasn't broken|was not broken
|
||||
> Zápor minulého trpného rodu.
|
||||
|
||||
|
||||
# Kvíz
|
||||
|
||||
## Which sentence is passive?
|
||||
- Someone stole my bike.
|
||||
- [x] My bike was stolen.
|
||||
- My bike stole.
|
||||
- Someone was steal my bike.
|
||||
> was + stolen.
|
||||
|
||||
## The news ___ at ten.
|
||||
- is reading
|
||||
- are read
|
||||
- [x] is read
|
||||
- read
|
||||
> News je jednotné: is read.
|
||||
|
||||
## You ___ wear a badge. The factory requires it, in the passive of must.
|
||||
- must be worn a badge
|
||||
- [x] A badge must be worn
|
||||
- A badge must worn
|
||||
- A badge is must wear
|
||||
> A badge must be worn.
|
||||
|
||||
## They built the school in 1998. → The school ___ in 1998.
|
||||
- built
|
||||
- [x] was built
|
||||
- was build
|
||||
- has built
|
||||
> was built.
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
nazev: A school people talk about
|
||||
popis: Reported statements. Reading and a quiz.
|
||||
---
|
||||
92
content/anglictina/3-rocnik/02-skola-o-ktere-se-mluvi.md
Normal file
92
content/anglictina/3-rocnik/02-skola-o-ktere-se-mluvi.md
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
---
|
||||
id: anglictina-3-skola-o-ktere-se-mluvi
|
||||
puvodni: en.3.2
|
||||
nazev: Škola, o které se mluví
|
||||
popis: Nepřímá řeč oznamovací. Čtení a kvíz.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## Posun času
|
||||
*Reported speech*
|
||||
|
||||
- „I am tired.“ → She said she was tired.
|
||||
- „I will help.“ → He said he would help.
|
||||
- „I have finished.“ → She told me she had finished.
|
||||
- „I can't come.“ → He said he couldn't come.
|
||||
|
||||
> Tip: said that, told me that. Tell potřebuje osobu, say ne.
|
||||
|
||||
## Pořád to platí
|
||||
*Kdy čas neposouvat*
|
||||
|
||||
- The teacher said that water boils at 100 degrees.
|
||||
- She said she lives in Kolín, a pořád tam bydlí.
|
||||
- Zájmena se mění podle smyslu: „my book“ → he said his book.
|
||||
- Today → that day, tomorrow → the next day, yesterday → the day before. V testu to bude jen u jasných vět.
|
||||
|
||||
> Tip: obecné pravdy a situace, které trvají, často zůstávají v přítomném čase.
|
||||
|
||||
|
||||
# Čtení
|
||||
|
||||
Our head teacher told the local paper that the school was changing. She said that students would start an hour later next term. One pupil told the reporter that he was pleased because he hated early buses. A parent said that she was worried. She said her daughter had joined three clubs and had very little time. The cook said that lunch would still be at noon. He added that the menu was going to include more vegetables.
|
||||
|
||||
## What did the head teacher say about the start of school?
|
||||
- [x] It would start an hour later
|
||||
- It would start at night
|
||||
- It had already closed
|
||||
- Clubs would end
|
||||
> students would start an hour later.
|
||||
|
||||
## Why was the pupil pleased?
|
||||
- He liked buses
|
||||
- [x] He hated early buses
|
||||
- He wanted less lunch
|
||||
- He had three clubs
|
||||
> because he hated early buses.
|
||||
|
||||
## What had the daughter done?
|
||||
- She had left school
|
||||
- [x] She had joined three clubs
|
||||
- She had become a cook
|
||||
- She had bought a bus
|
||||
> had joined three clubs.
|
||||
|
||||
## Lunch, according to the cook, …
|
||||
- would move to the evening
|
||||
- [x] would still be at noon
|
||||
- had been cancelled
|
||||
- was only vegetables
|
||||
> would still be at noon.
|
||||
|
||||
|
||||
# Kvíz
|
||||
|
||||
## „I am hungry.“ → She said she ___ hungry.
|
||||
- is
|
||||
- [x] was
|
||||
- has
|
||||
- were be
|
||||
> am → was.
|
||||
|
||||
## „I will call.“ → He said he ___ call.
|
||||
- will
|
||||
- [x] would
|
||||
- called
|
||||
- has
|
||||
> will → would.
|
||||
|
||||
## Which verb needs a person?
|
||||
- say
|
||||
- [x] tell
|
||||
- speak that
|
||||
- talk that
|
||||
> tell somebody.
|
||||
|
||||
## She said, „I can't swim.“ → She said she ___.
|
||||
- can't swim
|
||||
- [x] couldn't swim
|
||||
- doesn't swim
|
||||
- hasn't swum
|
||||
> can → could. V nepřímé řeči o minulém rozhovoru.
|
||||
4
content/anglictina/3-rocnik/03-posledni-buk.en.md
Normal file
4
content/anglictina/3-rocnik/03-posledni-buk.en.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
nazev: The last beech
|
||||
popis: Conditionals and environment vocabulary. A podcast and gaps.
|
||||
---
|
||||
80
content/anglictina/3-rocnik/03-posledni-buk.md
Normal file
80
content/anglictina/3-rocnik/03-posledni-buk.md
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
---
|
||||
id: anglictina-3-posledni-buk
|
||||
puvodni: en.3.3
|
||||
nazev: Poslední buk
|
||||
popis: Podmínky a slovník prostředí. Poslech podcastu a doplňování.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## Konkrétní slova, ne jen nature
|
||||
*Prostředí*
|
||||
|
||||
- A drought is a long time without rain. Soil is the earth plants grow in.
|
||||
- Unless it rains, the young trees will die.
|
||||
- If the town banned cars, the air would be cleaner. Teď je nezakázalo, proto would.
|
||||
- If people keep using the road, the soil will wash away. To se může stát.
|
||||
|
||||
> Tip: drought, soil, volunteer, ban, shortcut. U maturitního tématu zabírají víc než slovo pollution samo.
|
||||
|
||||
## Kdo co řekl
|
||||
*Podcast*
|
||||
|
||||
- Ranger = strážce lesa.
|
||||
- Young trees were planted, but many may still die.
|
||||
- A shortcut šetří čas a někdy ničí místo.
|
||||
- Čísla si zapište: two thousand.
|
||||
|
||||
> Tip: u nepřímé řeči v poslechu si pamatujte sloveso řekl/řekla a pak obsah.
|
||||
|
||||
|
||||
# Poslech
|
||||
|
||||
Last month our class recorded a podcast called The Last Beech. A ranger said that the trees were thirsty because the summers had become hotter. She told us that volunteers had planted two thousand young trees, but she added that many would die unless it rained. If the town banned cars from the forest road, the air would be cleaner. If people keep using it as a shortcut, the soil will wash away.
|
||||
|
||||
## What did the ranger say about the trees?
|
||||
- [x] They were thirsty
|
||||
- They had been cut down
|
||||
- They were a shortcut
|
||||
- They banned cars
|
||||
> the trees were thirsty.
|
||||
|
||||
## How many young trees had volunteers planted?
|
||||
- Two hundred
|
||||
- [x] Two thousand
|
||||
- Twenty
|
||||
- None
|
||||
> two thousand.
|
||||
|
||||
## The young trees will die unless…
|
||||
- people drive there
|
||||
- [x] it rains
|
||||
- the podcast ends
|
||||
- the soil is sold
|
||||
> unless it rained / unless it rains. V textu: unless it rained v nepřímé řeči.
|
||||
|
||||
## What would make the air cleaner?
|
||||
- [x] Banning cars from the forest road
|
||||
- Using the road as a shortcut
|
||||
- Cutting the beeches
|
||||
- Washing the soil
|
||||
> If the town banned cars.
|
||||
|
||||
|
||||
# Doplňování
|
||||
|
||||
## If we ___ (ban) cars here, the air would be cleaner.
|
||||
= banned
|
||||
> 2. podmínka.
|
||||
|
||||
## The soil will wash away ___ people stop using the shortcut.
|
||||
= unless
|
||||
> Unless = if not. Pozor: věta chce if not ve významu dokud nepřestanou. Unless people stop = if they don't stop.
|
||||
|
||||
## Many young trees ___ (plant) last month.
|
||||
= were planted
|
||||
> Minulý trpný rod.
|
||||
|
||||
## She said the summers ___ (become) hotter.
|
||||
= had become
|
||||
> Posun předpřítomného času.
|
||||
4
content/anglictina/3-rocnik/04-pro-a-proti.en.md
Normal file
4
content/anglictina/3-rocnik/04-pro-a-proti.en.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
nazev: For and against
|
||||
popis: Essay structure and linking words. An essay and a quiz.
|
||||
---
|
||||
78
content/anglictina/3-rocnik/04-pro-a-proti.md
Normal file
78
content/anglictina/3-rocnik/04-pro-a-proti.md
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
---
|
||||
id: anglictina-3-pro-a-proti
|
||||
puvodni: en.3.4
|
||||
nazev: Pro a proti
|
||||
popis: Stavba úvahy a spojovací výrazy. Esej a kvíz.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## Úvod, dvě strany, závěr
|
||||
*Čtyři kroky*
|
||||
|
||||
- Úvod: o čem text je a že existují dva pohledy.
|
||||
- Jeden odstavec pro výhody, jeden pro nevýhody.
|
||||
- On the one hand … On the other hand …
|
||||
- Závěr: váš názor. In my opinion, I believe. Nepřidávejte úplně nový argument.
|
||||
|
||||
> Tip: v úvodu otázku neopakujte doslova. Převeďte ji vlastními slovy.
|
||||
|
||||
## However není because
|
||||
*Spojky*
|
||||
|
||||
- School uniforms are cheaper. However, they limit personality.
|
||||
- Although uniforms save time, many students hate them.
|
||||
- Because dává důvod. So dává výsledek.
|
||||
- In conclusion shrnuje. Nepíše se In the conclusion.
|
||||
|
||||
> Tip: however stojí mezi větami a odděluje se čárkou. Although spojuje věty v jednu.
|
||||
|
||||
|
||||
# Psaní
|
||||
|
||||
Write a for-and-against paragraph of at least 50 words about school uniforms. Use however and because, and finish with your opinion using believe.
|
||||
|
||||
## Vzorová odpověď
|
||||
|
||||
School uniforms are a common argument. They are practical because students do not have to decide what to wear, and families spend less money. However, a uniform hides personality and can feel childish at eighteen. Although it makes mornings faster, it does not make lessons better. I believe schools should keep a simple dress code, but they should not force one jacket on everyone.
|
||||
|
||||
## Musí obsahovat
|
||||
|
||||
- however
|
||||
- because
|
||||
- believe
|
||||
|
||||
## Minimum slov
|
||||
|
||||
50
|
||||
|
||||
|
||||
# Kvíz
|
||||
|
||||
## Which linker shows contrast?
|
||||
- because
|
||||
- [x] however
|
||||
- so
|
||||
- for example
|
||||
> However staví protiklad.
|
||||
|
||||
## ___ uniforms save time, students still complain.
|
||||
- However
|
||||
- [x] Although
|
||||
- So
|
||||
- Believe
|
||||
> Although spojuje dvě části jedné věty.
|
||||
|
||||
## Choose the best ending of an essay.
|
||||
- In conclusion, I have no idea.
|
||||
- [x] In conclusion, I believe a simple rule is enough.
|
||||
- Because however so.
|
||||
- To begin with, the essay starts now.
|
||||
> Závěr má názor, ne nový zmatek.
|
||||
|
||||
## Because introduces…
|
||||
- a result only
|
||||
- [x] a reason
|
||||
- a list of names
|
||||
- a question
|
||||
> Because = důvod.
|
||||
4
content/anglictina/3-rocnik/05-kdo-to-musel-byt.en.md
Normal file
4
content/anglictina/3-rocnik/05-kdo-to-musel-byt.en.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
nazev: It must have been
|
||||
popis: Modals of deduction. A short mystery and a quiz.
|
||||
---
|
||||
92
content/anglictina/3-rocnik/05-kdo-to-musel-byt.md
Normal file
92
content/anglictina/3-rocnik/05-kdo-to-musel-byt.md
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
---
|
||||
id: anglictina-3-kdo-to-musel-byt
|
||||
puvodni: en.3.5
|
||||
nazev: Kdo to musel být
|
||||
popis: Modální slovesa dedukce. Čtení záhady a kvíz.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## Jisté, možné, vyloučené
|
||||
*Dedukce*
|
||||
|
||||
- The lights are on. She must be at home.
|
||||
- He might be in the lab. I'm not sure.
|
||||
- That can't be Eva. Eva is in Vienna this week.
|
||||
- O minulosti: must have left, might have forgotten, can't have seen it.
|
||||
|
||||
> Tip: must je skoro jistota, might je možnost, can't je „to přece nejde“.
|
||||
|
||||
## Čtěte důkazy, ne nadpis
|
||||
*Vynález*
|
||||
|
||||
- A notebook with today's date is stronger than a guess.
|
||||
- Can't have znamená, že to odporuje faktu.
|
||||
- Might have nechává dvě možnosti otevřené.
|
||||
- Nepoužívejte can pro dedukci v kladné větě. Can umí, must musí být.
|
||||
|
||||
> Tip: u must have hledejte důkaz, který už nejde rozumně popřít.
|
||||
|
||||
|
||||
# Čtení
|
||||
|
||||
Someone left a strange machine in the physics lab. It was warm, so it must have been switched on recently. The only key can't have been used by the caretaker, because he is in hospital. Two students, Nora and Adam, know the code. Nora might have come back after the club, but her train ticket shows she was in Pardubice. Adam's notebook is on the bench and the handwriting matches the label. He must have built it.
|
||||
|
||||
## Why must the machine have been on recently?
|
||||
- It was noisy
|
||||
- [x] It was warm
|
||||
- It was new
|
||||
- It was labelled
|
||||
> It was warm.
|
||||
|
||||
## Why can't the caretaker have used the key?
|
||||
- He lost it
|
||||
- [x] He is in hospital
|
||||
- He hates physics
|
||||
- He was in Pardubice
|
||||
> he is in hospital.
|
||||
|
||||
## Where was Nora?
|
||||
- In the lab
|
||||
- [x] In Pardubice
|
||||
- In hospital
|
||||
- On the bench
|
||||
> her ticket shows Pardubice.
|
||||
|
||||
## Who must have built the machine?
|
||||
- The caretaker
|
||||
- Nora
|
||||
- [x] Adam
|
||||
- Nobody
|
||||
> The notebook and the handwriting point to Adam.
|
||||
|
||||
|
||||
# Kvíz
|
||||
|
||||
## The window is broken and his bag is gone. He ___ left in a hurry.
|
||||
- [x] must have
|
||||
- must
|
||||
- can have
|
||||
- should
|
||||
> Minulá skoro jistota: must have left.
|
||||
|
||||
## That ___ be Lea. Lea is abroad.
|
||||
- must
|
||||
- [x] can't
|
||||
- should
|
||||
- is
|
||||
> Odporuje faktu: can't.
|
||||
|
||||
## I'm not sure. They ___ have missed the bus.
|
||||
- must
|
||||
- can't
|
||||
- [x] might
|
||||
- are
|
||||
> Možnost: might have.
|
||||
|
||||
## Which sentence is a deduction, not a duty?
|
||||
- You must wear gloves.
|
||||
- [x] She must be tired.
|
||||
- You must sign this.
|
||||
- Visitors must wait.
|
||||
> She must be tired je úsudek.
|
||||
4
content/anglictina/3-rocnik/06-zpravy-dne.en.md
Normal file
4
content/anglictina/3-rocnik/06-zpravy-dne.en.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
nazev: The news desk
|
||||
popis: Reported questions. An interview and a quiz.
|
||||
---
|
||||
92
content/anglictina/3-rocnik/06-zpravy-dne.md
Normal file
92
content/anglictina/3-rocnik/06-zpravy-dne.md
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
---
|
||||
id: anglictina-3-zpravy-dne
|
||||
puvodni: en.3.6
|
||||
nazev: Zprávy dne
|
||||
popis: Nepřímé otázky. Poslech rozhovoru a kvíz.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## Otázka se v nepřímé řeči narovná
|
||||
*Reported questions*
|
||||
|
||||
- „Where do you live?“ → She asked me where I lived.
|
||||
- „Did you see it?“ → He asked if I had seen it.
|
||||
- Whether a if jsou u zjišťovacích otázek obě možné.
|
||||
- Tázací výraz zůstává: what, where, why, how long.
|
||||
|
||||
> Tip: žádný otazník a pořadí podmětu a slovesa jako v oznamovací větě.
|
||||
|
||||
## Novinář se ptá starosty
|
||||
*Redakce*
|
||||
|
||||
- Asked if the bridge was safe.
|
||||
- Wondered how long the repairs would take.
|
||||
- The mayor said he didn't know yet.
|
||||
- Slovesa ask, wonder, want to know.
|
||||
|
||||
> Tip: v poslechu odlište otázku reportéra od odpovědi starosty.
|
||||
|
||||
|
||||
# Poslech
|
||||
|
||||
Reporter: Mayor, is the old bridge safe? Mayor: I can't promise that. An engineer told me that two cables were weak. Reporter: How long will the repairs take? Mayor: She asked the firm the same question yesterday. They said they didn't know yet. Reporter: Did anyone complain? Mayor: A shopkeeper asked me why the bus stop had moved. I asked her if she could wait until Friday. Reporter: Will you close the bridge? Mayor: We might. I have asked the police whether they can send officers tonight.
|
||||
|
||||
## What did the engineer tell the mayor?
|
||||
- The bridge was new
|
||||
- [x] Two cables were weak
|
||||
- The shop was closed
|
||||
- Friday was impossible
|
||||
> two cables were weak.
|
||||
|
||||
## What didn't the firm know?
|
||||
- The mayor's name
|
||||
- [x] How long the repairs would take
|
||||
- Where the bus stop was
|
||||
- Who the police were
|
||||
> They said they didn't know yet. Šlo o délku oprav.
|
||||
|
||||
## What did the shopkeeper ask?
|
||||
- [x] Why the bus stop had moved
|
||||
- If the mayor could swim
|
||||
- Where the cables were made
|
||||
- Whether Friday was a holiday
|
||||
> why the bus stop had moved.
|
||||
|
||||
## Who might come tonight?
|
||||
- The firm
|
||||
- The shopkeeper
|
||||
- [x] Police officers
|
||||
- The engineer only
|
||||
> whether they can send officers tonight.
|
||||
|
||||
|
||||
# Kvíz
|
||||
|
||||
## „Where do you live?“ → He asked me where I ___.
|
||||
- did live
|
||||
- [x] lived
|
||||
- do live
|
||||
- living
|
||||
> Pořadí oznamovací věty: where I lived.
|
||||
|
||||
## „Are you ready?“ → She asked if I ___.
|
||||
- [x] was ready
|
||||
- am I ready
|
||||
- ready was
|
||||
- did ready
|
||||
> if I was ready.
|
||||
|
||||
## Which sentence is wrong?
|
||||
- He asked where she was.
|
||||
- [x] He asked where was she.
|
||||
- He asked if she was tired.
|
||||
- He wanted to know why she had left.
|
||||
> V nepřímé otázce není inverze.
|
||||
|
||||
## Whether means about the same as…
|
||||
- because
|
||||
- [x] if
|
||||
- however
|
||||
- whose
|
||||
> Whether ≈ if v nepřímé zjišťovací otázce.
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
nazev: Phrasal verbs in a story
|
||||
popis: Common phrasal verbs. Gaps and a quiz.
|
||||
---
|
||||
82
content/anglictina/3-rocnik/07-frazova-slovesa-v-pribehu.md
Normal file
82
content/anglictina/3-rocnik/07-frazova-slovesa-v-pribehu.md
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
---
|
||||
id: anglictina-3-frazova-slovesa-v-pribehu
|
||||
puvodni: en.3.7
|
||||
nazev: Frázová slovesa v příběhu
|
||||
popis: Běžná frázová slovesa. Doplňování a kvíz.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## Look není look after
|
||||
*Částice mění význam*
|
||||
|
||||
- look after = starat se, look for = hledat, look forward to = těšit se.
|
||||
- give up = vzdát se, find out = zjistit, run out of = dojít zásoba.
|
||||
- turn off = vypnout, take off = sundat nebo vzlétnout, get on = nastoupit i vycházet.
|
||||
- Look forward to je následované -ing: I look forward to seeing you.
|
||||
|
||||
> Tip: frázové sloveso se učte jako jednu jednotku, s českým protějškem ve větě.
|
||||
|
||||
## Jedno sloveso, jedna situace
|
||||
*Příběh*
|
||||
|
||||
- The bus took off není o oblečení. U letadla ano, u autobusu spíš pulled away.
|
||||
- Take off a coat = sundat. Take off = vzlétnout. Kontext rozhoduje.
|
||||
- Get on with somebody = vycházet s někým.
|
||||
- Run out of time je u testu častější než run out time.
|
||||
|
||||
> Tip: když částici neznáte, představte si gesto. Off je pryč, up je do konce.
|
||||
|
||||
|
||||
# Doplňování
|
||||
|
||||
## Can you look ___ my dog this weekend?
|
||||
= after
|
||||
> Look after = postarat se.
|
||||
|
||||
## We are looking ___ to the trip.
|
||||
= forward
|
||||
> Look forward to.
|
||||
|
||||
## Don't give ___. The last chapter is the best.
|
||||
= up
|
||||
> Give up = vzdát to.
|
||||
|
||||
## I need to find ___ who left the note.
|
||||
= out
|
||||
> Find out = zjistit.
|
||||
|
||||
## We've run ___ of milk.
|
||||
= out
|
||||
> Run out of.
|
||||
|
||||
|
||||
# Kvíz
|
||||
|
||||
## Please turn ___ the lights.
|
||||
- [x] off
|
||||
- after
|
||||
- forward
|
||||
- out of
|
||||
> Turn off = vypnout.
|
||||
|
||||
## She gets ___ well with her neighbours.
|
||||
- [x] on
|
||||
- off
|
||||
- up
|
||||
- after
|
||||
> Get on with = vycházet.
|
||||
|
||||
## He took ___ his wet coat.
|
||||
- [x] off
|
||||
- up to
|
||||
- after
|
||||
- forward
|
||||
> Sundat: take off.
|
||||
|
||||
## I look forward to ___ you.
|
||||
- see
|
||||
- [x] seeing
|
||||
- saw
|
||||
- seen
|
||||
> To je předložka, následuje -ing.
|
||||
4
content/anglictina/3-rocnik/08-test-3-rocniku.en.md
Normal file
4
content/anglictina/3-rocnik/08-test-3-rocniku.en.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
nazev: Year 3 test
|
||||
popis: Reading, listening, B1+ grammar and a short argument.
|
||||
---
|
||||
129
content/anglictina/3-rocnik/08-test-3-rocniku.md
Normal file
129
content/anglictina/3-rocnik/08-test-3-rocniku.md
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
---
|
||||
id: anglictina-3-test-3-rocniku
|
||||
puvodni: en.3.8
|
||||
nazev: Test 3. ročníku
|
||||
popis: Čtení, poslech, gramatika B1+ a krátká úvaha.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## Trpný rod, řeč, podmínky, dedukce
|
||||
*B1+*
|
||||
|
||||
- was written, must be signed, is spoken.
|
||||
- said she would, asked where I lived.
|
||||
- If they banned cars, the air would be cleaner.
|
||||
- must have, might have, can't have.
|
||||
|
||||
> Tip: u trpného rodu hledejte be. U nepřímé otázky žádnou inverzi.
|
||||
|
||||
## However a because v jednom textu
|
||||
*Úvaha ve zkratce*
|
||||
|
||||
- Neopakujte zadání první větou.
|
||||
- Phrasal verbs nechte ve správné částici. Look after není look for.
|
||||
- Told me, ne said me.
|
||||
- In conclusion je až na konci, ne v úvodu.
|
||||
|
||||
> Tip: jedna výhoda, jeden háček, jedna věta s názorem.
|
||||
|
||||
|
||||
# Čtení
|
||||
|
||||
A repair café opened in a former bakery. Broken radios are mended there on Saturdays. The founder said that people would rather repair than buy if they were shown how. She told a reporter that twenty kettles had been saved in March. Visitors have to bring the broken object, but they don't have to pay. If the café closed, a lot of working parts would be thrown away.
|
||||
|
||||
## What happens to radios there?
|
||||
- They are sold
|
||||
- [x] They are mended
|
||||
- They are banned
|
||||
- They are thrown away at once
|
||||
> are mended.
|
||||
|
||||
## How many kettles had been saved in March?
|
||||
- Twelve
|
||||
- [x] Twenty
|
||||
- Two thousand
|
||||
- None
|
||||
> twenty kettles.
|
||||
|
||||
## What would happen if the café closed?
|
||||
- [x] Parts would be thrown away
|
||||
- Radios would be cheaper
|
||||
- People would pay more
|
||||
- The bakery would reopen as a shop
|
||||
> working parts would be thrown away.
|
||||
|
||||
|
||||
# Poslech
|
||||
|
||||
Editor: Did the mayor answer you? Journalist: I asked him whether the bridge was safe. He said he didn't know. I also asked how long the repairs would take. He told me that the firm hadn't decided. A resident asked me why the paper hadn't printed a map. I said we would print one tomorrow.
|
||||
|
||||
## What did the journalist ask about safety?
|
||||
- [x] Whether the bridge was safe
|
||||
- If the paper was closed
|
||||
- Where the mayor lived
|
||||
- Why kettles break
|
||||
> whether the bridge was safe.
|
||||
|
||||
## What hadn't the firm done?
|
||||
- [x] Decided
|
||||
- Printed a map
|
||||
- Closed the paper
|
||||
- Asked the resident
|
||||
> hadn't decided.
|
||||
|
||||
## What did the journalist promise?
|
||||
- To close the bridge
|
||||
- [x] To print a map tomorrow
|
||||
- To repair the cables
|
||||
- To interview a baker
|
||||
> we would print one tomorrow.
|
||||
|
||||
|
||||
# Psaní
|
||||
|
||||
In at least 40 words, give one reason for repairing things and one objection. Use because and however.
|
||||
|
||||
## Vzorová odpověď
|
||||
|
||||
Repairing things matters because a kettle can work for years after a small fix. However, some people do not have the tools or the time, so a café where volunteers help is a fair idea. I believe every town should have one quiet room for broken objects. It is slower than shopping, but it is kinder.
|
||||
|
||||
## Musí obsahovat
|
||||
|
||||
- because
|
||||
- however
|
||||
|
||||
## Minimum slov
|
||||
|
||||
40
|
||||
|
||||
|
||||
# Kvíz
|
||||
|
||||
## The cake ___ by a student.
|
||||
- baked
|
||||
- [x] was baked
|
||||
- was bake
|
||||
- has bake
|
||||
> was baked.
|
||||
|
||||
## She asked me where I ___.
|
||||
- did live
|
||||
- [x] lived
|
||||
- do live
|
||||
- living
|
||||
> where I lived.
|
||||
|
||||
## He ___ be at school. I just saw him there.
|
||||
- can't
|
||||
- [x] must
|
||||
- mustn't
|
||||
- should to
|
||||
> Skoro jistota: must.
|
||||
|
||||
## Please look ___ the tickets. I can't find them.
|
||||
- [x] for
|
||||
- forward
|
||||
- after
|
||||
- up of
|
||||
> Look for = hledat. Look after by bylo hlídat.
|
||||
4
content/anglictina/4-rocnik/01-maturitni-karticka.en.md
Normal file
4
content/anglictina/4-rocnik/01-maturitni-karticka.en.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
nazev: The speaking card
|
||||
popis: Speaking-exam strategy and personal-topic collocations. A quiz and gaps.
|
||||
---
|
||||
82
content/anglictina/4-rocnik/01-maturitni-karticka.md
Normal file
82
content/anglictina/4-rocnik/01-maturitni-karticka.md
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
---
|
||||
id: anglictina-4-maturitni-karticka
|
||||
puvodni: en.4.1
|
||||
nazev: Maturitní kartička
|
||||
popis: Strategie ústní zkoušky a kolokace osobních témat. Kvíz a doplňování.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## Čtyři minuty nejsou román
|
||||
*Ústní zkouška*
|
||||
|
||||
- Úvod jednou větou: I'd like to talk about my town, which is smaller than it looks.
|
||||
- Obecné plus osobní: Many people commute. I cycle, because the centre is close.
|
||||
- Když slovo chybí, opis: the thing you use to open a tin.
|
||||
- Na obrázku: In the foreground, in the background, it looks as if.
|
||||
|
||||
> Tip: katalog CERMAT chce souvislý projev, popis obrázku, porovnání a reakci na otázky. Ne seznam slov.
|
||||
|
||||
## Make, do, have, take
|
||||
*Kolokace*
|
||||
|
||||
- Make a decision, make friends, make the bed.
|
||||
- Do the washing-up, do a course, do someone a favour.
|
||||
- Take part in, take care of, take an exam.
|
||||
- Have a look, have a word with, have trouble with.
|
||||
|
||||
> Tip: české „dělat“ se rozpadá. Do homework, make a mistake, take a photo, have a rest.
|
||||
|
||||
|
||||
# Doplňování
|
||||
|
||||
## I need to ___ a decision before Friday.
|
||||
= make
|
||||
> Make a decision.
|
||||
|
||||
## She ___ her homework on the train.
|
||||
= does|did
|
||||
> Do homework.
|
||||
|
||||
## Can I ___ a photo of the bridge?
|
||||
= take
|
||||
> Take a photo.
|
||||
|
||||
## Let's ___ a rest. We've walked for hours.
|
||||
= have
|
||||
> Have a rest.
|
||||
|
||||
## He ___ part in the school play every year.
|
||||
= takes|took
|
||||
> Take part in.
|
||||
|
||||
|
||||
# Kvíz
|
||||
|
||||
## You don't know the word kettle. What helps?
|
||||
- Stop the exam
|
||||
- [x] Paraphrase it
|
||||
- Switch to Czech for the rest
|
||||
- Invent a Latin word and insist
|
||||
> Opis je lepší než ticho.
|
||||
|
||||
## In the foreground means…
|
||||
- at the back
|
||||
- [x] at the front of the picture
|
||||
- outside the frame
|
||||
- in the past
|
||||
> Foreground = popředí.
|
||||
|
||||
## Which collocation is right?
|
||||
- do a mistake
|
||||
- [x] make a mistake
|
||||
- take a mistake
|
||||
- have a mistake
|
||||
> Make a mistake.
|
||||
|
||||
## A strong speaking answer…
|
||||
- is a list of single words
|
||||
- [x] adds a personal example
|
||||
- translates the question
|
||||
- avoids all verbs
|
||||
> Obecné plus vlastní příklad.
|
||||
4
content/anglictina/4-rocnik/02-formalni-e-mail.en.md
Normal file
4
content/anglictina/4-rocnik/02-formalni-e-mail.en.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
nazev: A formal email
|
||||
popis: A request and a complaint. Writing and a register quiz.
|
||||
---
|
||||
78
content/anglictina/4-rocnik/02-formalni-e-mail.md
Normal file
78
content/anglictina/4-rocnik/02-formalni-e-mail.md
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
---
|
||||
id: anglictina-4-formalni-e-mail
|
||||
puvodni: en.4.2
|
||||
nazev: Formální e-mail
|
||||
popis: Žádost a stížnost. Psaní a kvíz rejstříku.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## Komu, proč, co chcete, jak se loučíte
|
||||
*Kostra*
|
||||
|
||||
- I am writing to apply for… / to complain about…
|
||||
- I would be grateful if you could…
|
||||
- Kontrakce v čistě formálním textu omezte: I am, not I'm.
|
||||
- Na konci celé jméno. Žádné Cheers ani xoxo.
|
||||
|
||||
> Tip: neznámé jméno → Dear Sir or Madam a Yours faithfully. Známé jméno → Dear Ms Novák a Yours sincerely.
|
||||
|
||||
## Fakta, dopad, žádost
|
||||
*Stížnost*
|
||||
|
||||
- The train on 3 May, which I had booked, arrived 90 minutes late.
|
||||
- As a result I missed the interview.
|
||||
- I would like a refund or an explanation.
|
||||
- I look forward to your reply.
|
||||
|
||||
> Tip: zlost text oslabuje. Datum, číslo spoje a klidná žádost ho posílí.
|
||||
|
||||
|
||||
# Psaní
|
||||
|
||||
Write a formal email of at least 55 words to a railway company. Complain about a delay. Start with Dear, use would, and end with sincerely or faithfully.
|
||||
|
||||
## Vzorová odpověď
|
||||
|
||||
Dear Sir or Madam, I am writing to complain about the night train to Berlin on 3 May. It arrived ninety minutes late, so I missed a morning interview. I would be grateful if you could explain the delay and offer a refund. I have attached my ticket. Please reply to this address. Yours faithfully, Tereza Malá.
|
||||
|
||||
## Musí obsahovat
|
||||
|
||||
- dear
|
||||
- would
|
||||
- faithfully
|
||||
|
||||
## Minimum slov
|
||||
|
||||
55
|
||||
|
||||
|
||||
# Kvíz
|
||||
|
||||
## You do not know the person's name. You end with…
|
||||
- [x] Yours faithfully
|
||||
- Yours sincerely
|
||||
- Cheers
|
||||
- Love
|
||||
> Neznámé jméno: faithfully. Po Dear Sir or Madam.
|
||||
|
||||
## Dear Ms Novák, … ___
|
||||
- Yours faithfully
|
||||
- [x] Yours sincerely
|
||||
- Hi again
|
||||
- Bye
|
||||
> Jméno znáte: sincerely.
|
||||
|
||||
## Which opening is formal?
|
||||
- Hey!!!
|
||||
- [x] I am writing to apply for the post.
|
||||
- I wanna the job.
|
||||
- What's up
|
||||
> I am writing to…
|
||||
|
||||
## A formal request sounds like…
|
||||
- Give me a refund now.
|
||||
- [x] I would be grateful if you could look into this.
|
||||
- You guys messed up.
|
||||
- Send money pls.
|
||||
> I would be grateful if you could…
|
||||
4
content/anglictina/4-rocnik/03-nocni-vlak.en.md
Normal file
4
content/anglictina/4-rocnik/03-nocni-vlak.en.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
nazev: The night train
|
||||
popis: A longer reading in the style of the written paper. Four questions.
|
||||
---
|
||||
68
content/anglictina/4-rocnik/03-nocni-vlak.md
Normal file
68
content/anglictina/4-rocnik/03-nocni-vlak.md
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
---
|
||||
id: anglictina-4-nocni-vlak
|
||||
puvodni: en.4.3
|
||||
nazev: Noční vlak
|
||||
popis: Delší čtení ve stylu didaktického testu. Čtyři otázky k článku.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## Nečtěte každé slovo stejně pomalu
|
||||
*Čtení u maturity*
|
||||
|
||||
- Hlavní myšlenka bývá v úvodu nebo v závěru, ne v jednom příkladu.
|
||||
- Distraktor často opakuje slovo z textu, ale v jiném vztahu.
|
||||
- Which surprises… uvádí postoj, ne jen fakt o ceně.
|
||||
- Not given v tomhle cvičení není. Jedna možnost je opřená o text.
|
||||
|
||||
> Tip: u výběru ze čtyř možností nejdřív zjistěte, na co se otázka ptá, a teprve pak hledejte odstavec.
|
||||
|
||||
## Boarding gate a carriage
|
||||
*Slovník z kontextu*
|
||||
|
||||
- A boarding gate je letištní východ k letadlu. Text ho staví proti posteli ve vlaku.
|
||||
- A carriage je vůz vlaku.
|
||||
- Demand = poptávka. If demand stays high, přidají vozy.
|
||||
- Deleted journey by byl let, který člověk chce mít co nejkratší.
|
||||
|
||||
> Tip: neznámé slovo ohraničte větou před ním a za ním.
|
||||
|
||||
|
||||
# Čtení
|
||||
|
||||
When the night train from Prague to Berlin returned last spring, stations filled with people who prefer a bed to a boarding gate. A single ticket is often more expensive than a flight, which surprises anyone who thinks trains are always the cheap choice. Still, passengers say they arrive calmer. They can read, talk and avoid the bright shops of an airport. Critics point out that a delay of two hours is common and that the cabins are small. The railway has promised that new carriages will be added if demand stays high. A student I spoke to had taken the train three times. She said she would fly only if she missed the evening departure. For her, the journey is part of the trip, not a problem to be deleted.
|
||||
|
||||
## What is the main point?
|
||||
- Flights have been cancelled
|
||||
- [x] Some people choose the night train even when it costs more
|
||||
- Berlin has closed its station
|
||||
- Students may not travel
|
||||
> Lístek bývá dražší než let, a přesto lidé vlak volí.
|
||||
|
||||
## What surprises some readers?
|
||||
- [x] That a train ticket can cost more than a flight
|
||||
- That stations are empty
|
||||
- That nobody reads
|
||||
- That the train is free
|
||||
> more expensive than a flight, which surprises…
|
||||
|
||||
## What do critics mention?
|
||||
- Free meals
|
||||
- [x] Delays and small cabins
|
||||
- Too many books
|
||||
- A lack of stations
|
||||
> a delay of two hours, cabins are small.
|
||||
|
||||
## The student would fly only if…
|
||||
- the ticket was cheap
|
||||
- [x] she missed the evening departure
|
||||
- the cabins were small
|
||||
- she hated reading
|
||||
> only if she missed the evening departure.
|
||||
|
||||
## New carriages will be added if…
|
||||
- critics agree
|
||||
- [x] demand stays high
|
||||
- flights are banned
|
||||
- students complain
|
||||
> if demand stays high.
|
||||
4
content/anglictina/4-rocnik/04-tabor-ve-walesu.en.md
Normal file
4
content/anglictina/4-rocnik/04-tabor-ve-walesu.en.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
nazev: A camp in Wales
|
||||
popis: A longer listening: an interview. Five questions.
|
||||
---
|
||||
68
content/anglictina/4-rocnik/04-tabor-ve-walesu.md
Normal file
68
content/anglictina/4-rocnik/04-tabor-ve-walesu.md
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
---
|
||||
id: anglictina-4-tabor-ve-walesu
|
||||
puvodni: en.4.4
|
||||
nazev: Tábor ve Walesu
|
||||
popis: Delší poslech: pohovor. Pět otázek.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## Dvě přehrání stačí, když víte co
|
||||
*Poslech u maturity*
|
||||
|
||||
- Otázky si přečtěte dřív. Podtrhněte tázací slovo.
|
||||
- Čísla a never/already mění význam celé věty.
|
||||
- Wouldn't force není couldn't.
|
||||
- I didn't give him any medicine je důležité právě proto, že je zápor.
|
||||
|
||||
> Tip: při prvním poslechu chyťte kostru, při druhém doplňte past, podmínku a zápor.
|
||||
|
||||
## Slovník pohovoru
|
||||
*Práce s dětmi*
|
||||
|
||||
- For two years je délka, ne bod v čase.
|
||||
- A quieter task je alternativa, ne trest.
|
||||
- Although přiznává nevýhodu a názor nemění.
|
||||
- Boots jsou důkaz, že s deštěm počítá. Proto going to / already.
|
||||
|
||||
> Tip: deal with an emergency, refuse, offer, look forward to.
|
||||
|
||||
|
||||
# Poslech
|
||||
|
||||
Interviewer: Why did you apply to the summer camp in Wales? Hana: I have worked with children for two years, and I wanted a job where English is the only language. Interviewer: What would you do if a child refused to join an activity? Hana: I wouldn't force them. I would ask why, and I might offer a quieter task. Interviewer: Have you ever dealt with an emergency? Hana: Yes. Last August a boy cut his foot. I cleaned the cut and called the nurse. I didn't give him any medicine. Interviewer: The camp is rainy. Is that a problem? Hana: Not really. I have already bought boots. I look forward to the hills, although I know the work will be tiring.
|
||||
|
||||
## Why does Hana want the job?
|
||||
- She has never met children
|
||||
- [x] She wants a job where only English is spoken
|
||||
- She hates hills
|
||||
- She wants to sell boots
|
||||
> where English is the only language.
|
||||
|
||||
## How long has she worked with children?
|
||||
- For two weeks
|
||||
- [x] For two years
|
||||
- Since last August only
|
||||
- She hasn't
|
||||
> for two years.
|
||||
|
||||
## What would she do if a child refused an activity?
|
||||
- Force them
|
||||
- Send them home
|
||||
- [x] Ask why and maybe offer a quieter task
|
||||
- Give them medicine
|
||||
> I wouldn't force them. I might offer a quieter task.
|
||||
|
||||
## What didn't she do in the emergency?
|
||||
- Clean the cut
|
||||
- Call the nurse
|
||||
- [x] Give medicine
|
||||
- Help the boy
|
||||
> I didn't give him any medicine.
|
||||
|
||||
## How does she feel about the rain?
|
||||
- [x] She has already bought boots and still looks forward to the hills
|
||||
- She will refuse the job
|
||||
- She has never seen rain
|
||||
- She hates children
|
||||
> already bought boots, look forward to the hills.
|
||||
4
content/anglictina/4-rocnik/05-nazorova-esej.en.md
Normal file
4
content/anglictina/4-rocnik/05-nazorova-esej.en.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
nazev: An opinion essay
|
||||
popis: Opinion-essay structure. An essay and a quiz about paragraphs.
|
||||
---
|
||||
78
content/anglictina/4-rocnik/05-nazorova-esej.md
Normal file
78
content/anglictina/4-rocnik/05-nazorova-esej.md
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
---
|
||||
id: anglictina-4-nazorova-esej
|
||||
puvodni: en.4.5
|
||||
nazev: Názorová esej
|
||||
popis: Struktura názoru. Esej a kvíz o odstavcích.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## Nejdřív stanovisko, pak důvody
|
||||
*Názor*
|
||||
|
||||
- I believe that… / In my opinion…
|
||||
- First reason, second reason, a short answer to the other side.
|
||||
- Although some people argue that…, I still think…
|
||||
- Závěr ať zní jako závěr, ne jako třetí nový důvod.
|
||||
|
||||
> Tip: u názorové eseje čtenář nemá hádat, na čí straně jste. Řekněte to v úvodu.
|
||||
|
||||
## Radši čtyři hutné věty než deset prázdných
|
||||
*Rozsah*
|
||||
|
||||
- Každý důvod ať má příklad z běžného života.
|
||||
- Nepoužívejte etc. Místo toho jedno konkrétní slovo.
|
||||
- Spojky: firstly, in addition, on the other hand, in conclusion.
|
||||
- Kontraktované tvary jsou v názorové eseji v pořádku, když text není stížnost úřadu.
|
||||
|
||||
> Tip: u písemné práce se počítají slova. Opakování zadání se nepočítá jako myšlenka.
|
||||
|
||||
|
||||
# Psaní
|
||||
|
||||
Write an opinion of at least 60 words: should students have a gap year before university? Use believe, although and in conclusion.
|
||||
|
||||
## Vzorová odpověď
|
||||
|
||||
I believe a gap year can help, but only when it has a plan. Although some students waste the time, others work, travel or look after a relative and return calmer. A year in a job also shows whether a degree is really necessary. On the other hand, a long break can make it harder to study again. In conclusion, a gap year is useful if the person can explain what they will do with it.
|
||||
|
||||
## Musí obsahovat
|
||||
|
||||
- believe
|
||||
- although
|
||||
- conclusion
|
||||
|
||||
## Minimum slov
|
||||
|
||||
60
|
||||
|
||||
|
||||
# Kvíz
|
||||
|
||||
## Where should your opinion appear in this kind of essay?
|
||||
- Only in a footnote
|
||||
- [x] In the introduction and again at the end
|
||||
- Never
|
||||
- Only in the title
|
||||
> Úvod i závěr.
|
||||
|
||||
## Although introduces…
|
||||
- [x] a concession
|
||||
- a list of books
|
||||
- a greeting
|
||||
- a date
|
||||
> Ústupka: something true that does not win.
|
||||
|
||||
## In conclusion should…
|
||||
- start a brand-new topic
|
||||
- [x] sum up
|
||||
- replace the introduction
|
||||
- ask the examiner a question
|
||||
> Shrnutí.
|
||||
|
||||
## Which is the best topic sentence?
|
||||
- Gap year gap year gap year.
|
||||
- [x] A gap year is worth it when it has a clear plan.
|
||||
- Hello my name is and I will write.
|
||||
- Etc. etc. etc.
|
||||
> Věta, která už nese názor.
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
nazev: Topic vocabulary
|
||||
popis: Collocations for the exam topics. Gaps and a quiz.
|
||||
---
|
||||
82
content/anglictina/4-rocnik/06-slovni-zasoba-okruhu.md
Normal file
82
content/anglictina/4-rocnik/06-slovni-zasoba-okruhu.md
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
---
|
||||
id: anglictina-4-slovni-zasoba-okruhu
|
||||
puvodni: en.4.6
|
||||
nazev: Slovní zásoba okruhů
|
||||
popis: Kolokace k maturitním tématům. Doplňování a kvíz.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## Ne izolovaná slovíčka
|
||||
*Okruhy*
|
||||
|
||||
- Heavy rain, strong coffee, fast food, junk food. Ne strong rain.
|
||||
- A balanced diet, processed food, a food allergy.
|
||||
- Public transport, rush hour, a traffic jam, a return ticket.
|
||||
- Renewable energy, a carbon footprint, a heatwave, a drought.
|
||||
|
||||
> Tip: ústní zkouška sahá na osobu, rodinu, domov, školu, volný čas, kulturu, sport, cestování, zdraví, jídlo, služby, práci, společnost a přírodu.
|
||||
|
||||
## Fráze, které unesou odstavec
|
||||
*Společnost a práce*
|
||||
|
||||
- A gap year, an apprenticeship, a degree, tuition fees.
|
||||
- Freedom of speech, a stereotype, volunteer work.
|
||||
- Break the law, pay a fine, a witness.
|
||||
- Mental health, a check-up, be in pain. Ne have pain in the leg jako jediná možnost: My leg hurts.
|
||||
|
||||
> Tip: apply for a job, hand in a notice, earn a living, from home.
|
||||
|
||||
|
||||
# Doplňování
|
||||
|
||||
## There was heavy ___ all night.
|
||||
= rain
|
||||
> Heavy rain, ne strong rain.
|
||||
|
||||
## I'd like a ___ ticket to Brno.
|
||||
= return
|
||||
> Return ticket = zpáteční.
|
||||
|
||||
## She applied ___ the post of guide.
|
||||
= for
|
||||
> Apply for.
|
||||
|
||||
## Solar power is ___ energy.
|
||||
= renewable
|
||||
> Renewable energy.
|
||||
|
||||
## He has a nut ___, so he can't eat the cake.
|
||||
= allergy
|
||||
> A food allergy.
|
||||
|
||||
|
||||
# Kvíz
|
||||
|
||||
## Which pair is right?
|
||||
- strong rain / heavy coffee
|
||||
- [x] heavy rain / strong coffee
|
||||
- fast coffee / junk rain
|
||||
- a traffic diet
|
||||
> Heavy rain, strong coffee.
|
||||
|
||||
## Rush hour is…
|
||||
- a quiet morning
|
||||
- [x] the busiest time to travel
|
||||
- a kind of ticket
|
||||
- a school subject
|
||||
> Špička.
|
||||
|
||||
## An apprenticeship is…
|
||||
- a fine
|
||||
- [x] training for a job
|
||||
- a heatwave
|
||||
- a stereotype
|
||||
> Praktická příprava na řemeslo nebo práci.
|
||||
|
||||
## My leg ___.
|
||||
- [x] hurts
|
||||
- is pain
|
||||
- has hurted
|
||||
- does hurtness
|
||||
> My leg hurts.
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
nazev: Grammar clinic
|
||||
popis: Mixed points for the language paper. A quiz and gaps.
|
||||
---
|
||||
96
content/anglictina/4-rocnik/07-gramaticka-ambulance.md
Normal file
96
content/anglictina/4-rocnik/07-gramaticka-ambulance.md
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
---
|
||||
id: anglictina-4-gramaticka-ambulance
|
||||
puvodni: en.4.7
|
||||
nazev: Gramatická ambulance
|
||||
popis: Smíšené jevy k didaktickému testu. Kvíz a doplňování.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## To, co se v testu sype
|
||||
*Články a časy*
|
||||
|
||||
- I have lived here since May. I lived there in 2018.
|
||||
- If I were you, I would wait. If it rains, we will wait.
|
||||
- The book was written in 1962. People speak English here → English is spoken here.
|
||||
- Used to: I used to walk. Zvyk, který už neplatí. Didn't use to.
|
||||
|
||||
> Tip: the night train, a night train, night trains. Člen podle toho, jestli čtenář ví který.
|
||||
|
||||
## Slovosled a shoda
|
||||
*Věta*
|
||||
|
||||
- A little time, a few minutes. Much v záporu a otázce, a lot of v kladné větě je bezpečné.
|
||||
- Suggest + -ing nebo suggest that. Suggest me to go je chyba.
|
||||
- Enjoy, avoid, mind, can't help + -ing.
|
||||
- Want, decide, promise, hope + to.
|
||||
|
||||
> Tip: never dávejte před sloveso, ale za am/is/are: She is never late. She never arrives late.
|
||||
|
||||
|
||||
# Doplňování
|
||||
|
||||
## I ___ (live) in this flat since May.
|
||||
= have lived|'ve lived
|
||||
> Since → present perfect.
|
||||
|
||||
## She suggested ___ (take) the night train.
|
||||
= taking
|
||||
> Suggest + -ing.
|
||||
|
||||
## If I ___ you, I would book earlier.
|
||||
= were|was
|
||||
> If I were you.
|
||||
|
||||
## These letters must ___ (sign) today.
|
||||
= be signed
|
||||
> Must be + příčestí.
|
||||
|
||||
## I ___ to get up at five. I don't anymore.
|
||||
= used
|
||||
> Used to.
|
||||
|
||||
|
||||
# Kvíz
|
||||
|
||||
## She enjoys ___.
|
||||
- to swim
|
||||
- [x] swimming
|
||||
- swim
|
||||
- swam
|
||||
> Enjoy + -ing.
|
||||
|
||||
## I have ___ finished.
|
||||
- yet
|
||||
- [x] just
|
||||
- since
|
||||
- ago
|
||||
> Just before the participle. Yet belongs at the end in negatives.
|
||||
|
||||
## English ___ all over the building.
|
||||
- speaks
|
||||
- [x] is spoken
|
||||
- is spoke
|
||||
- speak
|
||||
> Trpný rod.
|
||||
|
||||
## There isn't ___ time.
|
||||
- many
|
||||
- [x] much
|
||||
- a few
|
||||
- several
|
||||
> Time je nepočitatelné: much.
|
||||
|
||||
## He asked me where ___.
|
||||
- did I live
|
||||
- [x] I lived
|
||||
- do I lived
|
||||
- lived I
|
||||
> Bez inverze.
|
||||
|
||||
## You ___ shout. The baby is asleep. It is forbidden.
|
||||
- don't have to
|
||||
- [x] mustn't
|
||||
- might
|
||||
- used to
|
||||
> Zákaz: mustn't.
|
||||
4
content/anglictina/4-rocnik/08-cvicna-maturita.en.md
Normal file
4
content/anglictina/4-rocnik/08-cvicna-maturita.en.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
nazev: A practice paper
|
||||
popis: Reading, listening, language in use and a short piece of writing.
|
||||
---
|
||||
143
content/anglictina/4-rocnik/08-cvicna-maturita.md
Normal file
143
content/anglictina/4-rocnik/08-cvicna-maturita.md
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
---
|
||||
id: anglictina-4-cvicna-maturita
|
||||
puvodni: en.4.8
|
||||
nazev: Cvičná maturita
|
||||
popis: Čtení, poslech, jazyková kompetence a krátká písemná práce.
|
||||
---
|
||||
|
||||
# Výklad
|
||||
|
||||
## Tři části, jeden mozek
|
||||
*Celá zkouška*
|
||||
|
||||
- Nejdřív přečtěte zadání psaní, ať víte, kolik času si necháte.
|
||||
- U čtení nehledejte stejná slova. Hledejte stejný význam.
|
||||
- U poslechu zápor bývá ta správná odpověď.
|
||||
- Když váháte mezi dvěma, vyhoďte tu, která přidává informaci v textu neslyšenou.
|
||||
|
||||
> Tip: didaktický test míchá poslech, čtení a jazykovou kompetenci. Písemná práce je zvlášť. Tady je zmenšený model.
|
||||
|
||||
## Účel, čtenář, rozsah
|
||||
*Písemná práce*
|
||||
|
||||
- Řekněte proč píšete hned v první větě.
|
||||
- Dejte tam čas a místo, ať text není mlha.
|
||||
- Jedna věta s because a jedna s if textu pomůžou.
|
||||
- Na konci otázka, která zní jako opravdový zájem.
|
||||
|
||||
> Tip: e-mail kamarádovi a stížnost úřadu se nepíšou stejným jazykem. Tady jde o kamaráda.
|
||||
|
||||
|
||||
# Čtení
|
||||
|
||||
The town library now lends tools as well as books. Hammers, sewing machines and a cake tin can be borrowed for a week. The idea came from a librarian who was tired of people buying things they would use once. She said the workshop had been visited by more teenagers than the reading room. Critics argue that a library should stay quiet. She replies that a library should be useful. If the experiment works, other branches will copy it. Users have to return each object clean, and they must not lend it to anyone else.
|
||||
|
||||
## What can people borrow besides books?
|
||||
- Cars
|
||||
- [x] Tools
|
||||
- Flats
|
||||
- Tickets to Berlin
|
||||
> Hammers, sewing machines, a cake tin.
|
||||
|
||||
## Why did the idea start?
|
||||
- [x] People were buying things they would use once
|
||||
- The reading room was too popular
|
||||
- Teenagers hated books
|
||||
- The tools were illegal
|
||||
> buying things they would use once.
|
||||
|
||||
## Who has visited the workshop more, according to her?
|
||||
- Critics
|
||||
- [x] Teenagers, more than the reading room
|
||||
- Other branches
|
||||
- Nobody
|
||||
> more teenagers than the reading room.
|
||||
|
||||
## What must users not do?
|
||||
- Return the object
|
||||
- Clean it
|
||||
- [x] Lend it to someone else
|
||||
- Visit the library
|
||||
> must not lend it to anyone else.
|
||||
|
||||
|
||||
# Poslech
|
||||
|
||||
Welcome to the night-train podcast. The 22:40 to Berlin has been delayed by forty minutes because a tree is on the line near Ústí. Passengers who already have a seat can wait in carriage four, where tea is being served. If you have not checked in, please do it on your phone. We would be grateful if you kept the corridor clear. The delay might be shorter. We will know more at ten.
|
||||
|
||||
## How long is the delay?
|
||||
- 14 minutes
|
||||
- [x] 40 minutes
|
||||
- 4 hours
|
||||
- 22 minutes
|
||||
> forty minutes.
|
||||
|
||||
## Why?
|
||||
- Snow
|
||||
- [x] A tree on the line
|
||||
- A missing driver
|
||||
- A festival
|
||||
> a tree is on the line.
|
||||
|
||||
## Where can passengers with a seat wait?
|
||||
- [x] Carriage four
|
||||
- The airport
|
||||
- Ústí station only
|
||||
- The corridor
|
||||
> carriage four.
|
||||
|
||||
## What should people without a check-in do?
|
||||
- Buy tea
|
||||
- [x] Check in on their phone
|
||||
- Leave the train
|
||||
- Call the mayor
|
||||
> do it on your phone.
|
||||
|
||||
|
||||
# Psaní
|
||||
|
||||
Write at least 45 words to a friend. Invite them to borrow something from a library of things. Use because and if.
|
||||
|
||||
## Vzorová odpověď
|
||||
|
||||
Hi Adam, the library now lends tools, and I think you would like it because you always need a drill for one afternoon. If you come on Saturday, I will show you how it works. You have to bring your card and return everything clean. We could borrow a cake tin and bake something after. Let me know if you are free.
|
||||
|
||||
## Musí obsahovat
|
||||
|
||||
- because
|
||||
- if
|
||||
|
||||
## Minimum slov
|
||||
|
||||
45
|
||||
|
||||
|
||||
# Kvíz
|
||||
|
||||
## Tea ___ in carriage four.
|
||||
- serves
|
||||
- [x] is being served
|
||||
- is serving
|
||||
- has serve
|
||||
> Průběhový trpný rod.
|
||||
|
||||
## We would be grateful if you ___ the corridor clear.
|
||||
- keep
|
||||
- [x] kept
|
||||
- keeping
|
||||
- to keep
|
||||
> Would be grateful if + minulý tvar.
|
||||
|
||||
## She said the workshop ___ by more teenagers.
|
||||
- visited
|
||||
- [x] had been visited
|
||||
- has visit
|
||||
- is visiting
|
||||
> Had been visited.
|
||||
|
||||
## Users ___ return the tools clean.
|
||||
- [x] have to
|
||||
- must to
|
||||
- don't must
|
||||
- are have
|
||||
> Have to.
|
||||
160
content/aplikace/novinky.txt
Normal file
160
content/aplikace/novinky.txt
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
# User-facing notes, newest first. Folded into content.json for every app.
|
||||
# After an update the home screen shows the latest blocks until dismissed.
|
||||
#
|
||||
# --- YYYY-MM-DD
|
||||
# cs: bullet
|
||||
# en: bullet
|
||||
|
||||
--- 2026-10-07
|
||||
cs: Sítě a technické vybavení: doplněné 2. až 4. ročníky, v každém 8 lekcí
|
||||
cs: Výklad a kvíz od VLAN a sestavení počítače po maturitu
|
||||
en: Networks and hardware: years 2 to 4 are filled in, eight lessons each
|
||||
en: Slides and a quiz, from VLANs and PC assembly through to the exam
|
||||
|
||||
--- 2026-10-07
|
||||
cs: Němčina: čtyři ročníky, 24 lekcí s poslechem, čtením a psaním
|
||||
cs: Učebnice Neue Freunde zůstává, k ní přibyl kurz od A1 k B1
|
||||
en: German: four years, 24 lessons with listening, reading and writing
|
||||
en: The Neue Freunde textbook stays, and a course from A1 to B1 sits beside it
|
||||
|
||||
--- 2026-10-07
|
||||
cs: Angličtina: čtyři ročníky, 32 lekcí podle osnov gymnázia
|
||||
cs: Poslech, čtení, psaní, doplňování, kvízy a testy od A2 k maturitě
|
||||
en: English: four years, 32 lessons from the gymnasium syllabus
|
||||
en: Listening, reading, writing, gap-fill, quizzes and tests from A2 to the exam
|
||||
|
||||
--- 2026-10-06
|
||||
cs: Matematika: opakování základní školy a čtyři ročníky, 40 lekcí
|
||||
cs: Příklady se píšou a kontrolují, u geometrie se rýsuje na mřížku
|
||||
en: Mathematics: elementary review and four years, 40 lessons
|
||||
en: Examples are typed and checked, and some geometry is drawn on a grid
|
||||
|
||||
--- 2026-10-06
|
||||
cs: Fyzika: čtyři ročníky, 32 lekcí podle osnov středních škol
|
||||
cs: Od mechaniky přes teplo a elektřinu až po optiku, jádro a astrofyziku
|
||||
en: Physics: four years, 32 lessons from the secondary-school syllabus
|
||||
en: From mechanics through heat and electricity to optics, the nucleus and astrophysics
|
||||
|
||||
--- 2026-10-06
|
||||
cs: Základy přírodopisných věd: chemie a biologie, v každé 8 lekcí podle osnov
|
||||
cs: Každá lekce má výklad a kvíz se čtyřmi otázkami
|
||||
en: Natural sciences: chemistry and biology, eight lessons each, from the syllabus
|
||||
en: Every lesson has an overview and a four-question quiz
|
||||
cs: Český jazyk: literatura ve čtyřech ročnících podle osnov středních škol
|
||||
cs: 32 lekcí od starověku po současnost, každá s výkladem a kvízem
|
||||
en: Czech: literature across four years, following the secondary-school syllabus
|
||||
en: 32 lessons from antiquity to the present, each with an overview and a quiz
|
||||
|
||||
--- 2026-10-03
|
||||
cs: Občanská nauka: 4. ročník, 16 lekcí (hospodářství, svět a filozofie)
|
||||
en: Civics: year 4, 16 lessons (the economy, the world and philosophy)
|
||||
|
||||
--- 2026-10-02
|
||||
cs: Občanská nauka: 1. ročník, 17 lekcí (člověk v lidském společenství)
|
||||
cs: Občanská nauka: 2. ročník, 16 lekcí (člověk jako občan)
|
||||
cs: Občanská nauka: 3. ročník, 16 lekcí (člověk a právo)
|
||||
en: Civics: year 1, 17 lessons (the individual and society)
|
||||
en: Civics: year 2, 16 lessons (the citizen in a democratic state)
|
||||
en: Civics: year 3, 16 lessons (the individual and the law)
|
||||
|
||||
--- 2026-09-25
|
||||
cs: Technické vybavení: pět lekcí o digitalizaci zvuku (vzorkování, kvantování, PCM)
|
||||
cs: Technické vybavení: skříň, zdroj, deska, CPU, karty, disky a vstupní zařízení
|
||||
cs: Technické vybavení: dosavadní lekce jsou 1. ročník, další ročníky jsou zatím zamčené
|
||||
en: Hardware: five lessons on digitizing sound (sampling, quantization, PCM)
|
||||
en: Hardware: case, PSU, board, CPU, cards, drives and input devices
|
||||
en: Hardware: current lessons are year 1; later years are still locked
|
||||
|
||||
--- 2026-09-23
|
||||
cs: Repozitář se jmenuje Graduately; instalátory a updater míří tam
|
||||
cs: Balíčky a instalátory se jmenují graduately-* (už ne maturita-*)
|
||||
cs: Aplikace se jmenuje Graduately; úvod stále říká „Maturita? To dáme.“
|
||||
cs: Kompletní maturitní četba (82 knih) se zápisky, kvízem a sestavením děje
|
||||
cs: Studium knih: nejdřív procvičení (kvíz / sestavte děj), pak zápisky
|
||||
cs: Kvíz a sestavení děje u všech knih i na GTK (Linux / Windows)
|
||||
cs: Větší a čitelnější rozhraní na Macu
|
||||
cs: Opravy výběru slov v dialogu a otevření knihy z vyhledávání
|
||||
en: Repository renamed to Graduately; installers and updater follow
|
||||
en: Packages and installers are now graduately-* (no more maturita-*)
|
||||
en: The app is now Graduately; the welcome line still says “Maturita? We've got this.”
|
||||
en: Full maturita reading list (82 books) with notes, quiz, and plot ordering
|
||||
en: Book study flow: practice first (quiz / order the plot), then notes
|
||||
en: Quiz and plot assembly for every book on GTK too (Linux / Windows)
|
||||
en: Larger, more readable Mac interface
|
||||
en: Fixes for dialogue word picking and opening a book from search
|
||||
|
||||
--- 2026-09-18
|
||||
cs: Po aktualizaci se na hlavní stránce ukáže, co je nového
|
||||
cs: Android aplikace se stejnými cvičeními a funkčním updaterem
|
||||
cs: iOS aplikace nativně na iOS 26 (Liquid Glass) z Maturita.xcworkspace
|
||||
en: After an update the home screen shows what is new
|
||||
en: Android app with the same exercises and a working updater
|
||||
en: Native iOS 26 app (Liquid Glass) from Maturita.xcworkspace
|
||||
|
||||
--- 2026-09-17
|
||||
cs: Vestavěný updater a instalátory, které stáhnou nejnovější build
|
||||
cs: Vyhledávání předmětů, lekcí a cvičení
|
||||
cs: Nový vzhled rozhraní a publikování do větve builds
|
||||
en: Built-in updater and installers that fetch the newest build
|
||||
en: Search for subjects, lessons and exercises
|
||||
en: A new interface look and publishing to the builds branch
|
||||
|
||||
--- 2026-09-16
|
||||
cs: Samostatné balíčky pro Linux, macOS a Windows
|
||||
en: Self-contained packages for Linux, macOS and Windows
|
||||
|
||||
--- 2026-09-15
|
||||
cs: Cvičení z české mluvnice
|
||||
cs: Ikona aplikace na macOS, Windows i Linuxu
|
||||
en: Czech grammar exercises
|
||||
en: App icon on macOS, Windows and Linux
|
||||
|
||||
--- 2026-09-14
|
||||
cs: Česká literatura: 1984 a Spalovač mrtvol
|
||||
cs: Sítě: ročníky 1–4 a jednotky až po Wi-Fi
|
||||
cs: Slovní zásoba pro Deutsch jednotky 2 a 3
|
||||
en: Czech literature: 1984 and The Cremator
|
||||
en: Networks: years 1–4 and units through Wi-Fi
|
||||
en: Vocabulary for Deutsch units 2 and 3
|
||||
|
||||
--- 2026-09-11
|
||||
cs: Technické vybavení: von Neumann, historie počítačů, bity a bajty
|
||||
cs: Deset jednotek sítí s kvízy
|
||||
cs: Slovní zásoba v Deutsch jednotce 1
|
||||
en: Hardware: von Neumann, computer history, bits and bytes
|
||||
en: Ten network units with quizzes
|
||||
en: Vocabulary in Deutsch unit 1
|
||||
|
||||
--- 2026-09-10
|
||||
cs: Sestavení na Windows
|
||||
en: Windows build support
|
||||
|
||||
--- 2026-09-09
|
||||
cs: Otevřený předmět sítí
|
||||
cs: Statistiky postupu po jednotkách
|
||||
en: Networks subject unlocked
|
||||
en: Progress statistics by unit
|
||||
|
||||
--- 2026-09-08
|
||||
cs: Deutsch jednotka 3 a vylepšený hangman
|
||||
en: Deutsch unit 3 and a better hangman
|
||||
|
||||
--- 2026-09-07
|
||||
cs: Z němčiny na více předmětů
|
||||
cs: Deutsch jednotka 2
|
||||
cs: Témata, světlý režim a čeština / angličtina
|
||||
en: From German-only to multiple subjects
|
||||
en: Deutsch unit 2
|
||||
en: Themes, light mode and Czech / English
|
||||
|
||||
--- 2026-09-06
|
||||
cs: Cesta cvičení a překlady po kontrole
|
||||
en: Exercise path and translations after checking
|
||||
|
||||
--- 2026-09-05
|
||||
cs: Cvičení v Deutsch jednotce 1
|
||||
en: Exercises in Deutsch unit 1
|
||||
|
||||
--- 2026-09-03
|
||||
cs: První verze Graduately
|
||||
en: First version of Graduately
|
||||
17
content/aplikace/predmety.md
Normal file
17
content/aplikace/predmety.md
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# Předměty
|
||||
|
||||
| Klíč | Česky | Anglicky | Ikona | Cíl | Otevřeno |
|
||||
|---|---|---|---|---|---|
|
||||
| Deutsch | Deutsch | Deutsch | de | dehome | ano |
|
||||
| Správa počítačových sítí | Správa počítačových sítí | Computer Network Administration | wifi | netyears | ano |
|
||||
| Technické vybavení | Technické vybavení | Computer Hardware | chip | hwyears | ano |
|
||||
| Český jazyk a literatura | Český jazyk a literatura | Czech Language and Literature | cz | czechmap | ano |
|
||||
| Občanská nauka | Občanská nauka | Civics | people | onyears | ano |
|
||||
| English | Angličtina | English | uk | enyears | ano |
|
||||
| Matematika | Matematika | Mathematics | function | matyears | ano |
|
||||
| Fyzika | Fyzika | Physics | bolt | fyzyears | ano |
|
||||
| Základy Přírodopisných věd | Základy Přírodopisných věd | Fundamentals of Natural Sciences | flask | scimap | ano |
|
||||
| Technická grafika | Technická grafika | Technical Drawing | lock | | ne |
|
||||
| Prezentační grafika | Prezentační grafika | Presentation Graphics | lock | | ne |
|
||||
| Programování | Programování | Programming | lock | | ne |
|
||||
| Programové vybavení | Programové vybavení | Software | lock | | ne |
|
||||
514
content/aplikace/texty.md
Normal file
514
content/aplikace/texty.md
Normal file
|
|
@ -0,0 +1,514 @@
|
|||
# Nastavení a aktualizace
|
||||
|
||||
| Klíč | Česky | Anglicky |
|
||||
|---|---|---|
|
||||
| back | Zpět | Back |
|
||||
| settings | Nastavení | Settings |
|
||||
| settings_title | Nastavení | Settings |
|
||||
| mode | REŽIM | MODE |
|
||||
| mode_dark | Tmavý | Dark |
|
||||
| mode_light | Světlý | Light |
|
||||
| theme | TÉMA | THEME |
|
||||
| language | JAZYK | LANGUAGE |
|
||||
| updates | AKTUALIZACE | UPDATES |
|
||||
| update_current | Build %s | Build %s |
|
||||
| update_checking | Hledám aktualizace… | Checking for updates… |
|
||||
| update_uptodate | Máte nejnovější build (%s). | You are up to date (%s). |
|
||||
| update_available | Je dostupný novější build (%s). | A newer build is available (%s). |
|
||||
| update_downloading | Stahuji aktualizaci… | Downloading the update… |
|
||||
| update_staged | Aktualizace je připravená — restartujte aplikaci. | The update is ready — restart the app to finish. |
|
||||
| update_check | Zkontrolovat | Check |
|
||||
| update_install | Aktualizovat | Update |
|
||||
| update_restart | Restartovat | Restart |
|
||||
| update_later | Později | Later |
|
||||
| update_failed | Aktualizace se nepovedla. | The update failed. |
|
||||
| update_err_network | Nepodařilo se zjistit nejnovější verzi. | Could not find out the latest version. |
|
||||
| update_err_download | Stahování se nepovedlo. | The download failed. |
|
||||
| update_err_curl | V systému chybí curl, aktualizace nejsou dostupné. | curl is missing, so updates are unavailable. |
|
||||
| update_err_unsupported | Pro tuto platformu se build nepublikuje. | No build is published for this platform. |
|
||||
| update_err_readonly | Do umístění aplikace nelze zapisovat. Přesuňte ji třeba do Aplikací. | The app's location is not writable. Move it somewhere else, for example to Applications. |
|
||||
| update_err_stage | Aktualizaci nešlo připravit. | Could not prepare the update. |
|
||||
| update_err_devbuild | Tento build nepochází z repozitáře (dev). | This build did not come from the repository (dev). |
|
||||
| update_ios_sideload | Nový build je na GitHubu. Nainstalujte ho znovu přes Xcode nebo AltStore (%s). | A newer build is on GitHub. Reinstall it with Xcode or AltStore (%s). |
|
||||
| update_android_allow | Povolte této aplikaci instalovat aplikace a klepněte znovu na Aktualizovat. | Allow this app to install apps, then tap Update again. |
|
||||
| update_android_installing | Systém teď nabídne instalaci nové verze (%s). | The system will now offer to install the new version (%s). |
|
||||
| update_err_badapk | Stažený soubor není platný build Graduately. | The downloaded file is not a valid Graduately build. |
|
||||
|
||||
# Úvod a novinky
|
||||
|
||||
| Klíč | Česky | Anglicky |
|
||||
|---|---|---|
|
||||
| welcome_kicker | Graduately | Graduately |
|
||||
| welcome_title | Maturita?\nTo dáme. | Maturita?\nWe've got this. |
|
||||
| welcome_body | Procvičování k maturitě v jednom okně. Česky i anglicky, napsané v C studenty ze SSŠVT. | Exam practice in one window. Czech and English, written in C by students from SSŠVT. |
|
||||
| welcome_body_android | Procvičování k maturitě v telefonu. Česky i anglicky, stejný obsah jako na počítači. | Exam practice on your phone. Czech and English, the same content as on the computer. |
|
||||
| welcome_body_desktop | Procvičování k maturitě na počítači. Česky i anglicky, stejný obsah jako v telefonu. | Exam practice on your computer. Czech and English, the same content as on your phone. |
|
||||
| welcome_body_ios | Nativní procvičování na iPhonu. Česky i anglicky, stejný obsah, rozhraní podle iOS. | Native exam practice on iPhone. Czech and English, the same content, adapted to iOS. |
|
||||
| welcome_body_macos | Nativní procvičování na Macu. Česky i anglicky, stejný obsah, rozhraní podle macOS. | Native exam practice on the Mac. Czech and English, the same content, adapted to macOS. |
|
||||
| changelog_title | Co je nového | What's new |
|
||||
| changelog_dismiss | Rozumím | Got it |
|
||||
| welcome_feat1_title | Efektivní procvičování | Focused practice |
|
||||
| welcome_feat1_body | Cvičení, nápovědy a vokabeltraining. Aplikace si pamatuje, kde jste skončili. | Exercises, hints and vocabulary drills. The app remembers where you left off. |
|
||||
| welcome_feat1_link | Začít procvičovat | Start practicing |
|
||||
| welcome_feat2_title | Osm otevřených předmětů | Eight open subjects |
|
||||
| welcome_feat2_body | Deutsch, sítě, hardware, čeština, občanská nauka, matematika, fyzika a přírodní vědy. Ostatní předměty čekají na svůj obsah. | German, networks, hardware, Czech, civics, mathematics, physics and natural sciences. The other subjects are still locked. |
|
||||
| welcome_feat2_link | Jaké předměty jsou otevřené? | Which subjects are open? |
|
||||
| welcome_stat_value | 8 | 8 |
|
||||
| welcome_stat_label | otevřené\npředměty | open\nsubjects |
|
||||
| continue | Pokračuj | Continue |
|
||||
| roadmap_title | Učební plán | Learning path |
|
||||
| roadmap_sub | Vyberte jednotku na cestě a začněte procvičovat. | Pick a unit on the path and start practicing. |
|
||||
|
||||
# Cvičení
|
||||
|
||||
| Klíč | Česky | Anglicky |
|
||||
|---|---|---|
|
||||
| check | Zkontrolovat | Check |
|
||||
| finish | Dokončit | Finish |
|
||||
| show_sample | Ukázat vzor | Show sample |
|
||||
| your_answer | Vaše odpověď… | Your answer… |
|
||||
| feedback_ok | Výborně! | Great! |
|
||||
| feedback_retry | Ještě to není správně. Zkuste to znovu. | Not quite right yet. Try again. |
|
||||
| feedback_retry_short | Ještě to není správně. | Not quite right yet. |
|
||||
| feedback_sentences | Některé věty nejsou správně. Zkuste to znovu. | Some sentences are not correct. Try again. |
|
||||
| hint_umlauts | Na klávesnici nemáte německé znaky? Můžete psát ä jako ae, ö jako oe, ü jako ue a ß jako ss. | No German keyboard? You can type ä as ae, ö as oe, ü as ue and ß as ss. |
|
||||
| sample_fmt | Otázka: %s\nVzor: %s (česky: %s) | Question: %s\nSample: %s (English: %s) |
|
||||
| sub_translate | Přeložte slovo. Špatná odpověď se vrátí na konec. | Translate the word. Wrong answers come back at the end. |
|
||||
| trans_wrong | Špatně. Správně: %s | Wrong. Correct: %s |
|
||||
| trans_incomplete | Nepřesné – něco chybí. | Almost – something is missing. |
|
||||
| trans_progress | Hotovo: %d / %d | Done: %d / %d |
|
||||
| trans_done | Hotovo! Zvládl(a) jsi všechna slova. | Done! You mastered all the words. |
|
||||
| assign_hint | Vyberte skupinu a klikněte na kartu. Kliknutím na kartu ve skupině ji vrátíte zpět. | Pick a group and click a card. Click a card inside a group to send it back. |
|
||||
| wordbank | Nabídka slov: | Word bank: |
|
||||
| sample_line | Příklad: %s | Sample: %s |
|
||||
| hm_progress | Slovo %d / %d | Word %d / %d |
|
||||
| hm_hint | Nápověda | Hint |
|
||||
| hm_wrong | Slovo je uhodnuto! | Word guessed! |
|
||||
| hm_fail | Oběšenec! Slovo bylo „%s“. | Hanged! The word was “%s”. |
|
||||
| hm_retry | Zkusit znovu | Try again |
|
||||
| hm_done | Výborně! Uhodli jste všechna povolání. | Great! You guessed all the jobs. |
|
||||
| hm_guess | Hádejte písmeno | Guess a letter |
|
||||
|
||||
# Statistiky, hledání a předměty
|
||||
|
||||
| Klíč | Česky | Anglicky |
|
||||
|---|---|---|
|
||||
| stats | Statistiky | Statistics |
|
||||
| stats_title | Statistiky | Statistics |
|
||||
| stats_sub | Přehled vašeho pokroku. | Overview of your progress. |
|
||||
| stats_ex_label | Cvičení | Exercises |
|
||||
| stats_pct_label | Hotovo | Done |
|
||||
| stats_units_label | Jednotky | Units |
|
||||
| stats_section | Předměty | Subjects |
|
||||
| stats_locked | Zamčeno | Locked |
|
||||
| stats_complete | Hotovo | Complete |
|
||||
| stats_ex_fmt | %d / %d | %d / %d |
|
||||
| stats_pct_fmt | %d %% | %d %% |
|
||||
| stats_units_fmt | %d / %d | %d / %d |
|
||||
| search | Hledat | Search |
|
||||
| search_placeholder | Hledat předmět, lekci nebo cvičení | Search a subject, lesson or exercise |
|
||||
| search_empty | Nic se nenašlo | No matches |
|
||||
| search_hint | Zkuste předmět, lekci nebo název cvičení | Try a subject, lesson or exercise name |
|
||||
| search_subject | Předmět | Subject |
|
||||
| search_unit | Jednotka | Unit |
|
||||
| search_lesson | Lekce | Lesson |
|
||||
| search_exercise | Cvičení | Exercise |
|
||||
| search_book | Četba | Reading |
|
||||
| search_page | Stránka | Page |
|
||||
| search_home | Úvod | Welcome |
|
||||
| subjects_title | Předměty | Subjects |
|
||||
| subjects_sub | Otevřený předmět spustí učební cestu. Zamčené zatím jen čekají. | An open subject opens its path. Locked ones are placeholders for now. |
|
||||
|
||||
# Čeština
|
||||
|
||||
| Klíč | Česky | Anglicky |
|
||||
|---|---|---|
|
||||
| mluv_sub | Cvičení z mluvnice – styl maturita / přijímačky z ČJL | Grammar exercises in the style of the maturita and entrance exams |
|
||||
| lit_years_sub | Literatura podle osnov středních škol. Vyberte ročník. | Literature from the secondary-school syllabus. Pick a year. |
|
||||
| lit_year1 | 1. ročník | Year 1 |
|
||||
| lit_year2 | 2. ročník | Year 2 |
|
||||
| lit_year3 | 3. ročník | Year 3 |
|
||||
| lit_year4 | 4. ročník | Year 4 |
|
||||
| lit_sub | Od literární teorie po osvícenství. | From literary theory to the Enlightenment. |
|
||||
| lit2_sub | Od národního obrození k moderně. | From the National Revival to the modern movement. |
|
||||
| lit3_sub | První polovina 20. století. | The first half of the 20th century. |
|
||||
| lit4_sub | Od roku 1945 k interpretaci textu. | From 1945 to reading a text. |
|
||||
| czech_sub | Vyberte oblast a začněte procvičovat. | Pick an area and start practicing. |
|
||||
| Literatura | Literatura | Literature |
|
||||
| Mluvnice | Mluvnice | Grammar |
|
||||
| reading_sub | Vyberte knihu, kterou chcete studovat. | Pick a book to study. |
|
||||
| book_study_hint | Nejdřív si projděte zápisky. Pak si látku ověřte v kvízu a seřaďte děj. | Read the study notes first. Then check yourself with the quiz and order the plot. |
|
||||
| book_notes | Zápisky k maturitě | Study notes |
|
||||
| book_practice | Procvičení | Practice |
|
||||
| book_done | Hotovo | Done |
|
||||
| book_open | Otevřít | Open |
|
||||
| book_quiz_heading | Kvíz | Quiz |
|
||||
| book_1984_sub | Antiutopický román • 1949 | Dystopian novel • 1949 |
|
||||
| cetba1984_sub | Přehled knihy, klíčové pojmy a cvičení. | Book overview, key terms and exercises. |
|
||||
| cetba_entry_sub | Údaje ze školního seznamu maturitní četby. | Details from the school maturita reading list. |
|
||||
| cetba_stub_soon | Podrobný přehled a cvičení zatím nejsou k dispozici. | A detailed overview and exercises are not available yet. |
|
||||
| lit_quiz_sub | U každé otázky vyberte jednu správnou odpověď. | Pick one correct answer for each question. |
|
||||
| lit_plot_title | Sestavte děj | Order the plot |
|
||||
| lit_plot_sub | Přetáhněte části příběhu do správného pořadí. | Drag the story parts into the correct order. |
|
||||
| lit_next | Další | Next |
|
||||
| lit_show_result | Zobrazit výsledek | Show result |
|
||||
| lit_again | Zkusit znovu | Try again |
|
||||
| lit_question_fmt | Otázka %d / %d | Question %d / %d |
|
||||
| lit_score_fmt | Skóre: %d / %d | Score: %d / %d |
|
||||
| lit_finished | Hotovo! | Done! |
|
||||
| lit_finished_text | Prošli jste všemi otázkami. | You have finished all the questions. |
|
||||
|
||||
# Počítačové sítě a hardware
|
||||
|
||||
| Klíč | Česky | Anglicky |
|
||||
|---|---|---|
|
||||
| net_sub | Vyberte lekci na cestě a začněte procvičovat. | Pick a unit on the path and start practicing. |
|
||||
| net_years_title | Správa počítačových sítí | Computer Network Administration |
|
||||
| net_years_sub | Vyberte ročník a začněte procvičovat. | Pick a school year and start practicing. |
|
||||
| net_year1 | 1. ročník | Year 1 |
|
||||
| net_year2 | 2. ročník | Year 2 |
|
||||
| net_year3 | 3. ročník | Year 3 |
|
||||
| net_year4 | 4. ročník | Year 4 |
|
||||
| net_year_locked_sub | Zatím bez obsahu | No content yet |
|
||||
| net_ex_title | Cvičení: výpočet IP adres | Exercise: IP address calculation |
|
||||
| net_quiz_intro | Vyberte u každé otázky jednu správnou odpověď a stiskněte Zkontrolovat. | Choose one correct answer for each question and press Check. |
|
||||
| net_slide_next | Další | Next |
|
||||
| net_slide_prev | Zpět | Back |
|
||||
| net_slide_start | Přejít na cvičení | Go to the exercise |
|
||||
| net_solution | Ukázat řešení | Show solution |
|
||||
| net_infeasible | Toto zadání se do sítě /24 nevejde – vyzkoušej „Ukázat řešení“ a přečti si proč. | This assignment does not fit into a /24 network — tap “Show solution” to see why. |
|
||||
| hw_sub | Vyberte lekci na cestě a začněte procvičovat. | Pick a unit on the path and start practicing. |
|
||||
| hw_years_sub | Vyberte ročník a začněte procvičovat. | Pick a school year and start practicing. |
|
||||
| hw_year1 | 1. ročník | Year 1 |
|
||||
| hw_year2 | 2. ročník | Year 2 |
|
||||
| hw_year3 | 3. ročník | Year 3 |
|
||||
| hw_year4 | 4. ročník | Year 4 |
|
||||
| hw_year_locked_sub | Zatím bez obsahu | No content yet |
|
||||
| net2_sub | VLAN, STP, DHCP, DNS, NAT, IPv6, statické směrování a ACL. | VLANs, STP, DHCP, DNS, NAT, IPv6, static routing and ACLs. |
|
||||
| net3_sub | OSPF, směrování mezi VLAN, WAN, VPN, firewall, QoS a dohled. | OSPF, inter-VLAN routing, WAN, VPN, firewalls, QoS and monitoring. |
|
||||
| net4_sub | Návrh adres, redundance, 802.1X, hledání chyb, cloud a maturita. | Address plans, redundancy, 802.1X, troubleshooting, cloud and the exam. |
|
||||
| hw2_sub | Monitory, tisk, sběrnice, chlazení, sestavení, UEFI a diagnostika. | Displays, printing, buses, cooling, assembly, UEFI and diagnostics. |
|
||||
| hw3_sub | RAID, NAS, servery, virtualizace, zálohy, UPS a firmware. | RAID, NAS, servers, virtualisation, backups, UPS and firmware. |
|
||||
| hw4_sub | Údržba, TPM, nákup, mobily, periferie, ekologie a maturita. | Maintenance, TPM, buying, mobiles, peripherals, disposal and the exam. |
|
||||
|
||||
# Občanská nauka
|
||||
|
||||
| Klíč | Česky | Anglicky |
|
||||
|---|---|---|
|
||||
| on_sub | Člověk v lidském společenství. Vyberte lekci na cestě. | The individual and society. Pick a lesson on the path. |
|
||||
| on_years_sub | Vyberte ročník a začněte procvičovat. | Pick a school year and start practicing. |
|
||||
| on_year1 | 1. ročník | Year 1 |
|
||||
| on_year2 | 2. ročník | Year 2 |
|
||||
| on_year3 | 3. ročník | Year 3 |
|
||||
| on_year4 | 4. ročník | Year 4 |
|
||||
| on_year_locked_sub | Zatím bez obsahu | No content yet |
|
||||
| on2_sub | Člověk jako občan v demokratickém státě. Vyberte lekci na cestě. | The citizen in a democratic state. Pick a lesson on the path. |
|
||||
| on3_sub | Člověk a právo. Vyberte lekci na cestě. | The individual and the law. Pick a lesson on the path. |
|
||||
| on4_sub | Hospodářství, svět a filozofie. Vyberte lekci na cestě. | The economy, the world and philosophy. Pick a lesson on the path. |
|
||||
|
||||
# Přírodní vědy
|
||||
|
||||
| Klíč | Česky | Anglicky |
|
||||
|---|---|---|
|
||||
| sci_sub | Vyberte chemii nebo biologii. | Pick chemistry or biology. |
|
||||
| Biologie | Biologie | Biology |
|
||||
| chem_sub | Osm lekcí od atomu po biochemii. | Eight lessons from the atom to biochemistry. |
|
||||
| bio_sub | Osm lekcí od buňky po ekologii. | Eight lessons from the cell to ecology. |
|
||||
|
||||
# Fyzika
|
||||
|
||||
| Klíč | Česky | Anglicky |
|
||||
|---|---|---|
|
||||
| fyz_years_sub | Fyzika podle osnov středních škol. Vyberte ročník. | Physics from the secondary-school syllabus. Choose a year. |
|
||||
| fyz_year1 | 1. ročník | Year 1 |
|
||||
| fyz_year2 | 2. ročník | Year 2 |
|
||||
| fyz_year3 | 3. ročník | Year 3 |
|
||||
| fyz_year4 | 4. ročník | Year 4 |
|
||||
| fyz_sub | Mechanika: veličiny, pohyb, síly a energie. | Mechanics: quantities, motion, forces and energy. |
|
||||
| fyz2_sub | Molekulová fyzika, teplo, kmity a vlny. | Molecular physics, heat, oscillations and waves. |
|
||||
| fyz3_sub | Elektřina a magnetismus. | Electricity and magnetism. |
|
||||
| fyz4_sub | Optika, relativita, mikročástice a vesmír. | Optics, relativity, the micro-world and the universe. |
|
||||
|
||||
# Angličtina a němčina
|
||||
|
||||
| Klíč | Česky | Anglicky |
|
||||
|---|---|---|
|
||||
| en_years_sub | Čtyři ročníky podle osnov gymnázia, od A2 k maturitě. | Four years of the gymnasium syllabus, from A2 to the exam. |
|
||||
| en_year1 | 1. ročník | Year 1 |
|
||||
| en_year2 | 2. ročník | Year 2 |
|
||||
| en_year3 | 3. ročník | Year 3 |
|
||||
| en_year4 | 4. ročník | Year 4 |
|
||||
| en_sec_read | Čtení | Reading |
|
||||
| en_sec_listen | Poslech | Listening |
|
||||
| en_sec_write | Psaní | Writing |
|
||||
| en_sec_gap | Doplňte | Complete |
|
||||
| en_sec_quiz | Kvíz | Quiz |
|
||||
| en_sec_test | Jazyková část | Language |
|
||||
| en_play | Přehrát | Play |
|
||||
| en_pause | Pauza | Pause |
|
||||
| en_resume | Pokračovat | Resume |
|
||||
| en_speed | Rychlost | Speed |
|
||||
| en_volume | Hlasitost | Volume |
|
||||
| en_listen_note | Text nahrávky zůstává vidět. Přehrání obstará hlas zařízení. | The recording text stays visible. The device voice plays it. |
|
||||
| en_listen_first | Nejdřív poslech přehrajte. | Play the recording first. |
|
||||
| en_listen_fallback | Hlas není dostupný. Text si můžete přečíst. | No voice is available. You can read the text. |
|
||||
| en_write_short | Text je krátký nebo v něm chybí požadovaná slova. | The text is short or it misses the required words. |
|
||||
| en_model | Vzor | Model |
|
||||
| en_write_ph | Pište anglicky… | Write in English… |
|
||||
| en_y1_sub | Osobní život, škola, domov a minulost. Úroveň A2. | Personal life, school, home and the past. Level A2. |
|
||||
| en_y2_sub | Cestování, zdraví, práce, média a příroda. Úroveň B1. | Travel, health, work, the media and nature. Level B1. |
|
||||
| en_y3_sub | Společnost, prostředí, média a složitější gramatika. Úroveň B1 až B2. | Society, the environment, the media and harder grammar. Level B1 to B2. |
|
||||
| en_y4_sub | Maturitní dovednosti: mluvení, formální psaní, čtení, poslech a gramatika. Úroveň B2. | Exam skills: speaking, formal writing, reading, listening and grammar. Level B2. |
|
||||
| de_home_sub | Učebnice a čtyři ročníky s poslechem, čtením a psaním. | The textbook plus four years of listening, reading and writing. |
|
||||
| de_book_title | Učebnice | Textbook |
|
||||
| de_book_sub | Neue Freunde, Aus aller Welt a Bei uns zu Hause. | Neue Freunde, Aus aller Welt and Bei uns zu Hause. |
|
||||
| de_years_title | Ročníky | School years |
|
||||
| de_y1_sub | Pozdravy, rodina, škola, jídlo a den. Úroveň A1. | Greetings, family, school, food and the day. Level A1. |
|
||||
| de_year1 | 1. ročník | Year 1 |
|
||||
| de_y2_sub | Město, nákupy, volný čas, bydlení a perfektum. Úroveň A2. | Town, shopping, free time, home and the perfect. Level A2. |
|
||||
| de_year2 | 2. ročník | Year 2 |
|
||||
| de_y3_sub | Zdraví, cestování, věty s weil, práce a srovnání. Úroveň A2+. | Health, travel, weil-clauses, work and comparison. Level A2+. |
|
||||
| de_year3 | 3. ročník | Year 3 |
|
||||
| de_y4_sub | Média, formální dopis, čtení, konjunktiv a maturitní témata. Úroveň B1. | Media, a formal letter, reading, the subjunctive and exam topics. Level B1. |
|
||||
| de_year4 | 4. ročník | Year 4 |
|
||||
|
||||
# Matematika
|
||||
|
||||
| Klíč | Česky | Anglicky |
|
||||
|---|---|---|
|
||||
| mat_years_sub | Opakování základní školy a čtyři ročníky gymnázia. | Elementary review and four years of gymnasium mathematics. |
|
||||
| math_quiz_intro | Napište výsledek. Zlomky jako 3/4, desetinnou čárku i tečku, π jako pi, odmocninu jako sqrt(2) nebo √2. Více čísel oddělte středníkem. | Write the result. Fractions as 3/4, a decimal comma or point, π as pi, a root as sqrt(2) or √2. Separate several numbers with a semicolon. |
|
||||
| math_answer_ph | výsledek | result |
|
||||
| math_undo | Zpět | Undo |
|
||||
| math_clear | Smazat body | Clear points |
|
||||
| math_draw_hint | Klepněte na mřížku. Osa y směřuje nahoru. | Tap the grid. The y-axis points up. |
|
||||
| mat0_year | Opakování základní školy | Elementary-school review |
|
||||
| mat0_sub | Pořadí operací, zlomky, procenta, rovnice a rýsování. | Order of operations, fractions, percentages, equations and a construction. |
|
||||
| mat_year1 | 1. ročník | Year 1 |
|
||||
| mat_sub | Dělitelnost, výrazy, rovnice, planimetrie a konstrukce. | Divisibility, expressions, equations, plane figures and a construction. |
|
||||
| mat_year2 | 2. ročník | Year 2 |
|
||||
| mat2_sub | Funkce, soustavy, kvadratické rovnice, goniometrie a kružnice. | Functions, systems, quadratic equations, trigonometry and circles. |
|
||||
| mat_year3 | 3. ročník | Year 3 |
|
||||
| mat3_sub | Logaritmus, posloupnosti, pravděpodobnost a stereometrie. | Logarithms, sequences, probability and solid geometry. |
|
||||
| mat_year4 | 4. ročník | Year 4 |
|
||||
| mat4_sub | Analytická geometrie, derivace, integrál a maturitní opakování. | Coordinate geometry, derivatives, integrals and a maturita review. |
|
||||
|
||||
# Ostatní
|
||||
|
||||
| Klíč | Česky | Anglicky |
|
||||
|---|---|---|
|
||||
| ARP dotaz jde broadcastem | | An ARP request goes out as a broadcast |
|
||||
|
||||
# Německá učebnice
|
||||
|
||||
| Klíč | Česky | Anglicky |
|
||||
|---|---|---|
|
||||
| tvoje | | yours (f.) |
|
||||
| moje | | mine (f.) |
|
||||
| u3g_dein | (tvůj) | (your) |
|
||||
| u3g_sein | (jeho) | (his) |
|
||||
| u3g_ihr_sie | (její) | (her) |
|
||||
| u3g_sein_es | (jeho) | (its) |
|
||||
| u3g_unser | (náš) | (our) |
|
||||
| u3g_euer | (váš) | (your) |
|
||||
| u3g_ihr_sie_pl | (jejich) | (their) |
|
||||
|
||||
# Další překlady
|
||||
|
||||
| Klíč | Česky | Anglicky |
|
||||
|---|---|---|
|
||||
| Maturitní četba | Maturitní četba | Maturita reading list |
|
||||
| 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 |
|
||||
| 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 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 |
|
||||
| tvůj | | yours (m.) |
|
||||
| můj | | mine (m.) |
|
||||
| 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. |
|
||||
| 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 |
|
||||
| Ř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 |
|
||||
3
content/cestina/cetba/01-1984.en.md
Normal file
3
content/cestina/cetba/01-1984.en.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
kviz_nadpis: Quiz: George Orwell – 1984
|
||||
---
|
||||
286
content/cestina/cetba/01-1984.md
Normal file
286
content/cestina/cetba/01-1984.md
Normal file
|
|
@ -0,0 +1,286 @@
|
|||
---
|
||||
id: 1984
|
||||
autor: George Orwell
|
||||
nazev: 1984
|
||||
zanr: Próza
|
||||
preklad: Šimečková
|
||||
stranka: cetba1984
|
||||
plna: ano
|
||||
kviz_nadpis: Kvíz: George Orwell – 1984
|
||||
---
|
||||
|
||||
# O knize
|
||||
|
||||
- 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
|
||||
|
||||
# Svět a strana
|
||||
|
||||
- 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.
|
||||
|
||||
# Postavy
|
||||
|
||||
- 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.
|
||||
|
||||
# Klíčové pojmy
|
||||
|
||||
- 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.
|
||||
|
||||
|
||||
# Kvíz
|
||||
|
||||
## Kdo je hlavní hrdina románu a co dělá?
|
||||
- [x] Winston Smith – přepisuje historii na Ministerstvu pravdy
|
||||
- O'Brien – řídí Ministerstvo lásky
|
||||
- Emmanuel Goldstein – vede Bratrstvo
|
||||
- Winston Smith – velí Policii myšlení
|
||||
> Winston Smith je vnější člen strany, který na Ministerstvu pravdy upravuje staré záznamy a novinové články.
|
||||
|
||||
## Ve kterém fiktivním státě se děj odehrává?
|
||||
- V Eurasii
|
||||
- [x] V Oceánii
|
||||
- Ve Východasii
|
||||
- V Angsocu
|
||||
> 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.
|
||||
|
||||
## Co znamená slogan „VÁLKA JE MÍR, SVOBODA JE OTROCTVÍ, NEVĚDOMOST JE SÍLA“?
|
||||
- Jsou to tři zásady Bratrstva
|
||||
- Jsou to názvy ministerstev
|
||||
- Jde o hesla prolety
|
||||
- [x] Jsou to paradoxní hesla, kterými strana ospravedlňuje útlak
|
||||
> Strana používá dvojité myšlení: hesla znějí vznešeně, ale ve skutečnosti obhajují válku, otroctví a nevědomost.
|
||||
|
||||
## Kdo je Velký bratr a je reálnou osobou?
|
||||
- Skutečný vůdce Bratrstva
|
||||
- Winstonův nadřízený na ministerstvu
|
||||
- [x] Symbol všemocné moci a kultu osobnosti; možná vůbec neexistuje
|
||||
- O'Brienův pseudonym
|
||||
> Velký bratr je tvář režimu. Není jasné, zda jde o živou osobu, nebo jen o symbol, který drží strach a poslušnost.
|
||||
|
||||
## Co je Newspeak (novořeč) a proč ho strana zavádí?
|
||||
- Tajná řeč Bratrstva
|
||||
- [x] Zjednodušená angličtina omezující slovní zásobu, aby nešlo vyslovit zakázané myšlenky
|
||||
- Úřední jazyk prolety
|
||||
- Šifra Policie myšlení
|
||||
> Newspeak neustále ubírá slova. Když pro svobodu nebo odpor neexistuje slovo, nelze o nich ani myslet.
|
||||
|
||||
## Co je teleobrazovka (telescreen) a jak funguje?
|
||||
- Televize určená jen pro zábavu
|
||||
- [x] Zařízení, které vysílá i sleduje; nelze ji úplně vypnout
|
||||
- Rozhlasová stanice
|
||||
- Počítač Ministerstva pravdy
|
||||
> Telescreen funguje obousměrně – neustále sleduje občany. Vypnout lze jen zvuk, obraz běží dál.
|
||||
|
||||
## Jak se jmenují tři supervelmoci světa 1984?
|
||||
- [x] Oceánie, Eurasie a Východasie
|
||||
- Oceánie, Evropa a Asie
|
||||
- Anglie, Eurasie a Ostasie
|
||||
- Oceánie, Východasie a Afrika
|
||||
> Svět je rozdělen na tři státy ve věčném, ale nerozhodném konfliktu: Oceánii, Eurasii a Východasii.
|
||||
|
||||
## Čím se zabývá Ministerstvo pravdy?
|
||||
- Vede válku
|
||||
- Dohlíží na morálku a sňatky
|
||||
- [x] Upravuje a přepisuje historii, noviny a archivy
|
||||
- Rozděluje potraviny
|
||||
> Ministerstvo pravdy vyrábí „pravdu“ – Winston v něm přepisuje staré záznamy tak, aby vždy odpovídaly současné linii strany.
|
||||
|
||||
## K čemu slouží Ministerstvo lásky?
|
||||
- Zajišťuje sňatky a lásku
|
||||
- [x] Je to budova bez oken, kde se mučí a likvidují nepřátelé strany
|
||||
- Vyrábí zbraně
|
||||
- Školí děti
|
||||
> 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.
|
||||
|
||||
## V čem je paradox Ministerstva hojnosti?
|
||||
- [x] 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
|
||||
> Ministerstvo hojnosti plánuje výrobu, ale ekonomika je záměrně nastavena tak, aby lidé žili v trvalém nedostatku.
|
||||
|
||||
## Co je Ministerstvo míru a čím se zabývá?
|
||||
- Uzavírá mírové smlouvy
|
||||
- Dojednává příměří
|
||||
- [x] Ve skutečnosti vede válku
|
||||
- Velí Policii myšlení
|
||||
> 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.
|
||||
|
||||
## Kdo je Julie a jaký vztah s ní Winston naváže?
|
||||
- Winstonova žena
|
||||
- [x] Mladá členka strany, s níž Winston prožije tajnou milostnou aféru
|
||||
- O'Brienova asistentka
|
||||
- Proletka a obchodnice
|
||||
> Julie pracuje v oddělení beletrie a naoko je vzornou členkou strany. S Winstonem vytvoří tajný milostný vztah.
|
||||
|
||||
## Proč je vztah Winstona a Julie zakázaný?
|
||||
- [x] 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
|
||||
> Strana potlačuje citové a sexuální vazby, protože oddanost má patřit jen straně. Tajný vztah je proto dvojnásob nebezpečný.
|
||||
|
||||
## Kdo je O'Brien a jakou roli hraje v příběhu?
|
||||
- Skutečný vůdce Bratrstva
|
||||
- [x] Vysoce postavený člen vnitřní strany, který Winstona nakonec mučí a „vyléčí“
|
||||
- Winstonův přítel z dětství
|
||||
- Proletářský básník
|
||||
> 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.
|
||||
|
||||
## Co je Bratrstvo a existuje vůbec?
|
||||
- Skutečná armáda Oceánie
|
||||
- Náboženská organizace
|
||||
- [x] Údajná tajná organizace odporu; není jisté, zda existuje
|
||||
- Odbory prolety
|
||||
> Bratrstvo zmiňuje Goldstein i O'Brien, ale kniha nikdy nepotvrdí, že doopravdy existuje – může jít o past strany.
|
||||
|
||||
## Kdo je Emmanuel Goldstein?
|
||||
- Ministr pravdy
|
||||
- [x] Oficiální nepřítel státu a údajný vůdce Bratrstva
|
||||
- Winstonův kolega
|
||||
- Velký bratrův dvojník
|
||||
> Goldstein je terčem dvouminutovky nenávisti. Má ztělesňovat nepřítele, proti kterému strana sjednocuje občany.
|
||||
|
||||
## Co je dvojité myšlení (doublethink)?
|
||||
- Schopnost myslet ve dvou jazycích
|
||||
- Zdvojení osobnosti
|
||||
- [x] Schopnost věřit dvěma protikladným tvrzením zároveň
|
||||
- Tajné zapisování myšlenek
|
||||
> Dvojité myšlení je jádro stranické ideologie – člověk přijme i zjevné rozpory, jako „válka je mír“.
|
||||
|
||||
## Proč strana neustále přepisuje minulost?
|
||||
- Aby opravila chyby v archivech
|
||||
- [x] Aby měla vždy pravdu a nepřítel jí nemohl dokázat opak
|
||||
- Aby ušetřila papír
|
||||
- Aby potěšila prolety
|
||||
> Kdo ovládá minulost, ovládá i budoucnost. Přepisováním historie strana udržuje absolutní kontrolu nad pravdou.
|
||||
|
||||
## Co je zločin myšlení (thoughtcrime)?
|
||||
- [x] Pouhá myšlenka nebo názor, který se nelíbí straně
|
||||
- Krádež státního majetku
|
||||
- Nelegální obchod
|
||||
- Opomenutí dvouminutovky
|
||||
> Strana trestá už samotné myšlenky. Winston se proviní tím, že si do deníku napíše „Dolů s Velkým bratrem“.
|
||||
|
||||
## Kdo je pan Charrington a jaké je jeho skutečné postavení?
|
||||
- Winstonův přítel a majitel hospody
|
||||
- Proletářský básník
|
||||
- [x] Zdánlivě starý majitel obchodu, ve skutečnosti agent Policie myšlení
|
||||
- Člen Bratrstva
|
||||
> Charrington Winstonovi pronajme pokoj bez teleobrazovky, ale právě on nakonec oba milence udá.
|
||||
|
||||
## Co je místnost 101?
|
||||
- Winstonova cela na policii
|
||||
- Skladiště knih
|
||||
- [x] Místnost, ve které každého čeká jeho největší strach
|
||||
- Zasedací místnost vnitřní strany
|
||||
> Místnost 101 je vrcholný mučicí nástroj. Winstonovi v ní hrozí krysy – jeho největší fobie.
|
||||
|
||||
## Jak skončí vztah Winstona a Julie?
|
||||
- Utečou spolu do Eurasie
|
||||
- Vezmou se a žijí svobodně
|
||||
- Winston se stane členem Bratrstva
|
||||
- [x] Zradí se a nakonec se přestanou milovat
|
||||
> Oba jsou po mučení zlomení a vzájemně se zradí. Na konci už k sobě nic necítí.
|
||||
|
||||
## Co znamená závěrečná věta „Miloval Velkého bratra“?
|
||||
- [x] 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
|
||||
> Winston byl vnitřně zlomen. Přestal být sám sebou a nakonec režim opravdu přijal za svůj.
|
||||
|
||||
## Které tvrzení NENÍ jedním z hlavních témat románu?
|
||||
- Moc a absolutní kontrola
|
||||
- Pravda a přepisování historie
|
||||
- Svoboda a identita
|
||||
- [x] Idylický venkovský život
|
||||
> 1984 je temná antiutopie. Hlavními tématy jsou moc, kontrola, manipulace s pravdou a ztráta svobody, ne venkovská idyla.
|
||||
|
||||
## V jakém roce byl román 1984 poprvé vydán?
|
||||
- 1936
|
||||
- [x] 1949
|
||||
- 1954
|
||||
- 1984
|
||||
> Román vyšel v roce 1949; letopočet 1984 označuje blízkou budoucnost, do níž Orwell příběh zasadil.
|
||||
|
||||
## Které další Orwellovo dílo se dá s 1984 srovnat?
|
||||
- [x] Farma zvířat
|
||||
- Velký Gatsby
|
||||
- Zločin a trest
|
||||
- Babička
|
||||
> Obě Orwellova díla varují před totalitou. Farma zvířat ji líčí alegoricky pomocí zvířat, 1984 očima jedince.
|
||||
|
||||
## Co je „dvouminutovka nenávisti“?
|
||||
- [x] 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
|
||||
> Slouží k uvolnění a přesměrování agrese občanů na nepřítele státu, čímž strana posiluje svou moc.
|
||||
|
||||
## Proč je podle knihy válka pro systém nezbytná?
|
||||
- Přináší mír a blahobyt
|
||||
- [x] 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
|
||||
> Trvalá válka pohlcuje nadbytečnou produkci a udržuje lidi ve strachu i chudobě, takže se nemohou vzbouřit.
|
||||
|
||||
## Jaký je rozdíl mezi vnějšími členy strany a prolety?
|
||||
- Proleti mají více práv než členové strany
|
||||
- [x] 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
|
||||
> Proleti tvoří asi 85 % obyvatel. Žijí v bídě a jsou považováni za neškodné, dokud si neuvědomí svou sílu.
|
||||
|
||||
## Jak strana kontroluje sexualitu a osobní vztahy?
|
||||
- Podporuje volnou lásku a nezávislost
|
||||
- [x] Potlačuje lásku a sexualitu, děti vede k oddanosti straně
|
||||
- Zakazuje veškerá manželství
|
||||
- Povoluje vztahy jen s prolety
|
||||
> 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.
|
||||
|
||||
## Co symbolizuje papírové těžítko, které si Winston koupí?
|
||||
- Jeho nenávist ke Goldsteinovi
|
||||
- [x] Kousek krásy a minulosti, kterou už nelze vrátit
|
||||
- Moc Velkého bratra
|
||||
- Lásku k Julii
|
||||
> Těžítko je drobný, krásný předmět z minulosti. Pro Winstona ztělesňuje svět, který strana zničila.
|
||||
|
||||
## Jaké poselství chtěl Orwell románem nejspíš předat?
|
||||
- [x] 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
|
||||
> 1984 je varování: když lidé přestanou bránit pravdu a svobodu, mohou o ně nenávratně přijít.
|
||||
|
||||
|
||||
# Děj
|
||||
|
||||
## Přetáhněte části příběhu do správného pořadí:
|
||||
|
||||
1. Winston upravuje historii na Ministerstvu pravdy
|
||||
2. Seznámí se s Julií a začnou se tajně scházet
|
||||
3. Pronajme si pokoj nad obchodem pana Charringtona
|
||||
4. Přečte Goldsteinovu knihu u O'Briena
|
||||
5. Jsou zatčeni Policií myšlení
|
||||
6. Winston se zlomí v místnosti 101
|
||||
|
||||
> Správné pořadí: přepisování historie → seznámení s Julií → pronájem pokoje → četba Goldsteinovy knihy → zatčení → místnost 101.
|
||||
283
content/cestina/cetba/02-fahrenheit451.md
Normal file
283
content/cestina/cetba/02-fahrenheit451.md
Normal file
|
|
@ -0,0 +1,283 @@
|
|||
---
|
||||
id: fahrenheit451
|
||||
autor: Ray Bradbury
|
||||
nazev: 451 stupňů Fahrenheita
|
||||
zanr: Próza
|
||||
preklad: Nezval
|
||||
---
|
||||
|
||||
# O knize
|
||||
|
||||
- Autor: Ray Bradbury
|
||||
- Žánr: antiutopický (dystopický) sci-fi román
|
||||
- Poprvé vydáno: 1953
|
||||
- Děj/prostředí: anonymní americké město v blízké budoucnosti
|
||||
- Vyprávění/forma: er-forma, lyricky obrazný styl; český překlad Vítězslava Nezvala
|
||||
|
||||
# Doba a svět
|
||||
|
||||
- Knihy jsou zakázané; hasiči pálí knihovny a domy, ne hasí požáry.
|
||||
- Lidé tráví čas u televizních „stěn“ a rychlých, prázdných pořadů.
|
||||
- Samostatné myšlení je podezřelé; společnost preferuje rychlou zábavu před hloubkou.
|
||||
- V pozadí hrozí válka; město působí sterilně a agresivně.
|
||||
- Odboj tvoří skrytí čtenáři a „pamatovači“, kteří uchovávají texty v paměti.
|
||||
- Román varuje před cenzurou, konformitou a odpoutáním od literatury.
|
||||
|
||||
# Postavy
|
||||
|
||||
- Guy Montag – hasič, který přestane věřit systému pálení knih.
|
||||
- Clarisse McClellan – zvědavá dívka, probudí v Montagovi otázky.
|
||||
- Mildred Montagová – Guyova žena, závislá na televizi a prášcích.
|
||||
- Kapitán Beatty – šéf hasičů, vzdělaný obhájce ničení knih.
|
||||
- Profesor Faber – bývalý učitel, Montagův tajný rádce.
|
||||
- Granger – vůdce komunity pamatovačů literatury.
|
||||
|
||||
# Klíčové pojmy a motivy
|
||||
|
||||
- 451 °F – symbol teploty hoření papíru a ničení knih.
|
||||
- Televizní stěny – náhrada skutečného života a dialogu.
|
||||
- Mechanický pes – technologie sledování a likvidace nepohodlných.
|
||||
- Oheň – nejdřív ničení, později i obnova (fénix).
|
||||
- Paměť – literatura přežívá v lidech, když zmizí knihy.
|
||||
- Svoboda myšlení – hlavní téma odporu proti režimu.
|
||||
|
||||
|
||||
# Kvíz
|
||||
|
||||
## Kdo je hlavní hrdina a jaké má povolání?
|
||||
- [x] Guy Montag – hasič pálící knihy
|
||||
- Beatty – spisovatel
|
||||
- Faber – politik
|
||||
- Granger – televizní režisér
|
||||
> Montag pracuje v hasičské jednotce, která místo hašení požárů ničí knihy.
|
||||
|
||||
## Co znamená titulní „451 stupňů Fahrenheita“ v kontextu románu?
|
||||
- Teplota varu vody
|
||||
- [x] Údajná teplota hoření knižního papíru
|
||||
- Rychlost hasičského vozu
|
||||
- Kód tajné policie
|
||||
> Bradbury používá číslo jako symbol ničení literatury ohněm.
|
||||
|
||||
## Kdo poprvé naruší Montagovu spokojenost s režimem?
|
||||
- Mildred
|
||||
- [x] Clarisse McClellan
|
||||
- Beatty
|
||||
- Granger
|
||||
> Clarisse klade otázky o štěstí, přírodě a smyslu života.
|
||||
|
||||
## Jak žije Mildred Montagová?
|
||||
- Jako odbojářka se skrytými knihami
|
||||
- [x] Pasivně u televizních stěn a prášků
|
||||
- Jako učitelka literatury
|
||||
- Jako velitelka hasičů
|
||||
> Mildred je otupělá masovou zábavou a nevnímá hlubší vztah k Guyovi.
|
||||
|
||||
## Proč podle Beattyho společnost knihy zakázala?
|
||||
- Kvůli nedostatku papíru
|
||||
- [x] Aby lidé nemysleli samostatně a byli spokojení
|
||||
- Protože knihy jsou drahé
|
||||
- Kvůli náboženským důvodům
|
||||
> Beatty tvrdí, že knihy kazí „klid“ tím, že nutí přemýšlet a polemizovat.
|
||||
|
||||
## Kdo je profesor Faber?
|
||||
- Velitel hasičů
|
||||
- [x] Bývalý učitel, který Montagovi pomáhá
|
||||
- Montagův švagr
|
||||
- Autor zakázaných románů v tisku
|
||||
> Faber Montaga vede k čtení a přes sluchátko ho podporuje v krizi.
|
||||
|
||||
## Co je mechanický pes v románu?
|
||||
- Mildredin domácí mazlíček
|
||||
- [x] Robotický lovec stíhající režimem označené osoby
|
||||
- Hasičské auto
|
||||
- Postava dětského pořadu
|
||||
> Mechanický pes je nástroj strachu; později stíhá i Montaga.
|
||||
|
||||
## Co Montag udělá s kapitánem Beattym při zatýkání?
|
||||
- Přesvědčí ho ke čtení
|
||||
- [x] Spálí ho proudem plamenometu
|
||||
- Uteče s ním z města
|
||||
- Udá ho policii
|
||||
> Po Beattyho provokacích Montag obrátí oheň proti svému nadřízenému.
|
||||
|
||||
## Kdo jsou „pamatovači“ na konci románu?
|
||||
- Hasiči v důchodu
|
||||
- [x] Lidé, kteří si pamatují knihy nazpaměť
|
||||
- Televizní herci
|
||||
- Vojáci v zákopu
|
||||
> Skupina kolem Grangera uchovává literární texty v paměti jako most k budoucnosti.
|
||||
|
||||
## Jaký symbol nese oheň v průběhu příběhu?
|
||||
- Pouze ničení
|
||||
- [x] Nejdřív ničení, později i možnost obnovy (metafora fénixe)
|
||||
- Jen romantická láska
|
||||
- Výhradně válka
|
||||
> Montag přechází od pálení knih k vnímání ohně jako zdroje tepla i nového začátku.
|
||||
|
||||
## Jak Mildred reaguje na Montagovo skryté čtení?
|
||||
- Podporuje ho
|
||||
- [x] Je vyděšená a raději knihy nechce vidět
|
||||
- Okamžitě utíká k hasičům
|
||||
- Začne psát vlastní deník
|
||||
> Mildred se bojí následků a zůstává věrná konzumnímu životnímu stylu.
|
||||
|
||||
## Co se stane s Montagovou domácností?
|
||||
- Stane se útočištěm odboje
|
||||
- [x] Beatty nechá Montaga sám spálit jeho dům s knihami
|
||||
- Mildred ji prodá
|
||||
- Faber v ní otevře knihovnu
|
||||
> Beatty nutí Montaga zničit vlastní domov jako veřejnou lekci poslušnosti.
|
||||
|
||||
## Proč Montag utíká k řece?
|
||||
- Chce najít Clarisse
|
||||
- [x] Uteče před mechanickým psem a pronásledováním
|
||||
- Jde k Beattymu na večeři
|
||||
- Hledá televizní studio
|
||||
> Po zabití Beattyho musí opustit město a skrýt se před technologií i lidmi.
|
||||
|
||||
## Jakou roli hraje televize ve společnosti románu?
|
||||
- Vzdělává občany
|
||||
- [x] Nahrazuje knihy, dialog a kritické myšlení
|
||||
- Slouží jen hasičům
|
||||
- Vysílá výhradně zprávy o válce
|
||||
> Interaktivní stěny a rychlé pořady udržují lidi pasivní a spokojené.
|
||||
|
||||
## Které téma román NEZdůrazňuje?
|
||||
- Cenzura
|
||||
- Nebezpečí konzumní zábavy
|
||||
- [x] Idylický venkovský realism 19. století
|
||||
- Odpor jednotlivce
|
||||
> Jde o dystopii o knihách a médiích, ne o historický venkovský román.
|
||||
|
||||
## V jakém roce román poprvé vyšel?
|
||||
- 1949
|
||||
- [x] 1953
|
||||
- 1968
|
||||
- 1984
|
||||
> 451 stupňů Fahrenheita vyšlo v roce 1953 a patří k klasice antiutopie.
|
||||
|
||||
## Jaký vztah měl Bradbury k televizi podle kontextu díla?
|
||||
- Bezvýhradně ji oslavoval
|
||||
- [x] Varoval před jejím návykovým vlivem na kulturu
|
||||
- Ignoroval ji
|
||||
- Považoval ji za náhradu školy
|
||||
> Román kritizuje pasivní sledování obrazovek místo čtení a rozhovoru.
|
||||
|
||||
## Co Montag ukradne u staré ženy s knihami?
|
||||
- Televizní ovladač
|
||||
- [x] Kniha (biblický text)
|
||||
- Plamenomet
|
||||
- Mechanický pes
|
||||
> Montag si nechá knihu, i když vidí, jak žena raději zemře v plamenech než knihy vydá.
|
||||
|
||||
## Proč je scéna se starou ženou důležitá?
|
||||
- Ukazuje lehkost smrti
|
||||
- [x] Montag chápe, že knihy mají pro lidi hodnotu života
|
||||
- Beatty se stane hrdinou
|
||||
- Mildred se obrátí
|
||||
> Obětí ženy v plamenech Montag poprvé silně pocítí absurditu pálení knih.
|
||||
|
||||
## Jak Faber pomáhá Montagovi během pronásledování?
|
||||
- Letí s ním vrtulníkem
|
||||
- [x] Komunikuje přes miniaturní sluchátko v uchu
|
||||
- Zastřelí mechanického psa
|
||||
- Spálí Beattyho knihovnu
|
||||
> Faber ho radí na dálku, dokud Montag neunikne z města.
|
||||
|
||||
## Co se stane s městem na konci?
|
||||
- Slaví mír
|
||||
- [x] Je zničeno leteckým útokem
|
||||
- Stane se knihovnou
|
||||
- Zmizí televize
|
||||
> Válka na pozadí exploduje; město letecky zničí, zatímco Montag je mimo.
|
||||
|
||||
## Jak Granger vnímá budoucnost po zkáze?
|
||||
- Bez naděje
|
||||
- [x] Jako šanci znovu budovat kulturu z paměti
|
||||
- Jako konec světa bez smyslu
|
||||
- Jako vítězství hasičů
|
||||
> Pamatovači přirovnávají obnovu k fénixovi – z popela může vyrůst nové.
|
||||
|
||||
## Která postava představuje konformitu nejvíc?
|
||||
- Clarisse
|
||||
- [x] Mildred
|
||||
- Granger
|
||||
- Faber
|
||||
> Mildred je vzor občana spokojeného s prázdnou zábavou.
|
||||
|
||||
## Která postava ztělesňuje vzdělaný cynismus moci?
|
||||
- Faber
|
||||
- [x] Beatty
|
||||
- Clarisse
|
||||
- Granger
|
||||
> Beatty cituje literaturu, ale obhajuje její ničení.
|
||||
|
||||
## Jaký žánr nejlépe vystihuje román?
|
||||
- [x] Antiutopický sci-fi román
|
||||
- Historický epos
|
||||
- Detektivka
|
||||
- Pastorální idyla
|
||||
> Děj v budoucnosti kritizuje společnost a technologie – typická antiutopie.
|
||||
|
||||
## Co Montag dělá na začátku knihy profesně?
|
||||
- Učí na gymnáziu
|
||||
- [x] Pálí knihy jako hasič
|
||||
- Píše pro televizi
|
||||
- Vyrábí mechanické psy
|
||||
> Úvodní scény ukazují rutinní pálení knih.
|
||||
|
||||
## Proč je Clarisse „nebezpečná“ pro systém?
|
||||
- Je bohatá
|
||||
- [x] Ptá se na zakázané otázky a myslí jinak
|
||||
- Je hasička
|
||||
- Píše knihy
|
||||
> Její zvědavost a pomalost odporují konzumnímu tempu společnosti.
|
||||
|
||||
## Jaký význam má řeka v závěru?
|
||||
- Hranice státu
|
||||
- [x] Cesta úniku a symbol očištění
|
||||
- Místo pálení knih
|
||||
- Beattyho hrob
|
||||
> Montag se v řece skrývá před psem a přechází k novému životu.
|
||||
|
||||
## Kdo v románu představuje most mezi starou kulturou a odbojem?
|
||||
- Beatty
|
||||
- [x] Faber
|
||||
- Mildred
|
||||
- Mechanický pes
|
||||
> Faber zná knihy, ale dlouho se bál jednat – Montaga k akci povzbudí.
|
||||
|
||||
## Jaké poselství je pro maturitu nejdůležitější?
|
||||
- Knihy lze nahradit televizí
|
||||
- [x] Svoboda myšlení a kultura se brání i za cenu rizika
|
||||
- Hasiči by měli pálit domy
|
||||
- Válka je lepší než čtení
|
||||
> Román obhajuje literaturu a kritické myšlení proti cenzuře a pasivitě.
|
||||
|
||||
## Jaký český překladatel je u díla tradičně uváděn v maturitních seznamech?
|
||||
- Gössell
|
||||
- [x] Nezval
|
||||
- Skoumal
|
||||
- Nevrla
|
||||
> V katalogu maturitní četby je u díla uveden překlad Vítězslava Nezvala.
|
||||
|
||||
## Co následuje po Montagově připojení k pamatovačům?
|
||||
- Návrat k Mildred
|
||||
- [x] Pohled na zkázu města a naděje v obnovu
|
||||
- Beattyho rehabilitace
|
||||
- Zákaz paměti
|
||||
> Závěr spojuje zkázu s možností nového začátku skrze paměť a knihy.
|
||||
|
||||
|
||||
# Děj
|
||||
|
||||
## Přetáhněte části příběhu do správného pořadí:
|
||||
|
||||
1. Montag rutinně pálí knihy jako hasič
|
||||
2. Clarisse ho přiměje pochybovat o systému
|
||||
3. Montag schovává knihy a hledá radu u Fabera
|
||||
4. Beatty nechá Montaga spálit vlastní dům
|
||||
5. Montag zabije Beattyho a utíká z města
|
||||
6. Připojí se k pamatovačům a vidí zkázu města
|
||||
|
||||
> Správné pořadí: rutinní pálení → Clarisse a pochybnosti → knihy a Faber → spálení domu → útěk a Beatty → pamatovači a zkáza města.
|
||||
282
content/cestina/cetba/03-audience.md
Normal file
282
content/cestina/cetba/03-audience.md
Normal file
|
|
@ -0,0 +1,282 @@
|
|||
---
|
||||
id: audience
|
||||
autor: Václav Havel
|
||||
nazev: Audience
|
||||
zanr: Drama
|
||||
---
|
||||
|
||||
# O knize
|
||||
|
||||
- Autor: Václav Havel
|
||||
- Žánr: drama (jednoaktovka, absurdní / groteskní)
|
||||
- Poprvé vydáno: 1975 (součást Vaněkovy trilogie)
|
||||
- Děj/prostředí: kancelář vedoucího skladu pivovaru
|
||||
- Vyprávění/forma: divadelní dialog, jedno dějství, jazyk moci vs. jazyk obyčejného člověka
|
||||
|
||||
# Doba a svět
|
||||
|
||||
- Dílo vzniklo v normalizačním období; metaforicky kritizuje totalitní společnost.
|
||||
- Hrdina Vaněk je bývalý spisovatel přeřazený na manuální práci.
|
||||
- Moc se projevuje v byrokracii, strachu a pokrytectví „nadřízených“.
|
||||
- Rozhovor není o práci, ale o testu loajality a ideologické poslušnosti.
|
||||
- Groteska: banální situace skrývá vážný tlak na svědomí jedince.
|
||||
- Havel rozvíjí téma „slov odpovědnosti“ a falešné ideologické fráze.
|
||||
|
||||
# Postavy
|
||||
|
||||
- Ferdinand Vaněk – bývalý spisovatel, dělník ve skladu pivovaru.
|
||||
- Vedoucí skladu (Šéf) – malý funkcionář toužící po kariéře, ideologicky nejistý.
|
||||
- Vaněkova manželka (zmíněna) – představuje tlak rodiny a strach ze ztráty výdělku.
|
||||
- Kolegové (nepřítomní) – symbol kolektivního dohledu.
|
||||
- Šéf jako typ – přizpůsobivý člověk, který opakuje fráze moci.
|
||||
- Vaněk jako typ disidenta – mlčí, ale nepodléhá.
|
||||
|
||||
# Klíčové pojmy a motivy
|
||||
|
||||
- Audience – „audience u vedoucího“ = výslech, nátlak, pokus o spolupráci.
|
||||
- Hovory o pravdě – rozdíl mezi oficiální rétorikou a skutečným prožíváním.
|
||||
- Strach a kariéra – vedoucí se bojí, ale chce postup.
|
||||
- Práce vs. svědomí – Vaněk odmítá hrát ideologickou hru.
|
||||
- Groteska – vážné téma v banálním prostředí skladu.
|
||||
- Jazyk moci – prázdné fráze, které mají nahradit morální rozhodnutí.
|
||||
|
||||
|
||||
# Kvíz
|
||||
|
||||
## Kdo je autorem hry Audience?
|
||||
- Jaroslav Hašek
|
||||
- [x] Václav Havel
|
||||
- Karel Čapek
|
||||
- Ladislav Smoljak
|
||||
> Audience napsal Václav Havel jako součást Vaněkovy trilogie.
|
||||
|
||||
## Jaký je žánr díla?
|
||||
- Epos
|
||||
- [x] Jednoaktové drama
|
||||
- Lyrická báseň
|
||||
- Detektivní román
|
||||
> Jde o jednoaktovou divadelní hru s dialogem dvou postav.
|
||||
|
||||
## Kde se děj odehrává?
|
||||
- Na ministerstvu
|
||||
- [x] V kanceláři vedoucího skladu pivovaru
|
||||
- V divadle
|
||||
- V exilu
|
||||
> Celá hra probíhá v kanceláři vedoucího skladu.
|
||||
|
||||
## Kdo je Ferdinand Vaněk?
|
||||
- Vedoucí skladu
|
||||
- [x] Bývalý spisovatel přeřazený na manuální práci
|
||||
- Ministr
|
||||
- Hasič
|
||||
> Vaněk je inteligent přeřazený do dělnické profese – alter ego Havla.
|
||||
|
||||
## Proč vedoucí Vaněka „předvolá“?
|
||||
- Kvůli inventuře
|
||||
- [x] Aby ho ideologicky „ převýchovali“ a získali informace
|
||||
- Kvůli dovolené
|
||||
- Kvůli pivu zdarma
|
||||
> Rozhovor je nátlak na poslušnost a spolupráci s mocí.
|
||||
|
||||
## Jak vedoucí vnímá svou pozici?
|
||||
- Jako mučedníka
|
||||
- [x] Jako malého funkcionáře toužícího po kariéře
|
||||
- Jako disidenta
|
||||
- Jako umělce
|
||||
> Vedoucí se přizpůsobuje systému a chce postup.
|
||||
|
||||
## Jak Vaněk reaguje na nátlak?
|
||||
- Okamžitě udává
|
||||
- [x] Mlčí, ironizuje, nepodléhá
|
||||
- Odejde z práce
|
||||
- Napadne vedoucího
|
||||
> Vaněk odmítá hrát hru moci, i když riskuje problémy.
|
||||
|
||||
## Co je typické pro Havlovy hry s Vaněkem?
|
||||
- Historický realismus 19. století
|
||||
- [x] Groteskní situace a jazyk moci
|
||||
- Pohádková fantasy
|
||||
- Přírodní lyrika
|
||||
> Havel ukazuje absurditu režimu skrze banální rozhovory.
|
||||
|
||||
## Kdy hra vznikla / poprvé vyšla?
|
||||
- 1948
|
||||
- [x] 1975
|
||||
- 1989
|
||||
- 2000
|
||||
> Audience patří k Vaněkově trilogii z normalizačního období (1975).
|
||||
|
||||
## Jaké další hry tvoří Vaněkovu trilogii kromě Audience?
|
||||
- Hamlet a Macbeth
|
||||
- [x] Protest a Vyrozumění
|
||||
- R.U.R. a Bílá nemoc
|
||||
- Čekání na Godota a Endgame
|
||||
> Trilogie: Audience, Protest, Vyrozumění.
|
||||
|
||||
## Proč je hra „absurdní“?
|
||||
- Protože se dějí zázraky
|
||||
- [x] Protože vážný nátlak probíhá v banální situaci skladu
|
||||
- Protože je bez dialogu
|
||||
- Protože je v rýmu
|
||||
> Absurdita je v rozporu mezi tématem a prostředím.
|
||||
|
||||
## Co symbolizuje pivovar / sklad?
|
||||
- Exkluzivní elita
|
||||
- [x] Běžné pracovní prostředí, kde se testuje loajalita
|
||||
- Církev
|
||||
- Škola
|
||||
> Moc se prosazuje i v obyčejné fabrice.
|
||||
|
||||
## Jak vedoucí mluví o „pravdě“?
|
||||
- Jasně a otevřeně
|
||||
- [x] Používá ideologické fráze a ospravedlňuje se
|
||||
- V latině
|
||||
- Vůbec nemluví
|
||||
> Vedoucí opakuje fráze, ale neumí nést morální odpovědnost.
|
||||
|
||||
## Proč Vaněk nechce „spolupracovat“?
|
||||
- Neví jak
|
||||
- [x] Odmítá kompromis se lží a strachem
|
||||
- Chce být vedoucím
|
||||
- Je mu jedno
|
||||
> Hrdina volí svědomí před kariérním nebo materiálním klidem.
|
||||
|
||||
## Jaký vztah mají oba muži k alkoholu v hře?
|
||||
- Nepijí
|
||||
- [x] Pivo je součástí prostředí a uvolnění napětí
|
||||
- Pijí jen Vaněk
|
||||
- Pivo zakazují
|
||||
> Pivovar jako prostředí ovlivňuje tón rozhovoru.
|
||||
|
||||
## Co hrozí Vaněkovi, pokud neuspokojí vedoucího?
|
||||
- Pouze pokuta
|
||||
- [x] Další perzekuce, problémy v práci i rodině
|
||||
- Okamžitá sláva
|
||||
- Povýšení
|
||||
> Normalizační režim trestal odmítnutí spolupráce.
|
||||
|
||||
## Které téma Havel v Audience NEřeší primárně?
|
||||
- Morální odpovědnost
|
||||
- Jazyk moci
|
||||
- [x] Kosmické cestování
|
||||
- Strach z autorit
|
||||
> Hra je společenská groteska, ne sci-fi.
|
||||
|
||||
## Jak končí hra typicky v interpretaci?
|
||||
- Vítězstvím vedoucího
|
||||
- [x] Bez jasného „happy endu“ – napětí a Vaněkovo trvání na svém
|
||||
- Svatbou
|
||||
- Válka
|
||||
> Zůstává konflikt mezi mocí a svědomím.
|
||||
|
||||
## Proč je Audience maturitní četbou?
|
||||
- Kvůli pohádkovému ději
|
||||
- [x] Ukazuje českou literaturu 20. století a disidentskou zkušenost
|
||||
- Je nejkratší kniha
|
||||
- Je bez témat
|
||||
> Dílo reprezentuje Havla a období normalizace.
|
||||
|
||||
## Kdo je autorem termínu „slov odpovědnosti“ v kontextu Havla?
|
||||
- Shakespeare
|
||||
- [x] Václav Havel
|
||||
- Orwell
|
||||
- Kafka
|
||||
> Havel zdůrazňoval, že slova mají morální váhu.
|
||||
|
||||
## Jaký je tón dialogu?
|
||||
- Epický popis přírody
|
||||
- [x] Napětí mezi frázemi moci a Vaněkovou ironií
|
||||
- Pouze monolog
|
||||
- Pouze pění
|
||||
> Dialog odhaluje charakter obou postav.
|
||||
|
||||
## Vedoucí se bojí hlavně…
|
||||
- Přízraků
|
||||
- [x] Ztráty postavení a problémů s nadřízenými
|
||||
- Vaněkova talentu na pivo
|
||||
- Cizinců
|
||||
> Jeho kariéra závisí na ideologické spolehlivosti.
|
||||
|
||||
## Vaněk v hře představuje…
|
||||
- Typ spolupracovníka režimu
|
||||
- [x] Typ člověka, který nezradí svědomí
|
||||
- Krále
|
||||
- Detektiva
|
||||
> Vaněk je Havlovo alter ego disidenta.
|
||||
|
||||
## Kolik hlavních mluvících postav je v Audience?
|
||||
- Pět
|
||||
- [x] Dvě
|
||||
- Deset
|
||||
- Žádná
|
||||
> Dialog vedoucího a Vaněka tvoří jádro hry.
|
||||
|
||||
## Jak souvisí Audience s normalizací?
|
||||
- [x] Vznikla v období po roce 1968 jako metafora tlaku režimu
|
||||
- Popisuje středověk
|
||||
- Je z roku 1848
|
||||
- Je americký western
|
||||
> Hra reaguje na politickou situaci v Československu 70. let.
|
||||
|
||||
## Proč vedoucí opakuje fráze?
|
||||
- Nemá slovní zásobu
|
||||
- [x] Nahrazuje nimi vlastní rozhodnutí a odpovědnost
|
||||
- Učí se latinu
|
||||
- Je básník
|
||||
> Ideologický jazyk má ulevit od morální volby.
|
||||
|
||||
## Co Vaněk odmítá udělat?
|
||||
- Pracovat
|
||||
- [x] Hrát roli informátora / ideologicky se „ přizpůsobit“
|
||||
- Pít pivo
|
||||
- Chodit do skladu
|
||||
> Jde o odmítnutí spolupráce s mocí.
|
||||
|
||||
## Jaký literární směr je nejblíže Havlovu divadlu?
|
||||
- Romantismus
|
||||
- [x] Divadlo absurdní / groteskní
|
||||
- Klasicismus
|
||||
- Naturalismus venkova
|
||||
> Havel navazuje na absurdní drama, ale s českým politickým kontextem.
|
||||
|
||||
## Co je „audience“ v anglickém významu slova?
|
||||
- [x] Publikum / jednání s nadřízeným
|
||||
- Hasičský sbor
|
||||
- Pivní sud
|
||||
- Soudní trest
|
||||
> Název ironicky evokuje setkání, které je ve skutečnosti výslech.
|
||||
|
||||
## Která postava je víc „pro systém“?
|
||||
- Vaněk
|
||||
- [x] Vedoucí skladu
|
||||
- Obě stejně
|
||||
- Ani jedna
|
||||
> Vedoucí se snaží vyhovět nadřízeným.
|
||||
|
||||
## Jaké poselství je pro maturitu klíčové?
|
||||
- Poslušnost za každou cenu
|
||||
- [x] Člověk může odmítnout lhát, i když za to platí
|
||||
- Práce je vždy důležitější než pravda
|
||||
- Fráze nahrazují etiku
|
||||
> Hra obhajuje svědomí proti ideologickému nátlaku.
|
||||
|
||||
## V jakém žánru je Audience v katalogu maturitní četby?
|
||||
- Poezie
|
||||
- [x] Drama
|
||||
- Próza
|
||||
- Epos
|
||||
> V katalogu je uvedeno jako drama.
|
||||
|
||||
|
||||
# Děj
|
||||
|
||||
## Přetáhněte části příběhu do správného pořadí:
|
||||
|
||||
1. Vaněk pracuje ve skladu pivovaru jako dělník
|
||||
2. Vedoucí ho předvolá na rozhovor v kanceláři
|
||||
3. Vedoucí tlakem a frázemi testuje Vaněkovo přizpůsobení
|
||||
4. Vaněk odmítá ideologickou spolupráci
|
||||
5. Napětí mezi kariérou vedoucího a Vaněkovým svědomím roste
|
||||
6. Hra končí bez smíření – moc a disident zůstávají v konfliktu
|
||||
|
||||
> Správné pořadí: Vaněk ve skladu → předvolání → nátlak vedoucího → Vaněkovo odmítnutí → eskalace napětí → nevyřešený konflikt.
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue