diff --git a/README.md b/README.md index 8605cce..a57339b 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,9 @@ Vzdělávací aplikace k přípravě na maturitu (repo `Graduately`). / An educa Rozhraní je v češtině a angličtině. Otevřené předměty jsou v seznamu níže; ostatní jsou zatím zamčené. Aplikace se po instalaci aktualizuje sama. -| Úvod | Němčina | Neue Freunde | -| ---- | -------- | ------------ | -| ![Úvod](assets/home.png) | ![Němčina](assets/deutsch.png) | ![Neue Freunde](assets/neue-freunde.png) | +| Úvod | Předměty | Německá cesta | +| ---- | -------- | ------------- | +| ![Úvod](assets/welcomescreen.png) | ![Předměty](assets/subjectsscreen.png) | ![Německá cesta](assets/germanlection.png) | ### Instalace @@ -71,15 +71,6 @@ Intel Mac, jiná architektura nebo úpravy kódu → [sestavení ze zdroje](#ses - **Technické vybavení** — 4 ročníky: 1. ročník má 29 lekcí (architektura, data, skříň, deska, karty, disky a vstup), ročníky 2–4 po 8 lekcích (monitory, sestavení, RAID, servery, údržba) -- **Technická grafika** — 4 ročníky AutoCADu, v každém 8 lekcí: - výkres a souřadnice, úpravy a kóty, pohledy a tisk, 3D a maturitní zadání -- **Prezentační grafika** — 4 ročníky, v každém 8 lekcí: Photoshop od pixelu - po plakát, Premiere Pro a ve čtvrtém ročníku Illustrator, After Effects - a InDesign -- **Programové vybavení** — 4 ročníky, v každém 8 lekcí: Windows a licence, - Word a Excel, Access a MySQL, pak WordPress, Power BI, dávkové soubory a zásady -- **Programování** — 4 ročníky C# po vzoru W3Schools. U každé lekce se kód - píše a spouští vedle výkladu, od výpisu po třídy, LINQ a async - **Český jazyk a literatura** — literatura (4 ročníky, 32 lekcí podle osnov středních škol), mluvnice (20 cvičení) a maturitní četba (82 knih: zápisky, kvíz, sestavení děje) @@ -99,10 +90,10 @@ Intel Mac, jiná architektura nebo úpravy kódu → [sestavení ze zdroje](#ses ### Použití -1. **Úvod** ukáže postup a mřížku předmětů. Každý předmět spustí svou cestu. -2. U němčiny je učebnice (Neue Freunde, Aus aller Welt, Bei uns zu Hause) a čtyři ročníky. Ostatní otevřené předměty mají ročníky, lekce nebo knihy. -3. Z cesty se otevře výklad, poslech, čtení, psaní nebo kvíz. -4. **Statistiky**, **Nastavení** a **Hledat** jsou v postranním panelu na Macu. Na telefonu a v desktopové aplikaci jsou na záložkách, hledání navíc ikonou lupy. Zkratka je `Cmd/Ctrl+K`. +1. **Pokračuj** otevře mapu předmětů. +2. Otevřený předmět (vlajka, Wi‑Fi, čip, česká vlajka, váhy, funkce, atom, baňka) vede na učební cestu. +3. Uzly cvičení / lekcí otevřou obsah; zamčené nic nedělají. +4. **Hledat** (lupa), **Statistiky** (graf) a **Nastavení** (ozubené kolo) jsou vpravo nahoře. ### Sestavení ze zdroje @@ -207,9 +198,9 @@ Licence: [GPL-3.0](LICENSE). The UI is Czech and English. Open subjects are listed below; the rest are still locked. After install the app updates itself. -| Welcome | German | Neue Freunde | -| ------- | ------ | ----------- | -| ![Welcome](assets/home.png) | ![German](assets/deutsch.png) | ![Neue Freunde](assets/neue-freunde.png) | +| Welcome | Subjects | German path | +| ------- | -------- | ----------- | +| ![Welcome](assets/welcomescreen.png) | ![Subjects](assets/subjectsscreen.png) | ![German path](assets/germanlection.png) | ### Install @@ -268,10 +259,6 @@ Intel Mac, another architecture, or hacking on the code → - **Computer hardware** — 4 years: year 1 has 29 lessons (architecture, data, case, board, cards, drives and input), years 2–4 have 8 lessons each (displays, assembly, RAID, servers, maintenance) -- **Technical graphics** — 4 years of AutoCAD, 8 lessons each: - the sheet and coordinates, editing and dimensions, views and plotting, 3D and the exam drawing -- **Programming** — 4 years of C# in the style of W3Schools. Each lesson has - code you edit and run beside the explanation, from output to classes, LINQ and async - **Czech language** — literature (4 years, 32 lessons from the secondary-school syllabus), grammar (20 exercises) and required reading (82 books: notes, quiz, plot ordering) @@ -292,10 +279,10 @@ Intel Mac, another architecture, or hacking on the code → ### Usage -1. **Welcome** shows progress and the subject grid. An open subject starts its path. Locked tiles do nothing yet: presentation graphics and software. -2. German has the textbook (Neue Freunde, Aus aller Welt, Bei uns zu Hause) and four years. The other open subjects have years, lessons or books. -3. A path opens an overview, listening, reading, writing or a quiz. -4. **Statistics**, **Settings** and **Search** sit in the sidebar on Mac. On the phone and the desktop app they are tabs, with search also on the magnifier. The shortcut is `Cmd/Ctrl+K`. +1. **Continue** opens the subject map. +2. An open subject (flag, Wi‑Fi, chip, Czech flag, scales, function, atom, flask) opens its path. +3. Exercise / lesson nodes open content; locked nodes do nothing. +4. **Search** (magnifier), **Statistics** (chart) and **Settings** (gear) sit in the top-right. ### Build from source diff --git a/android/desktop/src/main/kotlin/org/maturita/maturita/desktop/CSharpLab.kt b/android/desktop/src/main/kotlin/org/maturita/maturita/desktop/CSharpLab.kt deleted file mode 100644 index ad7f5f1..0000000 --- a/android/desktop/src/main/kotlin/org/maturita/maturita/desktop/CSharpLab.kt +++ /dev/null @@ -1,128 +0,0 @@ -package org.maturita.maturita.desktop - -import org.maturita.maturita.platform.CSharpRun -import java.io.ByteArrayOutputStream -import java.io.File -import java.nio.charset.StandardCharsets -import java.util.concurrent.TimeUnit - -/** One cached console project. The student's program replaces Program.cs and `dotnet run` executes it. */ -object CSharpLab { - private val gate = Object() - - fun run(source: String, stdin: String): CSharpRun { - if (source.length > 100_000) return CSharpRun("fail", "Program je příliš dlouhý.") - val dotnet = findDotnet() ?: return CSharpRun("unavailable", "") - synchronized(gate) { - return try { - execute(dotnet, source, stdin) - } catch (e: Exception) { - CSharpRun("fail", e.message ?: "Spuštění selhalo.") - } - } - } - - private fun execute(dotnet: String, source: String, stdin: String): CSharpRun { - val dir = File(System.getProperty("user.home"), ".graduately/csharp-lab") - dir.mkdirs() - val csproj = File(dir, "Lab.csproj") - if (!csproj.isFile) { - csproj.writeText(projectFile(targetFramework(dotnet)), StandardCharsets.UTF_8) - val restored = command(dotnet, listOf("restore", dir.absolutePath), dir, "", 90) - if (restored.status != "ok") return restored - } - File(dir, "Program.cs").writeText(source, StandardCharsets.UTF_8) - val args = mutableListOf("run", "--project", dir.absolutePath, "--verbosity", "quiet") - if (File(dir, "obj").isDirectory) args += "--no-restore" - return command(dotnet, args, dir, stdin, 20) - } - - private fun command(dotnet: String, args: List, dir: File, stdin: String, seconds: Long): CSharpRun { - val process = ProcessBuilder(listOf(dotnet) + args) - .directory(dir) - .redirectErrorStream(true) - .apply { - environment().clear() - environment().putAll(environmentFor(dotnet)) - } - .start() - process.outputStream.use { it.write(stdin.toByteArray(StandardCharsets.UTF_8)) } - val output = ByteArrayOutputStream() - val reader = Thread { - process.inputStream.use { it.copyTo(output) } - } - reader.isDaemon = true - reader.start() - val finished = process.waitFor(seconds, TimeUnit.SECONDS) - if (!finished) { - process.descendants().forEach { it.destroyForcibly() } - process.destroyForcibly() - process.waitFor(2, TimeUnit.SECONDS) - reader.join(1000) - return CSharpRun("timeout", clip(output.toString(StandardCharsets.UTF_8))) - } - reader.join(2000) - val text = clip(output.toString(StandardCharsets.UTF_8)).trim() - return if (process.exitValue() == 0) CSharpRun("ok", text) else CSharpRun("fail", text) - } - - private fun clip(text: String): String = - if (text.length <= 16_000) text else text.take(16_000) + "\n…" - - private fun environmentFor(dotnet: String): Map { - val home = System.getProperty("user.home") - val root = File(dotnet).parent - val path = listOf(root, "/opt/homebrew/bin", "/usr/local/bin", "/usr/bin", "/bin") - .joinToString(File.pathSeparator) - val env = mutableMapOf( - "PATH" to path, - "HOME" to home, - "USERPROFILE" to home, - "DOTNET_ROOT" to root, - "DOTNET_CLI_TELEMETRY_OPTOUT" to "1", - "DOTNET_NOLOGO" to "1", - "DOTNET_SKIP_FIRST_TIME_EXPERIENCE" to "1", - "TEMP" to System.getProperty("java.io.tmpdir"), - "TMP" to System.getProperty("java.io.tmpdir"), - ) - System.getenv("SystemRoot")?.let { env["SystemRoot"] = it } - System.getenv("ComSpec")?.let { env["ComSpec"] = it } - return env - } - - private fun targetFramework(dotnet: String): String { - val version = command(dotnet, listOf("--version"), File(System.getProperty("java.io.tmpdir")), "", 20) - val major = version.output.trim().substringBefore('.').filter { it.isDigit() } - return if (major.isEmpty()) "net8.0" else "net$major.0" - } - - private fun projectFile(framework: String) = """ - - - Exe - $framework - enable - disable - latest - - - """.trimIndent() - - private fun findDotnet(): String? { - val home = System.getProperty("user.home") - val programFiles = System.getenv("ProgramFiles") ?: "C:\\Program Files" - val names = listOf( - "/usr/local/share/dotnet/dotnet", - "/usr/share/dotnet/dotnet", - "/opt/homebrew/share/dotnet/dotnet", - "$home/.dotnet/dotnet", - "$programFiles\\dotnet\\dotnet.exe", - ) - names.firstOrNull { File(it).canExecute() }?.let { return it } - val path = System.getenv("PATH") ?: return null - return path.split(File.pathSeparator) - .map { File(it, if (System.getProperty("os.name").startsWith("Windows")) "dotnet.exe" else "dotnet") } - .firstOrNull { it.canExecute() } - ?.absolutePath - } -} diff --git a/android/desktop/src/main/kotlin/org/maturita/maturita/desktop/DesktopPlatform.kt b/android/desktop/src/main/kotlin/org/maturita/maturita/desktop/DesktopPlatform.kt index c61e57c..ced42c6 100644 --- a/android/desktop/src/main/kotlin/org/maturita/maturita/desktop/DesktopPlatform.kt +++ b/android/desktop/src/main/kotlin/org/maturita/maturita/desktop/DesktopPlatform.kt @@ -1,10 +1,8 @@ package org.maturita.maturita.desktop -import org.maturita.maturita.platform.CSharpRun import org.maturita.maturita.platform.Platform import org.maturita.maturita.platform.Prefs import org.maturita.maturita.platform.Speaker -import javax.swing.SwingUtilities class DesktopPlatform( override val commit: String, @@ -16,11 +14,4 @@ class DesktopPlatform( override val updater = DesktopUpdater(commit, install) override fun speaker(): Speaker? = DesktopSpeaker.create() - - override fun runCSharp(source: String, stdin: String, cb: (CSharpRun) -> Unit) { - Thread { - val result = CSharpLab.run(source, stdin) - SwingUtilities.invokeLater { cb(result) } - }.apply { isDaemon = true }.start() - } } diff --git a/android/desktop/src/main/kotlin/org/maturita/maturita/desktop/Main.kt b/android/desktop/src/main/kotlin/org/maturita/maturita/desktop/Main.kt index aa9a704..98d77e9 100644 --- a/android/desktop/src/main/kotlin/org/maturita/maturita/desktop/Main.kt +++ b/android/desktop/src/main/kotlin/org/maturita/maturita/desktop/Main.kt @@ -40,8 +40,6 @@ fun main() { 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) - // `GRADUATELY_PAGE=u1e3 make run` opens a page, for screenshots. - System.getenv("GRADUATELY_PAGE")?.takeIf { it.isNotBlank() }?.let { vm.openPage(it) } val icon = Thread.currentThread().contextClassLoader.getResourceAsStream("icon.png") ?.use { ImageIO.read(it) }?.let { BitmapPainter(it.toComposeImageBitmap()) } diff --git a/android/shared/src/org/maturita/maturita/App.kt b/android/shared/src/org/maturita/maturita/App.kt index 27eef9d..7f796e1 100644 --- a/android/shared/src/org/maturita/maturita/App.kt +++ b/android/shared/src/org/maturita/maturita/App.kt @@ -23,8 +23,6 @@ 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.CodeLessonScreen -import org.maturita.maturita.ui.CsYearsScreen import org.maturita.maturita.ui.CzechMapScreen import org.maturita.maturita.ui.GermanExercise import org.maturita.maturita.ui.HomeScreen @@ -32,12 +30,6 @@ 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.PgQuizScreen -import org.maturita.maturita.ui.PgYearsScreen -import org.maturita.maturita.ui.SwQuizScreen -import org.maturita.maturita.ui.SwYearsScreen -import org.maturita.maturita.ui.TgQuizScreen -import org.maturita.maturita.ui.TgYearsScreen import org.maturita.maturita.ui.MathPracticeScreen import org.maturita.maturita.ui.MatYearsScreen import org.maturita.maturita.ui.FyzYearsScreen @@ -533,222 +525,6 @@ private fun MaturitaAppBody(vm: AppViewModel) { } } is Route.Fyz4Ex -> FyzQuizScreen(vm, 4, r.id) - Route.TgYears -> TgYearsScreen(vm) - Route.TgMap -> LessonListScreen( - vm, vm.tr("tg_year1"), vm.tr("tg_sub"), - vm.content.tg.map { l -> - val id = l.int("id") - LessonRow(vm.tr(l.str("titleKey")), vm.progress.tgDone(id), Route.TgLesson(id)) - }, - ) - is Route.TgLesson -> { - val l = vm.content.tgLesson(r.id) - if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) { - vm.replace(Route.TgEx(r.id)) - } - } - is Route.TgEx -> TgQuizScreen(vm, 1, r.id) - Route.Tg2Map -> LessonListScreen( - vm, vm.tr("tg_year2"), vm.tr("tg2_sub"), - vm.content.tg2.map { l -> - val id = l.int("id") - LessonRow(vm.tr(l.str("titleKey")), vm.progress.tg2Done(id), Route.Tg2Lesson(id)) - }, - ) - is Route.Tg2Lesson -> { - val l = vm.content.tg2Lesson(r.id) - if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) { - vm.replace(Route.Tg2Ex(r.id)) - } - } - is Route.Tg2Ex -> TgQuizScreen(vm, 2, r.id) - Route.Tg3Map -> LessonListScreen( - vm, vm.tr("tg_year3"), vm.tr("tg3_sub"), - vm.content.tg3.map { l -> - val id = l.int("id") - LessonRow(vm.tr(l.str("titleKey")), vm.progress.tg3Done(id), Route.Tg3Lesson(id)) - }, - ) - is Route.Tg3Lesson -> { - val l = vm.content.tg3Lesson(r.id) - if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) { - vm.replace(Route.Tg3Ex(r.id)) - } - } - is Route.Tg3Ex -> TgQuizScreen(vm, 3, r.id) - Route.Tg4Map -> LessonListScreen( - vm, vm.tr("tg_year4"), vm.tr("tg4_sub"), - vm.content.tg4.map { l -> - val id = l.int("id") - LessonRow(vm.tr(l.str("titleKey")), vm.progress.tg4Done(id), Route.Tg4Lesson(id)) - }, - ) - is Route.Tg4Lesson -> { - val l = vm.content.tg4Lesson(r.id) - if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) { - vm.replace(Route.Tg4Ex(r.id)) - } - } - is Route.Tg4Ex -> TgQuizScreen(vm, 4, r.id) - Route.PgYears -> PgYearsScreen(vm) - Route.PgMap -> LessonListScreen( - vm, vm.tr("pg_year1"), vm.tr("pg_sub"), - vm.content.pg.map { l -> - val id = l.int("id") - LessonRow(vm.tr(l.str("titleKey")), vm.progress.pgDone(id), Route.PgLesson(id)) - }, - ) - is Route.PgLesson -> { - val l = vm.content.pgLesson(r.id) - if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) { - vm.replace(Route.PgEx(r.id)) - } - } - is Route.PgEx -> PgQuizScreen(vm, 1, r.id) - Route.Pg2Map -> LessonListScreen( - vm, vm.tr("pg_year2"), vm.tr("pg2_sub"), - vm.content.pg2.map { l -> - val id = l.int("id") - LessonRow(vm.tr(l.str("titleKey")), vm.progress.pg2Done(id), Route.Pg2Lesson(id)) - }, - ) - is Route.Pg2Lesson -> { - val l = vm.content.pg2Lesson(r.id) - if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) { - vm.replace(Route.Pg2Ex(r.id)) - } - } - is Route.Pg2Ex -> PgQuizScreen(vm, 2, r.id) - Route.Pg3Map -> LessonListScreen( - vm, vm.tr("pg_year3"), vm.tr("pg3_sub"), - vm.content.pg3.map { l -> - val id = l.int("id") - LessonRow(vm.tr(l.str("titleKey")), vm.progress.pg3Done(id), Route.Pg3Lesson(id)) - }, - ) - is Route.Pg3Lesson -> { - val l = vm.content.pg3Lesson(r.id) - if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) { - vm.replace(Route.Pg3Ex(r.id)) - } - } - is Route.Pg3Ex -> PgQuizScreen(vm, 3, r.id) - Route.Pg4Map -> LessonListScreen( - vm, vm.tr("pg_year4"), vm.tr("pg4_sub"), - vm.content.pg4.map { l -> - val id = l.int("id") - LessonRow(vm.tr(l.str("titleKey")), vm.progress.pg4Done(id), Route.Pg4Lesson(id)) - }, - ) - is Route.Pg4Lesson -> { - val l = vm.content.pg4Lesson(r.id) - if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) { - vm.replace(Route.Pg4Ex(r.id)) - } - } - is Route.Pg4Ex -> PgQuizScreen(vm, 4, r.id) - Route.SwYears -> SwYearsScreen(vm) - Route.SwMap -> LessonListScreen( - vm, vm.tr("sw_year1"), vm.tr("sw_sub"), - vm.content.sw.map { l -> - val id = l.int("id") - LessonRow(vm.tr(l.str("titleKey")), vm.progress.swDone(id), Route.SwLesson(id)) - }, - ) - is Route.SwLesson -> { - val l = vm.content.swLesson(r.id) - if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) { - vm.replace(Route.SwEx(r.id)) - } - } - is Route.SwEx -> SwQuizScreen(vm, 1, r.id) - Route.Sw2Map -> LessonListScreen( - vm, vm.tr("sw_year2"), vm.tr("sw2_sub"), - vm.content.sw2.map { l -> - val id = l.int("id") - LessonRow(vm.tr(l.str("titleKey")), vm.progress.sw2Done(id), Route.Sw2Lesson(id)) - }, - ) - is Route.Sw2Lesson -> { - val l = vm.content.sw2Lesson(r.id) - if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) { - vm.replace(Route.Sw2Ex(r.id)) - } - } - is Route.Sw2Ex -> SwQuizScreen(vm, 2, r.id) - Route.Sw3Map -> LessonListScreen( - vm, vm.tr("sw_year3"), vm.tr("sw3_sub"), - vm.content.sw3.map { l -> - val id = l.int("id") - LessonRow(vm.tr(l.str("titleKey")), vm.progress.sw3Done(id), Route.Sw3Lesson(id)) - }, - ) - is Route.Sw3Lesson -> { - val l = vm.content.sw3Lesson(r.id) - if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) { - vm.replace(Route.Sw3Ex(r.id)) - } - } - is Route.Sw3Ex -> SwQuizScreen(vm, 3, r.id) - Route.Sw4Map -> LessonListScreen( - vm, vm.tr("sw_year4"), vm.tr("sw4_sub"), - vm.content.sw4.map { l -> - val id = l.int("id") - LessonRow(vm.tr(l.str("titleKey")), vm.progress.sw4Done(id), Route.Sw4Lesson(id)) - }, - ) - is Route.Sw4Lesson -> { - val l = vm.content.sw4Lesson(r.id) - if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) { - vm.replace(Route.Sw4Ex(r.id)) - } - } - is Route.Sw4Ex -> SwQuizScreen(vm, 4, r.id) - Route.CsYears -> CsYearsScreen(vm) - Route.CsMap -> LessonListScreen( - vm, vm.tr("cs_year1"), vm.tr("cs_sub"), - vm.content.cs.map { l -> - val id = l.int("id") - LessonRow(vm.tr(l.str("titleKey")), vm.progress.csDone(id), Route.CsLesson(id)) - }, - ) - is Route.CsLesson -> { - val l = vm.content.csLesson(r.id) - if (l != null) CodeLessonScreen(vm, l) { vm.markCs(r.id) } - } - Route.Cs2Map -> LessonListScreen( - vm, vm.tr("cs_year2"), vm.tr("cs2_sub"), - vm.content.cs2.map { l -> - val id = l.int("id") - LessonRow(vm.tr(l.str("titleKey")), vm.progress.cs2Done(id), Route.Cs2Lesson(id)) - }, - ) - is Route.Cs2Lesson -> { - val l = vm.content.cs2Lesson(r.id) - if (l != null) CodeLessonScreen(vm, l) { vm.markCs2(r.id) } - } - Route.Cs3Map -> LessonListScreen( - vm, vm.tr("cs_year3"), vm.tr("cs3_sub"), - vm.content.cs3.map { l -> - val id = l.int("id") - LessonRow(vm.tr(l.str("titleKey")), vm.progress.cs3Done(id), Route.Cs3Lesson(id)) - }, - ) - is Route.Cs3Lesson -> { - val l = vm.content.cs3Lesson(r.id) - if (l != null) CodeLessonScreen(vm, l) { vm.markCs3(r.id) } - } - Route.Cs4Map -> LessonListScreen( - vm, vm.tr("cs_year4"), vm.tr("cs4_sub"), - vm.content.cs4.map { l -> - val id = l.int("id") - LessonRow(vm.tr(l.str("titleKey")), vm.progress.cs4Done(id), Route.Cs4Lesson(id)) - }, - ) - is Route.Cs4Lesson -> { - val l = vm.content.cs4Lesson(r.id) - if (l != null) CodeLessonScreen(vm, l) { vm.markCs4(r.id) } - } Route.SciMap -> SciMapScreen(vm) Route.ChemMap -> LessonListScreen( vm, vm.tr("Chemie"), vm.tr("chem_sub"), diff --git a/android/shared/src/org/maturita/maturita/AppViewModel.kt b/android/shared/src/org/maturita/maturita/AppViewModel.kt index 4be6a80..03fd3ea 100644 --- a/android/shared/src/org/maturita/maturita/AppViewModel.kt +++ b/android/shared/src/org/maturita/maturita/AppViewModel.kt @@ -242,86 +242,6 @@ class AppViewModel(val content: Content, val platform: Platform) { refresh() } - fun markTg(id: Int) { - progress.markTg(id) - refresh() - } - - fun markTg2(id: Int) { - progress.markTg2(id) - refresh() - } - - fun markTg3(id: Int) { - progress.markTg3(id) - refresh() - } - - fun markTg4(id: Int) { - progress.markTg4(id) - refresh() - } - - fun markPg(id: Int) { - progress.markPg(id) - refresh() - } - - fun markPg2(id: Int) { - progress.markPg2(id) - refresh() - } - - fun markPg3(id: Int) { - progress.markPg3(id) - refresh() - } - - fun markPg4(id: Int) { - progress.markPg4(id) - refresh() - } - - fun markSw(id: Int) { - progress.markSw(id) - refresh() - } - - fun markSw2(id: Int) { - progress.markSw2(id) - refresh() - } - - fun markSw3(id: Int) { - progress.markSw3(id) - refresh() - } - - fun markSw4(id: Int) { - progress.markSw4(id) - refresh() - } - - fun markCs(id: Int) { - progress.markCs(id) - refresh() - } - - fun markCs2(id: Int) { - progress.markCs2(id) - refresh() - } - - fun markCs3(id: Int) { - progress.markCs3(id) - refresh() - } - - fun markCs4(id: Int) { - progress.markCs4(id) - refresh() - } - fun markMluv(n: Int) { progress.markMluv(n) refresh() diff --git a/android/shared/src/org/maturita/maturita/Route.kt b/android/shared/src/org/maturita/maturita/Route.kt index af79af8..c90685e 100644 --- a/android/shared/src/org/maturita/maturita/Route.kt +++ b/android/shared/src/org/maturita/maturita/Route.kt @@ -105,54 +105,6 @@ sealed class Route(val page: String) { data object Fyz4Map : Route("fyz4map") data class Fyz4Lesson(val id: Int) : Route("fyz4unit$id") data class Fyz4Ex(val id: Int) : Route("fyz4ex$id") - data object TgYears : Route("tgyears") - data object TgMap : Route("tgmap") - data class TgLesson(val id: Int) : Route("tgunit$id") - data class TgEx(val id: Int) : Route("tgex$id") - data object Tg2Map : Route("tg2map") - data class Tg2Lesson(val id: Int) : Route("tg2unit$id") - data class Tg2Ex(val id: Int) : Route("tg2ex$id") - data object Tg3Map : Route("tg3map") - data class Tg3Lesson(val id: Int) : Route("tg3unit$id") - data class Tg3Ex(val id: Int) : Route("tg3ex$id") - data object Tg4Map : Route("tg4map") - data class Tg4Lesson(val id: Int) : Route("tg4unit$id") - data class Tg4Ex(val id: Int) : Route("tg4ex$id") - data object PgYears : Route("pgyears") - data object PgMap : Route("pgmap") - data class PgLesson(val id: Int) : Route("pgunit$id") - data class PgEx(val id: Int) : Route("pgex$id") - data object Pg2Map : Route("pg2map") - data class Pg2Lesson(val id: Int) : Route("pg2unit$id") - data class Pg2Ex(val id: Int) : Route("pg2ex$id") - data object Pg3Map : Route("pg3map") - data class Pg3Lesson(val id: Int) : Route("pg3unit$id") - data class Pg3Ex(val id: Int) : Route("pg3ex$id") - data object Pg4Map : Route("pg4map") - data class Pg4Lesson(val id: Int) : Route("pg4unit$id") - data class Pg4Ex(val id: Int) : Route("pg4ex$id") - data object SwYears : Route("swyears") - data object SwMap : Route("swmap") - data class SwLesson(val id: Int) : Route("swunit$id") - data class SwEx(val id: Int) : Route("swex$id") - data object Sw2Map : Route("sw2map") - data class Sw2Lesson(val id: Int) : Route("sw2unit$id") - data class Sw2Ex(val id: Int) : Route("sw2ex$id") - data object Sw3Map : Route("sw3map") - data class Sw3Lesson(val id: Int) : Route("sw3unit$id") - data class Sw3Ex(val id: Int) : Route("sw3ex$id") - data object Sw4Map : Route("sw4map") - data class Sw4Lesson(val id: Int) : Route("sw4unit$id") - data class Sw4Ex(val id: Int) : Route("sw4ex$id") - data object CsYears : Route("csyears") - data object CsMap : Route("csmap") - data class CsLesson(val id: Int) : Route("csunit$id") - data object Cs2Map : Route("cs2map") - data class Cs2Lesson(val id: Int) : Route("cs2unit$id") - data object Cs3Map : Route("cs3map") - data class Cs3Lesson(val id: Int) : Route("cs3unit$id") - data object Cs4Map : Route("cs4map") - data class Cs4Lesson(val id: Int) : Route("cs4unit$id") data object CzechMap : Route("czechmap") data object Mluvnice : Route("mluvnice") data class MluvEx(val n: Int) : Route("mluve$n") @@ -285,54 +237,6 @@ sealed class Route(val page: String) { Fyz4Map -> listOf(Subjects, FyzYears, Fyz4Map) is Fyz4Lesson -> listOf(Subjects, FyzYears, Fyz4Map, this) is Fyz4Ex -> listOf(Subjects, FyzYears, Fyz4Map, Fyz4Lesson(id), this) - TgYears -> listOf(Subjects, TgYears) - TgMap -> listOf(Subjects, TgYears, TgMap) - is TgLesson -> listOf(Subjects, TgYears, TgMap, this) - is TgEx -> listOf(Subjects, TgYears, TgMap, TgLesson(id), this) - Tg2Map -> listOf(Subjects, TgYears, Tg2Map) - is Tg2Lesson -> listOf(Subjects, TgYears, Tg2Map, this) - is Tg2Ex -> listOf(Subjects, TgYears, Tg2Map, Tg2Lesson(id), this) - Tg3Map -> listOf(Subjects, TgYears, Tg3Map) - is Tg3Lesson -> listOf(Subjects, TgYears, Tg3Map, this) - is Tg3Ex -> listOf(Subjects, TgYears, Tg3Map, Tg3Lesson(id), this) - Tg4Map -> listOf(Subjects, TgYears, Tg4Map) - is Tg4Lesson -> listOf(Subjects, TgYears, Tg4Map, this) - is Tg4Ex -> listOf(Subjects, TgYears, Tg4Map, Tg4Lesson(id), this) - PgYears -> listOf(Subjects, PgYears) - PgMap -> listOf(Subjects, PgYears, PgMap) - is PgLesson -> listOf(Subjects, PgYears, PgMap, this) - is PgEx -> listOf(Subjects, PgYears, PgMap, PgLesson(id), this) - Pg2Map -> listOf(Subjects, PgYears, Pg2Map) - is Pg2Lesson -> listOf(Subjects, PgYears, Pg2Map, this) - is Pg2Ex -> listOf(Subjects, PgYears, Pg2Map, Pg2Lesson(id), this) - Pg3Map -> listOf(Subjects, PgYears, Pg3Map) - is Pg3Lesson -> listOf(Subjects, PgYears, Pg3Map, this) - is Pg3Ex -> listOf(Subjects, PgYears, Pg3Map, Pg3Lesson(id), this) - Pg4Map -> listOf(Subjects, PgYears, Pg4Map) - is Pg4Lesson -> listOf(Subjects, PgYears, Pg4Map, this) - is Pg4Ex -> listOf(Subjects, PgYears, Pg4Map, Pg4Lesson(id), this) - SwYears -> listOf(Subjects, SwYears) - SwMap -> listOf(Subjects, SwYears, SwMap) - is SwLesson -> listOf(Subjects, SwYears, SwMap, this) - is SwEx -> listOf(Subjects, SwYears, SwMap, SwLesson(id), this) - Sw2Map -> listOf(Subjects, SwYears, Sw2Map) - is Sw2Lesson -> listOf(Subjects, SwYears, Sw2Map, this) - is Sw2Ex -> listOf(Subjects, SwYears, Sw2Map, Sw2Lesson(id), this) - Sw3Map -> listOf(Subjects, SwYears, Sw3Map) - is Sw3Lesson -> listOf(Subjects, SwYears, Sw3Map, this) - is Sw3Ex -> listOf(Subjects, SwYears, Sw3Map, Sw3Lesson(id), this) - Sw4Map -> listOf(Subjects, SwYears, Sw4Map) - is Sw4Lesson -> listOf(Subjects, SwYears, Sw4Map, this) - is Sw4Ex -> listOf(Subjects, SwYears, Sw4Map, Sw4Lesson(id), this) - CsYears -> listOf(Subjects, CsYears) - CsMap -> listOf(Subjects, CsYears, CsMap) - is CsLesson -> listOf(Subjects, CsYears, CsMap, this) - Cs2Map -> listOf(Subjects, CsYears, Cs2Map) - is Cs2Lesson -> listOf(Subjects, CsYears, Cs2Map, this) - Cs3Map -> listOf(Subjects, CsYears, Cs3Map) - is Cs3Lesson -> listOf(Subjects, CsYears, Cs3Map, this) - Cs4Map -> listOf(Subjects, CsYears, Cs4Map) - is Cs4Lesson -> listOf(Subjects, CsYears, Cs4Map, this) CzechMap -> listOf(Subjects, CzechMap) Mluvnice -> listOf(Subjects, CzechMap, Mluvnice) is MluvEx -> listOf(Subjects, CzechMap, Mluvnice, this) @@ -385,26 +289,6 @@ fun routeFromPage(page: String): Route? = when (page) { "fyz2map" -> Route.Fyz2Map "fyz3map" -> Route.Fyz3Map "fyz4map" -> Route.Fyz4Map - "tgyears" -> Route.TgYears - "tgmap" -> Route.TgMap - "tg2map" -> Route.Tg2Map - "tg3map" -> Route.Tg3Map - "tg4map" -> Route.Tg4Map - "pgyears" -> Route.PgYears - "pgmap" -> Route.PgMap - "pg2map" -> Route.Pg2Map - "pg3map" -> Route.Pg3Map - "pg4map" -> Route.Pg4Map - "swyears" -> Route.SwYears - "swmap" -> Route.SwMap - "sw2map" -> Route.Sw2Map - "sw3map" -> Route.Sw3Map - "sw4map" -> Route.Sw4Map - "csyears" -> Route.CsYears - "csmap" -> Route.CsMap - "cs2map" -> Route.Cs2Map - "cs3map" -> Route.Cs3Map - "cs4map" -> Route.Cs4Map "czechmap" -> Route.CzechMap "mluvnice" -> Route.Mluvnice "readinglist" -> Route.ReadingList @@ -502,90 +386,6 @@ fun routeFromPage(page: String): Route? = when (page) { Regex("""fyzex(\d+)""").matchEntire(page)?.let { return Route.FyzEx(it.groupValues[1].toInt()) } - Regex("""tg4unit(\d+)""").matchEntire(page)?.let { - return Route.Tg4Lesson(it.groupValues[1].toInt()) - } - Regex("""tg4ex(\d+)""").matchEntire(page)?.let { - return Route.Tg4Ex(it.groupValues[1].toInt()) - } - Regex("""tg3unit(\d+)""").matchEntire(page)?.let { - return Route.Tg3Lesson(it.groupValues[1].toInt()) - } - Regex("""tg3ex(\d+)""").matchEntire(page)?.let { - return Route.Tg3Ex(it.groupValues[1].toInt()) - } - Regex("""tg2unit(\d+)""").matchEntire(page)?.let { - return Route.Tg2Lesson(it.groupValues[1].toInt()) - } - Regex("""tg2ex(\d+)""").matchEntire(page)?.let { - return Route.Tg2Ex(it.groupValues[1].toInt()) - } - Regex("""tgunit(\d+)""").matchEntire(page)?.let { - return Route.TgLesson(it.groupValues[1].toInt()) - } - Regex("""tgex(\d+)""").matchEntire(page)?.let { - return Route.TgEx(it.groupValues[1].toInt()) - } - Regex("""pg4unit(\d+)""").matchEntire(page)?.let { - return Route.Pg4Lesson(it.groupValues[1].toInt()) - } - Regex("""pg4ex(\d+)""").matchEntire(page)?.let { - return Route.Pg4Ex(it.groupValues[1].toInt()) - } - Regex("""pg3unit(\d+)""").matchEntire(page)?.let { - return Route.Pg3Lesson(it.groupValues[1].toInt()) - } - Regex("""pg3ex(\d+)""").matchEntire(page)?.let { - return Route.Pg3Ex(it.groupValues[1].toInt()) - } - Regex("""pg2unit(\d+)""").matchEntire(page)?.let { - return Route.Pg2Lesson(it.groupValues[1].toInt()) - } - Regex("""pg2ex(\d+)""").matchEntire(page)?.let { - return Route.Pg2Ex(it.groupValues[1].toInt()) - } - Regex("""pgunit(\d+)""").matchEntire(page)?.let { - return Route.PgLesson(it.groupValues[1].toInt()) - } - Regex("""pgex(\d+)""").matchEntire(page)?.let { - return Route.PgEx(it.groupValues[1].toInt()) - } - Regex("""sw4unit(\d+)""").matchEntire(page)?.let { - return Route.Sw4Lesson(it.groupValues[1].toInt()) - } - Regex("""sw4ex(\d+)""").matchEntire(page)?.let { - return Route.Sw4Ex(it.groupValues[1].toInt()) - } - Regex("""sw3unit(\d+)""").matchEntire(page)?.let { - return Route.Sw3Lesson(it.groupValues[1].toInt()) - } - Regex("""sw3ex(\d+)""").matchEntire(page)?.let { - return Route.Sw3Ex(it.groupValues[1].toInt()) - } - Regex("""sw2unit(\d+)""").matchEntire(page)?.let { - return Route.Sw2Lesson(it.groupValues[1].toInt()) - } - Regex("""sw2ex(\d+)""").matchEntire(page)?.let { - return Route.Sw2Ex(it.groupValues[1].toInt()) - } - Regex("""swunit(\d+)""").matchEntire(page)?.let { - return Route.SwLesson(it.groupValues[1].toInt()) - } - Regex("""swex(\d+)""").matchEntire(page)?.let { - return Route.SwEx(it.groupValues[1].toInt()) - } - Regex("""cs4unit(\d+)""").matchEntire(page)?.let { - return Route.Cs4Lesson(it.groupValues[1].toInt()) - } - Regex("""cs3unit(\d+)""").matchEntire(page)?.let { - return Route.Cs3Lesson(it.groupValues[1].toInt()) - } - Regex("""cs2unit(\d+)""").matchEntire(page)?.let { - return Route.Cs2Lesson(it.groupValues[1].toInt()) - } - Regex("""csunit(\d+)""").matchEntire(page)?.let { - return Route.CsLesson(it.groupValues[1].toInt()) - } Regex("""lit4unit(\d+)""").matchEntire(page)?.let { return Route.Lit4Lesson(it.groupValues[1].toInt()) } diff --git a/android/shared/src/org/maturita/maturita/data/Content.kt b/android/shared/src/org/maturita/maturita/data/Content.kt index ecb0c93..44176ee 100644 --- a/android/shared/src/org/maturita/maturita/data/Content.kt +++ b/android/shared/src/org/maturita/maturita/data/Content.kt @@ -56,22 +56,6 @@ class Content(root: JSONObject) { val fyz2 = raw.arr("fyz2") val fyz3 = raw.arr("fyz3") val fyz4 = raw.arr("fyz4") - val tg = raw.arr("tg") - val tg2 = raw.arr("tg2") - val tg3 = raw.arr("tg3") - val tg4 = raw.arr("tg4") - val pg = raw.arr("pg") - val pg2 = raw.arr("pg2") - val pg3 = raw.arr("pg3") - val pg4 = raw.arr("pg4") - val sw = raw.arr("sw") - val sw2 = raw.arr("sw2") - val sw3 = raw.arr("sw3") - val sw4 = raw.arr("sw4") - val cs = raw.arr("cs") - val cs2 = raw.arr("cs2") - val cs3 = raw.arr("cs3") - val cs4 = raw.arr("cs4") val mat0 = raw.arr("mat0") val mat = raw.arr("mat") val mat2 = raw.arr("mat2") @@ -124,22 +108,6 @@ class Content(root: JSONObject) { fun fyz2Lesson(id: Int) = fyz2.firstOrNull { it.int("id") == id } fun fyz3Lesson(id: Int) = fyz3.firstOrNull { it.int("id") == id } fun fyz4Lesson(id: Int) = fyz4.firstOrNull { it.int("id") == id } - fun tgLesson(id: Int) = tg.firstOrNull { it.int("id") == id } - fun tg2Lesson(id: Int) = tg2.firstOrNull { it.int("id") == id } - fun tg3Lesson(id: Int) = tg3.firstOrNull { it.int("id") == id } - fun tg4Lesson(id: Int) = tg4.firstOrNull { it.int("id") == id } - fun pgLesson(id: Int) = pg.firstOrNull { it.int("id") == id } - fun pg2Lesson(id: Int) = pg2.firstOrNull { it.int("id") == id } - fun pg3Lesson(id: Int) = pg3.firstOrNull { it.int("id") == id } - fun pg4Lesson(id: Int) = pg4.firstOrNull { it.int("id") == id } - fun swLesson(id: Int) = sw.firstOrNull { it.int("id") == id } - fun sw2Lesson(id: Int) = sw2.firstOrNull { it.int("id") == id } - fun sw3Lesson(id: Int) = sw3.firstOrNull { it.int("id") == id } - fun sw4Lesson(id: Int) = sw4.firstOrNull { it.int("id") == id } - fun csLesson(id: Int) = cs.firstOrNull { it.int("id") == id } - fun cs2Lesson(id: Int) = cs2.firstOrNull { it.int("id") == id } - fun cs3Lesson(id: Int) = cs3.firstOrNull { it.int("id") == id } - fun cs4Lesson(id: Int) = cs4.firstOrNull { it.int("id") == id } fun mat0Lesson(id: Int) = mat0.firstOrNull { it.int("id") == id } fun matLesson(id: Int) = mat.firstOrNull { it.int("id") == id } fun mat2Lesson(id: Int) = mat2.firstOrNull { it.int("id") == id } diff --git a/android/shared/src/org/maturita/maturita/data/ProgressStore.kt b/android/shared/src/org/maturita/maturita/data/ProgressStore.kt index f4e5607..67ad66b 100644 --- a/android/shared/src/org/maturita/maturita/data/ProgressStore.kt +++ b/android/shared/src/org/maturita/maturita/data/ProgressStore.kt @@ -91,38 +91,6 @@ class ProgressStore(private val prefs: Prefs, content: Content) { fun markFyz3(id: Int) { mark("fyz3.$id") } fun fyz4Done(id: Int) = done("fyz4.$id") fun markFyz4(id: Int) { mark("fyz4.$id") } - fun tgDone(id: Int) = done("tg.$id") - fun markTg(id: Int) { mark("tg.$id") } - fun tg2Done(id: Int) = done("tg2.$id") - fun markTg2(id: Int) { mark("tg2.$id") } - fun tg3Done(id: Int) = done("tg3.$id") - fun markTg3(id: Int) { mark("tg3.$id") } - fun tg4Done(id: Int) = done("tg4.$id") - fun markTg4(id: Int) { mark("tg4.$id") } - fun pgDone(id: Int) = done("pg.$id") - fun markPg(id: Int) { mark("pg.$id") } - fun pg2Done(id: Int) = done("pg2.$id") - fun markPg2(id: Int) { mark("pg2.$id") } - fun pg3Done(id: Int) = done("pg3.$id") - fun markPg3(id: Int) { mark("pg3.$id") } - fun pg4Done(id: Int) = done("pg4.$id") - fun markPg4(id: Int) { mark("pg4.$id") } - fun swDone(id: Int) = done("sw.$id") - fun markSw(id: Int) { mark("sw.$id") } - fun sw2Done(id: Int) = done("sw2.$id") - fun markSw2(id: Int) { mark("sw2.$id") } - fun sw3Done(id: Int) = done("sw3.$id") - fun markSw3(id: Int) { mark("sw3.$id") } - fun sw4Done(id: Int) = done("sw4.$id") - fun markSw4(id: Int) { mark("sw4.$id") } - fun csDone(id: Int) = done("cs.$id") - fun markCs(id: Int) { mark("cs.$id") } - fun cs2Done(id: Int) = done("cs2.$id") - fun markCs2(id: Int) { mark("cs2.$id") } - fun cs3Done(id: Int) = done("cs3.$id") - fun markCs3(id: Int) { mark("cs3.$id") } - fun cs4Done(id: Int) = done("cs4.$id") - fun markCs4(id: Int) { mark("cs4.$id") } fun mat0Done(id: Int) = done("mat0.$id") fun markMat0(id: Int) { mark("mat0.$id") } fun matDone(id: Int) = done("mat.$id") @@ -312,134 +280,6 @@ fun summarize(content: Content, p: ProgressStore): ProgressSum { sum.doneUnits += 1 } } - content.tg.forEach { l -> - sum.totalEx += 1 - sum.openUnits += 1 - if (p.tgDone(l.int("id"))) { - sum.doneEx += 1 - sum.doneUnits += 1 - } - } - content.tg2.forEach { l -> - sum.totalEx += 1 - sum.openUnits += 1 - if (p.tg2Done(l.int("id"))) { - sum.doneEx += 1 - sum.doneUnits += 1 - } - } - content.tg3.forEach { l -> - sum.totalEx += 1 - sum.openUnits += 1 - if (p.tg3Done(l.int("id"))) { - sum.doneEx += 1 - sum.doneUnits += 1 - } - } - content.tg4.forEach { l -> - sum.totalEx += 1 - sum.openUnits += 1 - if (p.tg4Done(l.int("id"))) { - sum.doneEx += 1 - sum.doneUnits += 1 - } - } - content.pg.forEach { l -> - sum.totalEx += 1 - sum.openUnits += 1 - if (p.pgDone(l.int("id"))) { - sum.doneEx += 1 - sum.doneUnits += 1 - } - } - content.pg2.forEach { l -> - sum.totalEx += 1 - sum.openUnits += 1 - if (p.pg2Done(l.int("id"))) { - sum.doneEx += 1 - sum.doneUnits += 1 - } - } - content.pg3.forEach { l -> - sum.totalEx += 1 - sum.openUnits += 1 - if (p.pg3Done(l.int("id"))) { - sum.doneEx += 1 - sum.doneUnits += 1 - } - } - content.pg4.forEach { l -> - sum.totalEx += 1 - sum.openUnits += 1 - if (p.pg4Done(l.int("id"))) { - sum.doneEx += 1 - sum.doneUnits += 1 - } - } - content.sw.forEach { l -> - sum.totalEx += 1 - sum.openUnits += 1 - if (p.swDone(l.int("id"))) { - sum.doneEx += 1 - sum.doneUnits += 1 - } - } - content.sw2.forEach { l -> - sum.totalEx += 1 - sum.openUnits += 1 - if (p.sw2Done(l.int("id"))) { - sum.doneEx += 1 - sum.doneUnits += 1 - } - } - content.sw3.forEach { l -> - sum.totalEx += 1 - sum.openUnits += 1 - if (p.sw3Done(l.int("id"))) { - sum.doneEx += 1 - sum.doneUnits += 1 - } - } - content.sw4.forEach { l -> - sum.totalEx += 1 - sum.openUnits += 1 - if (p.sw4Done(l.int("id"))) { - sum.doneEx += 1 - sum.doneUnits += 1 - } - } - content.cs.forEach { l -> - sum.totalEx += 1 - sum.openUnits += 1 - if (p.csDone(l.int("id"))) { - sum.doneEx += 1 - sum.doneUnits += 1 - } - } - content.cs2.forEach { l -> - sum.totalEx += 1 - sum.openUnits += 1 - if (p.cs2Done(l.int("id"))) { - sum.doneEx += 1 - sum.doneUnits += 1 - } - } - content.cs3.forEach { l -> - sum.totalEx += 1 - sum.openUnits += 1 - if (p.cs3Done(l.int("id"))) { - sum.doneEx += 1 - sum.doneUnits += 1 - } - } - content.cs4.forEach { l -> - sum.totalEx += 1 - sum.openUnits += 1 - if (p.cs4Done(l.int("id"))) { - sum.doneEx += 1 - sum.doneUnits += 1 - } - } content.mat0.forEach { l -> sum.totalEx += 1 sum.openUnits += 1 diff --git a/android/shared/src/org/maturita/maturita/platform/Platform.kt b/android/shared/src/org/maturita/maturita/platform/Platform.kt index e275434..afd88fa 100644 --- a/android/shared/src/org/maturita/maturita/platform/Platform.kt +++ b/android/shared/src/org/maturita/maturita/platform/Platform.kt @@ -18,18 +18,8 @@ interface Platform { /** A speech engine for listening exercises, or null when there is none. */ fun speaker(): Speaker? - - /** - * Compiles and runs a C# program. [cb] runs on the UI thread. - * Status is ok, fail, timeout or unavailable. - */ - fun runCSharp(source: String, stdin: String, cb: (CSharpRun) -> Unit) { - cb(CSharpRun("unavailable", "")) - } } -data class CSharpRun(val status: String, val output: String) - /** The subset of Android's SharedPreferences the app uses. */ interface Prefs { fun getBoolean(key: String, fallback: Boolean): Boolean diff --git a/android/shared/src/org/maturita/maturita/ui/CodeLesson.kt b/android/shared/src/org/maturita/maturita/ui/CodeLesson.kt deleted file mode 100644 index 3e8640e..0000000 --- a/android/shared/src/org/maturita/maturita/ui/CodeLesson.kt +++ /dev/null @@ -1,303 +0,0 @@ -package org.maturita.maturita.ui - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.BoxWithConstraints -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.text.BasicTextField -import androidx.compose.foundation.verticalScroll -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Cancel -import androidx.compose.material.icons.filled.CheckCircle -import androidx.compose.material.icons.filled.Code -import androidx.compose.material.icons.filled.PlayArrow -import androidx.compose.material.icons.filled.Refresh -import androidx.compose.material.icons.filled.Terminal -import androidx.compose.material3.Button -import androidx.compose.material3.CircularProgressIndicator -import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedButton -import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.SolidColor -import androidx.compose.ui.graphics.luminance -import androidx.compose.ui.text.AnnotatedString -import androidx.compose.ui.text.SpanStyle -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.buildAnnotatedString -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.text.input.OffsetMapping -import androidx.compose.ui.text.input.TransformedText -import androidx.compose.ui.text.input.VisualTransformation -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.max -import androidx.compose.ui.unit.min -import androidx.compose.ui.unit.sp -import org.maturita.maturita.AppViewModel -import org.maturita.maturita.data.J - -/** Explanation on one side, the program and its output on the other. */ -@Composable -fun CodeLessonScreen(vm: AppViewModel, lesson: J, onSuccess: () -> Unit) { - val key = lesson.str("key") - val starter = lesson.str("code") - var code by remember(key) { mutableStateOf(starter) } - var stdin by remember(key) { mutableStateOf("") } - var output by remember(key) { mutableStateOf("") } - var status by remember(key) { mutableStateOf("") } - val running = status == "running" - val needsInput = "ReadLine" in code - - fun run() { - if (running) return - status = "running" - output = vm.tr("cs_running") - vm.platform.runCSharp(code, if (needsInput) stdin else "") { result -> - status = result.status - output = when (result.status) { - "unavailable" -> vm.tr("cs_unavailable") - "timeout" -> (result.output + "\n\n" + vm.tr("cs_timeout")).trim() - else -> result.output.ifEmpty { vm.tr("cs_empty") } - } - if (result.status == "ok") onSuccess() - } - } - - fun reset() { - code = starter - output = "" - status = "" - } - - DetailScaffold(vm, vm.tr(lesson.str("titleKey")), vm.tr(lesson.str("subKey")), maxContentWidth = 1640.dp) { inner -> - BoxWithConstraints(Modifier.fillMaxSize().padding(inner)) { - val width = maxWidth - val height = maxHeight - if (width >= 900.dp) { - Row( - Modifier.fillMaxSize().padding(horizontal = 24.dp, vertical = 16.dp), - horizontalArrangement = Arrangement.spacedBy(24.dp), - ) { - Column(Modifier.width(min(560.dp, width * 0.4f)).fillMaxHeight().verticalScroll(rememberScrollState())) { - Explanation(lesson) - } - Column(Modifier.weight(1f).fillMaxHeight(), verticalArrangement = Arrangement.spacedBy(16.dp)) { - EditorCard(vm, code, { code = it }, running, ::run, ::reset, compact = false, Modifier.weight(1f)) - if (needsInput) InputField(vm, stdin) { stdin = it } - OutputCard(vm, output, status, Modifier.height(max(180.dp, height * 0.32f))) - } - } - } else { - Column( - Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(16.dp), - verticalArrangement = Arrangement.spacedBy(16.dp), - ) { - Explanation(lesson) - EditorCard(vm, code, { code = it }, running, ::run, ::reset, compact = true, Modifier.height(320.dp)) - if (needsInput) InputField(vm, stdin) { stdin = it } - OutputCard(vm, output, status, Modifier.height(220.dp)) - } - } - } - } -} - -@Composable -private fun Explanation(lesson: J) { - Column(verticalArrangement = Arrangement.spacedBy(28.dp)) { - lesson.arr("slides").forEach { SlideContent(it) } - } -} - -@Composable -private fun EditorCard( - vm: AppViewModel, - code: String, - onCode: (String) -> Unit, - running: Boolean, - onRun: () -> Unit, - onReset: () -> Unit, - compact: Boolean, - modifier: Modifier, -) { - val dark = MaterialTheme.colorScheme.background.luminance() < 0.5f - val highlight = remember(dark) { CSharpHighlight(dark) } - Surface(modifier.fillMaxWidth(), shape = RoundedCornerShape(16.dp), color = MaterialTheme.colorScheme.surfaceContainerHigh) { - Column { - Row( - Modifier.fillMaxWidth().padding(horizontal = 14.dp, vertical = 8.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(10.dp), - ) { - Icon(Icons.Filled.Code, null, tint = MaterialTheme.colorScheme.primary) - Text("Program.cs", style = MaterialTheme.typography.titleSmall.copy(fontFamily = FontFamily.Monospace)) - Spacer(Modifier.weight(1f)) - if (compact) { - IconButton(onClick = onReset, enabled = !running) { - Icon(Icons.Filled.Refresh, contentDescription = vm.tr("cs_reset")) - } - } else { - OutlinedButton(onClick = onReset, enabled = !running) { - Icon(Icons.Filled.Refresh, null, Modifier.size(18.dp)) - Spacer(Modifier.width(6.dp)) - Text(vm.tr("cs_reset")) - } - } - Button(onClick = onRun, enabled = !running) { - Icon(Icons.Filled.PlayArrow, null, Modifier.size(18.dp)) - Spacer(Modifier.width(6.dp)) - Text(vm.tr("cs_run")) - } - } - HorizontalDivider(color = MaterialTheme.colorScheme.outlineVariant) - BasicTextField( - value = code, - onValueChange = onCode, - textStyle = codeStyle().copy(color = MaterialTheme.colorScheme.onSurface), - cursorBrush = SolidColor(MaterialTheme.colorScheme.primary), - visualTransformation = highlight, - modifier = Modifier.fillMaxSize().padding(14.dp), - ) - } - } -} - -@Composable -private fun InputField(vm: AppViewModel, stdin: String, onStdin: (String) -> Unit) { - Column(verticalArrangement = Arrangement.spacedBy(6.dp)) { - Text(vm.tr("cs_stdin"), style = MaterialTheme.typography.labelLarge, color = MaterialTheme.colorScheme.onSurfaceVariant) - OutlinedTextField( - value = stdin, - onValueChange = onStdin, - textStyle = codeStyle(), - minLines = 1, - maxLines = 4, - modifier = Modifier.fillMaxWidth(), - ) - } -} - -@Composable -private fun OutputCard(vm: AppViewModel, output: String, status: String, modifier: Modifier) { - val muted = output.isEmpty() || status == "running" - Surface(modifier.fillMaxWidth(), shape = RoundedCornerShape(16.dp), color = MaterialTheme.colorScheme.surfaceContainerHigh) { - Column { - Row( - Modifier.fillMaxWidth().height(48.dp).padding(horizontal = 14.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - Icon(Icons.Filled.Terminal, null, tint = MaterialTheme.colorScheme.onSurfaceVariant, modifier = Modifier.size(18.dp)) - Spacer(Modifier.width(8.dp)) - Text(vm.tr("cs_output"), style = MaterialTheme.typography.titleSmall) - Spacer(Modifier.weight(1f)) - StatusBadge(vm, status) - } - HorizontalDivider(color = MaterialTheme.colorScheme.outlineVariant) - Text( - output.ifEmpty { vm.tr("cs_empty") }, - style = codeStyle(), - color = if (muted) MaterialTheme.colorScheme.onSurfaceVariant else MaterialTheme.colorScheme.onSurface, - modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(14.dp), - ) - } - } -} - -@Composable -private fun StatusBadge(vm: AppViewModel, status: String) { - when (status) { - "running" -> CircularProgressIndicator(Modifier.size(18.dp), strokeWidth = 2.dp) - "ok" -> Badge(vm.tr("cs_done"), Icons.Filled.CheckCircle, MaterialTheme.colorScheme.primary) - "fail", "timeout" -> Badge(vm.tr("cs_failed"), Icons.Filled.Cancel, MaterialTheme.colorScheme.error) - } -} - -@Composable -private fun Badge(text: String, icon: androidx.compose.ui.graphics.vector.ImageVector, color: Color) { - Row(verticalAlignment = Alignment.CenterVertically) { - Icon(icon, null, tint = color, modifier = Modifier.size(18.dp)) - Spacer(Modifier.width(6.dp)) - Text(text, style = MaterialTheme.typography.labelLarge, color = color) - } -} - -private fun codeStyle() = TextStyle(fontFamily = FontFamily.Monospace, fontSize = 15.sp, lineHeight = 22.sp) - -/** Colours C# keywords, types, numbers, strings and comments without changing the text. */ -private class CSharpHighlight(dark: Boolean) : VisualTransformation { - private val palette = listOf( - Color(if (dark) 0xFFFF7AB2 else 0xFF9B2393), - Color(if (dark) 0xFF5DD8FF else 0xFF0B4F79), - Color(if (dark) 0xFFD9C97C else 0xFF1C00CF), - Color(if (dark) 0xFFFC6A5D else 0xFFC41A16), - Color(if (dark) 0xFF7F8C98 else 0xFF5D6C79), - ) - - override fun filter(text: AnnotatedString): TransformedText = - TransformedText(highlight(text.text), OffsetMapping.Identity) - - private fun highlight(code: String): AnnotatedString { - val kind = IntArray(code.length) { -1 } - RULES.forEachIndexed { index, rule -> - rule.findAll(code).forEach { m -> for (i in m.range) kind[i] = index } - } - return buildAnnotatedString { - var start = 0 - while (start < code.length) { - var end = start - while (end < code.length && kind[end] == kind[start]) end++ - val k = kind[start] - if (k >= 0) { - pushStyle(SpanStyle(color = palette[k])) - append(code, start, end) - pop() - } else { - append(code, start, end) - } - start = end - } - } - } - - companion object { - private val KEYWORDS = listOf( - "abstract", "as", "async", "await", "base", "bool", "break", "case", "catch", "char", "class", - "const", "continue", "decimal", "default", "do", "double", "else", "enum", "false", "finally", - "float", "for", "foreach", "get", "if", "in", "int", "interface", "internal", "is", "long", - "namespace", "new", "null", "object", "out", "override", "private", "protected", "public", - "readonly", "record", "ref", "return", "sealed", "set", "static", "string", "struct", "switch", - "this", "throw", "true", "try", "using", "var", "virtual", "void", "while", - ) - - /** Later rules win, so strings and comments override keywords inside them. */ - private val RULES = listOf( - Regex("\\b(?:" + KEYWORDS.joinToString("|") + ")\\b"), - Regex("\\b(?:Console|Math|List|Dictionary|File|Task|Exception|Func|Action|String|DateTime|Random)\\b"), - Regex("\\b\\d+(?:\\.\\d+)?\\b"), - Regex("\\$?@?\"(?:\\\\.|[^\"\\\\\\n])*\"|'(?:\\\\.|[^'\\\\\\n])'"), - Regex("//[^\\n]*|/\\*[\\s\\S]*?\\*/"), - ) - } -} diff --git a/android/shared/src/org/maturita/maturita/ui/Components.kt b/android/shared/src/org/maturita/maturita/ui/Components.kt index 6bdde68..6798891 100644 --- a/android/shared/src/org/maturita/maturita/ui/Components.kt +++ b/android/shared/src/org/maturita/maturita/ui/Components.kt @@ -8,22 +8,15 @@ import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.animation.shrinkVertically import androidx.compose.animation.animateColorAsState -import androidx.compose.foundation.Canvas -import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.WindowInsets -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.heightIn @@ -31,17 +24,7 @@ import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width -import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.layout.windowInsetsPadding -import androidx.compose.foundation.layout.wrapContentWidth -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.ui.draw.clip -import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.geometry.Size -import androidx.compose.ui.graphics.StrokeCap -import androidx.compose.ui.graphics.drawscope.Stroke -import androidx.compose.ui.unit.Dp import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.foundation.text.KeyboardOptions @@ -61,6 +44,7 @@ import androidx.compose.material3.FilterChip import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.LargeTopAppBar +import androidx.compose.material3.LinearProgressIndicator import androidx.compose.material3.ListItem import androidx.compose.material3.ListItemDefaults import androidx.compose.material3.MaterialTheme @@ -166,19 +150,7 @@ fun AppNavBar(vm: AppViewModel) { private fun navIconColor(selected: Boolean): Color = if (selected) MaterialTheme.colorScheme.onSecondaryContainer else MaterialTheme.colorScheme.onSurfaceVariant -/** Lists and exercises stop growing here so they keep their shape in wide desktop windows. */ -val ContentMaxWidth = 880.dp -val ActionMaxWidth = 560.dp - -/** Caps the width of [content] and centres it; phones are narrower than the cap anyway. */ -@Composable -fun CenteredColumn(maxWidth: Dp = ContentMaxWidth, content: @Composable () -> Unit) { - Box(Modifier.fillMaxSize(), contentAlignment = Alignment.TopCenter) { - Box(Modifier.widthIn(max = maxWidth).fillMaxSize()) { content() } - } -} - -/** Tab root: large collapsing title on phones, a compact one in wide windows. */ +/** Tab root: large collapsing title, search action, bottom navigation. */ @OptIn(ExperimentalMaterial3Api::class) @Composable fun RootScaffold( @@ -187,48 +159,30 @@ fun RootScaffold( showSearch: Boolean = true, content: LazyListScope.() -> Unit, ) { - BoxWithConstraints { - val wide = maxWidth >= 600.dp - val scroll = if (wide) { - TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState()) - } else { - TopAppBarDefaults.exitUntilCollapsedScrollBehavior(rememberTopAppBarState()) - } - val actions: @Composable RowScope.() -> Unit = { - if (showSearch) { - IconButton(onClick = { vm.searchOpen = true }) { - Icon(Icons.Filled.Search, contentDescription = vm.tr("search_placeholder")) - } - } - } - Scaffold( - modifier = Modifier.nestedScroll(scroll.nestedScrollConnection), - topBar = { - if (wide) { - TopAppBar( - title = { Text(title, maxLines = 1, overflow = TextOverflow.Ellipsis, style = MaterialTheme.typography.headlineSmall) }, - actions = actions, - scrollBehavior = scroll, - ) - } else { - LargeTopAppBar( - title = { Text(title, maxLines = 1, overflow = TextOverflow.Ellipsis) }, - actions = actions, - scrollBehavior = scroll, - ) - } - }, - bottomBar = { AppNavBar(vm) }, - ) { inner -> - CenteredColumn { - LazyColumn( - contentPadding = PaddingValues( - top = inner.calculateTopPadding(), - bottom = inner.calculateBottomPadding() + 16.dp, - ), - ) { content() } - } - } + val scroll = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(rememberTopAppBarState()) + Scaffold( + modifier = Modifier.nestedScroll(scroll.nestedScrollConnection), + topBar = { + LargeTopAppBar( + title = { Text(title, maxLines = 1, overflow = TextOverflow.Ellipsis) }, + actions = { + if (showSearch) { + IconButton(onClick = { vm.searchOpen = true }) { + Icon(Icons.Filled.Search, contentDescription = vm.tr("search_placeholder")) + } + } + }, + scrollBehavior = scroll, + ) + }, + bottomBar = { AppNavBar(vm) }, + ) { inner -> + LazyColumn( + contentPadding = PaddingValues( + top = inner.calculateTopPadding(), + bottom = inner.calculateBottomPadding() + 16.dp, + ), + ) { content() } } } @@ -240,7 +194,6 @@ fun DetailScaffold( title: String, subtitle: String? = null, bottomBar: (@Composable () -> Unit)? = null, - maxContentWidth: Dp = ContentMaxWidth, content: @Composable (PaddingValues) -> Unit, ) { val scroll = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState()) @@ -271,9 +224,8 @@ fun DetailScaffold( ) }, bottomBar = { bottomBar?.invoke() }, - ) { inner -> - CenteredColumn(maxContentWidth) { content(inner) } - } + content = content, + ) } /** Feedback line plus the primary action, anchored at the bottom of an exercise. */ @@ -290,8 +242,6 @@ fun ActionBar( Column( Modifier .fillMaxWidth() - .wrapContentWidth(Alignment.CenterHorizontally) - .widthIn(max = ActionMaxWidth) .windowInsetsPadding(WindowInsets.navigationBars) .padding(horizontal = 16.dp, vertical = 12.dp), ) { @@ -326,27 +276,6 @@ fun SectionHeader(text: String) { ) } -/** Number or short label in a tinted square, so rows line up whatever the label's width. */ -@Composable -fun LeadingBadge(text: String) { - Box( - Modifier.size(36.dp).clip(RoundedCornerShape(10.dp)).background(MaterialTheme.colorScheme.primary.copy(alpha = 0.14f)), - contentAlignment = Alignment.Center, - ) { - Text(text, style = MaterialTheme.typography.titleSmall, color = MaterialTheme.colorScheme.primary) - } -} - -@Composable -fun LeadingIcon(icon: ImageVector) { - Box( - Modifier.size(36.dp).clip(RoundedCornerShape(10.dp)).background(MaterialTheme.colorScheme.primary.copy(alpha = 0.14f)), - contentAlignment = Alignment.Center, - ) { - Icon(icon, null, tint = MaterialTheme.colorScheme.primary, modifier = Modifier.size(20.dp)) - } -} - /** One navigable row: done/pending/locked state on the left, chevron on the right. */ @Composable fun NavRow( @@ -355,33 +284,15 @@ fun NavRow( done: Boolean = false, locked: Boolean = false, leading: (@Composable () -> Unit)? = null, - progress: Pair? = null, onClick: (() -> Unit)?, ) { val enabled = !locked && onClick != null val textColor = if (enabled) MaterialTheme.colorScheme.onSurface else MaterialTheme.colorScheme.onSurfaceVariant val rowModifier = if (enabled) Modifier.clickable(onClick = onClick!!) else Modifier - val shownSubtitle = subtitle?.takeIf { it.isNotBlank() } - val shownProgress = progress?.takeIf { it.second > 0 } ListItem( headlineContent = { Text(title, color = textColor) }, - supportingContent = if (shownSubtitle == null && shownProgress == null) null else { - { - Column { - shownSubtitle?.let { Text(it, color = MaterialTheme.colorScheme.onSurfaceVariant) } - shownProgress?.let { (doneCount, total) -> - Row(Modifier.padding(top = 8.dp), verticalAlignment = Alignment.CenterVertically) { - SmoothProgress(doneCount / total.toFloat(), Modifier.weight(1f).height(6.dp)) - Spacer(Modifier.width(10.dp)) - Text( - "$doneCount / $total", - style = MaterialTheme.typography.labelMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant, - ) - } - } - } - } + supportingContent = subtitle?.takeIf { it.isNotBlank() }?.let { + { Text(it, color = MaterialTheme.colorScheme.onSurfaceVariant) } }, leadingContent = { when { @@ -417,38 +328,19 @@ fun SmoothProgress( progress: Float, modifier: Modifier = Modifier, color: Color = MaterialTheme.colorScheme.primary, - trackColor: Color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.1f), + trackColor: Color = MaterialTheme.colorScheme.surfaceVariant, ) { val animated by animateFloatAsState( targetValue = progress.coerceIn(0f, 1f), animationSpec = tween(durationMillis = 380), label = "progress", ) - Box(modifier.heightIn(min = 4.dp).clip(CircleShape).background(trackColor)) { - if (animated > 0f) { - Box(Modifier.fillMaxHeight().fillMaxWidth(animated).clip(CircleShape).background(color)) - } - } -} - -/** Circular progress with a label in the middle. */ -@Composable -fun ProgressRing(progress: Float, modifier: Modifier = Modifier, stroke: Dp = 10.dp, label: @Composable () -> Unit) { - val animated by animateFloatAsState(progress.coerceIn(0f, 1f), tween(durationMillis = 380), label = "ring") - val track = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.1f) - val fill = MaterialTheme.colorScheme.primary - Box(modifier, contentAlignment = Alignment.Center) { - Canvas(Modifier.fillMaxSize()) { - val width = stroke.toPx() - val inset = width / 2 - val arcSize = Size(size.width - width, size.height - width) - drawArc(track, 0f, 360f, false, Offset(inset, inset), arcSize, style = Stroke(width)) - if (animated > 0f) { - drawArc(fill, -90f, 360f * animated, false, Offset(inset, inset), arcSize, style = Stroke(width, cap = StrokeCap.Round)) - } - } - label() - } + LinearProgressIndicator( + progress = { animated }, + modifier = modifier, + color = color, + trackColor = trackColor, + ) } @Composable diff --git a/android/shared/src/org/maturita/maturita/ui/Exercises.kt b/android/shared/src/org/maturita/maturita/ui/Exercises.kt index 4bf3a47..fb9cabe 100644 --- a/android/shared/src/org/maturita/maturita/ui/Exercises.kt +++ b/android/shared/src/org/maturita/maturita/ui/Exercises.kt @@ -1082,78 +1082,6 @@ fun ChoiceLessonScreen(vm: AppViewModel, lesson: J?, onDone: () -> Unit) { DispatchExercise(vm, spec, vm.tr(lesson.str("exTitleKey")), onDone) } -@Composable -fun TgQuizScreen(vm: AppViewModel, year: Int, id: Int) { - val lesson = when (year) { - 2 -> vm.content.tg2Lesson(id) - 3 -> vm.content.tg3Lesson(id) - 4 -> vm.content.tg4Lesson(id) - else -> vm.content.tgLesson(id) - } ?: return - val spec = J(org.json.JSONObject().apply { - put("type", "choice") - put("title", vm.tr(lesson.str("exTitleKey"))) - put("sub", lesson.str("quizHeadKey")) - put("questions", lesson.o.optJSONArray("quiz")) - }) - DispatchExercise(vm, spec, vm.tr(lesson.str("exTitleKey"))) { - when (year) { - 2 -> vm.markTg2(id) - 3 -> vm.markTg3(id) - 4 -> vm.markTg4(id) - else -> vm.markTg(id) - } - } -} - -@Composable -fun PgQuizScreen(vm: AppViewModel, year: Int, id: Int) { - val lesson = when (year) { - 2 -> vm.content.pg2Lesson(id) - 3 -> vm.content.pg3Lesson(id) - 4 -> vm.content.pg4Lesson(id) - else -> vm.content.pgLesson(id) - } ?: return - val spec = J(org.json.JSONObject().apply { - put("type", "choice") - put("title", vm.tr(lesson.str("exTitleKey"))) - put("sub", lesson.str("quizHeadKey")) - put("questions", lesson.o.optJSONArray("quiz")) - }) - DispatchExercise(vm, spec, vm.tr(lesson.str("exTitleKey"))) { - when (year) { - 2 -> vm.markPg2(id) - 3 -> vm.markPg3(id) - 4 -> vm.markPg4(id) - else -> vm.markPg(id) - } - } -} - -@Composable -fun SwQuizScreen(vm: AppViewModel, year: Int, id: Int) { - val lesson = when (year) { - 2 -> vm.content.sw2Lesson(id) - 3 -> vm.content.sw3Lesson(id) - 4 -> vm.content.sw4Lesson(id) - else -> vm.content.swLesson(id) - } ?: return - val spec = J(org.json.JSONObject().apply { - put("type", "choice") - put("title", vm.tr(lesson.str("exTitleKey"))) - put("sub", lesson.str("quizHeadKey")) - put("questions", lesson.o.optJSONArray("quiz")) - }) - DispatchExercise(vm, spec, vm.tr(lesson.str("exTitleKey"))) { - when (year) { - 2 -> vm.markSw2(id) - 3 -> vm.markSw3(id) - 4 -> vm.markSw4(id) - else -> vm.markSw(id) - } - } -} - @Composable fun FyzQuizScreen(vm: AppViewModel, year: Int, id: Int) { val lesson = when (year) { diff --git a/android/shared/src/org/maturita/maturita/ui/Screens.kt b/android/shared/src/org/maturita/maturita/ui/Screens.kt index 1f57231..1a4e87c 100644 --- a/android/shared/src/org/maturita/maturita/ui/Screens.kt +++ b/android/shared/src/org/maturita/maturita/ui/Screens.kt @@ -25,13 +25,7 @@ import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.automirrored.filled.MenuBook -import androidx.compose.material.icons.filled.Apps -import androidx.compose.material.icons.filled.Architecture -import androidx.compose.material.icons.filled.AutoAwesome -import androidx.compose.material.icons.filled.AutoStories import androidx.compose.material.icons.filled.Bolt -import androidx.compose.material.icons.filled.Brush -import androidx.compose.material.icons.filled.Eco import androidx.compose.material.icons.filled.Functions import androidx.compose.material.icons.filled.Check import androidx.compose.material.icons.filled.Close @@ -41,7 +35,6 @@ import androidx.compose.material.icons.filled.Groups import androidx.compose.material.icons.filled.Lock import androidx.compose.material.icons.filled.Quiz import androidx.compose.material.icons.filled.Science -import androidx.compose.material.icons.filled.Terminal import androidx.compose.material.icons.filled.Search import androidx.compose.material.icons.outlined.Lightbulb import androidx.compose.material3.Card @@ -106,61 +99,50 @@ fun HomeScreen(vm: AppViewModel) { item { Card( modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp, vertical = 8.dp), - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.surfaceContainerHigh, - contentColor = MaterialTheme.colorScheme.onSurface, - ), + colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.primaryContainer), ) { - Row(Modifier.padding(20.dp), verticalAlignment = Alignment.CenterVertically) { - Column(Modifier.weight(1f)) { - Text(vm.tr("welcome_title"), style = MaterialTheme.typography.headlineMedium) - Spacer(Modifier.height(8.dp)) - Text( - vm.tr(vm.platform.welcomeKey), - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant, - ) - } - Spacer(Modifier.width(16.dp)) - ProgressRing(pct, Modifier.size(104.dp)) { - Column(horizontalAlignment = Alignment.CenterHorizontally) { - Text(vm.fmt("stats_pct_fmt", (pct * 100).toInt()), style = MaterialTheme.typography.titleLarge) - Text( - vm.fmt("stats_ex_fmt", sum.doneEx, sum.totalEx), - style = MaterialTheme.typography.labelSmall, - color = MaterialTheme.colorScheme.onSurfaceVariant, - ) - } - } + Column(Modifier.padding(20.dp)) { + Text( + vm.tr("welcome_title"), + style = MaterialTheme.typography.headlineMedium, + color = MaterialTheme.colorScheme.onPrimaryContainer, + ) + Spacer(Modifier.height(8.dp)) + Text( + vm.tr(vm.platform.welcomeKey), + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onPrimaryContainer.copy(alpha = 0.8f), + ) + Spacer(Modifier.height(16.dp)) + SmoothProgress( + progress = pct, + modifier = Modifier.fillMaxWidth().height(6.dp).clip(CircleShape), + color = MaterialTheme.colorScheme.onPrimaryContainer, + trackColor = MaterialTheme.colorScheme.onPrimaryContainer.copy(alpha = 0.18f), + ) + Spacer(Modifier.height(6.dp)) + Text( + vm.fmt("stats_ex_fmt", sum.doneEx, sum.totalEx), + style = MaterialTheme.typography.labelMedium, + color = MaterialTheme.colorScheme.onPrimaryContainer.copy(alpha = 0.8f), + ) } } } if (vm.update.canInstall || vm.update.status == "downloading" || vm.update.status == "staged") { item { UpdateBanner(vm) } } - val open = vm.content.subjects.filter { it.bool("open") } - val soon = vm.content.subjects.filter { !it.bool("open") } item { SectionHeader(vm.tr("subjects_title")) } - items(open) { s -> - val part = subjectSum(vm, s) + items(vm.content.subjects) { s -> + val open = s.bool("open") NavRow( title = vm.tr(s.str("key")), - leading = { SubjectIcon(s.str("icon"), true) }, - progress = part.doneEx to part.totalEx, - onClick = { vm.goPage(s.str("target")) }, + subtitle = if (open) null else vm.tr("stats_locked"), + locked = !open, + leading = { SubjectIcon(s.str("icon"), open) }, + onClick = if (open) ({ vm.goPage(s.str("target")) }) else null, ) } - if (soon.isNotEmpty()) { - item { SectionHeader(vm.tr("subjects_soon")) } - items(soon) { s -> - NavRow( - title = vm.tr(s.str("key")), - locked = true, - leading = { SubjectIcon(s.str("icon"), false) }, - onClick = null, - ) - } - } } } @@ -170,18 +152,14 @@ private fun ChangelogCard(vm: AppViewModel) { val blocks = vm.content.changelog.take(3) Card( modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp, vertical = 8.dp), - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.surfaceContainerHigh, - contentColor = MaterialTheme.colorScheme.onSurface, - ), + colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.tertiaryContainer), ) { Column(Modifier.padding(20.dp)) { Row(verticalAlignment = Alignment.CenterVertically) { - Icon(Icons.Filled.AutoAwesome, null, tint = MaterialTheme.colorScheme.primary, modifier = Modifier.size(20.dp)) - Spacer(Modifier.width(8.dp)) Text( vm.tr("changelog_title"), style = MaterialTheme.typography.titleMedium, + color = MaterialTheme.colorScheme.onTertiaryContainer, modifier = Modifier.weight(1f), ) val date = blocks.firstOrNull()?.str("date").orEmpty() @@ -189,7 +167,7 @@ private fun ChangelogCard(vm: AppViewModel) { Text( date, style = MaterialTheme.typography.labelMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant, + color = MaterialTheme.colorScheme.onTertiaryContainer.copy(alpha = 0.7f), ) } } @@ -200,6 +178,7 @@ private fun ChangelogCard(vm: AppViewModel) { Text( "• $line", style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onTertiaryContainer, modifier = Modifier.padding(bottom = 4.dp), ) } @@ -246,10 +225,6 @@ private fun SubjectIcon(icon: String, open: Boolean) { "flask" -> Icon(Icons.Filled.Science, null, tint = tint, modifier = Modifier.size(26.dp)) "bolt" -> Icon(Icons.Filled.Bolt, null, tint = tint, modifier = Modifier.size(26.dp)) "function" -> Icon(Icons.Filled.Functions, null, tint = tint, modifier = Modifier.size(26.dp)) - "ruler" -> Icon(Icons.Filled.Architecture, null, tint = tint, modifier = Modifier.size(26.dp)) - "code" -> Icon(Icons.Filled.Terminal, null, tint = tint, modifier = Modifier.size(26.dp)) - "brush" -> Icon(Icons.Filled.Brush, null, tint = tint, modifier = Modifier.size(26.dp)) - "apps" -> Icon(Icons.Filled.Apps, null, tint = tint, modifier = Modifier.size(26.dp)) else -> Icon(Icons.Filled.Lock, null, tint = tint) } } @@ -314,75 +289,6 @@ private fun Metric(label: String, value: String, modifier: Modifier) { } } -/** Done and total exercises behind one row of a years screen, or null when there is no count. */ -fun routeProgress(vm: AppViewModel, r: Route): Pair? { - val c = vm.content - val p = vm.progress - fun tally(lessons: List, done: (Int) -> Boolean) = lessons.count { done(it.int("id")) } to lessons.size - return when (r) { - Route.NetMap -> tally(c.netLessons, p::netDone) - Route.Net2Map -> tally(c.itLessons("net2")) { p.courseDone("net2", it) } - Route.Net3Map -> tally(c.itLessons("net3")) { p.courseDone("net3", it) } - Route.Net4Map -> tally(c.itLessons("net4")) { p.courseDone("net4", it) } - Route.HwMap -> tally(c.hw, p::hwDone) - Route.Hw2Map -> tally(c.itLessons("hw2")) { p.courseDone("hw2", it) } - Route.Hw3Map -> tally(c.itLessons("hw3")) { p.courseDone("hw3", it) } - Route.Hw4Map -> tally(c.itLessons("hw4")) { p.courseDone("hw4", it) } - Route.OnMap -> tally(c.on, p::onDone) - Route.On2Map -> tally(c.on2, p::on2Done) - Route.On3Map -> tally(c.on3, p::on3Done) - Route.On4Map -> tally(c.on4, p::on4Done) - is Route.EnMap -> tally(c.enYear(r.year)) { p.enDone(r.year, it) } - is Route.DeMap -> tally(c.deYear(r.year)) { p.deDone(r.year, it) } - Route.Roadmap -> { - var done = 0 - var total = 0 - c.german.filter { it.bool("unlocked") }.forEach { u -> - val n = u.strs("names").size - total += n - done += (1..n).count { p.germanDone(u.int("id"), it) } - } - done to total - } - Route.LitYears -> listOf( - tally(c.lit, p::litDone), tally(c.lit2, p::lit2Done), tally(c.lit3, p::lit3Done), tally(c.lit4, p::lit4Done), - ).let { parts -> parts.sumOf { it.first } to parts.sumOf { it.second } } - Route.LitMap -> tally(c.lit, p::litDone) - Route.Lit2Map -> tally(c.lit2, p::lit2Done) - Route.Lit3Map -> tally(c.lit3, p::lit3Done) - Route.Lit4Map -> tally(c.lit4, p::lit4Done) - Route.Mluvnice -> tally(c.mluvnice, p::mluvDone) - Route.ChemMap -> tally(c.chem, p::chemDone) - Route.BioMap -> tally(c.bio, p::bioDone) - Route.Mat0Map -> tally(c.mat0, p::mat0Done) - Route.MatMap -> tally(c.mat, p::matDone) - Route.Mat2Map -> tally(c.mat2, p::mat2Done) - Route.Mat3Map -> tally(c.mat3, p::mat3Done) - Route.Mat4Map -> tally(c.mat4, p::mat4Done) - Route.FyzMap -> tally(c.fyz, p::fyzDone) - Route.Fyz2Map -> tally(c.fyz2, p::fyz2Done) - Route.Fyz3Map -> tally(c.fyz3, p::fyz3Done) - Route.Fyz4Map -> tally(c.fyz4, p::fyz4Done) - Route.TgMap -> tally(c.tg, p::tgDone) - Route.Tg2Map -> tally(c.tg2, p::tg2Done) - Route.Tg3Map -> tally(c.tg3, p::tg3Done) - Route.Tg4Map -> tally(c.tg4, p::tg4Done) - Route.PgMap -> tally(c.pg, p::pgDone) - Route.Pg2Map -> tally(c.pg2, p::pg2Done) - Route.Pg3Map -> tally(c.pg3, p::pg3Done) - Route.Pg4Map -> tally(c.pg4, p::pg4Done) - Route.SwMap -> tally(c.sw, p::swDone) - Route.Sw2Map -> tally(c.sw2, p::sw2Done) - Route.Sw3Map -> tally(c.sw3, p::sw3Done) - Route.Sw4Map -> tally(c.sw4, p::sw4Done) - Route.CsMap -> tally(c.cs, p::csDone) - Route.Cs2Map -> tally(c.cs2, p::cs2Done) - Route.Cs3Map -> tally(c.cs3, p::cs3Done) - Route.Cs4Map -> tally(c.cs4, p::cs4Done) - else -> null - } -} - private fun subjectSum(vm: AppViewModel, s: J): ProgressSum { val sum = ProgressSum() when (s.str("target")) { @@ -442,34 +348,6 @@ private fun subjectSum(vm: AppViewModel, s: J): ProgressSum { vm.content.fyz3.count { vm.progress.fyz3Done(it.int("id")) } + vm.content.fyz4.count { vm.progress.fyz4Done(it.int("id")) } } - "csyears", "csmap", "cs2map", "cs3map", "cs4map" -> { - sum.totalEx = vm.content.cs.size + vm.content.cs2.size + vm.content.cs3.size + vm.content.cs4.size - sum.doneEx = vm.content.cs.count { vm.progress.csDone(it.int("id")) } + - vm.content.cs2.count { vm.progress.cs2Done(it.int("id")) } + - vm.content.cs3.count { vm.progress.cs3Done(it.int("id")) } + - vm.content.cs4.count { vm.progress.cs4Done(it.int("id")) } - } - "tgyears", "tgmap", "tg2map", "tg3map", "tg4map" -> { - sum.totalEx = vm.content.tg.size + vm.content.tg2.size + vm.content.tg3.size + vm.content.tg4.size - sum.doneEx = vm.content.tg.count { vm.progress.tgDone(it.int("id")) } + - vm.content.tg2.count { vm.progress.tg2Done(it.int("id")) } + - vm.content.tg3.count { vm.progress.tg3Done(it.int("id")) } + - vm.content.tg4.count { vm.progress.tg4Done(it.int("id")) } - } - "pgyears", "pgmap", "pg2map", "pg3map", "pg4map" -> { - sum.totalEx = vm.content.pg.size + vm.content.pg2.size + vm.content.pg3.size + vm.content.pg4.size - sum.doneEx = vm.content.pg.count { vm.progress.pgDone(it.int("id")) } + - vm.content.pg2.count { vm.progress.pg2Done(it.int("id")) } + - vm.content.pg3.count { vm.progress.pg3Done(it.int("id")) } + - vm.content.pg4.count { vm.progress.pg4Done(it.int("id")) } - } - "swyears", "swmap", "sw2map", "sw3map", "sw4map" -> { - sum.totalEx = vm.content.sw.size + vm.content.sw2.size + vm.content.sw3.size + vm.content.sw4.size - sum.doneEx = vm.content.sw.count { vm.progress.swDone(it.int("id")) } + - vm.content.sw2.count { vm.progress.sw2Done(it.int("id")) } + - vm.content.sw3.count { vm.progress.sw3Done(it.int("id")) } + - vm.content.sw4.count { vm.progress.sw4Done(it.int("id")) } - } "czechmap" -> { val litDone = vm.content.lit.count { vm.progress.litDone(it.int("id")) } + vm.content.lit2.count { vm.progress.lit2Done(it.int("id")) } + @@ -771,86 +649,6 @@ private fun buildSearch(vm: AppViewModel): List { add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "fyz4unit${l.int("id")}", extra = "fyzika") add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "fyz4ex${l.int("id")}") } - add(vm.tr("Programové vybavení"), vm.tr("search_lesson"), "swyears", extra = "office windows excel mysql") - add(vm.tr("sw_year1"), vm.tr("search_lesson"), "swmap", extra = "rocnik") - add(vm.tr("sw_year2"), vm.tr("search_lesson"), "sw2map", extra = "rocnik") - add(vm.tr("sw_year3"), vm.tr("search_lesson"), "sw3map", extra = "rocnik") - add(vm.tr("sw_year4"), vm.tr("search_lesson"), "sw4map", extra = "rocnik") - vm.content.sw.forEach { l -> - add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "swunit${l.int("id")}", extra = "windows") - add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "swex${l.int("id")}") - } - vm.content.sw2.forEach { l -> - add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "sw2unit${l.int("id")}", extra = "word excel") - add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "sw2ex${l.int("id")}") - } - vm.content.sw3.forEach { l -> - add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "sw3unit${l.int("id")}", extra = "access mysql") - add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "sw3ex${l.int("id")}") - } - vm.content.sw4.forEach { l -> - add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "sw4unit${l.int("id")}", extra = "wordpress") - add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "sw4ex${l.int("id")}") - } - add(vm.tr("Prezentační grafika"), vm.tr("search_lesson"), "pgyears", extra = "photoshop premiere illustrator") - add(vm.tr("pg_year1"), vm.tr("search_lesson"), "pgmap", extra = "rocnik") - add(vm.tr("pg_year2"), vm.tr("search_lesson"), "pg2map", extra = "rocnik") - add(vm.tr("pg_year3"), vm.tr("search_lesson"), "pg3map", extra = "rocnik") - add(vm.tr("pg_year4"), vm.tr("search_lesson"), "pg4map", extra = "rocnik") - vm.content.pg.forEach { l -> - add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "pgunit${l.int("id")}", extra = "photoshop") - add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "pgex${l.int("id")}") - } - vm.content.pg2.forEach { l -> - add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "pg2unit${l.int("id")}", extra = "photoshop") - add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "pg2ex${l.int("id")}") - } - vm.content.pg3.forEach { l -> - add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "pg3unit${l.int("id")}", extra = "premiere") - add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "pg3ex${l.int("id")}") - } - vm.content.pg4.forEach { l -> - add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "pg4unit${l.int("id")}", extra = "illustrator") - add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "pg4ex${l.int("id")}") - } - add(vm.tr("Technická grafika"), vm.tr("search_lesson"), "tgyears", extra = "autocad grafika") - add(vm.tr("tg_year1"), vm.tr("search_lesson"), "tgmap", extra = "rocnik") - add(vm.tr("tg_year2"), vm.tr("search_lesson"), "tg2map", extra = "rocnik") - add(vm.tr("tg_year3"), vm.tr("search_lesson"), "tg3map", extra = "rocnik") - add(vm.tr("tg_year4"), vm.tr("search_lesson"), "tg4map", extra = "rocnik") - vm.content.tg.forEach { l -> - add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "tgunit${l.int("id")}", extra = "autocad") - add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "tgex${l.int("id")}") - } - vm.content.tg2.forEach { l -> - add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "tg2unit${l.int("id")}", extra = "autocad") - add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "tg2ex${l.int("id")}") - } - vm.content.tg3.forEach { l -> - add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "tg3unit${l.int("id")}", extra = "autocad") - add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "tg3ex${l.int("id")}") - } - vm.content.tg4.forEach { l -> - add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "tg4unit${l.int("id")}", extra = "autocad") - add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "tg4ex${l.int("id")}") - } - add(vm.tr("Programování"), vm.tr("search_lesson"), "csyears", extra = "csharp c#") - add(vm.tr("cs_year1"), vm.tr("search_lesson"), "csmap", extra = "rocnik") - add(vm.tr("cs_year2"), vm.tr("search_lesson"), "cs2map", extra = "rocnik") - add(vm.tr("cs_year3"), vm.tr("search_lesson"), "cs3map", extra = "rocnik") - add(vm.tr("cs_year4"), vm.tr("search_lesson"), "cs4map", extra = "rocnik") - vm.content.cs.forEach { l -> - add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "csunit${l.int("id")}", extra = "csharp") - } - vm.content.cs2.forEach { l -> - add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "cs2unit${l.int("id")}", extra = "csharp") - } - vm.content.cs3.forEach { l -> - add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "cs3unit${l.int("id")}", extra = "csharp") - } - vm.content.cs4.forEach { l -> - add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "cs4unit${l.int("id")}", extra = "csharp") - } add(vm.tr("Chemie"), vm.tr("search_lesson"), "chemmap", extra = "chemie") add(vm.tr("Biologie"), vm.tr("search_lesson"), "biomap", extra = "biologie") vm.content.chem.forEach { l -> @@ -947,10 +745,10 @@ fun NetYearsScreen(vm: AppViewModel) { DetailScaffold(vm, vm.tr("net_years_title"), vm.tr("net_years_sub")) { inner -> LazyColumn(contentPadding = PaddingValues(top = inner.calculateTopPadding(), bottom = inner.calculateBottomPadding() + 16.dp)) { item { - NavRow(title = vm.tr("net_year1"), subtitle = vm.tr("net_sub"), leading = { LeadingBadge("1") }, progress = routeProgress(vm, Route.NetMap)) { vm.go(Route.NetMap) } - NavRow(title = vm.tr("net_year2"), subtitle = vm.tr("net2_sub"), leading = { LeadingBadge("2") }, progress = routeProgress(vm, Route.Net2Map)) { vm.go(Route.Net2Map) } - NavRow(title = vm.tr("net_year3"), subtitle = vm.tr("net3_sub"), leading = { LeadingBadge("3") }, progress = routeProgress(vm, Route.Net3Map)) { vm.go(Route.Net3Map) } - NavRow(title = vm.tr("net_year4"), subtitle = vm.tr("net4_sub"), leading = { LeadingBadge("4") }, progress = routeProgress(vm, Route.Net4Map)) { vm.go(Route.Net4Map) } + NavRow(title = vm.tr("net_year1"), subtitle = vm.tr("net_sub"), leading = { Text("1.", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.NetMap) } + NavRow(title = vm.tr("net_year2"), subtitle = vm.tr("net2_sub"), leading = { Text("2.", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.Net2Map) } + NavRow(title = vm.tr("net_year3"), subtitle = vm.tr("net3_sub"), leading = { Text("3.", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.Net3Map) } + NavRow(title = vm.tr("net_year4"), subtitle = vm.tr("net4_sub"), leading = { Text("4.", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.Net4Map) } } } } @@ -961,10 +759,10 @@ fun HwYearsScreen(vm: AppViewModel) { DetailScaffold(vm, vm.tr("Technické vybavení"), vm.tr("hw_years_sub")) { inner -> LazyColumn(contentPadding = PaddingValues(top = inner.calculateTopPadding(), bottom = inner.calculateBottomPadding() + 16.dp)) { item { - NavRow(title = vm.tr("hw_year1"), subtitle = vm.tr("hw_sub"), leading = { LeadingBadge("1") }, progress = routeProgress(vm, Route.HwMap)) { vm.go(Route.HwMap) } - NavRow(title = vm.tr("hw_year2"), subtitle = vm.tr("hw2_sub"), leading = { LeadingBadge("2") }, progress = routeProgress(vm, Route.Hw2Map)) { vm.go(Route.Hw2Map) } - NavRow(title = vm.tr("hw_year3"), subtitle = vm.tr("hw3_sub"), leading = { LeadingBadge("3") }, progress = routeProgress(vm, Route.Hw3Map)) { vm.go(Route.Hw3Map) } - NavRow(title = vm.tr("hw_year4"), subtitle = vm.tr("hw4_sub"), leading = { LeadingBadge("4") }, progress = routeProgress(vm, Route.Hw4Map)) { vm.go(Route.Hw4Map) } + NavRow(title = vm.tr("hw_year1"), subtitle = vm.tr("hw_sub"), leading = { Text("1.", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.HwMap) } + NavRow(title = vm.tr("hw_year2"), subtitle = vm.tr("hw2_sub"), leading = { Text("2.", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.Hw2Map) } + NavRow(title = vm.tr("hw_year3"), subtitle = vm.tr("hw3_sub"), leading = { Text("3.", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.Hw3Map) } + NavRow(title = vm.tr("hw_year4"), subtitle = vm.tr("hw4_sub"), leading = { Text("4.", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.Hw4Map) } } } } @@ -975,7 +773,7 @@ fun DeHomeScreen(vm: AppViewModel) { DetailScaffold(vm, vm.tr("Deutsch"), vm.tr("de_home_sub")) { inner -> LazyColumn(contentPadding = PaddingValues(top = inner.calculateTopPadding(), bottom = inner.calculateBottomPadding() + 16.dp)) { item { - NavRow(title = vm.tr("de_book_title"), subtitle = vm.tr("de_book_sub"), leading = { LeadingBadge("U") }, progress = routeProgress(vm, Route.Roadmap)) { + NavRow(title = vm.tr("de_book_title"), subtitle = vm.tr("de_book_sub"), leading = { Text("U", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.Roadmap) } } @@ -984,8 +782,7 @@ fun DeHomeScreen(vm: AppViewModel) { NavRow( title = vm.tr("de_year$year"), subtitle = vm.tr("de_y${year}_sub"), - leading = { LeadingBadge("$year") }, - progress = routeProgress(vm, Route.DeMap(year)), + leading = { Text("$year.", style = MaterialTheme.typography.titleMedium) }, ) { vm.go(Route.DeMap(year)) } } } @@ -1001,8 +798,7 @@ fun EnYearsScreen(vm: AppViewModel) { NavRow( title = vm.tr("en_year$year"), subtitle = vm.tr("en_y${year}_sub"), - leading = { LeadingBadge("$year") }, - progress = routeProgress(vm, Route.EnMap(year)), + leading = { Text("$year.", style = MaterialTheme.typography.titleMedium) }, ) { vm.go(Route.EnMap(year)) } } } @@ -1014,10 +810,10 @@ fun OnYearsScreen(vm: AppViewModel) { DetailScaffold(vm, vm.tr("Občanská nauka"), vm.tr("on_years_sub")) { inner -> LazyColumn(contentPadding = PaddingValues(top = inner.calculateTopPadding(), bottom = inner.calculateBottomPadding() + 16.dp)) { item { - NavRow(title = vm.tr("on_year1"), subtitle = vm.tr("on_sub"), leading = { LeadingBadge("1") }, progress = routeProgress(vm, Route.OnMap)) { vm.go(Route.OnMap) } - NavRow(title = vm.tr("on_year2"), subtitle = vm.tr("on2_sub"), leading = { LeadingBadge("2") }, progress = routeProgress(vm, Route.On2Map)) { vm.go(Route.On2Map) } - NavRow(title = vm.tr("on_year3"), subtitle = vm.tr("on3_sub"), leading = { LeadingBadge("3") }, progress = routeProgress(vm, Route.On3Map)) { vm.go(Route.On3Map) } - NavRow(title = vm.tr("on_year4"), subtitle = vm.tr("on4_sub"), leading = { LeadingBadge("4") }, progress = routeProgress(vm, Route.On4Map)) { vm.go(Route.On4Map) } + NavRow(title = vm.tr("on_year1"), subtitle = vm.tr("on_sub"), leading = { Text("1.", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.OnMap) } + NavRow(title = vm.tr("on_year2"), subtitle = vm.tr("on2_sub"), leading = { Text("2.", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.On2Map) } + NavRow(title = vm.tr("on_year3"), subtitle = vm.tr("on3_sub"), leading = { Text("3.", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.On3Map) } + NavRow(title = vm.tr("on_year4"), subtitle = vm.tr("on4_sub"), leading = { Text("4.", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.On4Map) } } } } @@ -1028,10 +824,10 @@ fun LitYearsScreen(vm: AppViewModel) { DetailScaffold(vm, vm.tr("Literatura"), vm.tr("lit_years_sub")) { inner -> LazyColumn(contentPadding = PaddingValues(top = inner.calculateTopPadding(), bottom = inner.calculateBottomPadding() + 16.dp)) { item { - NavRow(title = vm.tr("lit_year1"), subtitle = vm.tr("lit_sub"), leading = { LeadingBadge("1") }, progress = routeProgress(vm, Route.LitMap)) { vm.go(Route.LitMap) } - NavRow(title = vm.tr("lit_year2"), subtitle = vm.tr("lit2_sub"), leading = { LeadingBadge("2") }, progress = routeProgress(vm, Route.Lit2Map)) { vm.go(Route.Lit2Map) } - NavRow(title = vm.tr("lit_year3"), subtitle = vm.tr("lit3_sub"), leading = { LeadingBadge("3") }, progress = routeProgress(vm, Route.Lit3Map)) { vm.go(Route.Lit3Map) } - NavRow(title = vm.tr("lit_year4"), subtitle = vm.tr("lit4_sub"), leading = { LeadingBadge("4") }, progress = routeProgress(vm, Route.Lit4Map)) { vm.go(Route.Lit4Map) } + NavRow(title = vm.tr("lit_year1"), subtitle = vm.tr("lit_sub"), leading = { Text("1.", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.LitMap) } + NavRow(title = vm.tr("lit_year2"), subtitle = vm.tr("lit2_sub"), leading = { Text("2.", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.Lit2Map) } + NavRow(title = vm.tr("lit_year3"), subtitle = vm.tr("lit3_sub"), leading = { Text("3.", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.Lit3Map) } + NavRow(title = vm.tr("lit_year4"), subtitle = vm.tr("lit4_sub"), leading = { Text("4.", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.Lit4Map) } } } } @@ -1042,67 +838,11 @@ fun MatYearsScreen(vm: AppViewModel) { DetailScaffold(vm, vm.tr("Matematika"), vm.tr("mat_years_sub")) { inner -> LazyColumn(contentPadding = PaddingValues(top = inner.calculateTopPadding(), bottom = inner.calculateBottomPadding() + 16.dp)) { item { - NavRow(title = vm.tr("mat0_year"), subtitle = vm.tr("mat0_sub"), leading = { LeadingBadge("ZŠ") }, progress = routeProgress(vm, Route.Mat0Map)) { vm.go(Route.Mat0Map) } - NavRow(title = vm.tr("mat_year1"), subtitle = vm.tr("mat_sub"), leading = { LeadingBadge("1") }, progress = routeProgress(vm, Route.MatMap)) { vm.go(Route.MatMap) } - NavRow(title = vm.tr("mat_year2"), subtitle = vm.tr("mat2_sub"), leading = { LeadingBadge("2") }, progress = routeProgress(vm, Route.Mat2Map)) { vm.go(Route.Mat2Map) } - NavRow(title = vm.tr("mat_year3"), subtitle = vm.tr("mat3_sub"), leading = { LeadingBadge("3") }, progress = routeProgress(vm, Route.Mat3Map)) { vm.go(Route.Mat3Map) } - NavRow(title = vm.tr("mat_year4"), subtitle = vm.tr("mat4_sub"), leading = { LeadingBadge("4") }, progress = routeProgress(vm, Route.Mat4Map)) { vm.go(Route.Mat4Map) } - } - } - } -} - -@Composable -fun CsYearsScreen(vm: AppViewModel) { - DetailScaffold(vm, vm.tr("Programování"), vm.tr("cs_years_sub")) { inner -> - LazyColumn(contentPadding = PaddingValues(top = inner.calculateTopPadding(), bottom = inner.calculateBottomPadding() + 16.dp)) { - item { - NavRow(title = vm.tr("cs_year1"), subtitle = vm.tr("cs_sub"), leading = { LeadingBadge("1") }, progress = routeProgress(vm, Route.CsMap)) { vm.go(Route.CsMap) } - NavRow(title = vm.tr("cs_year2"), subtitle = vm.tr("cs2_sub"), leading = { LeadingBadge("2") }, progress = routeProgress(vm, Route.Cs2Map)) { vm.go(Route.Cs2Map) } - NavRow(title = vm.tr("cs_year3"), subtitle = vm.tr("cs3_sub"), leading = { LeadingBadge("3") }, progress = routeProgress(vm, Route.Cs3Map)) { vm.go(Route.Cs3Map) } - NavRow(title = vm.tr("cs_year4"), subtitle = vm.tr("cs4_sub"), leading = { LeadingBadge("4") }, progress = routeProgress(vm, Route.Cs4Map)) { vm.go(Route.Cs4Map) } - } - } - } -} - -@Composable -fun SwYearsScreen(vm: AppViewModel) { - DetailScaffold(vm, vm.tr("Programové vybavení"), vm.tr("sw_years_sub")) { inner -> - LazyColumn(contentPadding = PaddingValues(top = inner.calculateTopPadding(), bottom = inner.calculateBottomPadding() + 16.dp)) { - item { - NavRow(title = vm.tr("sw_year1"), subtitle = vm.tr("sw_sub"), leading = { LeadingBadge("1") }, progress = routeProgress(vm, Route.SwMap)) { vm.go(Route.SwMap) } - NavRow(title = vm.tr("sw_year2"), subtitle = vm.tr("sw2_sub"), leading = { LeadingBadge("2") }, progress = routeProgress(vm, Route.Sw2Map)) { vm.go(Route.Sw2Map) } - NavRow(title = vm.tr("sw_year3"), subtitle = vm.tr("sw3_sub"), leading = { LeadingBadge("3") }, progress = routeProgress(vm, Route.Sw3Map)) { vm.go(Route.Sw3Map) } - NavRow(title = vm.tr("sw_year4"), subtitle = vm.tr("sw4_sub"), leading = { LeadingBadge("4") }, progress = routeProgress(vm, Route.Sw4Map)) { vm.go(Route.Sw4Map) } - } - } - } -} - -@Composable -fun PgYearsScreen(vm: AppViewModel) { - DetailScaffold(vm, vm.tr("Prezentační grafika"), vm.tr("pg_years_sub")) { inner -> - LazyColumn(contentPadding = PaddingValues(top = inner.calculateTopPadding(), bottom = inner.calculateBottomPadding() + 16.dp)) { - item { - NavRow(title = vm.tr("pg_year1"), subtitle = vm.tr("pg_sub"), leading = { LeadingBadge("1") }, progress = routeProgress(vm, Route.PgMap)) { vm.go(Route.PgMap) } - NavRow(title = vm.tr("pg_year2"), subtitle = vm.tr("pg2_sub"), leading = { LeadingBadge("2") }, progress = routeProgress(vm, Route.Pg2Map)) { vm.go(Route.Pg2Map) } - NavRow(title = vm.tr("pg_year3"), subtitle = vm.tr("pg3_sub"), leading = { LeadingBadge("3") }, progress = routeProgress(vm, Route.Pg3Map)) { vm.go(Route.Pg3Map) } - NavRow(title = vm.tr("pg_year4"), subtitle = vm.tr("pg4_sub"), leading = { LeadingBadge("4") }, progress = routeProgress(vm, Route.Pg4Map)) { vm.go(Route.Pg4Map) } - } - } - } -} - -@Composable -fun TgYearsScreen(vm: AppViewModel) { - DetailScaffold(vm, vm.tr("Technická grafika"), vm.tr("tg_years_sub")) { inner -> - LazyColumn(contentPadding = PaddingValues(top = inner.calculateTopPadding(), bottom = inner.calculateBottomPadding() + 16.dp)) { - item { - NavRow(title = vm.tr("tg_year1"), subtitle = vm.tr("tg_sub"), leading = { LeadingBadge("1") }, progress = routeProgress(vm, Route.TgMap)) { vm.go(Route.TgMap) } - NavRow(title = vm.tr("tg_year2"), subtitle = vm.tr("tg2_sub"), leading = { LeadingBadge("2") }, progress = routeProgress(vm, Route.Tg2Map)) { vm.go(Route.Tg2Map) } - NavRow(title = vm.tr("tg_year3"), subtitle = vm.tr("tg3_sub"), leading = { LeadingBadge("3") }, progress = routeProgress(vm, Route.Tg3Map)) { vm.go(Route.Tg3Map) } - NavRow(title = vm.tr("tg_year4"), subtitle = vm.tr("tg4_sub"), leading = { LeadingBadge("4") }, progress = routeProgress(vm, Route.Tg4Map)) { vm.go(Route.Tg4Map) } + NavRow(title = vm.tr("mat0_year"), subtitle = vm.tr("mat0_sub"), leading = { Text("ZŠ", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.Mat0Map) } + NavRow(title = vm.tr("mat_year1"), subtitle = vm.tr("mat_sub"), leading = { Text("1.", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.MatMap) } + NavRow(title = vm.tr("mat_year2"), subtitle = vm.tr("mat2_sub"), leading = { Text("2.", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.Mat2Map) } + NavRow(title = vm.tr("mat_year3"), subtitle = vm.tr("mat3_sub"), leading = { Text("3.", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.Mat3Map) } + NavRow(title = vm.tr("mat_year4"), subtitle = vm.tr("mat4_sub"), leading = { Text("4.", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.Mat4Map) } } } } @@ -1113,10 +853,10 @@ fun FyzYearsScreen(vm: AppViewModel) { DetailScaffold(vm, vm.tr("Fyzika"), vm.tr("fyz_years_sub")) { inner -> LazyColumn(contentPadding = PaddingValues(top = inner.calculateTopPadding(), bottom = inner.calculateBottomPadding() + 16.dp)) { item { - NavRow(title = vm.tr("fyz_year1"), subtitle = vm.tr("fyz_sub"), leading = { LeadingBadge("1") }, progress = routeProgress(vm, Route.FyzMap)) { vm.go(Route.FyzMap) } - NavRow(title = vm.tr("fyz_year2"), subtitle = vm.tr("fyz2_sub"), leading = { LeadingBadge("2") }, progress = routeProgress(vm, Route.Fyz2Map)) { vm.go(Route.Fyz2Map) } - NavRow(title = vm.tr("fyz_year3"), subtitle = vm.tr("fyz3_sub"), leading = { LeadingBadge("3") }, progress = routeProgress(vm, Route.Fyz3Map)) { vm.go(Route.Fyz3Map) } - NavRow(title = vm.tr("fyz_year4"), subtitle = vm.tr("fyz4_sub"), leading = { LeadingBadge("4") }, progress = routeProgress(vm, Route.Fyz4Map)) { vm.go(Route.Fyz4Map) } + NavRow(title = vm.tr("fyz_year1"), subtitle = vm.tr("fyz_sub"), leading = { Text("1.", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.FyzMap) } + NavRow(title = vm.tr("fyz_year2"), subtitle = vm.tr("fyz2_sub"), leading = { Text("2.", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.Fyz2Map) } + NavRow(title = vm.tr("fyz_year3"), subtitle = vm.tr("fyz3_sub"), leading = { Text("3.", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.Fyz3Map) } + NavRow(title = vm.tr("fyz_year4"), subtitle = vm.tr("fyz4_sub"), leading = { Text("4.", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.Fyz4Map) } } } } @@ -1130,17 +870,11 @@ fun SciMapScreen(vm: AppViewModel) { NavRow( title = vm.tr("Chemie"), subtitle = vm.tr("chem_sub"), - leading = { LeadingIcon(Icons.Filled.Science) }, - progress = routeProgress(vm, Route.ChemMap), + leading = { Icon(Icons.Filled.Science, null, tint = MaterialTheme.colorScheme.primary) }, ) { vm.go(Route.ChemMap) } } item { - NavRow( - title = vm.tr("Biologie"), - subtitle = vm.tr("bio_sub"), - leading = { LeadingIcon(Icons.Filled.Eco) }, - progress = routeProgress(vm, Route.BioMap), - ) { vm.go(Route.BioMap) } + NavRow(title = vm.tr("Biologie"), subtitle = vm.tr("bio_sub")) { vm.go(Route.BioMap) } } } } @@ -1151,26 +885,20 @@ fun CzechMapScreen(vm: AppViewModel) { DetailScaffold(vm, vm.tr("Český jazyk a literatura"), vm.tr("czech_sub")) { inner -> LazyColumn(contentPadding = PaddingValues(top = inner.calculateTopPadding(), bottom = inner.calculateBottomPadding() + 16.dp)) { item { - NavRow( - title = vm.tr("Literatura"), - subtitle = vm.tr("lit_years_sub"), - leading = { LeadingIcon(Icons.Filled.AutoStories) }, - progress = routeProgress(vm, Route.LitYears), - ) { vm.go(Route.LitYears) } + NavRow(title = vm.tr("Literatura"), subtitle = vm.tr("lit_years_sub")) { vm.go(Route.LitYears) } } item { NavRow( title = vm.tr("Mluvnice"), subtitle = vm.tr("mluv_sub"), - leading = { LeadingIcon(Icons.Filled.FormatListNumbered) }, - progress = routeProgress(vm, Route.Mluvnice), + leading = { Icon(Icons.Filled.FormatListNumbered, null, tint = MaterialTheme.colorScheme.primary) }, ) { vm.go(Route.Mluvnice) } } item { NavRow( title = vm.tr("Maturitní četba"), subtitle = vm.tr("reading_sub"), - leading = { LeadingIcon(Icons.AutoMirrored.Filled.MenuBook) }, + leading = { Icon(Icons.AutoMirrored.Filled.MenuBook, null, tint = MaterialTheme.colorScheme.primary) }, ) { vm.go(Route.ReadingList) } } } @@ -1233,52 +961,6 @@ fun BookScreen(vm: AppViewModel, id: String) { // --------------------------------------------------------------------------- // Lesson slides -/** One explanation slide: label, title, tip and numbered points. */ -@Composable -fun SlideContent(slide: J) { - Column { - Text(slide.str("kicker"), style = MaterialTheme.typography.labelMedium, color = MaterialTheme.colorScheme.onSurfaceVariant) - Text(slide.str("title"), style = MaterialTheme.typography.headlineSmall, modifier = Modifier.padding(top = 4.dp, bottom = 12.dp)) - slide.strOrNull("tip")?.let { tip -> - Card( - modifier = Modifier.fillMaxWidth().padding(bottom = 12.dp), - colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.secondaryContainer), - ) { - Row(Modifier.padding(14.dp), verticalAlignment = Alignment.CenterVertically) { - Icon(Icons.Outlined.Lightbulb, null, tint = MaterialTheme.colorScheme.onSecondaryContainer) - Spacer(Modifier.width(10.dp)) - Text(tip, style = MaterialTheme.typography.bodyMedium) - } - } - } - slide.strs("lines").forEachIndexed { index, line -> - val numbered = Regex("""^(\d+)\.\s+(.*)$""").find(line) - val badge = numbered?.groupValues?.get(1) ?: "${index + 1}" - val text = numbered?.groupValues?.get(2) ?: line - Row( - Modifier - .fillMaxWidth() - .padding(vertical = 5.dp) - .background(MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.45f), androidx.compose.foundation.shape.RoundedCornerShape(16.dp)) - .padding(horizontal = 14.dp, vertical = 12.dp), - verticalAlignment = Alignment.Top, - ) { - Box( - Modifier - .padding(top = 2.dp) - .size(28.dp) - .background(MaterialTheme.colorScheme.primary.copy(alpha = 0.14f), CircleShape), - contentAlignment = Alignment.Center, - ) { - Text(badge, style = MaterialTheme.typography.labelLarge, color = MaterialTheme.colorScheme.primary) - } - Spacer(Modifier.width(12.dp)) - Text(text, style = MaterialTheme.typography.bodyLarge, modifier = Modifier.weight(1f)) - } - } - } -} - @OptIn(ExperimentalFoundationApi::class) @Composable fun SlidesScreen( @@ -1329,13 +1011,52 @@ fun SlidesScreen( }, ) { inner -> HorizontalPager(state = pager, modifier = Modifier.fillMaxSize().padding(inner)) { page -> + val slide = slides[page] Column( Modifier .fillMaxSize() .verticalScroll(rememberScrollState()) .padding(horizontal = 16.dp, vertical = 12.dp), ) { - SlideContent(slides[page]) + Text(slide.str("kicker"), style = MaterialTheme.typography.labelMedium, color = MaterialTheme.colorScheme.onSurfaceVariant) + Text(slide.str("title"), style = MaterialTheme.typography.headlineSmall, modifier = Modifier.padding(top = 4.dp, bottom = 12.dp)) + slide.strOrNull("tip")?.let { tip -> + Card( + modifier = Modifier.fillMaxWidth().padding(bottom = 12.dp), + colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.secondaryContainer), + ) { + Row(Modifier.padding(14.dp), verticalAlignment = Alignment.CenterVertically) { + Icon(Icons.Outlined.Lightbulb, null, tint = MaterialTheme.colorScheme.onSecondaryContainer) + Spacer(Modifier.width(10.dp)) + Text(tip, style = MaterialTheme.typography.bodyMedium) + } + } + } + slide.strs("lines").forEachIndexed { index, line -> + val numbered = Regex("""^(\d+)\.\s+(.*)$""").find(line) + val badge = numbered?.groupValues?.get(1) ?: "${index + 1}" + val text = numbered?.groupValues?.get(2) ?: line + Row( + Modifier + .fillMaxWidth() + .padding(vertical = 5.dp) + .background(MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.45f), androidx.compose.foundation.shape.RoundedCornerShape(16.dp)) + .padding(horizontal = 14.dp, vertical = 12.dp), + verticalAlignment = Alignment.Top, + ) { + Box( + Modifier + .padding(top = 2.dp) + .size(28.dp) + .background(MaterialTheme.colorScheme.primary.copy(alpha = 0.14f), CircleShape), + contentAlignment = Alignment.Center, + ) { + Text(badge, style = MaterialTheme.typography.labelLarge, color = MaterialTheme.colorScheme.primary) + } + Spacer(Modifier.width(12.dp)) + Text(text, style = MaterialTheme.typography.bodyLarge, modifier = Modifier.weight(1f)) + } + } Spacer(Modifier.height(24.dp)) } } diff --git a/assets/deutsch.png b/assets/deutsch.png deleted file mode 100644 index 91ed3e6..0000000 Binary files a/assets/deutsch.png and /dev/null differ diff --git a/assets/germanlection.png b/assets/germanlection.png new file mode 100644 index 0000000..ab5fd6f Binary files /dev/null and b/assets/germanlection.png differ diff --git a/assets/home.png b/assets/home.png deleted file mode 100644 index 4762690..0000000 Binary files a/assets/home.png and /dev/null differ diff --git a/assets/neue-freunde.png b/assets/neue-freunde.png deleted file mode 100644 index 3c10067..0000000 Binary files a/assets/neue-freunde.png and /dev/null differ diff --git a/assets/subjectsscreen.png b/assets/subjectsscreen.png new file mode 100644 index 0000000..6c09b75 Binary files /dev/null and b/assets/subjectsscreen.png differ diff --git a/assets/welcomescreen.png b/assets/welcomescreen.png new file mode 100644 index 0000000..9edb54e Binary files /dev/null and b/assets/welcomescreen.png differ diff --git a/content/README.md b/content/README.md index ed6dca9..ce160ef 100644 --- a/content/README.md +++ b/content/README.md @@ -18,7 +18,7 @@ Skript vypíše počet lekcí, nebo chyby s cestou a číslem řádku | Složka | Obsah | |---|---| -| `pocitacove-site/`, `technicke-vybaveni/`, `technicka-grafika/`, `prezentacni-grafika/`, `programove-vybaveni/`, `programovani/`, `obcanska-nauka/`, `fyzika/` | `N-rocnik/`, v nich lekce | +| `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 | @@ -97,7 +97,7 @@ a smažte `puvodni`. ## Běžná lekce -Sítě, hardware, technická grafika, prezentační grafika, programové vybavení, občanka, literatura, chemie, biologie, fyzika. +Sítě, hardware, občanka, literatura, chemie, biologie, fyzika. ```md --- diff --git a/content/aplikace/novinky.txt b/content/aplikace/novinky.txt index e8365ba..1f6aef9 100644 --- a/content/aplikace/novinky.txt +++ b/content/aplikace/novinky.txt @@ -5,30 +5,6 @@ # cs: bullet # en: bullet ---- 2026-10-11 -cs: Programové vybavení: Windows, Word, Excel, Access, MySQL a správa účtů -cs: Čtyři ročníky, od licence a složek po WordPress, Power BI a zásady -en: Software: Windows, Word, Excel, Access, MySQL and account administration -en: Four years, from licences and folders to WordPress, Power BI and policy - ---- 2026-10-11 -cs: Prezentační grafika: Photoshop, Premiere Pro a další programy Adobe -cs: Čtyři ročníky, v každé lekci postup, zadání a kvíz -en: Presentation graphics: Photoshop, Premiere Pro and the other Adobe apps -en: Four years, and every lesson has a method, an assignment and a quiz - ---- 2026-10-11 -cs: Programování: čtyři ročníky C#, od výpisu po LINQ a async -cs: Kód se píše v lekci a hned vedle se spustí -en: Programming: four years of C#, from output to LINQ and async -en: You write the code in the lesson and run it right beside the text - ---- 2026-10-11 -cs: Technická grafika: čtyři ročníky AutoCADu, od výkresu po 3D -cs: V každé lekci je postup, zadání s rozměry a kvíz -en: Technical graphics: four years of AutoCAD, from the drawing sheet to 3D -en: Every lesson has a method, a dimensioned assignment and a quiz - --- 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 diff --git a/content/aplikace/predmety.md b/content/aplikace/predmety.md index 37363dd..39592ae 100644 --- a/content/aplikace/predmety.md +++ b/content/aplikace/predmety.md @@ -11,7 +11,7 @@ | Matematika | Matematika | Mathematics | function | matyears | ano | | Fyzika | Fyzika | Physics | bolt | fyzyears | ano | | Základy přírodních věd | Základy přírodních věd | Fundamentals of Natural Sciences | flask | scimap | ano | -| Technická grafika | Technická grafika | Technical Graphics | ruler | tgyears | ano | -| Prezentační grafika | Prezentační grafika | Presentation Graphics | brush | pgyears | ano | -| Programování | Programování | Programming | code | csyears | ano | -| Programové vybavení | Programové vybavení | Software | apps | swyears | 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 | diff --git a/content/aplikace/texty.md b/content/aplikace/texty.md index fb62a94..089a5b0 100644 --- a/content/aplikace/texty.md +++ b/content/aplikace/texty.md @@ -40,7 +40,7 @@ |---|---|---| | 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é studenty ze SSŠVT. | Exam practice in one window. Czech and English, written by students from SSŠVT. | +| 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. | @@ -117,7 +117,6 @@ | search_page | Stránka | Page | | search_home | Úvod | Welcome | | subjects_title | Předměty | Subjects | -| subjects_soon | Připravujeme | Coming soon | | 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 @@ -230,73 +229,6 @@ | 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. | -# Technická grafika - -| Klíč | Česky | Anglicky | -|---|---|---| -| tg_years_sub | Čtyři ročníky AutoCADu, od výkresu po maturitní zadání. | Four years of AutoCAD, from the drawing sheet to the exam project. | -| tg_year1 | 1. ročník | Year 1 | -| tg_year2 | 2. ročník | Year 2 | -| tg_year3 | 3. ročník | Year 3 | -| tg_year4 | 4. ročník | Year 4 | -| tg_sub | Výkres, souřadnice a první příkazy. | The sheet, coordinates and the first commands. | -| tg2_sub | Úpravy, hladiny, šrafy a kóty. | Editing, layers, hatches and dimensions. | -| tg3_sub | Pohledy, řezy, bloky a tisk. | Views, sections, blocks and plotting. | -| tg4_sub | 3D model a výkres k maturitě. | A 3D model and the exam drawing. | - -# Prezentační grafika - -| Klíč | Česky | Anglicky | -|---|---|---| -| pg_years_sub | Od Photoshopu přes Premiere Pro k Illustratoru, After Effects a InDesignu. | From Photoshop through Premiere Pro to Illustrator, After Effects and InDesign. | -| pg_year1 | 1. ročník | Year 1 | -| pg_year2 | 2. ročník | Year 2 | -| pg_year3 | 3. ročník | Year 3 | -| pg_year4 | 4. ročník | Year 4 | -| pg_sub | Photoshop: pixely, vrstvy, výběr a retuš. | Photoshop: pixels, layers, selections and retouching. | -| pg2_sub | Masky, barvy, plakát a export. | Masks, colour, a poster and export. | -| pg3_sub | Premiere Pro: střih, zvuk, titulky a video. | Premiere Pro: the cut, sound, titles and the video. | -| pg4_sub | Illustrator, After Effects, InDesign a maturitní kampaň. | Illustrator, After Effects, InDesign and the exam campaign. | - -# Programové vybavení - -| Klíč | Česky | Anglicky | -|---|---|---| -| sw_years_sub | Operační systém, Office, databáze a správa Windows. | The operating system, Office, databases and Windows administration. | -| sw_year1 | 1. ročník | Year 1 | -| sw_year2 | 2. ročník | Year 2 | -| sw_year3 | 3. ročník | Year 3 | -| sw_year4 | 4. ročník | Year 4 | -| sw_sub | Software, licence a práce ve Windows. | Software, licences and working in Windows. | -| sw2_sub | Word a Excel: dokument, vzorce a graf. | Word and Excel: a document, formulas and a chart. | -| sw3_sub | Access a MySQL: tabulky, dotazy a vztahy. | Access and MySQL: tables, queries and relationships. | -| sw4_sub | WordPress, Power BI, dávkové soubory a zásady. | WordPress, Power BI, batch files and policy. | - -# Programování - -| Klíč | Česky | Anglicky | -|---|---|---| -| cs_years_sub | C# od prvního výpisu po pokročilejší nástroje. Kód se píše a spouští vedle výkladu. | C# from the first line of output to the later tools. You write the code and run it beside the lesson. | -| cs_year1 | 1. ročník | Year 1 | -| cs_year2 | 2. ročník | Year 2 | -| cs_year3 | 3. ročník | Year 3 | -| cs_year4 | 4. ročník | Year 4 | -| cs_sub | Výpis, proměnné, typy, operátory a řetězce. | Output, variables, types, operators and strings. | -| cs2_sub | Podmínky, cykly, pole a metody. | Conditions, loops, arrays and methods. | -| cs3_sub | Třídy, dědičnost, rozhraní a výčty. | Classes, inheritance, interfaces and enums. | -| cs4_sub | Výjimky, kolekce, LINQ, soubory a async. | Exceptions, collections, LINQ, files and async. | -| cs_code | Kód | Code | -| cs_output | Výstup | Output | -| cs_stdin | Vstup pro Console.ReadLine | Input for Console.ReadLine | -| cs_run | Spustit | Run | -| cs_reset | Obnovit ukázku | Reset example | -| cs_running | Překládám… | Compiling… | -| cs_done | Hotovo | Done | -| cs_failed | Chyba | Error | -| cs_empty | Zatím nic. Upravte kód a spusťte ho. | Nothing yet. Edit the code and run it. | -| cs_timeout | Program běžel příliš dlouho a byl zastaven. | The program ran too long and was stopped. | -| cs_unavailable | Tady C# nespustíte. Na počítači s nainstalovaným .NET se výstup objeví vedle kódu. | C# cannot run here. On a computer with .NET installed the output appears beside the code. | - # Angličtina a němčina | Klíč | Česky | Anglicky | diff --git a/content/prezentacni-grafika/1-rocnik/01-bitmapa-a-vektor.en.md b/content/prezentacni-grafika/1-rocnik/01-bitmapa-a-vektor.en.md deleted file mode 100644 index 2e28f6f..0000000 --- a/content/prezentacni-grafika/1-rocnik/01-bitmapa-a-vektor.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Bitmap and vector -popis: When a picture is pixels and when it is curves. -nazev_cviceni: Quiz: bitmap and vector -nadpis_kvizu: Tell what goes soft when you enlarge it ---- diff --git a/content/prezentacni-grafika/1-rocnik/01-bitmapa-a-vektor.md b/content/prezentacni-grafika/1-rocnik/01-bitmapa-a-vektor.md deleted file mode 100644 index 167b175..0000000 --- a/content/prezentacni-grafika/1-rocnik/01-bitmapa-a-vektor.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: pg-1-bitmapa-a-vektor -nazev: Bitmapa a vektor -popis: Kdy je obrázek z pixelů a kdy z křivek. -nazev_cviceni: Kvíz: bitmapa a vektor -nadpis_kvizu: Poznejte, co se při zvětšení rozmaže ---- - -# Výklad - -## Dva druhy obrázku -*Pixel a křivka* - -- Bitmapa je mřížka pixelů. Fotka z telefonu je bitmapa a otevírá se ve Photoshopu. -- Vektor je popis křivek. Logo a ikona se kreslí v Illustratoru a při zvětšení zůstávají ostré. -- Photoshop umí obojí, ale fotku v něm nepřekreslíte na křivky. Naopak Illustrator není na retuš. -- Když nevíte, který soubor je který, přibližte ho na 400 %. Bitmapa ukáže čtverečky. - -> Tip: Přípona napoví: JPG a PNG jsou bitmapa, SVG a AI jsou vektor. PSD může obsahovat obojí. - -## Co se stane při zvětšení -*Kvalita* - -- Bitmapu 800 px širokou nelze vytisknout ostře na velký plakát. Pixely se jen roztáhnou. -- Vektor se zvětší přepočtem křivky. Hranu má pořád hladkou. -- Zmenšení bitmapy pixely zahodí. Zvětšení zpět je nevrátí. -- Proto se logo neukládá jako malé JPG a fotka se nefotí až ve chvíli, kdy už je pozdě. - -> Tip: Jednou zmenšenou fotku už nedostanete zpátky. Nechte si původní soubor. - -## Který program kdy -*Volba* - -- Fotku, retuš a plakát z fotografie berte do Photoshopu. -- Logo, piktogram a čisté tvary berte do Illustratoru. Ten přijde ve čtvrtém ročníku. -- Video nepatří ani do jednoho. Na střih je Premiere Pro, ve třeťáku. -- Hotové logo z Illustratoru se do Photoshopu vloží jako chytrý objekt, ne jako malý JPG. - -> Tip: Chytrý objekt drží původní kvalitu. ZJPG-ované logo už křivky nemá. - -## Zadání: porovnání -*Cvičení* - -- Otevřete ve Photoshopu fotku a přibližte ji na 400 %. Okraj předmětu se rozpadne na pixely. -- Stejný pohled udělejte u loga ve formátu SVG nebo AI. Hrana zůstane hladká. -- Do sešitu napište, který soubor je bitmapa a který vektor, a proč. -- Fotku uložte jako porovnani.psd. Logo nepřevádějte na JPG. - -> Tip: Když SVG ve Photoshopu rastruje, zaškrtněte velký rozměr. Malý náhled nic neukáže. - -# Kvíz - -## Co uvidíte na fotce při zvětšení na 400 %? -- Hladkou křivku bez pixelů -- [x] Čtverečky pixelů -- Jen ořezové značky -- Prázdné plátno -> Fotka je bitmapa. Zvětšení roztáhne pixely, křivku z ní neudělá. - -## Kam patří nové logo školy? -- Do Photoshopu jako malé JPG -- [x] Do Illustratoru jako křivky -- Do Premiere jako titulek -- Do JPG o šířce 80 px -> Logo se zvětšuje na plakát i na vizitku. Křivka to zvládne, malé JPG ne. - -## Co se stane, když bitmapu zmenšíte a pak znovu zvětšíte? -- Pixely se vrátí -- [x] Ostrost se ztratí -- Soubor se stane vektorem -- Přibude spadávka -> Zmenšení pixely zahodí. Zvětšení je neumí vymyslet zpět. - -## Jak se má logo vložit do plakátu ve Photoshopu? -- Jako JPG 80 px -- [x] Jako chytrý objekt -- Vložením snímku obrazovky -- Jako zvuková stopa -> Chytrý objekt podrží zdroj. JPG logo už nejde zvětšit bez rozmazání. diff --git a/content/prezentacni-grafika/1-rocnik/02-rozliseni-a-barva.en.md b/content/prezentacni-grafika/1-rocnik/02-rozliseni-a-barva.en.md deleted file mode 100644 index 902f025..0000000 --- a/content/prezentacni-grafika/1-rocnik/02-rozliseni-a-barva.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Resolution and colour -popis: Pixels, 300 ppi for print, and RGB against CMYK. -nazev_cviceni: Quiz: resolution and colour -nadpis_kvizu: Pick the size and the colour mode ---- diff --git a/content/prezentacni-grafika/1-rocnik/02-rozliseni-a-barva.md b/content/prezentacni-grafika/1-rocnik/02-rozliseni-a-barva.md deleted file mode 100644 index 86b6f23..0000000 --- a/content/prezentacni-grafika/1-rocnik/02-rozliseni-a-barva.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: pg-1-rozliseni-a-barva -nazev: Rozlišení a barva -popis: Pixely, tisk 300 ppi a rozdíl mezi RGB a CMYK. -nazev_cviceni: Kvíz: rozlišení a barva -nadpis_kvizu: Vyberte rozměr a barevný režim ---- - -# Výklad - -## Pixely a tisk -*Rozlišení* - -- Rozměr v pixelech říká, kolik bodů obrázek má. 1920 × 1080 je Full HD. -- Rozlišení v ppi říká, kolik pixelů připadne na palec při tisku. -- Na obrazovku stačí 72 ppi. Do tisku se připravuje 300 ppi. -- Formát A4 při 300 ppi má zhruba 2480 × 3508 px. To je 210 × 297 mm. - -> Tip: 72 ppi na plakát nestačí. 300 ppi na web je zbytečně velký soubor. - -## RGB a CMYK -*Režim* - -- RGB je světlo obrazovky: červená, zelená a modrá. Web i video jsou RGB. -- CMYK jsou tiskové barvy: azurová, purpurová, žlutá a černá. -- Barva, která svítí na monitoru, se v tisku často smrskne. Základní červená v CMYK zešedne. -- Fotku upravujte v RGB. Do CMYK ji převádějte až při exportu pro tiskárnu. - -> Tip: Když tiskárna chce PDF v CMYK, převod nechte na export. Pracovní soubor zůstane RGB. - -## Nový dokument -*Plátno* - -- Webový obrázek: 1920 × 1080 px, 72 ppi, RGB, 8 bitů na kanál. -- Tiskové A4: předvolba A4, 300 ppi, RGB. Ořez řešte až u plakátu ve druháku. -- Pozadí nové školní práce nechte průhledné, ať pod ním není bílá omylem. -- Pojmenujte dokument hned. nazev-skoly.psd je lepší než Bez názvu-1. - -> Tip: 8 bitů na kanál je běžná fotka. 16 bitů nechte na složitou retuš, soubor je větší. - -## Zadání: dva dokumenty -*Cvičení* - -- Založte web.psd: 1920 × 1080 px, 72 ppi, RGB, 8 bitů. -- Založte tisk-a4.psd: A4, 300 ppi, RGB, 8 bitů. -- U obou zapište do vrstvy poznámku s rozměrem v pixelech. U A4 to má být kolem 2480 × 3508. -- Oba soubory uložte jako PSD. Zatím je neexportujte do JPG. - -> Tip: Obraz > Velikost obrazu ukáže pixely i centimetry. Jednotky si přepněte, ať čtete obojí. - -# Kvíz - -## Jaké rozlišení se bere pro tisk? -- 72 ppi -- [x] 300 ppi -- 25 sn/s -- 8 bitů -> 72 ppi je obrazovka. Tisk chce 300 ppi, jinak je fotka na papíře měkká. - -## Který režim patří na web a do videa? -- CMYK -- [x] RGB -- Jen černá -- Spadávka -> Obrazovka skládá barvu ze světla RGB. CMYK je pro tiskárnu. - -## Kolik pixelů má zhruba A4 při 300 ppi? -- 1920 × 1080 -- [x] 2480 × 3508 -- 210 × 297 -- 800 × 600 -> 210 × 297 mm je rozměr papíru. V pixelech při 300 ppi je to asi 2480 × 3508. - -## Kdy se má fotka převést do CMYK? -- Hned po otevření -- [x] Až při exportu pro tisk -- Před každou retuší -- Nikdy, ani pro tisk -> Úpravy nechte v RGB. CMYK je výstup pro tiskárnu, ne pracovní soubor. diff --git a/content/prezentacni-grafika/1-rocnik/03-prostredi-photoshopu.en.md b/content/prezentacni-grafika/1-rocnik/03-prostredi-photoshopu.en.md deleted file mode 100644 index 3f0a246..0000000 --- a/content/prezentacni-grafika/1-rocnik/03-prostredi-photoshopu.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: The Photoshop workspace -popis: Panels, zoom and saving a PSD. -nazev_cviceni: Quiz: the workspace -nadpis_kvizu: Find the shortcut and the right file ---- diff --git a/content/prezentacni-grafika/1-rocnik/03-prostredi-photoshopu.md b/content/prezentacni-grafika/1-rocnik/03-prostredi-photoshopu.md deleted file mode 100644 index a2bcd79..0000000 --- a/content/prezentacni-grafika/1-rocnik/03-prostredi-photoshopu.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: pg-1-prostredi -nazev: Prostředí Photoshopu -popis: Panely, lupa a ukládání PSD. -nazev_cviceni: Kvíz: prostředí -nadpis_kvizu: Najděte zkratku a správný soubor ---- - -# Výklad - -## Okno -*Panely* - -- Vlevo je panel nástrojů. Nahoře jsou volby vybraného nástroje, mění se s ním. -- Vpravo jsou Vrstvy, Barvy a Vlastnosti. Když panel zmizí, vrátí ho Okno a název panelu. -- Uprostřed je plátno. Šedé okolí není součást obrázku, netiskne se. -- Pracovní plochu Fotografie nebo Základní nastavíte vpravo nahoře. Cizí rozložení si neukládejte přes cizí účet. - -> Tip: Na Macu je Ctrl většinou Cmd. Alt je Option. Zkratky v lekcích jsou windowsové. - -## Pohyb po obraze -*Lupa* - -- Mezerník dočasně vezme ručičku a obraz se posouvá. -- Ctrl+0 vměstná celé plátno do okna. Ctrl+1 ukáže 100 %, jeden pixel na pixel. -- Nástroj lupa je Z. Alt a klik zmenšuje. -- Při retuši kontrolujte 100 %. Na celém plátně drobná chyba zanikne. - -> Tip: Ctrl+Alt+Z krokne zpět o víc než jeden krok. Panel Historie ukáže, kam až se dá vrátit. - -## Uložení -*PSD a JPG* - -- Pracovní soubor je PSD. Drží vrstvy, masky a text. -- JPG je kopie na odevzdání nebo na web. Vrstvy v něm nejsou. -- Soubor > Uložit jako nechá PSD. Export > Exportovat jako udělá JPG nebo PNG. -- JPG kvalitu 10 (nebo 80 %) berte na fotku. Nižší kvalita dělá kostky. - -> Tip: Jednou uložené JPG znovu neukládejte jako jediný zdroj. Každý export ubere detail. - -## Zadání: první soubor -*Cvičení* - -- Otevřete web.psd z minulé lekce, nebo založte nový 1920 × 1080 px. -- Přejmenujte první vrstvu na pozadi a uložte soubor jako uvod.psd. -- Ctrl+0 a Ctrl+1 si vyzkoušejte. Na 100 % má být vidět pixel, ne celé plátno. -- Exportujte kopii uvod.jpg v kvalitě 10. PSD si nechte. - -> Tip: Když Exportovat jako nabídne PNG, přepněte formát na JPG. PNG tu ještě nepotřebujeme. - -# Kvíz - -## Co udělá Ctrl+1? -- Vloží novou vrstvu -- [x] Ukáže obraz v měřítku 100 % -- Smaže plátno -- Převede barvy do CMYK -> 100 % je jeden pixel souboru na jeden pixel obrazovky. Ctrl+0 naopak vměstná celé plátno. - -## Který soubor si necháváte jako pracovní? -- JPG -- [x] PSD -- MP4 -- Jen snímek obrazovky -> PSD drží vrstvy. JPG je plochá kopie. - -## Čím se při přiblížení posouvá obraz? -- Nástrojem text -- [x] Mezerníkem -- Klávesou D -- Exportem -> Mezerník dočasně přepne na ručičku, ať nemusíte měnit nástroj. - -## Jakou kvalitu JPG berete na obyčejnou fotku? -- 1 -- [x] 10, tedy kolem 80 % -- JPG se na fotku nehodí -- Jen PNG -> Kvalita 1 obraz rozbije na kostky. Kolem 10 je rozumný kompromis velikosti a vzhledu. diff --git a/content/prezentacni-grafika/1-rocnik/04-vrstvy.en.md b/content/prezentacni-grafika/1-rocnik/04-vrstvy.en.md deleted file mode 100644 index 468d0a9..0000000 --- a/content/prezentacni-grafika/1-rocnik/04-vrstvy.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Layers -popis: Order, opacity and groups. An edit does not sit on the photo pixels. -nazev_cviceni: Quiz: layers -nadpis_kvizu: Put the layers in the right order ---- diff --git a/content/prezentacni-grafika/1-rocnik/04-vrstvy.md b/content/prezentacni-grafika/1-rocnik/04-vrstvy.md deleted file mode 100644 index 25253f5..0000000 --- a/content/prezentacni-grafika/1-rocnik/04-vrstvy.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: pg-1-vrstvy -nazev: Vrstvy -popis: Pořadí, krytí a skupiny. Úprava nesedí na pixelech fotky. -nazev_cviceni: Kvíz: vrstvy -nadpis_kvizu: Dejte vrstvy do správného pořadí ---- - -# Výklad - -## Proč vrstva -*Pořádek* - -- Každá úprava má vlastní vrstvu. Fotka vespod zůstane nedotčená. -- Horní vrstva překrývá spodní. Text patří nahoru, fotka dolů. -- Oko u vrstvy ji skryje. Zámek zabrání posunu. -- Vrstvu pojmenujte: fotka, retus, nadpis. Název Vrstva 1 nic neřekne. - -> Tip: Když smažete vrstvu, fotka pod ní zůstane. Když malujete přímo do fotky, už ji neoddělíte. - -## Krytí a pořadí -*Vzhled* - -- Krytí 100 % je plná vrstva. Krytí 70 % nechá prosvítat to, co je pod ní. -- Pořadí změníte tažením v panelu Vrstvy. -- Režim prolnutí nechte na Normální, dokud ho lekce výslovně nezmění. -- Jedna věc na jedné vrstvě. Nadpis a stín textu k sobě patří, retuš ne. - -> Tip: Krytí je u horního okraje panelu Vrstvy. Není to totéž co Výplň, tu zatím nechte 100 %. - -## Skupina -*Složka* - -- Ctrl+G vloží vybrané vrstvy do skupiny. Skupina je složka v panelu. -- Skupina Popisek ať drží nadpis i podnadpis. Skupina Foto ať drží fotku a retuš. -- Skrytí skupiny skryje všechno v ní. Jednotlivé vrstvy tím nesmažete. -- Rozdělit skupinu jde Ctrl+Shift+G. - -> Tip: Nejdřív vyberte vrstvy se Shiftem, pak Ctrl+G. Prázdná skupina sama nic nesrovná. - -## Zadání: tři patra -*Cvičení* - -- V uvod.psd mějte dole vrstvu fotka. -- Nad ní vrstvu uprav, krytí 70 %. Zatím na ni stačí jednobarevný obdélník přes spodní třetinu. -- Úplně nahoru vrstvu nadpis s textem Školní den. -- Vrstvy nadpis a uprav dejte do skupiny popisek. Uložte PSD. - -> Tip: Když text nejde přečíst, není špatně písmo, ale pořadí. Nadpis nesmí skončit pod fotkou. - -# Kvíz - -## Kam patří vrstva s fotkou? -- Úplně nahoru -- [x] Dolu, pod úpravy a text -- Mimo panel Vrstvy -- Do JPG -> Fotka je podklad. Všechno, co se má dát vypnout, leží nad ní. - -## Co znamená krytí 70 %? -- Vrstva je o 70 px menší -- [x] Vrstva je částečně průhledná -- Text má 70 bodů -- Soubor má 70 ppi -> 100 % je plná vrstva. Nižší krytí nechá prosvítat vrstvy pod ní. - -## Čím se vybrané vrstvy seskupí? -- Ctrl+1 -- [x] Ctrl+G -- Klávesou D -- Exportem do JPG -> Ctrl+G udělá skupinu. Ctrl+Shift+G ji zase rozebere. - -## Proč se nemaluje přímo do vrstvy fotky? -- Photoshop to zakazuje -- [x] Úprava pak nejde oddělit ani vypnout -- Fotka by se stala vektorem -- Změní se to na CMYK -> Vlastní vrstvu smažete nebo skryjete. Pixely fotky už od malby neočistíte. diff --git a/content/prezentacni-grafika/1-rocnik/05-vybery.en.md b/content/prezentacni-grafika/1-rocnik/05-vybery.en.md deleted file mode 100644 index fa401db..0000000 --- a/content/prezentacni-grafika/1-rocnik/05-vybery.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Selections -popis: Mark part of the picture and copy it to a new layer. -nazev_cviceni: Quiz: selections -nadpis_kvizu: Pick the tool and the shortcut ---- diff --git a/content/prezentacni-grafika/1-rocnik/05-vybery.md b/content/prezentacni-grafika/1-rocnik/05-vybery.md deleted file mode 100644 index 7d42859..0000000 --- a/content/prezentacni-grafika/1-rocnik/05-vybery.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: pg-1-vybery -nazev: Výběry -popis: Označení části obrazu a kopie na novou vrstvu. -nazev_cviceni: Kvíz: výběry -nadpis_kvizu: Vyberte nástroj a zkratku ---- - -# Výklad - -## Nástroje výběru -*Tvar* - -- Obdélníkový a eliptický výběr řežou pravidelný tvar. Hodí se na ořez a banner. -- Laso obkreslí nepravidelný okraj rukou. Na vlasy je nepřesné. -- Rychlý výběr a předmět malují přes plochu, kterou chcete. Photoshop dopočítá hranu. -- Kouzelná hůlka bere souvislou podobnou barvu. Na oblohu ano, na tvář ne. - -> Tip: Shift k výběru přidává, Alt ubírá. Ve volbách nástroje je totéž jako ikony. - -## Hrana -*Prolnutí* - -- Tvrdý výběr dělá nalepený obrys. Prolnutí okraje (feather) hranu změkčí. -- U postavy stačí prolnutí 1 až 2 px. U oblohy může být větší. -- Prolnutí se nastavuje před potvrzením, nebo přes Výběr > Upravit > Prolnout okraj. -- Když je kolem vlasů barevný lem, výběr byl moc hrubý. Zpřesněte ho, neschovávejte ho rozmazáním. - -> Tip: Prolnutí 20 px z člověka udělá ducha. Na výřez postavy je to moc. - -## Nová vrstva z výběru -*Ctrl+J* - -- Ctrl+J zkopíruje výběr na novou vrstvu. Původní fotka zůstane vespod. -- Tak se postava oddělí od pozadí, aniž byste pozadí mazali. -- Výběr zrušíte Ctrl+D. Když ho nezrušíte, další malování se ořeže jen do něj. -- Vrstvu s postavou pojmenujte osoba. Vrstvu pod ní pozadi. - -> Tip: Ctrl+J bez výběru zkopíruje celou vrstvu. Nejdřív musí běžet mravenci kolem výběru. - -## Zadání: osoba bokem -*Cvičení* - -- Vyberte postavu rychlým výběrem. Okraj doplňte se Shiftem a Alt. -- Dejte prolnutí 2 px a Ctrl+J. Vznikne vrstva osoba. -- Vrstvu pozadi ztmavte tak, aby šla vypnout. Postava zůstane ve své vrstvě světlá. -- Uložte vyber.psd. Výběr před uložením zrušte Ctrl+D. - -> Tip: Když ztmavení sedí i na postavě, malovali jste do špatné vrstvy. Ztmavení patří jen na pozadi. - -# Kvíz - -## Který nástroj bere souvislou podobnou barvu, třeba oblohu? -- Text -- [x] Kouzelná hůlka -- Ořez -- Pero v Illustratoru -> Hůlka skočí po podobné barvě. Na tvář, která má víc odstínů, se nehodí. - -## Co udělá Ctrl+J, když je něco vybrané? -- Smaže výběr -- [x] Zkopíruje výběr na novou vrstvu -- Převede obraz do CMYK -- Založí video -> Původní vrstva zůstane. Nová obsahuje jen vybranou část. - -## Jaké prolnutí okraje dává smysl u postavy? -- [x] 2 px -- 80 px -- 300 ppi -- Žádné, ale 40 px stín na celé fotce -> 1 až 2 px hranu změkčí. Desítky pixelů postavu rozmažou. - -## Čím se výběr zruší? -- [x] Ctrl+D -- Ctrl+0 -- Exportem JPG -- Krytím 70 % -> Nezrušený výběr omezí další malování jen dovnitř mravenců. diff --git a/content/prezentacni-grafika/1-rocnik/06-retus.en.md b/content/prezentacni-grafika/1-rocnik/06-retus.en.md deleted file mode 100644 index 6ff7911..0000000 --- a/content/prezentacni-grafika/1-rocnik/06-retus.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Retouching -popis: The clone stamp and the healing brush on their own layer. -nazev_cviceni: Quiz: retouching -nadpis_kvizu: Pick the tool and the layer ---- diff --git a/content/prezentacni-grafika/1-rocnik/06-retus.md b/content/prezentacni-grafika/1-rocnik/06-retus.md deleted file mode 100644 index e7def42..0000000 --- a/content/prezentacni-grafika/1-rocnik/06-retus.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: pg-1-retus -nazev: Retuš -popis: Klonovací razítko a opravný štětec na vlastní vrstvě. -nazev_cviceni: Kvíz: retuš -nadpis_kvizu: Vyberte nástroj a vrstvu ---- - -# Výklad - -## Dva nástroje -*Razítko a štětec* - -- Klonovací razítko kopíruje konkrétní místo. Nejdřív Alt+klik do zdroje, pak malujete cíl. -- Opravný štětec bere texturu z okolí sám. Hodí se na pupínek, prach a malou skvrnu. -- Razítko berte tam, kde musí sedět vzor: plot, spára, textura zdi. -- Na velkou plochu oblohy je často rychlejší výběr a výplň než hodina razítka. - -> Tip: Alt+klik není obyčejný klik. Bez zdroje razítko neví, odkud brát. - -## Vrstva retus -*Nesahejte na fotku* - -- Nad fotku přidejte prázdnou vrstvu retus. -- Ve volbách razítka i štětce zapněte Vzorkovat všechny vrstvy, jinak prázdná vrstva nemá co kopírovat. -- Retuš pak jde ztlumit krytím nebo vypnout okem. Fotka vespod zůstane. -- Když se vzor opakuje jako razítko, vezměte zdroj z jiného místa. Jedna cihla pětkrát je vidět. - -> Tip: Tvrdost štětce kolem 50 % a krytí 100 %. Měkké razítko na hraně předmětu rozmaže obrys. - -## Co retušovat -*Míra* - -- Pryč patří prach, datum z fotoaparátu, koš v záběru a drát, který tam nemá být. -- Nepatří pryč pihy, jizva ani rys, který dělá člověka. To už není oprava, ale jiná tvář. -- Datum vypálené v rohu je pixel, ne vrstva. Musí se přemalovat z okolí oblohy nebo zdi. -- Po retuši se podívejte na 100 %. Opakovaný vzor a šmouha jsou vidět zblízka. - -> Tip: Jedna školní fotka, tři konkrétní chyby. Celou kůži nepřemalovávejte. - -## Zadání: tři chyby -*Cvičení* - -- Najděte na fotce tři rušivé věci: třeba koš, drát a datum, nebo tři skvrny. -- Odstraňte je na vrstvě retus. Razítko i štětec vzorkují všechny vrstvy. -- Vrstvu fotka nezamykejte malbou. Po vypnutí retus musí být chyby zpátky. -- Uložte retus.psd a do názvů si poznamenejte, který nástroj byl na které chybě. - -> Tip: Když po vypnutí vrstvy retus obraz vypadá stejně, malovali jste do fotky. Vezměte to z historie zpět. - -# Kvíz - -## Jak se u klonovacího razítka určí zdroj? -- Ctrl+J -- [x] Alt+klik do místa, které se má kopírovat -- Exportem -- Krytím 70 % -> Alt+klik vezme zdroj. Další tahy ho kopírují do cíle. - -## Kam se retuš maluje? -- Přímo do vrstvy fotky -- [x] Na prázdnou vrstvu nad fotkou -- Do textové vrstvy -- Do JPG -> Vlastní vrstva jde vypnout. Fotka zůstane původní. - -## Který nástroj si bere texturu z okolí sám? -- [x] Opravný štětec -- Text -- Ořez na 1920 px -- Pero -> Štětec dopočítá okolí. Razítko kopíruje přesně to místo, které jste označili. - -## Co musí být zapnuté, když razítko maluje do prázdné vrstvy? -- CMYK -- [x] Vzorkovat všechny vrstvy -- Spadávka 3 mm -- 25 sn/s -> Bez vzorkování všech vrstev je zdroj prázdný a razítko nemá co kopírovat. diff --git a/content/prezentacni-grafika/1-rocnik/07-text-a-barvy.en.md b/content/prezentacni-grafika/1-rocnik/07-text-a-barvy.en.md deleted file mode 100644 index eb99105..0000000 --- a/content/prezentacni-grafika/1-rocnik/07-text-a-barvy.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Type and colour -popis: A headline, the eyedropper and the foreground colour. -nazev_cviceni: Quiz: type and colour -nadpis_kvizu: Name the colour shortcuts ---- diff --git a/content/prezentacni-grafika/1-rocnik/07-text-a-barvy.md b/content/prezentacni-grafika/1-rocnik/07-text-a-barvy.md deleted file mode 100644 index 9abe13c..0000000 --- a/content/prezentacni-grafika/1-rocnik/07-text-a-barvy.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: pg-1-text-a-barvy -nazev: Text a barvy -popis: Nápis, kapátko a barva popředí. -nazev_cviceni: Kvíz: text a barvy -nadpis_kvizu: Poznejte zkratky barev ---- - -# Výklad - -## Barva popředí -*Kapátko* - -- Levý horní čtvereček je barva popředí, pravý dolní je pozadí. -- D vrátí černou a bílou. X je prohodí. -- Kapátko je I. Klik do fotky vezme barvu, která už v obraze je. -- Barvu nadpisu berte z fotky, ne náhodnou jedovatou zelenou, která se s ní pere. - -> Tip: Na světlé nebe patří tmavý text, na tmavý kabát světlý. Stejná šedá na obojí zanikne. - -## Nástroj text -*Písmo* - -- Jedno kliknutí založí bodový text. Tažení myší založí odstavcový rámeček. -- Nadpis školní práce je bodový text. Delší odstavec patří do rámečku. -- Velikost nadpisu na plátně 1920 px je kolem 72 pt. Podnadpis kolem 28 pt. -- Písmo nechte jedno, nejvýš dvě. Třetí řez plakát rozbije. - -> Tip: Textová vrstva se jmenuje podle nápisu. Nepřevádějte ji na pixely, dokud nemusíte. V PSD ať jde text přepsat. - -## Čitelnost -*Kontrast* - -- Když text sedí na rušné fotce, dejte pod něj poloprůhledný pruh, ne jen stín. -- Stín textu: vzdálenost malá, třeba 4 px, rozmazání 8 px, krytí kolem 40 %. -- Bílý text na světlé obloze nečetete ani vy. Ztmavte místo pod ním, nebo změňte barvu písma. -- Zarovnání na střed jen u krátkého nadpisu. Dlouhý text nechte vlevo. - -> Tip: Styl vrstvy je fx dole v panelu Vrstvy. Stín pak jde vypnout, písmo zůstane. - -## Zadání: nápis z fotky -*Cvičení* - -- Kapátkem I vezměte světlou barvu z fotky a nadpis Školní den napište barvou, která je k ní kontrastní. -- Podnadpis se jménem autora dejte na 28 pt. -- Pod text dejte pruh s krytím 70 %, ať nápis drží i na světlém místě. -- Uložte napis.psd. Text nechte jako textovou vrstvu, nerasterizujte ho. - -> Tip: X prohodí barvy, když kapátko vezme pravou. D vás vrátí na černou a bílou, když se ztratíte. - -# Kvíz - -## Co udělá klávesa D? -- Smaže vrstvu -- [x] Vrátí výchozí černou a bílou -- Spustí export -- Založí masku -> D je default. X potom černou a bílou prohodí. - -## Čím se nabere barva z fotky? -- Klonovacím razítkem -- [x] Kapátkem, klávesa I -- Ořezem -- Ctrl+0 -> Kapátko uloží barvu pixelu do popředí. Nadpis pak ladí s fotkou. - -## Jak velký má být podnadpis na plátně 1920 px? -- 4 pt -- [x] kolem 28 pt -- 300 pt -- 2480 pt -> Nadpis je velký, kolem 72 pt. Podnadpis je menší, kolem 28 pt, ať je vidět hierarchie. - -## Proč se text hned nerasterizuje? -- PSD by nešel uložit -- [x] V pracovním souboru má jít nápis přepsat -- Raster je vektor -- Premiere ho jinak nepřečte -> Z pixelů text už neopravíte. Na pixely ho převádějte až v kopii, když musíte. diff --git a/content/prezentacni-grafika/1-rocnik/08-zadani-fotografie.en.md b/content/prezentacni-grafika/1-rocnik/08-zadani-fotografie.en.md deleted file mode 100644 index f4da788..0000000 --- a/content/prezentacni-grafika/1-rocnik/08-zadani-fotografie.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Assignment: edit a photograph -popis: One photo, retouch, a selection, type and two exports. -nazev_cviceni: Quiz: the photograph -nadpis_kvizu: Check the finished piece ---- diff --git a/content/prezentacni-grafika/1-rocnik/08-zadani-fotografie.md b/content/prezentacni-grafika/1-rocnik/08-zadani-fotografie.md deleted file mode 100644 index f330581..0000000 --- a/content/prezentacni-grafika/1-rocnik/08-zadani-fotografie.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: pg-1-zadani-fotografie -nazev: Zadání: úprava fotografie -popis: Jedna fotka, retuš, výběr, nápis a dva výstupy. -nazev_cviceni: Kvíz: úprava fotografie -nadpis_kvizu: Zkontrolujte hotovou práci ---- - -# Výklad - -## Co se odevzdává -*Rozsah* - -- Jedna fotka školní akce nebo místa, ořez na 1920 × 1080 px, RGB, 72 ppi. -- Pracovní soubor fotografie.psd a plochá kopie fotografie.jpg v kvalitě 10. -- Na plátně je nápis Školní den a pod ním vaše jméno. -- JPG nesmí být jediný soubor. Bez PSD nejde práce opravit. - -> Tip: Ořez udělá nástroj Ořez. Poměr stran zadejte 16 : 9, ať z fotky nezbude čtverec omylem. - -## Vrstvy, které musí být -*Skladba* - -- Dole fotka. Nad ní retus s aspoň jednou odstraněnou věcí, vzorkuje všechny vrstvy. -- Osoba nebo hlavní předmět je vybraný a leží na vlastní vrstvě, prolnutí okraje 2 px. -- Pozadí jde ztmavit samostatně. Po vypnutí této úpravy je pozadí zpět světlé. -- Skupina popisek drží pruh s krytím 70 % a oba texty. Texty nejsou rasterizované. - -> Tip: Pět vteřin kontroly: vypínejte skupiny okem. Každá musí něco změnit a po zapnutí to vrátit. - -## Nápis -*Čitelnost* - -- Barva nadpisu je z kapátka nebo k němu kontrastní. Na světlém místě nesmí zmizet. -- Podnadpis má asi 28 pt. Nadpis je výrazně větší. -- Pruh pod textem nelpí na horní hraně, sedí ve spodní třetině. -- Žádný text není oříznutý hranou plátna. Nechte od okraje aspoň 48 px. - -> Tip: 48 px je bezpečný okraj i na telefonu, když se JPG někde ořízne na krajích. - -## Kontrola před odevzdáním -*Seznam* - -- Obraz je 1920 × 1080 px. Větší export zmenšete, menší nezvětšujte rozmazáním. -- Retuš na 100 % nemá opakovaný vzor ani šmouhu přes obličej. -- V JPG nejsou vrstvy, v PSD jsou. Oba soubory se jmenují fotografie, liší se příponou. -- Původní fotku nemažte. Když ořez přetáhnete, musí být z čeho začít znovu. - -> Tip: Soubor > Exportovat jako ukáže rozměr. Když tam není 1920 × 1080, ořez ještě nesedí. - -# Kvíz - -## Jaký má být výsledný rozměr? -- 2480 × 3508 px -- [x] 1920 × 1080 px -- A4 při 300 ppi -- 80 × 80 px -> Zadání je obrazovka, Full HD, 16 : 9. A4 při 300 ppi by bylo do tisku. - -## Kde smí ležet retuš? -- Jen v JPG -- [x] Na vlastní vrstvě nad fotkou -- V rasterizovaném textu -- V dokumentu CMYK -> Vrstva retus jde vypnout. JPG je až plochá kopie na odevzdání. - -## Jaké krytí má pruh pod nápisem? -- 10 % -- [x] 70 % -- 300 % -- Pruh se nedělá -> 70 % podrží text a ještě nechá tušit fotku. Plný pruh ji zakryje celou. - -## Co se odevzdává? -- Jen JPG -- [x] PSD i JPG -- Jen SVG -- Projekt Premiere -> PSD je práce s vrstvami. JPG je náhled, který otevře i člověk bez Photoshopu. diff --git a/content/prezentacni-grafika/2-rocnik/01-masky.en.md b/content/prezentacni-grafika/2-rocnik/01-masky.en.md deleted file mode 100644 index a1ed65d..0000000 --- a/content/prezentacni-grafika/2-rocnik/01-masky.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Masks -popis: A mask hides, it does not delete. Black conceals, white reveals. -nazev_cviceni: Quiz: masks -nadpis_kvizu: Read the mask ---- diff --git a/content/prezentacni-grafika/2-rocnik/01-masky.md b/content/prezentacni-grafika/2-rocnik/01-masky.md deleted file mode 100644 index 8d02198..0000000 --- a/content/prezentacni-grafika/2-rocnik/01-masky.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: pg-2-masky -nazev: Masky -popis: Maska skrývá, nemaže. Černá kryje, bílá ukazuje. -nazev_cviceni: Kvíz: masky -nadpis_kvizu: Přečtěte masku ---- - -# Výklad - -## K čemu maska je -*Nedestruktivně* - -- Smazaný pixel je pryč. Maska ho jen schová a jde přemalovat zpátky. -- Každá vrstva může mít jednu masku. Bílá plocha masky obraz ukazuje, černá ho kryje. -- Šedá je poloprůhledná. 50 % šedá nechá vrstvu napůl vidět. -- Masku přidáte ikonou obdélníku s kolečkem dole v panelu Vrstvy. - -> Tip: Když mažete gumou, nemáte cestu zpět. Když malujete do masky černou, stačí přetřít bílou. - -## Malování do masky -*Štětec* - -- Klik na miniaturu masky, ne na miniaturu obrazu. Jinak malujete do fotky. -- Alt+klik na masku ji ukáže přes celé plátno. Černobílý obraz je jen maska, ne výsledek. -- Měkký štětec, tvrdost 0 %, krytí 30 %, černá barva. Okraj předmětu pak není vystřižený nůžkami. -- X prohodí černou a bílou, takže stejný štětec umí skrýt i vrátit. - -> Tip: Kolem miniatury masky je rámeček, když je aktivní. Rámeček kolem fotky znamená, že malujete špatně. - -## Výběr a maska -*Spolu* - -- Výběr postavy a pak ikona masky schová všechno mimo výběr. -- Prolnutí 2 px udělejte ještě ve výběru, nebo okraj domalujte měkkým štětcem. -- Maska není nová vrstva. V panelu sedí vpravo vedle miniatury. -- Masku neslučujte s vrstvou, dokud učitel neřekne. Sloučení už nejde odmaskovat. - -> Tip: Ctrl+I na masce, když je vybraná, černou a bílou otočí. Hodí se, když jste skryli opak. - -## Zadání: výřez maskou -*Cvičení* - -- Postavu oddělte maskou, ne gumou. Původní fotka po Alt+klik a přemalování bílou musí být celá. -- Okraj dopracujte štětcem tvrdost 0 % a krytí 30 %. -- Pozadí nechte ve vrstvě pod ní, ať jde vyměnit. -- Uložte maska.psd. V souboru nesmí být jen jedna sloučená vrstva. - -> Tip: Vypněte a zapněte masku Shiftem a klikem na ni. Obraz se musí vrátit celý. - -# Kvíz - -## Co dělá černá barva v masce? -- Vrstvu ukáže -- [x] Vrstvu skryje -- Převede ji na text -- Zvýší rozlišení na 300 ppi -> Černá kryje, bílá ukazuje, šedá je mezi tím. - -## Čím se maska zobrazí přes celé plátno? -- Ctrl+1 -- [x] Alt+klik na miniaturu masky -- Exportem JPG -- Klávesou D na textu -> Alt+klik ukáže černobílou masku. Další Alt+klik vrátí normální obraz. - -## Proč se výřez nedělá gumou? -- Guma je v Illustratoru -- [x] Smazané pixely už nevrátíte, masku ano -- Guma umí jen CMYK -- Premiere gumu nepustí -> Masku přemalujete. Guma na obyčejné vrstvě pixely zahodí. - -## Jaké krytí štětce se hodí na jemný okraj masky? -- 100 % tvrdý štětec -- [x] 30 % a tvrdost 0 % -- Krytí textu 28 pt -- 10 Mb/s -> Nízké krytí a měkký štětec skládají hranu postupně. Tvrdý tah je vidět jako střih. diff --git a/content/prezentacni-grafika/2-rocnik/02-urovne-a-krivky.en.md b/content/prezentacni-grafika/2-rocnik/02-urovne-a-krivky.en.md deleted file mode 100644 index 0ae3082..0000000 --- a/content/prezentacni-grafika/2-rocnik/02-urovne-a-krivky.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Levels and curves -popis: Brightness and contrast as an adjustment layer, not a rewrite of the pixels. -nazev_cviceni: Quiz: curves -nadpis_kvizu: Recognise a non-destructive edit ---- diff --git a/content/prezentacni-grafika/2-rocnik/02-urovne-a-krivky.md b/content/prezentacni-grafika/2-rocnik/02-urovne-a-krivky.md deleted file mode 100644 index cc53a24..0000000 --- a/content/prezentacni-grafika/2-rocnik/02-urovne-a-krivky.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: pg-2-krivky -nazev: Úrovně a křivky -popis: Světlost a kontrast jako vrstva úprav, ne jako přepis pixelů. -nazev_cviceni: Kvíz: křivky -nadpis_kvizu: Poznejte nedestruktivní úpravu ---- - -# Výklad - -## Vrstva úprav -*Nad pixely* - -- Vrstva úprav mění vzhled všeho pod sebou a pixely fotky nepřepisuje. -- Přidá se kolečkem dole v panelu Vrstvy. Položka Křivky nebo Úrovně. -- Když úpravu vypnete okem, fotka je jako na začátku. -- Úprava přímo přes Obraz > Přizpůsobení fotku přepíše. Ve školní práci ji neberte. - -> Tip: Vrstva úprav má vlastní masku. Černou v masce úpravu na části obrazu vypnete. - -## Úrovně -*Tři body* - -- Černý bod říká, co má být nejtmavší. Bílý bod, co má být nejsvětlejší. -- Šedý bod srovná nádech. Klik do místa, které má být neutrální šedé. -- Bod světel nechte kolem 245, ne na 255, ať v obloze nezmizí kresba. -- Bod stínů kolem 15, ne na 0, ať černá není slitá. - -> Tip: Když histogram na obou koncích nic nemá, fotka je mdlá. Body přitáhněte k místu, kde data začínají. - -## Křivka S -*Kontrast* - -- Křivka zdola zleva nahoru doprava je světlost od stínů ke světlům. -- Jemná křivka do S zvedne kontrast: stíny o trochu níž, světla o trochu výš. -- Ostré S přepálí tváře a zabije stíny. Stačí malý oblouk. -- Jedna vrstva Křivky na celou fotku. Druhou přidejte jen na oblohu, a maskou ji tam omezte. - -> Tip: Na křivce táhněte málo. Oko si na přepálený náhled rychle zvykne a původní fotka pak vypadá špatně, i když byla lepší. - -## Zadání: dvě úpravy -*Cvičení* - -- Nad fotku dejte vrstvu úprav Křivky. Bod stínů nechte u 15, bod světel u 245, mezi tím jemné S. -- Druhou křivku omezte maskou jen na pozadí, ať tvář nejde do přepalu. -- Obě úpravy pojmenujte. Fotka vespod ať nemá žádné Přizpůsobení zapékané v pixelech. -- Uložte krivky.psd. Vypnutí obou úprav vrátí původní světlost. - -> Tip: Alt při tahu černého a bílého bodu v Úrovních ukáže, které místo už je slité. U křivek stačí oko a 100 %. - -# Kvíz - -## Kam patří školní zesvětlení fotky? -- Obraz > Přizpůsobení, přímo do pixelů -- [x] Vrstva úprav nad fotkou -- Do textové vrstvy -- Do exportu JPG jako jediná úprava -> Vrstva úprav jde vypnout. Přizpůsobení přes nabídku Obraz pixely přepíše. - -## Kam dát bod světel, aby obloha neztratila kresbu? -- 0 -- [x] kolem 245 -- 255 a přes -- 28 pt -> 255 je čistá bílá bez kresby. 245 nechá ve světlech detail. - -## Co dělá jemná křivka ve tvaru S? -- Sníží rozlišení -- [x] Zvedne kontrast -- Převede RGB na vektor -- Přidá spadávku -> Stíny jdou trochu níž a světla trochu výš. Kontrast stoupne, barva se nemění v jiný režim. - -## Čím se křivka omezí jen na pozadí? -- Gumou na fotce -- [x] Maskou vrstvy úprav -- Exportem -- Krytím textu -> Černá v masce úpravy řekne: tady křivku nepoužívej. Tvář může zůstat bílá, tedy upravená jinou vrstvou, nebo naopak. diff --git a/content/prezentacni-grafika/2-rocnik/03-chytre-objekty-a-filtry.en.md b/content/prezentacni-grafika/2-rocnik/03-chytre-objekty-a-filtry.en.md deleted file mode 100644 index 5811b67..0000000 --- a/content/prezentacni-grafika/2-rocnik/03-chytre-objekty-a-filtry.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Smart objects and filters -popis: Blur and sharpening you can still change. -nazev_cviceni: Quiz: filters -nadpis_kvizu: Fill in the filter values ---- diff --git a/content/prezentacni-grafika/2-rocnik/03-chytre-objekty-a-filtry.md b/content/prezentacni-grafika/2-rocnik/03-chytre-objekty-a-filtry.md deleted file mode 100644 index 78c29d2..0000000 --- a/content/prezentacni-grafika/2-rocnik/03-chytre-objekty-a-filtry.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: pg-2-chytre-objekty -nazev: Chytré objekty a filtry -popis: Rozostření a doostření, které jde změnit. -nazev_cviceni: Kvíz: filtry -nadpis_kvizu: Doplňte hodnoty filtru ---- - -# Výklad - -## Chytrý objekt -*Obal* - -- Vrstva > Chytré objekty > Převést na chytrý objekt zabalí vrstvu do obalu. -- Filtr na chytrém objektu zůstane jako položka pod vrstvou. Dvojklik ho otevře znovu. -- Filtr na obyčejné vrstvě pixely přepíše. Ve školním plakátu ho neberte. -- Logo z Illustratoru vkládejte rovnou jako chytrý objekt, ať jde zvětšit. - -> Tip: V rohu miniatury chytrého objektu je malá ikona. Když tam není, filtr se zapíše natvrdo. - -## Rozostření pozadí -*Hloubka* - -- Gaussovské rozostření oddělí pozadí od předmětu. Na pozadí stačí 8 px. -- Předmět rozostřením nechte být. Buď je na vrstvě nad ním, nebo má masku. -- Silnější rozostření, třeba 30 px, už pozadí smaže. Berte ho jen jako záměr. -- Rozostření celého obrazu včetně tváře je chyba, ne hloubka ostrosti. - -> Tip: Nejdřív výřez maskou z minulé lekce, potom rozostření jen vrstvy pozadí. - -## Doostření -*Unsharp* - -- Filtr Doostření (Unsharp Mask) zvedne kontrast na hraně. Není to zvětšení pixelů. -- Školní hodnoty na fotku: množství 80 %, poloměr 1 px, práh 2. -- Vyšší množství dělá světlý a tmavý obrys kolem větví a vlasů. -- Doostřujte až nakonec a jen jednou. Doostřené doostření je vidět. - -> Tip: Náhled filtru přepínejte, ať vidíte rozdíl. Na 100 %, ne na zmenšeném plátně. - -## Zadání: hloubka a hrana -*Cvičení* - -- Pozadí převeďte na chytrý objekt a dejte mu Gaussovské rozostření 8 px. -- Předmět nechte ostrý. Maska nebo samostatná vrstva ho chrání. -- Na předmět dejte Doostření 80 %, poloměr 1 px, práh 2, taky jako filtr chytrého objektu. -- Uložte filtry.psd. Oba filtry musí jít otevřít dvojklikem a hodnoty změnit. - -> Tip: Když dvojklik filtr neotevře, vrstva nebyla chytrý objekt. Vezměte krok z historie a převeďte ji znovu. - -# Kvíz - -## Jaké rozostření má školní pozadí? -- [x] 8 px Gaussovské -- 80 px na celou fotku včetně tváře -- 0 px -- Rozostření se dělá v Premiere -> 8 px pozadí oddělí a ještě ho nechá poznat. Celý obraz včetně předmětu se nerozostřuje. - -## Jaké hodnoty má školní Doostření? -- [x] množství 80 %, poloměr 1 px, práh 2 -- množství 300 %, poloměr 20 px -- jen krytí 70 % -- 300 ppi -> Malý poloměr drží hranu. Velký poloměr kreslí kolem předmětů svatozář. - -## Proč filtr patří na chytrý objekt? -- Jinak nejde uložit PSD -- [x] Hodnoty jdou potom změnit a pixely se nepřepíšou -- Chytrý objekt je vždy CMYK -- Kvůli 25 sn/s -> Pod vrstvou zůstane řádek filtru. Dvojklik ho otevře se stejnými čísly. - -## Co Doostření ve skutečnosti dělá? -- Dopočítá nové pixely jako při zvětšení -- [x] Zvedne kontrast na hraně -- Převede fotku na křivky -- Přidá masku -> Unsharp Mask není zvětšení. Měkkou fotku z malého souboru nezachrání, jen zdůrazní hranu. diff --git a/content/prezentacni-grafika/2-rocnik/04-tvary-a-styly.en.md b/content/prezentacni-grafika/2-rocnik/04-tvary-a-styly.en.md deleted file mode 100644 index 82e7d6e..0000000 --- a/content/prezentacni-grafika/2-rocnik/04-tvary-a-styly.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Shapes and layer styles -popis: A vector bar, a shadow and a stroke inside Photoshop. -nazev_cviceni: Quiz: shapes -nadpis_kvizu: Fill in the bar and the shadow ---- diff --git a/content/prezentacni-grafika/2-rocnik/04-tvary-a-styly.md b/content/prezentacni-grafika/2-rocnik/04-tvary-a-styly.md deleted file mode 100644 index fba437e..0000000 --- a/content/prezentacni-grafika/2-rocnik/04-tvary-a-styly.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: pg-2-tvary -nazev: Tvary a styly vrstvy -popis: Vektorový pruh, stín a tah přímo ve Photoshopu. -nazev_cviceni: Kvíz: tvary -nadpis_kvizu: Doplňte rozměr pruhu a stínu ---- - -# Výklad - -## Tvar -*Vektor ve Photoshopu* - -- Nástroj obdélník a elipsa kreslí tvarovou vrstvu. Není to namalovaný pixel. -- Tvar jde zvětšit a hrana zůstane hladká, podobně jako v Illustratoru. -- Barvu změníte dvojklikem na miniaturu. Nemalujte přes tvar štětcem. -- Na fotku 1920 × 1080 patří spodní pruh 1920 × 280 px, od kraje ke kraji. - -> Tip: Když podržíte Shift, elipsa je kružnice a obdélník čtverec. - -## Styl vrstvy -*fx* - -- fx dole v panelu přidá stín, tah nebo přechod. Písmo ani tvar se nerasterizuje. -- Stín školního pruhu: vzdálenost 8 px, velikost 16 px, krytí 40 %. -- Tah 2 px berte jen na tlačítko nebo rámeček. Na velký pruh je zbytečný. -- Styl zkopírujete Alt+tažením řádku fx na jinou vrstvu. - -> Tip: Krytí ve stínu není krytí celé vrstvy. Pruh může být plný a stín lehký. - -## Pruh a text -*Spolu* - -- Pruh je jedna vrstva, text druhá. Neslučujte je. -- Pruh má krytí 75 %, ať fotka pod ním nezmizí celá. -- Text je bílý, když je pruh tmavý. Sedí aspoň 48 px od levého okraje pruhu. -- Skupina spodni drží pruh i text. Vypnutí skupiny je sundá najednou. - -> Tip: Zarovnání textu k pruhu: vyberte obě vrstvy a v nástroji přesun použijte ikony zarovnání. - -## Zadání: spodní pruh -*Cvičení* - -- Na plátně 1920 × 1080 nakreslete tvar 1920 × 280 px, krytí vrstvy 75 %. -- Stín: vzdálenost 8, velikost 16, krytí stínu 40 %. -- Bílý nadpis a podnadpis 28 pt jsou ve skupině s pruhem, 48 px od levého kraje. -- Uložte pruh.psd. Tvar nesmí být rasterizovaný. - -> Tip: V panelu Vrstvy je u tvaru ikona, ne jen malba. Když chybí, kreslili jste štětcem. - -# Kvíz - -## Jak velký je spodní pruh na Full HD? -- 280 × 280 px -- [x] 1920 × 280 px -- 2480 × 3508 px -- A4 -> Šířka plátna je 1920. Výška pruhu 280 nechá fotce horní část. - -## Jaké krytí má vrstva pruhu? -- [x] 75 % -- 10 % -- 100 % a navíc CMYK -- Krytí se nenastavuje -> 75 % pruh podrží text a fotku pod ním ještě tušíte. - -## Jaký stín má školní pruh? -- [x] vzdálenost 8, velikost 16, krytí 40 % -- vzdálenost 80, velikost 80, krytí 100 % -- žádný, stín nejde u tvaru -- jen filtr 8 px na fotku -> Malý stín pruh odlepí od fotky. Velký stín přes celou fotku je špína, ne styl. - -## Proč se tvar nespojuje s textem do jedné vrstvy? -- Photoshop to neumí oddělit -- [x] Text by nešel přepsat a pruh přebarvit zvlášť -- Kvůli 25 sn/s -- JPG umí vrstvy líp -> Každá věc vlastní vrstvu. Sloučení nechte až na plochý export. diff --git a/content/prezentacni-grafika/2-rocnik/05-kompozice-plakatu.en.md b/content/prezentacni-grafika/2-rocnik/05-kompozice-plakatu.en.md deleted file mode 100644 index 41ced0b..0000000 --- a/content/prezentacni-grafika/2-rocnik/05-kompozice-plakatu.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Poster composition -popis: A3, a 3 mm bleed and one main headline. -nazev_cviceni: Quiz: the poster -nadpis_kvizu: Pick the size and the bleed ---- diff --git a/content/prezentacni-grafika/2-rocnik/05-kompozice-plakatu.md b/content/prezentacni-grafika/2-rocnik/05-kompozice-plakatu.md deleted file mode 100644 index a52cbb3..0000000 --- a/content/prezentacni-grafika/2-rocnik/05-kompozice-plakatu.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: pg-2-kompozice -nazev: Kompozice plakátu -popis: A3, spadávka 3 mm a jeden hlavní nápis. -nazev_cviceni: Kvíz: plakát -nadpis_kvizu: Vyberte formát a spadávku ---- - -# Výklad - -## Formát a spadávka -*A3* - -- Školní plakát je A3 na výšku, 297 × 420 mm, 300 ppi, RGB. -- Tiskárna ořízne papír na čistý A3. Barva, která má jít do kraje, musí přesahovat. -- Spadávka je 3 mm na každé straně. Plátno tedy má 303 × 426 mm. -- Vodítka dejte 3 mm od okraje. Dovnitř vodítek patří text, ven až k okraji plátna smí jen pozadí. - -> Tip: 303 mm je 297 plus 3 a 3. Když je plátno jen 297, spadávka tam není. - -## Jeden plakát, jedna věc -*Hierarchie* - -- Největší je název akce. Pod ním datum a místo, menším písmem. -- Datum školního zadání je 12. 6. Místo je tělocvična. -- Hlavní prvek, třeba postava, sedí na třetině, ne uprostřed jako pasové foto. -- Dva stejně velké nadpisy se perou. Jeden musí vyhrát. - -> Tip: Třetiny: dvě svislé a dvě vodorovné čáry dělí plochu na devět polí. Průsečík je silné místo. - -## Okraj textu -*Klid* - -- Text je aspoň 10 mm od čistého ořezu, tedy dál než vodítko spadávky. -- Řádek delší než dvě třetiny šířky se čte špatně. Nadpis zalomte. -- Písmo nejvýš dvě. Jedno tučné na název, jedno obyčejné na údaj. -- Logo školy je malé a v rohu. Není to druhý plakát. - -> Tip: Když logo nemáte ve vektoru, berte největší PNG, které škola má, a zmenšete ho. Ne naopak. - -## Zadání: kostra plakátu -*Cvičení* - -- Nový dokument 303 × 426 mm, 300 ppi, RGB. Vodítka 3 mm od každého kraje. -- Fotku dejte přes celou spadávku. Pruh a text až za vodítka. -- Název akce, pod ním 12. 6. a tělocvična. Název je výrazně větší. -- Uložte plakat-kostra.psd. Čistý formát A3 ať jde poznat podle vodítek. - -> Tip: Zobrazení > Pravítka a táhněte vodítko z pravítka. Přichytávání k němu zapněte v menu Zobrazení. - -# Kvíz - -## Jak velké je plátno plakátu se spadávkou 3 mm? -- 297 × 420 mm -- [x] 303 × 426 mm -- 1920 × 1080 px -- 210 × 297 mm -> A3 je 297 × 420. Z každé strany 3 mm navíc dělá 303 × 426. - -## Kam nesmí text? -- [x] Do spadávky a blízko ořezu -- Za vodítko, dovnitř čistého formátu -- Pod název -- Na vlastní vrstvu -> Ořez spadávku uřízne. Text 10 mm od čistého kraje přežije i křivý řez. - -## Kam se má strefit hlavní prvek? -- Přesně na střed jako na občanku -- [x] Na třetinu plochy -- Do razítka -- Mimo plátno -> Střed je klidný a často nudný. Průsečík třetin drží oko. - -## Jaké rozlišení má tiskový plakát? -- 72 ppi -- [x] 300 ppi -- 25 sn/s -- 8 px -> Plakát je tisk. 300 ppi. 72 ppi by na A3 bylo vidět jako mřížka. diff --git a/content/prezentacni-grafika/2-rocnik/06-mockup.en.md b/content/prezentacni-grafika/2-rocnik/06-mockup.en.md deleted file mode 100644 index 538410f..0000000 --- a/content/prezentacni-grafika/2-rocnik/06-mockup.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: A mockup -popis: The poster design placed on a photograph of a wall. -nazev_cviceni: Quiz: the mockup -nadpis_kvizu: Pick the blend mode and the opacity ---- diff --git a/content/prezentacni-grafika/2-rocnik/06-mockup.md b/content/prezentacni-grafika/2-rocnik/06-mockup.md deleted file mode 100644 index bc41379..0000000 --- a/content/prezentacni-grafika/2-rocnik/06-mockup.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: pg-2-mockup -nazev: Mockup -popis: Návrh plakátu usazený na fotografii zdi. -nazev_cviceni: Kvíz: mockup -nadpis_kvizu: Vyberte režim a krytí ---- - -# Výklad - -## K čemu mockup je -*Náhled* - -- Mockup ukáže návrh v situaci: plakát na zdi, vizitka na stole, tričko na postavě. -- Není to náhrada tiskového PDF. Je to obrázek pro prezentaci práce. -- Fotka zdi má být velká aspoň jako výstup, ideálně 1920 px na delší straně. -- Návrh plakátu vložte jako chytrý objekt, ať ho jde ještě opravit. - -> Tip: Obraz > Umístit vložené, nebo přetáhněte PSD a potvrďte. Vznikne chytrý objekt. - -## Perspektiva -*Deformace* - -- Úpravy > Transformovat > Pokřivit, nebo Deformace, srovná rohy plakátu s rohy na zdi. -- Rohy táhněte na fotografii, ne od oka do prázdna. -- Shift při tažení rohu není vždy správně. Zeď má úběžník, plakát na ní není obdélník v pohledu. -- Po potvrzení transformace chytrý objekt deformaci podrží. - -> Tip: Když je zeď focená z boku, horní hrana plakátu je kratší než dolní, nebo naopak. To má mockup ukázat. - -## Potisk -*Násobit* - -- Režim prolnutí Násobit (Multiply) nechá prosvítit strukturu zdi. -- Krytí návrhu dejte 90 %. 100 % vypadá jako nalepená samolepka bez papíru. -- Bílá v režimu Násobit zmizí. Na bílý plakát se Násobit nehodí, nechte Normální a lehce snižte krytí. -- Stín pod plakátem: měkký, malý, na vlastní vrstvě, ať odlepí papír od zdi. - -> Tip: Násobit násobí barvy. Tmavé místa zůstanou tmavá, bílá se ztratí. - -## Zadání: plakát na zdi -*Cvičení* - -- Vezměte kostru plakátu a usaďte ji na fotku zdi jako chytrý objekt. -- Deformací srovnejte čtyři rohy. Krytí 90 %. -- Když plakát není bílý, zkuste Násobit. Když zbělá, vraťte Normální. -- Uložte mockup.psd na 1920 px delší strany, RGB. Tiskové PDF z toho nedělejte. - -> Tip: Mockup je obrazovka, 72 ppi stačí. Tiskové rozměry zůstávají v plakat-kostra.psd. - -# Kvíz - -## K čemu je mockup? -- Je to tiskové PDF pro tiskárnu -- [x] Ukáže návrh na fotografii místa -- Nahradí vrstvy v PSD -- Je to střih videa -> Tiskárna dostane PDF v ořezu. Mockup je na obhajobu a na web. - -## Jak se návrh srovná se zdí, která je focená z boku? -- Ořezem na čtverec -- [x] Deformací rohů -- Filtrem Doostření -- Převodem do CMYK -> Pokřivení nebo deformace vezme každý roh zvlášť. Obyčejné zmenšení úhel zdi neopraví. - -## Kdy dává smysl režim Násobit? -- [x] Když má prosvítit struktura zdi a plakát není bílý -- Vždy, i na bílý plakát -- Jen u textu 28 pt -- Jen v Premiere -> Násobit nechá tmavou strukturu a bílou zruší. Bílý plakát by zmizel. - -## Jaké krytí má návrh na zdi? -- [x] 90 % -- 10 % -- 100 % bez výjimky -- 300 % -> 90 % lehce spojí papír se zdí. 100 % často vypadá jako nalepený obdélník. diff --git a/content/prezentacni-grafika/2-rocnik/07-export-web-a-tisk.en.md b/content/prezentacni-grafika/2-rocnik/07-export-web-a-tisk.en.md deleted file mode 100644 index 1619e68..0000000 --- a/content/prezentacni-grafika/2-rocnik/07-export-web-a-tisk.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Export for screen and print -popis: JPG and PNG for the screen, a PDF with crop marks for the printer. -nazev_cviceni: Quiz: export -nadpis_kvizu: Match the format to the job ---- diff --git a/content/prezentacni-grafika/2-rocnik/07-export-web-a-tisk.md b/content/prezentacni-grafika/2-rocnik/07-export-web-a-tisk.md deleted file mode 100644 index 593d41c..0000000 --- a/content/prezentacni-grafika/2-rocnik/07-export-web-a-tisk.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: pg-2-export -nazev: Export pro web a tisk -popis: JPG a PNG na obrazovku, PDF s ořezem do tiskárny. -nazev_cviceni: Kvíz: export -nadpis_kvizu: Přiřaďte formát k použití ---- - -# Výklad - -## Tři výstupy -*Formát* - -- JPG je fotka bez průhlednosti. Kvalita 10, tedy kolem 80 %, na web. -- PNG drží průhlednost. Berte ho na logo a ikonu, ne na velkou fotku. -- PDF je pro tiskárnu. Vrstvy v něm být nemusí, musí sedět rozměr a ořez. -- PSD není výstup. PSD je pracovní soubor a odevzdává se k němu. - -> Tip: GIF na fotku neberte. Umí málo barev a školní plakát v něm pruhuje. - -## Web -*sRGB* - -- Delší strana webového JPG je 1600 px. Větší soubor na stránku školy netřeba. -- Barvy převeďte do sRGB, ať je telefon i projektor čtou stejně. -- Do webového JPG nedávejte spadávku ani ořezové značky. Ty jsou pro tiskárnu. -- Náhled pojmenujte plakat-web.jpg. Jméno Bez názvu-1.jpg se ve složce ztratí. - -> Tip: Úpravy > Převést do profilu, cíl sRGB. Obrazovkový JPG pak není v tajném profilu tiskárny. - -## Tisk -*Značky* - -- PDF plakátu je v rozměru se spadávkou, 303 × 426 mm, 300 ppi. -- Ořezové značky ukážou, kudy vede čistý A3. Ve Photoshopu je přidáte při exportu PDF, nebo je nakreslíte do spadávky, ne do textu. -- Do PDF nepatří vodítka a názvy vrstev. Patří do něj plochý obraz. -- Písmo, které tiskárna nemá, do PDF vloží export. V Photoshopu je text stejně často už vykreslený v obraze, to tiskárně nevadí. - -> Tip: Soubor > Uložit kopii a formát Photoshop PDF. Zaškrtněte, že se nemá ptát na vrstvy, ať je PDF ploché. - -## Zadání: dva výstupy z jednoho PSD -*Cvičení* - -- Z plakátu udělejte plakat-web.jpg, delší strana 1600 px, sRGB, kvalita 10, bez značek. -- Z téhož PSD udělejte plakat-tisk.pdf, 303 × 426 mm, 300 ppi, s ořezovými značkami. -- PSD plakat.psd si nechte s vrstvami. Do PDF vrstvy nedávejte. -- Obě kopie otevřete a zkontrolujte: JPG nemá značky, PDF nemá oříznutý text. - -> Tip: Když je JPG větší než 1600 px, obraz jste zmenšili špatně. Obraz > Velikost obrazu, přepočet Automaticky. - -# Kvíz - -## Který formát drží průhledné logo? -- JPG -- [x] PNG -- MP4 -- WAV -> JPG průhlednost vyplní bílou nebo černou. PNG ji umí. - -## Jak široký je webový náhled plakátu? -- [x] 1600 px na delší straně -- 303 mm -- 80 px -- Full HD a zároveň 300 ppi -> 1600 px stačí na obrazovku. Tiskové milimetry do JPG nepatří. - -## Co musí mít tiskové PDF plakátu? -- [x] Rozměr se spadávkou a ořezové značky -- Vrstvy Photoshopu a vodítka -- 25 sn/s -- Průhledné pozadí jako PNG -> Tiskárna řeže podle značek. Vrstvy a vodítka jsou věc PSD, ne PDF. - -## Který soubor je pracovní a nejde nahradit exportem? -- JPG -- [x] PSD -- PDF -- PNG -> Z PSD uděláte JPG i PDF znovu. Z JPG vrstvy neobnovíte. diff --git a/content/prezentacni-grafika/2-rocnik/08-zadani-plakat.en.md b/content/prezentacni-grafika/2-rocnik/08-zadani-plakat.en.md deleted file mode 100644 index 6f7f064..0000000 --- a/content/prezentacni-grafika/2-rocnik/08-zadani-plakat.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Assignment: a poster -popis: A3 with bleed, a mask, curves and two exports. -nazev_cviceni: Quiz: the finished poster -nadpis_kvizu: Check the print file and the web file ---- diff --git a/content/prezentacni-grafika/2-rocnik/08-zadani-plakat.md b/content/prezentacni-grafika/2-rocnik/08-zadani-plakat.md deleted file mode 100644 index 994b6d0..0000000 --- a/content/prezentacni-grafika/2-rocnik/08-zadani-plakat.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: pg-2-zadani-plakat -nazev: Zadání: plakát -popis: A3 se spadávkou, maskou, křivkami a dvěma exporty. -nazev_cviceni: Kvíz: hotový plakát -nadpis_kvizu: Zkontrolujte tisk i web ---- - -# Výklad - -## Zadání akce -*Obsah* - -- Plakát zve na školní den 12. 6. v tělocvičně. Název si zvolte jeden a držte ho. -- Formát A3 na výšku, plátno 303 × 426 mm, 300 ppi, RGB, spadávka 3 mm. -- Na plakátu je fotka, jeden hlavní nápis, datum, místo a malé logo nebo značka školy. -- Text je aspoň 10 mm od čistého ořezu. Ve spadávce smí být jen pozadí. - -> Tip: Jeden plakát, jedna akce. Nepřidávejte druhé datum a druhý sál. - -## Jak je složený -*Vrstvy* - -- Skupina foto: fotka, maska předmětu, křivky jako vrstva úprav, pozadí rozostřené 8 px. -- Skupina grafika: tvarový pruh 75 % a případný další tvar. Stín pruhu 8 / 16 / 40 %. -- Skupina text: název a údaje, pořád jako text, ne jako pixely. -- Vypnutí kterékoli skupiny musí být vidět. Když ne, je skupina prázdná nebo je všechno sloučené. - -> Tip: Křivka má bod světel kolem 245 a stínů kolem 15. Doostření předmětu 80 %, 1 px, práh 2. - -## Dva výstupy -*Soubory* - -- plakat.psd s vrstvami. -- plakat-web.jpg, delší strana 1600 px, sRGB, kvalita 10, bez ořezových značek. -- plakat-tisk.pdf, 303 × 426 mm, ořezové značky, bez vrstev. -- Mockup na zdi je navíc, ne místo PDF. Když ho přidáte, je to mockup.psd. - -> Tip: Soubory leží v jedné složce plakat. Název Bez názvu v odevzdání neberte. - -## Kontrola -*Než to odevzdáte* - -- Na 100 % nemá retuš opakovaný vzor a maska nemá barevný lem. -- Datum 12. 6. je celé a čitelné. Logo není rozmazaný JPG zvětšený z 80 px. -- Webový JPG otevřený na celou obrazovku nemá značky ani šedé okraje plátna. -- PDF má stejný název akce jako PSD. Dvě verze textu jsou chyba. - -> Tip: Vytiskněte si PDF na A4 jako náhled. Když je text u kraje už na A4, na A3 bude u řezu taky. - -# Kvíz - -## Jaké je plátno tiskového plakátu? -- 1920 × 1080 px, 72 ppi -- [x] 303 × 426 mm, 300 ppi -- A4 bez spadávky -- 1600 px -> A3 je 297 × 420, spadávka 3 mm z každé strany přidá 6 mm. 300 ppi je tisk. - -## Jak je rozostřené pozadí? -- [x] 8 px, předmět zůstane ostrý -- 8 px přes celý plakát včetně textu -- 80 % Doostření na pozadí -- Nijak -> Rozostření oddělí pozadí. Text a hlavní předmět jsou ostré. - -## Co je ve webovém JPG navíc chyba? -- sRGB a 1600 px -- [x] Ořezové značky -- Kvalita kolem 10 -- Název akce -> Značky jsou pro tiskárnu. Na webu vypadají jako čáry v rozích. - -## Který soubor musí obsahovat vrstvy? -- plakat-web.jpg -- [x] plakat.psd -- plakat-tisk.pdf -- Žádný -> PSD je práce. JPG a PDF jsou ploché kopie. diff --git a/content/prezentacni-grafika/3-rocnik/01-projekt-a-media.en.md b/content/prezentacni-grafika/3-rocnik/01-projekt-a-media.en.md deleted file mode 100644 index 2474ba9..0000000 --- a/content/prezentacni-grafika/3-rocnik/01-projekt-a-media.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Project and media -popis: A Full HD sequence, 25 fps and bins for the media. -nazev_cviceni: Quiz: the project -nadpis_kvizu: Set up the right sequence ---- diff --git a/content/prezentacni-grafika/3-rocnik/01-projekt-a-media.md b/content/prezentacni-grafika/3-rocnik/01-projekt-a-media.md deleted file mode 100644 index 791315e..0000000 --- a/content/prezentacni-grafika/3-rocnik/01-projekt-a-media.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: pg-3-projekt -nazev: Projekt a média -popis: Sekvence Full HD, 25 sn/s a složky materiálu. -nazev_cviceni: Kvíz: projekt -nadpis_kvizu: Založte správnou sekvenci ---- - -# Výklad - -## Projekt -*Soubor* - -- Premiere ukládá práci do projektu s příponou prproj. Video v něm není, jsou v něm odkazy. -- Materiál a projekt mějte v jedné složce. Když video přesunete, Premiere ho nenajde. -- Ztracený soubor se připojí znovu: pravý klik, Propojit médium, a ukážete novou cestu. -- Automatické ukládání nechte zapnuté. Projekt se jinak po pádu nevrátí celý. - -> Tip: prproj není mp4. Otevře ho jen Premiere. Na odevzdání videa je až export. - -## Sekvence -*25 sn/s* - -- Sekvence je časová osa s daným rozměrem a snímkovou frekvencí. -- Školní zadání: 1920 × 1080, čtvercové pixely, 25 snímků za sekundu. -- 25 sn/s je běžné evropské video. Materiál z telefonu má často 30. Sekvenci přesto založte na 25, Premiere snímky přepočítá. -- Pojmenujte ji skolni-den. Název Sekvence 01 se ve větším projektu ztratí. - -> Tip: Nová sekvence je v panelu Projekt ikonou nového objektu. Předvolba DSLR nebo Digital SLR 1080p25 se trefí. - -## Složky -*Pořádek* - -- V panelu Projekt založte složky Záběry, Zvuk a Grafika. -- Import je Ctrl+I, nebo soubor přetáhnete do správné složky. -- Do Grafiky patří logo a titulky. Do Zvuku hudba a komentář. Do Záběrů jen video. -- Na časovou osu netáhněte deset záběrů najednou, dokud ve složce nemají pořádek. - -> Tip: Přejmenujte záběry podle místa, ne podle DSC_1842. Za rok nepoznáte, co to bylo. - -## Zadání: prázdný projekt -*Cvičení* - -- Založte skolni-den.prproj ve složce, kde už leží záběry. -- Sekvence skolni-den: 1920 × 1080, 25 sn/s. -- Tři složky: Zabery, Zvuk, Grafika. Importujte aspoň jeden záběr a jednu hudbu do správných složek. -- Projekt uložte. Mp4 ještě nedělejte. - -> Tip: Když Premiere hlásí, že sekvence nesedí se záběrem, nechte sekvenci na 25. Je to zadání, ne chyba souboru. - -# Kvíz - -## Jakou příponu má projekt Premiere? -- mp4 -- [x] prproj -- psd -- svg -> prproj je projekt. mp4 vznikne až exportem. - -## Jaká je školní sekvence? -- 1280 × 720, 60 sn/s -- [x] 1920 × 1080, 25 sn/s -- 303 × 426 mm -- A4, 300 ppi -> Full HD a 25 snímků za sekundu. Milimetry patří plakátu, ne videu. - -## Kam v projektu patří hudba? -- Do složky Záběry -- [x] Do složky Zvuk -- Přímo do názvu sekvence -- Do PSD -> Záběry, Zvuk a Grafika se nemíchají. Jinak desátý soubor už nenajdete. - -## Co uděláte, když Premiere po přesunu složky video nevidí? -- Natočíte ho znovu -- [x] Propojíte médium a ukážete novou cestu -- Převedete projekt do JPG -- Změníte sekvenci na 72 ppi -> Projekt si pamatuje cestu. Propojit médium ji opraví, záběr se netočil znovu. diff --git a/content/prezentacni-grafika/3-rocnik/02-casova-osa-a-strih.en.md b/content/prezentacni-grafika/3-rocnik/02-casova-osa-a-strih.en.md deleted file mode 100644 index 5a9e1e6..0000000 --- a/content/prezentacni-grafika/3-rocnik/02-casova-osa-a-strih.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: The timeline and the cut -popis: Cuts with no gaps, 45 seconds long. -nazev_cviceni: Quiz: the cut -nadpis_kvizu: Pick the tool and the length ---- diff --git a/content/prezentacni-grafika/3-rocnik/02-casova-osa-a-strih.md b/content/prezentacni-grafika/3-rocnik/02-casova-osa-a-strih.md deleted file mode 100644 index 5a047a2..0000000 --- a/content/prezentacni-grafika/3-rocnik/02-casova-osa-a-strih.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: pg-3-strih -nazev: Časová osa a střih -popis: Střih záběrů bez mezer, délka 45 sekund. -nazev_cviceni: Kvíz: střih -nadpis_kvizu: Vyberte nástroj a délku ---- - -# Výklad - -## Stopy -*Obraz a zvuk* - -- V1 je první obrazová stopa, A1 první zvuková. Vyšší V leží vizuálně nad nižší. -- Záběr z kamery přinese obraz i zvuk. Na ose jsou spojené, dokud je nerozdělíte. -- Titulek patří na V2, ať nepřepíše záběr na V1. Sundáte ho a obraz pod ním zůstane. -- Mezera na ose je černé pole ve filmu. Mezi záběry být nemá. - -> Tip: Když přetáhnete jen obraz, držte Alt. Zvuk zůstane na místě, nebo se naopak nevezme. - -## Nástroje -*Žiletka* - -- V je výběr. C je žiletka, rozřízne záběr v místě přehrávací hlavy. -- I označí začátek, O konec. Čárka vloží výběr a zbytek odsunete. Tečka výběr přepíše. -- Delete smaže a nechá díru. Shift+Delete, nebo vyjmutí s uzavřením mezery, díru zatáhne. -- Mezerník přehrává. Šipky vlevo a vpravo jedou po střihu. - -> Tip: Po žiletce přepněte zpět na V. Jinak další klik zase řeže. - -## Co nechat -*45 sekund* - -- Ze surového záznamu nechte to, co nese větu nebo děj. Rozjezd a konec kamery pryč. -- Školní sestřih tohoto cvičení má 45 sekund. Kratší nestihne nic říct, delší se rozpadá. -- Střih je na pohybu nebo na začátku věty, ne uprostřed slova. -- Stejný záběr dvakrát po sobě nechte jen schválně. Jinak to vypadá jako chyba. - -> Tip: Délku sekvence čtete vpravo dole nebo na konci posledního záběru. 00:00:45:00 je 45 sekund. - -## Zadání: sestřih -*Cvičení* - -- Na ose skolni-den sestříhejte 45 sekund. Začátek je 00:00:00:00, konec 00:00:45:00. -- Mezi záběry není mezera. Černý snímek uprostřed je chyba. -- Aspoň čtyři různé záběry. Žádný kratší než jedna sekunda. -- Uložte projekt. Export až v pozdější lekci. - -> Tip: Když je konec 00:00:45:10, máte o 10 snímků navíc. U 25 sn/s je to necelá půlsekunda, zkraťte to. - -# Kvíz - -## Čím se záběr rozřízne? -- Nástrojem V -- [x] Žiletkou, klávesa C -- Exportem H.264 -- Krytím 70 % -> C je žiletka. V je výběr, tím se záběr posouvá, neřeže. - -## Jak dlouhý je sestřih v této lekci? -- [x] 45 sekund -- 8 sekund -- 4 minuty -- 303 mm -> 00:00:45:00. Titulky a export přijdou později, teď je čistý střih. - -## Co je chyba uprostřed sestřihu? -- Střih na začátku věty -- [x] Černá mezera mezi záběry -- Záběr delší než sekunda -- Stopa V1 -> Díra na ose je ve filmu černá. Po smazání ji zatáhněte. - -## Kam patří titulek, aby šel sundat bez ztráty záběru? -- Místo obrazu na V1 -- [x] Na stopu V2 nad záběrem -- Do složky Zvuk -- Do PSD plakátu -> V2 leží nad V1. Vypnete ho a záběr pod ním pokračuje. diff --git a/content/prezentacni-grafika/3-rocnik/03-tempo-a-prechody.en.md b/content/prezentacni-grafika/3-rocnik/03-tempo-a-prechody.en.md deleted file mode 100644 index c124f37..0000000 --- a/content/prezentacni-grafika/3-rocnik/03-tempo-a-prechody.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Pace and transitions -popis: A hard cut as the default, one short dissolve. -nazev_cviceni: Quiz: transitions -nadpis_kvizu: Choose the length of the dissolve ---- diff --git a/content/prezentacni-grafika/3-rocnik/03-tempo-a-prechody.md b/content/prezentacni-grafika/3-rocnik/03-tempo-a-prechody.md deleted file mode 100644 index 132fc8e..0000000 --- a/content/prezentacni-grafika/3-rocnik/03-tempo-a-prechody.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: pg-3-prechody -nazev: Tempo a přechody -popis: Tvrdý střih jako základ, jedna krátká prolínačka. -nazev_cviceni: Kvíz: přechody -nadpis_kvizu: Zvolte délku prolínačky ---- - -# Výklad - -## Střih stačí -*Přechod* - -- Obyčejný střih je nejčistší. Přechod mezi každými dvěma záběry film zpomalí a vypadá jako šablona. -- Prolínačku berte na změnu času nebo na vstup titulku, ne na každý řez. -- Stírání, hvězdičky a stránkování ve školním dokumentu nemají co dělat. -- Jeden typ přechodu v celém videu. Druhý je už výstřednost. - -> Tip: Přechod přetáhnete z panelu Účinky mezi dva záběry. Dvojklik otevře délku. - -## Délka -*12 snímků* - -- Při 25 sn/s je sekunda 25 snímků. Půl sekundy je zhruba 12 snímků. -- Školní prolínačka má 12 snímků. Delší než sekunda už je nálada, ne střih. -- Přechod potřebuje materiál za řezem. Když záběr končí přesně na řezu, Premiere ho nemá čím prolnout a konec zmrazí. -- Proto neřežte záběr úplně na doraz, když víte, že na něj přijde prolínačka. - -> Tip: 12 snímků je 00:00:00:12. V časovém kódu jsou snímky až za poslední dvojtečkou. - -## Rychlost -*Polovina* - -- Pravý klik na záběr, Rychlost a trvání. 50 % ho přehraje poloviční rychlostí a dvakrát prodlouží. -- 100 % je normální tempo. 200 % je dvojnásobná rychlost a poloviční délka. -- Zpomalení použijte na jeden záběr, který má být čtený: vstup do dveří, pohled, detail. -- Zvuk zpomalený na 50 % je bručivý. U zpomaleného záběru ho oddělte a nechte původní, nebo ho ztichte. - -> Tip: Když má zůstat délka a změnit se jen tempo, hlídejte zaškrtnutí, které drží nebo nedrží délku záběru. - -## Zadání: jeden přechod, jedno tempo -*Cvičení* - -- V 45sekundovém sestřihu nechte tvrdé střihy. -- Jednu prolínačku dejte jen před titulek nebo mezi dvě místa. Délka 12 snímků. -- Jeden záběr zpomalte na 50 % a jeho zvuk nechte v původní rychlosti, nebo ho vypněte. -- Délka celku ať zůstane čitelná. Když se sekvence protáhne, zkraťte jiný záběr. - -> Tip: Přehrávání od prolínačky: mezerník. Když obraz na vteřinu zmrzne, záběru chybí přesah. - -# Kvíz - -## Jak dlouhá je školní prolínačka? -- [x] 12 snímků -- 12 sekund -- 4 minuty -- 3 mm -> 12 snímků při 25 sn/s je necelá půlsekunda. 12 sekund by bylo uspávací. - -## Kolik prolínaček má být v tomto cvičení? -- Mezi všemi záběry -- [x] Jedna -- Žádná nikdy, ani před titulkem -- Deset různých typů -> Základ je tvrdý střih. Jedna prolínačka má důvod, deset je šablona. - -## Co udělá rychlost 50 %? -- Záběr zrychlí na dvojnásobek -- [x] Přehrá ho poloviční rychlostí a prodlouží -- Ořízne ho na 50 px -- Převede ho do CMYK -> 50 % je polovina tempa. 200 % je dvojnásobná rychlost. - -## Proč prolínačka na konci záběru někdy zmrazí obraz? -- Sekvence je v PNG -- [x] Za řezem už není materiál, kterým by šla prolnout -- Chybí spadávka -- Hudba je moc potichu -> Přechod potřebuje snímky za střihem. Doraz na posledním snímku je nemá. diff --git a/content/prezentacni-grafika/3-rocnik/04-titulky.en.md b/content/prezentacni-grafika/3-rocnik/04-titulky.en.md deleted file mode 100644 index 0393aa0..0000000 --- a/content/prezentacni-grafika/3-rocnik/04-titulky.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Titles -popis: An opening and a closing, four seconds each. -nazev_cviceni: Quiz: titles -nadpis_kvizu: Fill in the time and the size ---- diff --git a/content/prezentacni-grafika/3-rocnik/04-titulky.md b/content/prezentacni-grafika/3-rocnik/04-titulky.md deleted file mode 100644 index 88bceec..0000000 --- a/content/prezentacni-grafika/3-rocnik/04-titulky.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: pg-3-titulky -nazev: Titulky -popis: Úvod a závěr, každé po čtyřech sekundách. -nazev_cviceni: Kvíz: titulky -nadpis_kvizu: Doplňte čas a velikost ---- - -# Výklad - -## Kde se píšou -*Grafika* - -- Titulek je vrstva na ose, ne text vypálený do záběru ve Photoshopu. -- Panel Základní grafika, nebo nástroj text nad obrazem v programu, založí textovou vrstvu. -- Úvodní titulek leží na začátku na V2. Závěrečný na konci. -- Písmo nechte jedno. Bílé na tmavém podkladu, nebo tmavé na světlém pruhu. - -> Tip: Když text píšete do záběru razítkem, už ho nepřepíšete. Vrstva textu jde opravit kdykoli. - -## Velikost a čas -*4 sekundy* - -- Nadpis Školní den má kolem 72 pt. Jméno autora kolem 36 pt. -- Každý titulek trvá 4 sekundy. Kratší nestačí přečíst, delší drží obraz zbytečně. -- 4 sekundy při 25 sn/s jsou 100 snímků. -- Mezi úvodním titulkem a prvním záběrem může být prolínačka 12 snímků z minulé lekce. - -> Tip: Délku textové vrstvy táhnete za konec na ose jako záběr. Číslo 00:00:04:00 je přesně čtyři sekundy. - -## Bezpečný okraj -*Nepřeříznout* - -- Text nepatří až k hraně obrazu. Od kraje nechte aspoň 80 px. -- Televize a některé přehrávače kraj oříznou. Co je 40 px od hrany, může zmizet. -- Dlouhý název rozdělte na dva řádky. Jeden řádek přes celou šířku je malý, nebo přeteče. -- Zarovnání na střed jen u titulku. U seznamu jmen nechte zarovnání vlevo. - -> Tip: V nastavení náhledu se dá zapnout bezpečná oblast. Vnitřní rámeček je pro text. - -## Zadání: úvod a závěr -*Cvičení* - -- Na začátek dejte 4 sekundy titulku Školní den, kolem 72 pt, aspoň 80 px od kraje. -- Na konec 4 sekundy se jménem autora, kolem 36 pt. -- Oba texty jsou na V2 a jdou přepsat. Nejsou vypálené v záběru. -- Projekt uložte. Délka sekvence teď smí být delší než 45 sekund o těchto 8 sekund. - -> Tip: Když titulek leží na V1 místo záběru, přesuňte ho na V2. Záběr pod ním ať pokračuje, nebo ať je pod úvodem prázdná plocha schválně. - -# Kvíz - -## Jak dlouho trvá úvodní titulek? -- [x] 4 sekundy -- 12 snímků -- 45 sekund -- 1 snímek -> Čtyři sekundy se dají přečíst. 12 snímků je délka prolínačky, ne titulku. - -## Jak velké je zhruba jméno autora? -- 8 pt -- [x] kolem 36 pt -- 300 pt -- 1600 px -> Nadpis je kolem 72 pt, jméno menší, kolem 36. Pořád čitelné na telefonu. - -## Jak daleko od kraje má text být? -- Až v posledních 10 px -- [x] Aspoň 80 px -- Ve spadávce 3 mm -- To je jedno, video se neořezává -> Kraj obrazu přehrávač někdy seřízne. 80 px text udrží uvnitř. - -## Na které stopě má titulek ležet? -- A1 -- [x] V2 -- Jen v JPG plakátu -- Místo zvuku -> V2 je nad obrazem. Titulek jde sundat a záběr zůstane. diff --git a/content/prezentacni-grafika/3-rocnik/05-zvuk.en.md b/content/prezentacni-grafika/3-rocnik/05-zvuk.en.md deleted file mode 100644 index 2bbc076..0000000 --- a/content/prezentacni-grafika/3-rocnik/05-zvuk.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Sound -popis: Speech, music under it and a one-second fade. -nazev_cviceni: Quiz: sound -nadpis_kvizu: Set the levels ---- diff --git a/content/prezentacni-grafika/3-rocnik/05-zvuk.md b/content/prezentacni-grafika/3-rocnik/05-zvuk.md deleted file mode 100644 index a1779e7..0000000 --- a/content/prezentacni-grafika/3-rocnik/05-zvuk.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: pg-3-zvuk -nazev: Zvuk -popis: Řeč, hudba pod ní a jedna sekunda náběhu. -nazev_cviceni: Kvíz: zvuk -nadpis_kvizu: Nastavte hladiny ---- - -# Výklad - -## Dvě hladiny -*Řeč a hudba* - -- Řeč je hlavní. Na ukazateli ať se drží kolem −6 dB a do červené nuly nelezete. -- Hudba sama o sobě kolem −15 dB. Pod řečí ji stáhněte ještě na −24 dB. -- Dva stejně hlasité zdroje se přebijí. Divák pak neslyší ani jeden pořádně. -- Ztlumení je klíčový snímek hlasitosti na klipu, ne jednou provždy na celou píseň, pokud pod ní jen občas mluvíte. - -> Tip: Pravý klik na zvukový klip a zobrazení klíčových snímků hlasitosti. Přidáte je perem na čáře. - -## Náběh -*1 sekunda* - -- Hudba nemá nastoupit v plné hlasitosti na prvním snímku. Náběh 1 sekundu. -- Konec hudby stejně tak: jednu sekundu do ticha, ať video neuskakuje. -- Náběh je taky klíčový snímek, z ticha na cílovou hladinu. -- Střih hudby uprostřed taktu je slyšet. Řežte v pauze nebo na začátku fráze. - -> Tip: 1 sekunda je 25 snímků. Na ose je to krátký úsek, ne celý titulek. - -## Střih zvuku napřed -*J-cut* - -- J-cut znamená, že zvuk dalšího záběru začne dřív než jeho obraz. -- Nejdřív je slyšet věta, až pak se obraz přepne na mluvčího. Střih je měkčí než tvrdý řez obou stop. -- Obraz a zvuk jednoho klipu rozdělíte pravým klikem, Zrušit propojení, a zvuk přetáhnete doleva. -- Ve školním videu stačí jeden takový střih. Nemusí být všude. - -> Tip: Když zvuk předběhne obraz o víc než půl sekundy, už to působí jako chyba synchronu. Držte se kolem 10 až 15 snímků. - -## Zadání: hudba pod řečí -*Cvičení* - -- Hudbu dejte pod sestřih. Mimo řeč kolem −15 dB, pod řečí −24 dB. -- Náběh i doběh hudby 1 sekunda. -- Řeč srovnejte kolem −6 dB. Červená nula na ukazateli je chyba. -- Jeden přechod mezi záběry udělejte jako J-cut: zvuk o kousek dřív než obraz. - -> Tip: Sluchátka odhalí hukot, reproduktor v učebně ho schová. Poslechněte si to jednou na sluchátkách. - -# Kvíz - -## Kde má být hudba, když zrovna někdo mluví? -- [x] Kolem −24 dB -- Na nule -- Vypnutá natrvalo i v místech bez řeči -- Hlasitější než řeč -> Řeč je kolem −6 dB. Hudba pod ní musí ustoupit, školní hladina je −24 dB. - -## Jak dlouhý je náběh hudby? -- [x] 1 sekunda -- 12 sekund -- 4 minuty -- Náběh se nedělá -> Jedna sekunda z ticha. Nástup v plné hlasitosti na prvním snímku je skok. - -## Co je J-cut? -- Obraz dalšího záběru začne dřív než jeho zvuk -- [x] Zvuk dalšího záběru začne dřív než jeho obraz -- Střih uprostřed slova -- Přechod hvězdičkou -> Nejdřív je slyšet, až pak je vidět. Opačné pořadí je L-cut. - -## Kam nesmí ukazatel řeči? -- K −6 dB -- [x] Do červené nuly -- Na stopu A1 -- Pod hudbu -> Nula je přebuzení. Řeč se drží pod ní, kolem −6 dB. diff --git a/content/prezentacni-grafika/3-rocnik/06-barva-ve-videu.en.md b/content/prezentacni-grafika/3-rocnik/06-barva-ve-videu.en.md deleted file mode 100644 index 59224c3..0000000 --- a/content/prezentacni-grafika/3-rocnik/06-barva-ve-videu.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Colour in video -popis: Exposure first, then contrast, saturation last. -nazev_cviceni: Quiz: video colour -nadpis_kvizu: Put the steps in order ---- diff --git a/content/prezentacni-grafika/3-rocnik/06-barva-ve-videu.md b/content/prezentacni-grafika/3-rocnik/06-barva-ve-videu.md deleted file mode 100644 index c6f8264..0000000 --- a/content/prezentacni-grafika/3-rocnik/06-barva-ve-videu.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: pg-3-barva -nazev: Barva ve videu -popis: Nejdřív expozice, potom kontrast, sytost až nakonec. -nazev_cviceni: Kvíz: barva videa -nadpis_kvizu: Seřaďte postup ---- - -# Výklad - -## Lumetri -*Jeden panel* - -- Barva záběru se dělá efektem Lumetri Color, ne exportem přes Photoshop. -- Efekt dejte na záběr, nebo na úpravu vrstvy nad stopou, ať se dá vypnout. -- Nejdřív srovnejte expozici, ať není záběr tmavý nebo přepálený. -- Pak kontrast, nakonec sytost. Sytá tmavá fotka se špatně zachraňuje. - -> Tip: Panel Barva Lumetri otevřete z nabídky Okno. Když efekt jen přetáhnete a panel zavřete, hodnoty stejně zůstanou na klipu. - -## Dva záběry vedle sebe -*Srovnat* - -- Střih mezi teplým a studeným záběrem je vidět víc než samotná barva. -- Druhý záběr přiblížte prvnímu: podobné stíny, podobná pleť. -- Pleť nenechte oranžovou. Když je sytost vysoko, uberte ji dřív, než přidáte teplou barvu. -- Jeden záběr smí být černobílý schválně. Sytost 0. Ostatní nechte barevné. - -> Tip: Oko porovná záběry, když je přehrajete přes střih. Zastavený snímek klame. - -## LUT až potom -*Míra* - -- LUT je hotová tabulka vzhledu. Dá se na záběr jako vzhled, ne jako první krok. -- Intenzitu LUT nechte kolem 50 %, když záběr přebarví moc. -- Dva různé LUT v jednom minutovém videu působí jako dvě školy. Stačí jeden, nebo žádný. -- Bez LUT, jen se srovnanou expozicí, je video často čistší. - -> Tip: LUT na přepálenou oblohu kresbu nevrátí. Nejdřív expozice, tabulka až na srovnaný obraz. - -## Zadání: srovnat a jeden bez barvy -*Cvičení* - -- Dva sousední záběry srovnejte Lumetri: nejdřív expozice, pak kontrast, sytost jen mírně, třeba +10. -- Jeden jiný záběr dejte na sytost 0, ať je černobílý schválně a krátce. -- LUT buď žádný, nebo jeden na intenzitě nejvýš 50 %. -- Efekt ať jde vypnout. Vypnuté Lumetri vrátí původní barvu záběru. - -> Tip: Když vypnutí efektu nic nezmění, upravovali jste jiný klip. Efekt je na tom, který je na ose vybraný. - -# Kvíz - -## V jakém pořadí se barva srovnává? -- Nejdřív sytost, pak třeba expozice -- [x] Nejdřív expozice, pak kontrast, sytost nakonec -- Nejdřív LUT, surový záběr se nechá -- Barva se ve videu nedělá -> Špatně světlý záběr sytost jen zhorší. Nejdřív světlo, potom síla barvy. - -## Jak uděláte jeden záběr černobílý? -- Smažete stopu V1 -- [x] Sytost na 0 -- Exportem do JPG -- Rychlostí 50 % -> Sytost 0 nechá jas a vezme barvu. Ostatní záběry zůstanou barevné. - -## Jak vysoko necháte intenzitu LUT, když barví moc? -- 100 % vždy -- [x] Kolem 50 % -- 0 %, ale LUT stejně všechno přebarví -- 300 % -> LUT je volba vzhledu, ne povinnost. Poloviční intenzita ho podrží na uzdě. - -## Čím se barva na záběru vypne? -- Smazáním projektu -- [x] Vypnutím efektu Lumetri -- Převodem sekvence na 72 ppi -- To nejde, export je trvalý už na ose -> Efekt na klipu jde vypnout. Dokud není video exportované, původní záběr zůstává. diff --git a/content/prezentacni-grafika/3-rocnik/07-export-videa.en.md b/content/prezentacni-grafika/3-rocnik/07-export-videa.en.md deleted file mode 100644 index 9644011..0000000 --- a/content/prezentacni-grafika/3-rocnik/07-export-videa.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Exporting the video -popis: H.264, Full HD, 25 fps and 10 Mb/s. -nazev_cviceni: Quiz: the video export -nadpis_kvizu: Pick the format and the bitrate ---- diff --git a/content/prezentacni-grafika/3-rocnik/07-export-videa.md b/content/prezentacni-grafika/3-rocnik/07-export-videa.md deleted file mode 100644 index 9675ca9..0000000 --- a/content/prezentacni-grafika/3-rocnik/07-export-videa.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: pg-3-export -nazev: Export videa -popis: H.264, Full HD, 25 sn/s a 10 Mb/s. -nazev_cviceni: Kvíz: export videa -nadpis_kvizu: Vyberte formát a datový tok ---- - -# Výklad - -## Formát -*H.264* - -- Odevzdává se MP4 s kodekem H.264. Otevře ho telefon, projektor i Windows. -- Formát projektu prproj nikdo bez Premiere nepustí. Není to výstup. -- Sekvence 1920 × 1080 a 25 sn/s se do exportu přenese. Neměňte ji při exportu na 1280 × 720, pokud to zadání nechce. -- Zvuk nechte v exportu zapnutý. Němý výstup je často jen odškrtnutý zvuk, ne záměr. - -> Tip: Soubor > Export > Média. Zkratka Ctrl+M. Náhled vpravo ukáže první snímek, ne celý střih. - -## Datový tok -*10 Mb/s* - -- Cílový datový tok 10 Mb/s stačí na školní Full HD. Vyšší soubor zbytečně naroste. -- 1 Mb/s už na 1080p kostkuje, hlavně v pohybu. 10 je klidná střední hodnota. -- Nastavení zdroje, nebo shoda se sekvencí, podrží 25 sn/s a rozměr. -- Dva průchody export zpřesní, ale trvá déle. Na školní video stačí jeden. - -> Tip: Mb/s je megabit za sekundu, ne megabajt. Minutové video při 10 Mb/s má zhruba 75 MB. - -## Rozsah -*Celá sekvence* - -- Exportujte celou sekvenci, ne jen výběr mezi body In a Out, pokud jste je nechali uprostřed. -- Zaškrtnutí, které exportuje jen vstup až výstup, umí oříznout film na pět sekund. -- Název souboru skolni-den.mp4. Cesta ať vede do složky projektu, ne na plochu. -- Po exportu soubor pusťte mimo Premiere. V náhledu programu chybu často nevidíte. - -> Tip: Když je film moc krátký, otevřete body In a Out na ose. Ctrl+Shift+X je zruší. - -## Zadání: první mp4 -*Cvičení* - -- Exportujte skolni-den.mp4, H.264, 1920 × 1080, 25 sn/s, cílový tok 10 Mb/s. -- Zvuk je v souboru. Úvodní titulek je hned na začátku, ne po deseti sekundách černé. -- Projekt prproj nechte vedle mp4. Mp4 samo o sobě nejde znovu střihnout po vrstvách. -- Soubor přehrajte celý. Jednou. Zastavte se na titulku, na prolínačce a na konci hudby. - -> Tip: Když přehrávač hlásí, že soubor nejde otevřít, export nedoběhl. V Premiere je fronta, podívejte se, jestli neskončil chybou. - -# Kvíz - -## Který soubor se odevzdává jako video? -- prproj -- [x] mp4 v H.264 -- psd -- svg -> MP4 otevře i člověk bez Premiere. Projekt je zdroj. - -## Jaký datový tok má školní Full HD? -- [x] 10 Mb/s -- 1 Mb/s -- 300 ppi -- 72 Mb/s vždy -> 10 Mb/s je na 1080p25 dost. 1 Mb/s se v pohybu rozpadá. - -## Co zkontrolujete, když je export dlouhý jen pár sekund? -- Spadávku -- [x] Jestli se neexportoval jen úsek mezi In a Out -- Režim CMYK -- Krytí pruhu -> Body In a Out omezí export na výběr. Zrušte je a exportujte celou sekvenci. - -## Proč nestačí odevzdat jen prproj? -- Premiere ho neumí uložit -- [x] Bez Premiere ho nikdo nepřehraje a média mohou chybět -- Nemá 25 sn/s -- Je to totéž co mp4 -> Projekt je odkaz na střih. Film je až mp4. diff --git a/content/prezentacni-grafika/3-rocnik/08-zadani-video.en.md b/content/prezentacni-grafika/3-rocnik/08-zadani-video.en.md deleted file mode 100644 index 4bacdcf..0000000 --- a/content/prezentacni-grafika/3-rocnik/08-zadani-video.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Assignment: a short video -popis: 40 to 60 seconds, titles, sound and one J-cut. -nazev_cviceni: Quiz: the short video -nadpis_kvizu: Check the length and the export ---- diff --git a/content/prezentacni-grafika/3-rocnik/08-zadani-video.md b/content/prezentacni-grafika/3-rocnik/08-zadani-video.md deleted file mode 100644 index f415877..0000000 --- a/content/prezentacni-grafika/3-rocnik/08-zadani-video.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: pg-3-zadani-video -nazev: Zadání: krátké video -popis: 40 až 60 sekund, titulky, zvuk a jeden J-cut. -nazev_cviceni: Kvíz: krátké video -nadpis_kvizu: Zkontrolujte délku a export ---- - -# Výklad - -## Délka a obsah -*40 až 60 s* - -- Hotové video trvá 40 až 60 sekund včetně titulků. -- Téma je školní den: místo, lidé, jedna věta o tom, co se děje. -- Úvodní titulek Školní den trvá 4 sekundy. Závěrečný se jménem taky 4 sekundy. -- Aspoň čtyři záběry. Žádný pod jednu sekundu, kromě případného černobílého detailu. - -> Tip: Délku čtete na konci posledního titulku. Titulky se do limitu počítají. - -## Střih a obraz -*Pravidla* - -- Mezi záběry nejsou černé mezery. Střihy jsou tvrdé. -- Jedna prolínačka, 12 snímků, nejlépe mezi titulkem a záběrem. -- Jeden záběr smí být na 50 % rychlosti. Jeden smí mít sytost 0. -- Barva je srovnaná Lumetri: expozice, kontrast, sytost. Nejvýš jeden LUT na 50 %. - -> Tip: V2 je na titulky. Obrazové záběry ať zůstanou na V1, ať se ve stopách neztratíte. - -## Zvuk -*Hladiny* - -- Řeč kolem −6 dB, bez červené nuly. -- Hudba mimo řeč −15 dB, pod řečí −24 dB. Náběh a doběh 1 sekunda. -- Jeden J-cut: zvuk dalšího záběru začne dřív než obraz. -- Hudba nekončí uprostřed slova ani uprostřed taktu, pokud to jde střihnout jinak. - -> Tip: Poslechněte si export, ne jen osu. Export umí zvuk vynechat, když je odškrtnutý. - -## Odevzdání -*Dva soubory* - -- skolni-den.prproj ve složce s médií, složky Zabery, Zvuk, Grafika. -- skolni-den.mp4, H.264, 1920 × 1080, 25 sn/s, 10 Mb/s. -- Mp4 pusťte od začátku do konce mimo Premiere. -- Když média přesouváte, nejdřív složku celou. Rozbitý odkaz je neodevzdaná práce. - -> Tip: Na začátku mp4 má být titulek, ne černá. Černá znamená, že sekvence začíná později než export. - -# Kvíz - -## Jak dlouhé je hotové video i s titulky? -- Přesně 45 sekund bez titulků -- [x] 40 až 60 sekund -- 8 sekund -- 4 minuty -> Titulky se počítají. Pod 40 sekund téma nestačí, nad minutu se školní sestřih rozpadá. - -## Jak dlouhé jsou oba titulky? -- 12 snímků -- [x] 4 sekundy každý -- 1 sekunda -- Dokud hraje hudba -> Čtyři sekundy na úvod, čtyři na jméno. 12 snímků je prolínačka. - -## Kam patří hudba v okamžiku, kdy mluví člověk? -- [x] −24 dB -- 0 dB -- Stejně nahlas jako řeč -- Hudba se pod řeč nedává nikdy, ani ztišená -> Řeč zůstává kolem −6 dB. Hudba pod ní ustoupí na −24 dB. - -## Jaký je export? -- prproj jako jediný soubor -- [x] mp4, H.264, 1920 × 1080, 25 sn/s, 10 Mb/s -- JPG 1600 px -- PDF se spadávkou -> Film je mp4. Projekt se odevzdává k němu, ne místo něj. diff --git a/content/prezentacni-grafika/4-rocnik/01-illustrator.en.md b/content/prezentacni-grafika/4-rocnik/01-illustrator.en.md deleted file mode 100644 index 29c372b..0000000 --- a/content/prezentacni-grafika/4-rocnik/01-illustrator.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Illustrator: the artboard -popis: Curves, the V, A and P tools, an artboard for the screen. -nazev_cviceni: Quiz: Illustrator -nadpis_kvizu: Name the tool ---- diff --git a/content/prezentacni-grafika/4-rocnik/01-illustrator.md b/content/prezentacni-grafika/4-rocnik/01-illustrator.md deleted file mode 100644 index d6171c5..0000000 --- a/content/prezentacni-grafika/4-rocnik/01-illustrator.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: pg-4-illustrator -nazev: Illustrator: plocha a nástroje -popis: Křivky, nástroje V, A a P, plátno pro obrazovku. -nazev_cviceni: Kvíz: Illustrator -nadpis_kvizu: Poznejte nástroj ---- - -# Výklad - -## Proč Illustrator -*Křivka* - -- Illustrator kreslí křivky. Logo z něj vytisknete na vizitku i na banner a hrana zůstane hladká. -- Photoshopové logo z malého PNG sem nepatří. Vektor se tu staví znovu, nebo se otevře SVG a AI. -- Soubor je AI. Na výměnu s jiným programem se hodí i SVG a PDF. -- Na fotku Illustrator není. Fotka sem patří jen jako podklad, který pak skryjete. - -> Tip: Když v náhledu na 800 % uvidíte pixely, není to křivka. Je to vložená bitmapa. - -## Tři nástroje -*V, A, P* - -- V je výběr. Posouvá a mění celý objekt. -- A je přímý výběr. Táhne jeden kotevní bod, zbytek tvaru nechá. -- P je pero. Klik klade body, tah klade křivku. Pero je hlavní kreslicí nástroj. -- Na první cvičení pero nepotřebujete celé. Obdélník a elipsa stačí. - -> Tip: Na Macu jsou zkratky stejné. Přepínají se jednou klávesou, bez Cmd. - -## Plátno -*1920 × 1080* - -- Nový dokument pro obrazovku: 1920 × 1080 px, RGB, jeden artboard. -- Pro tisk se později založí milimetrový artboard. Teď je to obrazovka, ať sedí s Premiere a Photoshopem. -- Artboard není vrstva. Je to papír. Objekty mimo něj se neexportují, ale v souboru jsou. -- Bílé pozadí artboardu není objekt. Když chcete barvu v pozadí, nakreslete obdélník. - -> Tip: Více artboardů přijde u loga ve variantách. Zatím jeden. - -## Zadání: dva tvary -*Cvičení* - -- Dokument znacka-podklad.ai, 1920 × 1080 px, RGB. -- Nakreslete jeden obdélník a jednu elipsu. Každý ať má výplň a žádný tah, nebo tah 2 pt schválně. -- Elipsu vyberte nástrojem A a vytáhněte jeden kotevní bod, ať není pravidelná. -- Uložte AI. Do JPG to zatím nepřevádějte. - -> Tip: Výplň a tah jsou dole v panelu nástrojů. Prázdná výplň, červený přeškrtnutý čtverec, objekt neukáže, dokud nemá tah. - -# Kvíz - -## Co dělá nástroj A? -- Posouvá celý objekt -- [x] Táhne jeden kotevní bod -- Píše text ve Photoshopu -- Stříhá video -> A je přímý výběr bodu. V posouvá celý tvar. - -## Který nástroj kreslí křivku po bodech? -- V -- [x] P, pero -- C v Premiere -- Kapátko I -> Pero je P. Žiletka C patří do Premiere, sem ne. - -## Jak velký je školní dokument pro obrazovku? -- [x] 1920 × 1080 px, RGB -- A4, CMYK, 300 ppi jako jediná možnost -- 303 × 426 mm hned -- 80 × 80 px -> Obrazovka je Full HD a RGB. Tiskový artboard přijde, až bude značka na papír. - -## Kdy v náhledu poznáte vloženou bitmapu? -- Na 800 % zůstane hrana hladká -- [x] Na 800 % se objeví pixely -- Soubor má příponu AI, takže pixely nemá nikdy -- Podle stopy V2 -> Křivka se nezvětší do čtverečků. Bitmapa ano. diff --git a/content/prezentacni-grafika/4-rocnik/02-logo.en.md b/content/prezentacni-grafika/4-rocnik/02-logo.en.md deleted file mode 100644 index 2a00d3a..0000000 --- a/content/prezentacni-grafika/4-rocnik/02-logo.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Curves and a logo -popis: A mark made of three shapes, a full version and one colour. -nazev_cviceni: Quiz: the logo -nadpis_kvizu: Check the versions and the export ---- diff --git a/content/prezentacni-grafika/4-rocnik/02-logo.md b/content/prezentacni-grafika/4-rocnik/02-logo.md deleted file mode 100644 index 31c6033..0000000 --- a/content/prezentacni-grafika/4-rocnik/02-logo.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: pg-4-logo -nazev: Křivky a logo -popis: Značka ze tří tvarů, plná verze a jedna barva. -nazev_cviceni: Kvíz: logo -nadpis_kvizu: Zkontrolujte verze a export ---- - -# Výklad - -## Málo bodů -*Čistá křivka* - -- Logo je jednoduché. Tři tvary stačí: třeba kniha, paprsek a kruh. -- Každý tvar ať má co nejmíň kotevních bodů. Deset bodů na kružnici je zbytečných, elipsa je jeden objekt. -- Tah převeďte na obrys, až když má být tloušťka součástí tvaru. Do té doby ať je tah tahem a jde změnit. -- Text názvu školy nechte jako text, dokud nemáte vybrané písmo. Pak ho můžete převést na křivky. - -> Tip: Objekt > Cesta > Obrysy tahu, nebo Písmo > Vytvořit obrysy. Až v kopii. Původní text ať jde přepsat. - -## Dvě verze -*Plná a jedna barva* - -- Plná verze má barvy školy, nejvýš dvě plus bílou nebo černou. -- Jednobarevná verze je celá černá. Hodí se do razítka, do raznice a na světlý papír. -- Obě verze jsou dva artboardy v jednom AI, ne dva náhodné JPG. -- Na bílém i na černém podkladu musí být značka čitelná. Bílá značka na bílé není verze, je to chyba. - -> Tip: Třetí artboard si nechte na černé pozadí a bílou značku, když ji škola bude dávat na tričko. - -## Export -*SVG a PDF* - -- SVG je pro web. Křivky v něm zůstanou, stránka ho zvětší. -- PDF je pro tisk a pro vložení do InDesignu. -- JPG z loga dělejte jen jako náhled, velký aspoň 1600 px. Jako jediný zdroj je zakázaný. -- Názvy: logo.svg, logo.pdf, logo-cerna.svg. - -> Tip: Při exportu SVG nechte text v obrysech, pokud má značku otevřít někdo bez vašeho písma. - -## Zadání: značka školy -*Cvičení* - -- Nakreslete značku ze tří tvarů a názvu školy. -- Artboard plné verze a artboard černé verze. -- Exportujte SVG a PDF u obou. JPG jen jako náhled 1600 px, navíc. -- Soubor logo.ai si nechte. V něm musí jít značku přebarvit. - -> Tip: Tři tvary, ne třicet. Když značku nepřečtete na 16 px, je moc podrobná. - -# Kvíz - -## Z kolika tvarů je školní značka? -- [x] Ze tří -- Z jedné fotky -- Z dvaceti přechodů -- Z videa -> Tři tvary se pamatují a vejdou se na vizitku. Fotka není logo. - -## Která verze se hodí do razítka? -- Plnobarevná s přechodem -- [x] Jednobarevná černá -- JPG 80 px -- Černobílé video -> Razítko neumí přechod. Černá verze se vytiskne jednou barvou. - -## Který export podrží křivky na webu? -- JPG -- [x] SVG -- MP4 -- prproj -> SVG je vektor. JPG je bitmapa a při zvětšení se rozmaže. - -## Proč nestačí odevzdat jen JPG loga? -- JPG nejde otevřít -- [x] Nejsou v něm křivky a malý soubor nejde zvětšit -- JPG je totéž co AI -- Illustrator JPG neuloží -> Zdroj je AI. SVG a PDF jsou výstupy. JPG je jen náhled. diff --git a/content/prezentacni-grafika/4-rocnik/03-after-effects.en.md b/content/prezentacni-grafika/4-rocnik/03-after-effects.en.md deleted file mode 100644 index dcfedbb..0000000 --- a/content/prezentacni-grafika/4-rocnik/03-after-effects.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: After Effects: a composition -popis: Eight seconds, Full HD, 25 fps and the logo layers. -nazev_cviceni: Quiz: the composition -nadpis_kvizu: Set up the composition ---- diff --git a/content/prezentacni-grafika/4-rocnik/03-after-effects.md b/content/prezentacni-grafika/4-rocnik/03-after-effects.md deleted file mode 100644 index 2d9786e..0000000 --- a/content/prezentacni-grafika/4-rocnik/03-after-effects.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: pg-4-kompozice -nazev: After Effects: kompozice -popis: Osm sekund, Full HD, 25 sn/s a vrstvy loga. -nazev_cviceni: Kvíz: kompozice -nadpis_kvizu: Založte kompozici ---- - -# Výklad - -## Kompozice -*Jako sekvence* - -- Kompozice v After Effects je plátno v čase. Má rozměr, snímkovou frekvenci a délku. -- Školní úvod: 1920 × 1080, 25 sn/s, délka 8 sekund. -- 8 sekund je 200 snímků. Titulek z Premiere trval 4, tady je čas i na pohyb. -- Projekt má příponu aep. Není to mp4. - -> Tip: Nová kompozice je Ctrl+N. Délku pište 0:00:08:00, ne 8 snímků. - -## Vrstvy -*Stejný princip* - -- Horní vrstva překrývá spodní, jako ve Photoshopu. -- Logo z AI vložte jako kompozici nebo jako vrstvy, ať jde každý tvar animovat zvlášť. -- PSD s vrstvami importujte jako kompozici, ne jako sloučený snímek. -- Vrstvy pojmenujte. Tvar 1 a Tvar 2 se při animaci pletou. - -> Tip: Když je logo jedna sloučená vrstva, jednotlivý paprsek nerozhýbáte. Importujte znovu s vrstvami. - -## Kotva -*Kolem čeho se to točí* - -- Kotva je bod, kolem kterého vrstva roste a otáčí se. -- U loga má sedět uprostřed značky, ne v rohu plátna. -- Nástroj kotva, nebo dvojklik na ikonu kotvy v panelu, ji srovná na střed vrstvy. -- Špatná kotva je nejčastější důvod, proč logo přijede z boku, i když jste chtěli zvětšení. - -> Tip: Vrstvu si najeďte na začátek času, srovnejte kotvu, a teprve potom dávejte klíčové snímky. - -## Zadání: prázdný úvod -*Cvičení* - -- Projekt uvod.aep, kompozice uvod, 1920 × 1080, 25 sn/s, 8 sekund. -- Importujte logo tak, aby tvary byly samostatné vrstvy, a pojmenujte je. -- Kotvu každého tvaru dejte na jeho střed. -- Zatím nic neanimujte. Uložte aep. Mp4 z After Effects ještě nedělejte. - -> Tip: Délku kompozice přečtete nahoře v časové ose. Když končí na 10 sekundách, zkraťte ji na 8. - -# Kvíz - -## Jak dlouhá je školní kompozice úvodu? -- [x] 8 sekund -- 45 sekund -- 4 snímky -- 303 mm -> Osm sekund stačí na nástup loga a textu. Delší úvod sežere krátké video. - -## Jaká je snímková frekvence? -- [x] 25 sn/s -- 300 ppi -- 72 sn/s vždy -- 1 sn/s -> Stejně jako Premiere, 25. Jinak se úvod ve filmu cuká nebo přepočítává. - -## Kam má sedět kotva loga? -- Do levého horního rohu plátna -- [x] Na střed značky -- Mimo kompozici -- Na stopu A1 -> Od kotvy se počítá zvětšení a otočení. V rohu plátna značka odjíždí. - -## Jak se má importovat logo z Illustratoru? -- Jako jeden JPG -- [x] Po vrstvách, ať jde každý tvar zvlášť -- Jako zvuk -- Sloučené a hned exportované -> Sloučená vrstva se hýbe jen celá. Tvary potřebují vlastní vrstvy. diff --git a/content/prezentacni-grafika/4-rocnik/04-klicove-snimky.en.md b/content/prezentacni-grafika/4-rocnik/04-klicove-snimky.en.md deleted file mode 100644 index 8d9a26f..0000000 --- a/content/prezentacni-grafika/4-rocnik/04-klicove-snimky.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Keyframes -popis: The logo arrives in one second, and the motion eases. -nazev_cviceni: Quiz: keyframes -nadpis_kvizu: Fill in the times ---- diff --git a/content/prezentacni-grafika/4-rocnik/04-klicove-snimky.md b/content/prezentacni-grafika/4-rocnik/04-klicove-snimky.md deleted file mode 100644 index c586b4b..0000000 --- a/content/prezentacni-grafika/4-rocnik/04-klicove-snimky.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: pg-4-klice -nazev: Klíčové snímky -popis: Nástup loga za jednu sekundu a zjemnění pohybu. -nazev_cviceni: Kvíz: klíčové snímky -nadpis_kvizu: Doplňte časy ---- - -# Výklad - -## Dva snímky -*Od a do* - -- Klíčový snímek je hodnota v čase: pozice, měřítko nebo krytí. -- Na čase 0 má logo měřítko 0 %. Na čase 1 sekunda má 100 %. -- Mezi těmito dvěma snímky After Effects pohyb dopočítá. -- Jeden snímek nic neanimuje. Bez druhého hodnoty není kam dojít. - -> Tip: Stopky vedle vlastnosti v časové ose založí snímek. Druhý vznikne, když v jiném čase změníte hodnotu. - -## Zjemnění -*F9* - -- Rovnoměrný pohyb vypadá strojově. Easy Ease, klávesa F9, začátek a konec zpomalí. -- F9 mačkejte, když jsou snímky vybrané. Jinak se nezmění nic. -- Na nástup loga Easy Ease patří. Na střih záběru v Premiere ne, to je jiný program. -- Krytí textu nechte běžet taky mezi dvěma snímky, ne skokem z 0 na 100. - -> Tip: Změněný snímek má po F9 jinou ikonu, přesýpací, ne kosočtverec. Podle toho poznáte, že zjemnění sedí. - -## Text -*1 + 4 + 1* - -- Text se objeví za 1 sekundu, zůstane 4 sekundy a zmizí za 1 sekundu. -- To je 6 sekund textu. Logo nastupuje v první sekundě, text může začít po ní. -- Celá kompozice má 8 sekund, takže na konci zůstanou 2 sekundy klidu nebo doběhu. -- Text pište v After Effects. Nevypalujte ho do PSD, pokud ho chcete ještě posunout. - -> Tip: Čtyři sekundy klidu jsou stejné jako titulek v Premiere. Divák čte stejně pomalu. - -## Zadání: nástup -*Cvičení* - -- Logo z měřítka 0 % na 100 % za první sekundu. Oba snímky s F9. -- Název Školní den: nástup 1 sekunda, klid 4 sekundy, odchod 1 sekunda. -- Kotvy jsou uprostřed. Logo neodjíždí z rohu. -- Uložte uvod.aep. Export mp4 až po kontrole přehrávání, délka pořád 8 sekund. - -> Tip: Mezerník přehrává. Když logo skočí, chybí druhý snímek nebo je na stejném čase jako první. - -# Kvíz - -## Jaké měřítko má logo v čase 0 a v čase 1 sekunda? -- 100 % a 100 % -- [x] 0 % a 100 % -- 50 % a 50 % -- 300 ppi -> Z nuly na plnou velikost za sekundu. Bez dvou snímků se nic nepohne. - -## Čím se nástup zjemní? -- [x] F9, Easy Ease -- Ctrl+J -- Sytostí 0 -- Spadávkou -> F9 na vybraných snímcích zpomalí rozjezd a dojezd. Pohyb přestane být pravítko. - -## Jak je rozložený text? -- [x] 1 s nástup, 4 s klid, 1 s odchod -- 12 snímků celkem -- 8 s nástup a hned pryč -- Jen vypálený v JPG -> Jedna sekunda se objeví, čtyři se čte, jedna zmizí. Dohromady šest sekund. - -## Proč logo odjíždí z rohu, i když měníte jen měřítko? -- Sekvence je 30 sn/s -- [x] Kotva není uprostřed značky -- Chybí CMYK -- F9 je zapnuté -> Měřítko roste od kotvy. Kotva v rohu plátna žene značku přes obraz. diff --git a/content/prezentacni-grafika/4-rocnik/05-indesign.en.md b/content/prezentacni-grafika/4-rocnik/05-indesign.en.md deleted file mode 100644 index 1eb4419..0000000 --- a/content/prezentacni-grafika/4-rocnik/05-indesign.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: InDesign: a page -popis: A two-page A4 leaflet, a master and a placed image. -nazev_cviceni: Quiz: InDesign -nadpis_kvizu: Recognise the master and the link ---- diff --git a/content/prezentacni-grafika/4-rocnik/05-indesign.md b/content/prezentacni-grafika/4-rocnik/05-indesign.md deleted file mode 100644 index 1c2d5a1..0000000 --- a/content/prezentacni-grafika/4-rocnik/05-indesign.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: pg-4-indesign -nazev: InDesign: stránka -popis: Dvoustránkový leták A4, předloha a vložený obraz. -nazev_cviceni: Kvíz: InDesign -nadpis_kvizu: Poznejte předlohu a odkaz ---- - -# Výklad - -## Stránka, ne plátno -*A4* - -- InDesign skládá stránku: text, obraz a logo v rámcích. -- Leták je A4, 210 × 297 mm. Spadávka 3 mm se nastaví u dokumentu, stránka zůstane A4. -- Na rozdíl od Photoshopu se tu plátno nezvětšuje na 216 × 303. Přesah je spadávka mimo stránku. -- Dvě strany: přední s názvem akce, zadní s krátkým programem dne. - -> Tip: Nový dokument: záměr Tisk, A4, dvě stránky, spadávka 3 mm všude. - -## Rámce -*Text a obraz* - -- Text žije v textovém rámci. Obraz v rámci obrazu. Nejsou to vrstvy Photoshopu. -- Obraz se vkládá Soubor > Umístit. Nevkládejte ho přes schránku jako snímek obrazovky. -- Umístěný PSD nebo JPG je odkaz. Když opravíte PSD a uložíte, InDesign ho umí aktualizovat. -- Vložený obraz, který v souboru uvízne bez odkazu, se po opravě fotky sám nezmění. - -> Tip: Panel Odkazy ukáže, jestli je soubor aktuální, nebo chybí. Chybějící odkaz je červeně. - -## Předloha -*Číslo strany* - -- Předloha, master, je stránka pod ostatními. Co je na ní, opakuje se. -- Na předlohu dejte malé logo a číslo strany. Na běžnou stránku už jen obsah. -- Prvek z předlohy na jedné straně odemknete Ctrl+Shift+klik, když ho máte výjimečně posunout. -- Číslo strany je znak čísla stránky, ne ručně napsaná jednička. Druhá strana se pak očísluje sama. - -> Tip: Předloha je nahoře v panelu Stránky. Dvojklik ji otevře. Dvojklik na stránku 1 vás vrátí do dokumentu. - -## Zadání: dvě strany -*Cvičení* - -- letak.indd, A4, dvě strany, spadávka 3 mm, okraje aspoň 12 mm. -- Předloha: logo a automatické číslo strany. -- Strana 1: název Školní den, datum 12. 6., umístěná fotka jako odkaz. -- Strana 2: tři řádky programu. Uložte INDD a export nechte na pozdější lekci, nebo udělejte náhled PDF. - -> Tip: Fotku nejdřív upravte ve Photoshopu a uložte PSD. Do InDesignu ji umístěte, nekopírujte ji znovu. - -# Kvíz - -## Jak je v InDesignu nastavená spadávka? -- Stránka se zvětší na 303 × 426 mm -- [x] Stránka zůstane A4 a spadávka 3 mm je navíc -- Spadávka se v sazbě nedělá -- 72 ppi -> A4 je čistý format. 3 mm přesah je vlastnost dokumentu, ne jiný rozměr stránky. - -## Jak se má dostat fotka do letáku? -- Snímkem obrazovky -- [x] Soubor > Umístit, jako odkaz -- Vypálením do předlohy jednou provždy -- Jako mp4 -> Odkaz jde po opravě PSD aktualizovat. Snímek obrazovky je druhá, horší fotka. - -## Co patří na předlohu? -- Celý program dne, na každé straně jiný -- [x] Logo a automatické číslo strany -- Časová osa Premiere -- Maska z Photoshopu -> Předloha je to, co se opakuje. Program dne je obsah konkrétní strany. - -## Proč se číslo strany nepíše ručně jako 1? -- InDesign čísla neumí -- [x] Znak čísla stránky se na druhé straně změní sám -- Ruční jednička je vektor -- Kvůli 25 sn/s -> Znak čísla stránky čte, na které straně je. Ruční 1 zůstane 1 i na straně 2. diff --git a/content/prezentacni-grafika/4-rocnik/06-propojeni.en.md b/content/prezentacni-grafika/4-rocnik/06-propojeni.en.md deleted file mode 100644 index 362f549..0000000 --- a/content/prezentacni-grafika/4-rocnik/06-propojeni.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Linking the programs -popis: The Illustrator logo in After Effects, and the opener in Premiere without a middle export. -nazev_cviceni: Quiz: linking -nadpis_kvizu: Pick what updates ---- diff --git a/content/prezentacni-grafika/4-rocnik/06-propojeni.md b/content/prezentacni-grafika/4-rocnik/06-propojeni.md deleted file mode 100644 index 0c545f2..0000000 --- a/content/prezentacni-grafika/4-rocnik/06-propojeni.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: pg-4-propojeni -nazev: Propojení programů -popis: Logo z Illustratoru v After Effects a úvod v Premiere bez mezivýstupu. -nazev_cviceni: Kvíz: propojení -nadpis_kvizu: Vyberte, co se aktualizuje ---- - -# Výklad - -## Jeden zdroj -*Odkaz* - -- Logo má jeden zdroj, logo.ai. Photoshop, After Effects i InDesign ať na něj odkazují. -- Když značku přebarvíte v AI a uložíte, odkazy ji mohou načíst znovu. Kopírování JPG to neumí. -- JPG 80 px vložené do čtyř programů jsou čtyři různé značky. Jedna se opraví, tři zůstanou staré. -- Pojmenujte zdroj jednou. logo-final-final2.ai je cesta, jak odevzdat špatnou verzi. - -> Tip: V After Effects se odkaz obnoví v panelu projektu. V InDesignu v panelu Odkazy. - -## Dynamic Link -*AE do Premiere* - -- Dynamic Link vloží kompozici After Effects na časovou osu Premiere bez mezivýstupu mp4. -- Když v úvodu posunete text, Premiere po uložení aep ukáže novou verzi. -- Oba programy mají být stejná generace. Starší Premiere nový aep často neotevře. -- Soubory aep a prproj mějte ve stejné složce. Odkaz jinak spadne při přesunu jen jednoho z nich. - -> Tip: V Premiere: Soubor > Adobe Dynamic Link > Importovat kompozici After Effects. Na osu přijde jako záběr. - -## Co nepropojovat -*Kopie* - -- Zvuk do Illustratoru nepatří. Video do InDesignu taky ne, kromě náhledu, který tu neděláme. -- Plakát v PSD zůstává tisk. Do videa z něj berte jen logo nebo krátký náhled, ne celou spadávku se značkami. -- Ořezové značky plakátu ve videu jsou chyba. Ty má jen tiskové PDF. -- Když Dynamic Link nejde, exportujte úvod jako mp4 v ProRes nebo aspoň v kvalitním H.264 a ten vložte. Je to kopie, už se sama neopraví. - -> Tip: ProRes je mezisoubor, velký a kvalitní. H.264 je menší a už jednou stlačený. Do dalšího exportu je horší. - -## Zadání: úvod na ose -*Cvičení* - -- V Premiere na začátek sekvence vložte kompozici uvod z After Effects přes Dynamic Link. -- Délka ať sedí: 8 sekund úvodu, pak pokračuje sestřih. -- Změňte v AI jednu barvu loga, uložte, a obnovte odkaz až do videa. Když se barva nezmění, máte někde JPG. -- Uložte prproj i aep. Mp4 celého filmu exportujte znovu až na konci, ne po každém kroku. - -> Tip: Když se úvod na ose tváří jako offline, chybí aep nebo je jiná verze programu. Neexportujte přes to černou. - -# Kvíz - -## Kde má žít značka, aby šla opravit všude? -- [x] V jednom logo.ai -- Ve čtyřech různých JPG -- Jen vypálená ve videu -- V titulku Premiere jako jediném místě -> Jeden zdroj. Ostatní programy na něj odkazují. - -## Co dělá Dynamic Link? -- Převede plakát do CMYK -- [x] Vloží kompozici After Effects do Premiere bez mezivýstupu -- Smaže vrstvy v PSD -- Nahradí InDesign -> Úprava v aep se po uložení ukáže na ose. Mp4 mezi tím není potřeba. - -## Co do videa z plakátu nepatří? -- Logo -- [x] Ořezové značky -- Název akce -- Barva značky -> Značky jsou pro tiskárnu. Ve snímku videa vypadají jako omylem vyfocený tiskový arch. - -## Kdy je mp4 z After Effects horší než Dynamic Link? -- [x] Když chcete, aby se oprava textu sama propsala do Premiere -- Když video má 25 sn/s -- Když je úvod dlouhý 8 sekund -- Mp4 je vždycky zdroj -> Mp4 je kopie. Další oprava textu už do něj sama nevleze, musíte exportovat znovu. diff --git a/content/prezentacni-grafika/4-rocnik/07-export-a-formaty.en.md b/content/prezentacni-grafika/4-rocnik/07-export-a-formaty.en.md deleted file mode 100644 index af63637..0000000 --- a/content/prezentacni-grafika/4-rocnik/07-export-a-formaty.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Export and formats -popis: What goes to the printer, to the web and out as video. -nazev_cviceni: Quiz: formats -nadpis_kvizu: Match the file to the job ---- diff --git a/content/prezentacni-grafika/4-rocnik/07-export-a-formaty.md b/content/prezentacni-grafika/4-rocnik/07-export-a-formaty.md deleted file mode 100644 index d98d04a..0000000 --- a/content/prezentacni-grafika/4-rocnik/07-export-a-formaty.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: pg-4-export -nazev: Export a formáty -popis: Co se odevzdává tiskárně, na web a jako video. -nazev_cviceni: Kvíz: formáty -nadpis_kvizu: Přiřaďte soubor k použití ---- - -# Výklad - -## Tabulka výstupů -*Kam co* - -- Tiskárna dostane PDF. Plakát se spadávkou, leták A4 se spadávkou 3 mm. -- Web dostane JPG nebo PNG. Logo navíc SVG. -- Video dostane MP4, H.264, 1920 × 1080, 25 sn/s, 10 Mb/s. -- Pracovní soubory PSD, AI, AEP, PRPROJ a INDD se odevzdávají do složky zdroj, ne místo výstupů. - -> Tip: Jeden formát nespasí všechno. SVG na projektor s videem nehraje a MP4 tiskárna nevytiskne. - -## Jména -*Verze* - -- Název ať říká, co soubor je: plakat-tisk.pdf, plakat-web.jpg, skolni-den.mp4, logo.svg. -- Datum verze pište jako 2026-06-12, rok-měsíc-den. Seřadí se samo. -- Nepoužívejte final, final2 a oprava. Nová verze má nové datum, stará zůstane ve složce stare. -- Mezery a háčky v názvech na Windows i Macu projdou, ale odkaz mezi programy občas spadne. Bez háčků je jistější. - -> Tip: skolni-den_2026-06-12.mp4 je jasnější než video1.mp4. - -## Složka odevzdání -*Dvě hromádky* - -- Složka zdroj: ai, psd, aep, prproj, indd a použitá média. -- Složka export: pdf, jpg, png, svg, mp4. -- Média videa leží tam, kam vede odkaz projektu. Kopie na ploše se nepočítá. -- Když učitel otevře jen složku export, musí vidět plakát, leták, logo i video bez Adobe. - -> Tip: INDD bez odkazovaných fotek otevře prázdné rámečky. Fotky patří k němu, nebo se před odevzdáním zabalí. - -## Zadání: srovnat složku -*Cvičení* - -- Založte složku skolni-den se složkami zdroj a export. -- Do export dejte aspoň logo.svg, plakat-tisk.pdf, plakat-web.jpg a skolni-den.mp4. -- Do zdroj dejte odpovídající ai, psd, aep a prproj. -- Cizí soubor Bez názvu-1 smažte nebo přejmenujte. Ve složce ať není nic, co neumíte vysvětlit. - -> Tip: InDesign umí Soubor > Sbalit. Vznikne složka s INDD i s obrázky. Tu dejte do zdroj. - -# Kvíz - -## Co dostane tiskárna? -- prproj -- [x] PDF -- AEP -- Jen SVG na plakát A3 -> Tisk je PDF se spadávkou. Projekt Premiere tiskárna neotevře. - -## Který soubor loga patří na web a zůstane ostrý? -- logo.jpg o šířce 80 px -- [x] logo.svg -- skolni-den.mp4 -- plakat-tisk.pdf jako ikona -> SVG je křivka. Malé JPG se na webu rozmaže, jakmile ho stránka zvětší. - -## Jak se má jmenovat nová verze videa z 12. 6. 2026? -- final2.mp4 -- [x] skolni-den_2026-06-12.mp4 -- oprava oprava.mp4 -- DSC_1842.mp4 -> Datum rok-měsíc-den se seřadí a je vidět, která verze je nová. - -## Co musí být ve složce export, aby to otevřel člověk bez Adobe? -- Jen AEP a PRPROJ -- [x] PDF, JPG nebo PNG, SVG a MP4 -- Jen PSD -- Jen INDD -> Export je plochý výstup. Pracovní soubory Adobe bez programu nejdou přehrát ani otevřít naplno. diff --git a/content/prezentacni-grafika/4-rocnik/08-maturitni-zadani.en.md b/content/prezentacni-grafika/4-rocnik/08-maturitni-zadani.en.md deleted file mode 100644 index 93917ab..0000000 --- a/content/prezentacni-grafika/4-rocnik/08-maturitni-zadani.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Exam assignment -popis: A Školní den campaign: a mark, a poster, a leaflet and a video. -nazev_cviceni: Quiz: the campaign -nadpis_kvizu: Walk through the whole hand-in ---- diff --git a/content/prezentacni-grafika/4-rocnik/08-maturitni-zadani.md b/content/prezentacni-grafika/4-rocnik/08-maturitni-zadani.md deleted file mode 100644 index 0dd6875..0000000 --- a/content/prezentacni-grafika/4-rocnik/08-maturitni-zadani.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: pg-4-maturita -nazev: Maturitní zadání -popis: Kampaň Školní den: značka, plakát, leták a video. -nazev_cviceni: Kvíz: kampaň -nadpis_kvizu: Projdi celé odevzdání ---- - -# Výklad - -## Značka -*Illustrator* - -- Značka ze tří tvarů a názvu. Plná verze a černá verze, obě v logo.ai. -- Export logo.svg a logo.pdf. Černá verze jako logo-cerna.svg. -- Na 16 px musí být značka pořád čitelná. Když není, uberete detail. -- JPG není zdroj. Smí být jen náhled 1600 px. - -> Tip: Jedna značka na plakátu, v letáku i ve videu. Tři různé značky jsou tři práce, ne kampaň. - -## Tisk -*Plakát a leták* - -- Plakát A3 na výšku, plátno 303 × 426 mm, 300 ppi, spadávka 3 mm, text mimo ořez. -- Na plakátu je 12. 6. a tělocvična, fotka, maska, křivky a skupiny foto, grafika, text. -- Leták InDesign, A4, dvě strany, spadávka 3 mm, předloha s číslem strany, fotka jako odkaz. -- Výstupy: plakat-tisk.pdf se značkami, plakat-web.jpg 1600 px, letak.pdf. - -> Tip: Stejný název akce, stejné datum. Plakát a leták se nesmí rozejít. - -## Video -*Premiere a After Effects* - -- Úvod 8 sekund z After Effects: logo z 0 % na 100 % za 1 sekundu, text 1 + 4 + 1, snímky s F9. -- Úvod je v Premiere přes Dynamic Link, nebo jako jednou exportovaná kopie, když Link nejde. -- Celé video 40 až 60 sekund, titulky, jeden J-cut, hudba −15 a pod řečí −24 dB, řeč kolem −6 dB. -- Export skolni-den.mp4, H.264, 1920 × 1080, 25 sn/s, 10 Mb/s. - -> Tip: Na začátku mp4 hraje úvod, ne černá a ne ořezové značky z plakátu. - -## Složka -*Obhajoba* - -- skolni-den/zdroj drží ai, psd, aep, prproj, indd a média. -- skolni-den/export drží svg, pdf, jpg a mp4. Otevře je i člověk bez Adobe. -- Na obhajobu ukážete nejdřív video, pak plakát, pak jeden pracovní soubor s vrstvami. -- Řeknete, co je bitmapa a co vektor a proč je spadávka 3 mm. To je obsah čtyř ročníků. - -> Tip: Když se zeptají, proč není všechno v jednom JPG, odpověď je: tisk, web a video chtějí každý svůj soubor. - -# Kvíz - -## Co musí mít značka? -- [x] Tři tvary, plnou a černou verzi, SVG a PDF -- Jen JPG 80 px -- Jen titulek v Premiere -- Čtyři různé barvy na každém materiálu -> Zdroj je AI. SVG a PDF jsou výstupy. Černá verze je pro jednu barvu. - -## Jaké je plátno plakátu? -- A4 bez spadávky -- [x] 303 × 426 mm při 300 ppi -- 1920 × 1080 jako jediný tiskový rozměr -- 8 sekund -> A3 plus 3 mm z každé strany. 300 ppi. Video je zvlášť, ve Full HD. - -## Jak je dlouhý úvod z After Effects? -- [x] 8 sekund, logo nastoupí za 1 sekundu -- 45 sekund -- 12 snímků celé -- 4 minuty -> Kompozice má 8 sekund. Měřítko loga jde z 0 % na 100 % během první z nich. - -## Co leží ve složce export? -- Jen prproj a aep -- [x] SVG, PDF, JPG a MP4 -- Jen PSD s vrstvami -- Rozpracované bez názvu -> Export otevře i člověk bez Adobe. Pracovní soubory jsou ve složce zdroj. diff --git a/content/programovani/1-rocnik/01-ahoj-svete.en.md b/content/programovani/1-rocnik/01-ahoj-svete.en.md deleted file mode 100644 index ee64874..0000000 --- a/content/programovani/1-rocnik/01-ahoj-svete.en.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -nazev: Hello, world -popis: The first program: writing to the console. ---- diff --git a/content/programovani/1-rocnik/01-ahoj-svete.md b/content/programovani/1-rocnik/01-ahoj-svete.md deleted file mode 100644 index c150fe8..0000000 --- a/content/programovani/1-rocnik/01-ahoj-svete.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -id: cs-1-ahoj-svete -nazev: Ahoj světe -popis: První program: výpis na konzoli. ---- - -# Výklad - -## Výpis -*WriteLine* - -- Console.WriteLine vypíše text a odřádkuje. -- Console.Write vypíše text a zůstane na stejném řádku. -- Text se píše do uvozovek. Středník ukončuje příkaz. - -> Tip: Bez středníku se program nepřeloží. - -## Krátký a dlouhý zápis -*Main* - -- Starší učebnice mají třídu Program a metodu Main. -- Nový projekt stejný program zapíše několika řádky bez třídy. -- Obojí spustí stejný výpis. V lekcích používáme krátký zápis. - -> Tip: Krátký zápis je pořád C#. Není to jiný jazyk. - -## Vyzkoušejte -*Editor* - -- Vpravo je kód. Upravte ho a stiskněte Spustit. -- Výstup se objeví hned vedle. -- Obnovit ukázku vrátí původní program. - -> Tip: Změňte text v uvozovkách a spusťte znovu. - -# Kód - -``` -Console.WriteLine("Ahoj světe"); -Console.Write("Toto je "); -Console.WriteLine("C#"); -``` diff --git a/content/programovani/1-rocnik/02-komentare.en.md b/content/programovani/1-rocnik/02-komentare.en.md deleted file mode 100644 index c80ebee..0000000 --- a/content/programovani/1-rocnik/02-komentare.en.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -nazev: Comments -popis: Notes the program does not run. ---- diff --git a/content/programovani/1-rocnik/02-komentare.md b/content/programovani/1-rocnik/02-komentare.md deleted file mode 100644 index a54c0b2..0000000 --- a/content/programovani/1-rocnik/02-komentare.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -id: cs-1-komentare -nazev: Komentáře -popis: Poznámky, které se nespouštějí. ---- - -# Výklad - -## Jednořádkový -*//* - -- Vše za // na stejném řádku počítač přeskočí. -- Komentář vysvětluje, proč tam řádek je, ne co je vidět. -- Kód bez komentáře pořád běží stejně. - -> Tip: Komentář není výpis. Na konzoli se neobjeví. - -## Více řádků -*/* */* - -- Blok začíná /* a končí */. -- Hodí se, když chcete dočasně vypnout několik řádků. -- Zapomenuté */ rozbije zbytek souboru. - -> Tip: Nevnořujte blokové komentáře do sebe. - -# Kód - -``` -// Tohle se nespustí. -Console.WriteLine("Tento řádek ano"); -/* -Console.WriteLine("A tento ne"); -*/ -``` diff --git a/content/programovani/1-rocnik/03-promenne.en.md b/content/programovani/1-rocnik/03-promenne.en.md deleted file mode 100644 index e302009..0000000 --- a/content/programovani/1-rocnik/03-promenne.en.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -nazev: Variables -popis: A named value you can change. ---- diff --git a/content/programovani/1-rocnik/03-promenne.md b/content/programovani/1-rocnik/03-promenne.md deleted file mode 100644 index c17316f..0000000 --- a/content/programovani/1-rocnik/03-promenne.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -id: cs-1-promenne -nazev: Proměnné -popis: Pojmenovaná hodnota, kterou lze změnit. ---- - -# Výklad - -## Deklarace -*typ jméno* - -- Nejdřív typ, pak jméno, pak hodnota: int vek = 17; -- Jméno začíná písmenem. Mezery v něm být nesmí. -- Do stejné proměnné lze později uložit novou hodnotu stejného typu. - -> Tip: int drží celé číslo. string drží text. - -## Čtení -*jméno* - -- Jméno bez uvozovek je proměnná. Uvozovky by z něj udělaly text. -- WriteLine umí vypsat proměnnou i text spojený plusem. -- Hodnota se dosadí až při běhu, ne při psaní. - -> Tip: Změňte vek na 18 a spusťte znovu. - -# Kód - -``` -string jmeno = "Anna"; -int vek = 17; -jmeno = "Eva"; -Console.WriteLine(jmeno); -Console.WriteLine(vek); -Console.WriteLine(jmeno + " má " + vek + " let"); -``` diff --git a/content/programovani/1-rocnik/04-typy.en.md b/content/programovani/1-rocnik/04-typy.en.md deleted file mode 100644 index 0973087..0000000 --- a/content/programovani/1-rocnik/04-typy.en.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -nazev: Data types -popis: int, double, bool, char and string. ---- diff --git a/content/programovani/1-rocnik/04-typy.md b/content/programovani/1-rocnik/04-typy.md deleted file mode 100644 index bda4cec..0000000 --- a/content/programovani/1-rocnik/04-typy.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -id: cs-1-typy -nazev: Datové typy -popis: int, double, bool, char a string. ---- - -# Výklad - -## Čísla -*int a double* - -- int je celé číslo: 42. -- double je číslo s desetinnou tečkou: 3.14. -- V kódu je desetinná tečka, ne čárka. - -> Tip: 3,14 by C# přečetl jako dva údaje oddělené čárkou. - -## Text a ano/ne -*string, char, bool* - -- string je text v uvozovkách. -- char je jeden znak v apostrofech: 'A'. -- bool je jen true nebo false. - -> Tip: Apostrof a uvozovky nejsou totéž. 'A' je znak, "A" je text. - -# Kód - -``` -int cele = 42; -double desetinne = 3.14; -bool prsi = false; -char pismeno = 'A'; -string text = "ahoj"; -Console.WriteLine(cele); -Console.WriteLine(desetinne); -Console.WriteLine(prsi); -Console.WriteLine(pismeno); -Console.WriteLine(text); -``` diff --git a/content/programovani/1-rocnik/05-prevody.en.md b/content/programovani/1-rocnik/05-prevody.en.md deleted file mode 100644 index 291c616..0000000 --- a/content/programovani/1-rocnik/05-prevody.en.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -nazev: Type conversion -popis: From double to int and from text to a number. ---- diff --git a/content/programovani/1-rocnik/05-prevody.md b/content/programovani/1-rocnik/05-prevody.md deleted file mode 100644 index 3dd2e2a..0000000 --- a/content/programovani/1-rocnik/05-prevody.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -id: cs-1-prevody -nazev: Převody typů -popis: Z double na int a z textu na číslo. ---- - -# Výklad - -## Ořez desetin -*(int)* - -- (int)3.9 je 3. Desetinná část se odřízne, nezaokrouhlí. -- Opačně int do double ztrátu nemá: 3 se stane 3.0. -- Převod napište před hodnotu do závorky. - -> Tip: Když potřebujete zaokrouhlit, (int) na to není. - -## Text na číslo -*Parse* - -- int.Parse("20") udělá z textu číslo 20. -- Když text číslo není, program spadne. To později chytíme výjimkou. -- Číslo na text udělá ToString nebo zápis do řetězce. - -> Tip: Vstup z konzole je vždy text, i když uživatel napíše číslici. - -# Kód - -``` -double cena = 19.9; -int cele = (int)cena; -Console.WriteLine(cele); -string vstup = "20"; -int cislo = int.Parse(vstup); -Console.WriteLine(cislo + 1); -``` diff --git a/content/programovani/1-rocnik/06-operatory.en.md b/content/programovani/1-rocnik/06-operatory.en.md deleted file mode 100644 index e4c6901..0000000 --- a/content/programovani/1-rocnik/06-operatory.en.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -nazev: Operators -popis: Arithmetic, remainder, comparison and logic. ---- diff --git a/content/programovani/1-rocnik/06-operatory.md b/content/programovani/1-rocnik/06-operatory.md deleted file mode 100644 index b7c962a..0000000 --- a/content/programovani/1-rocnik/06-operatory.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -id: cs-1-operatory -nazev: Operátory -popis: Počítání, zbytek, porovnání a a zároveň. ---- - -# Výklad - -## Počet -*+ - * / %* - -- Sčítání, odčítání a násobení fungují, jak čekáte. -- Dělení dvou int je celočíselné: 17 / 5 je 3. -- % je zbytek po dělení: 17 % 5 je 2. - -> Tip: Když chcete desetinný podíl, jedno číslo udělejte double: 17 / 5.0. - -## Porovnání -*true a false* - -- == je rovnost. = je uložení. Nejsou totéž. -- && znamená a zároveň. || znamená nebo. -- ! otočí bool: !true je false. - -> Tip: Jedno = v podmínce je častá chyba. Podmínka chce ==. - -# Kód - -``` -int a = 17; -int b = 5; -Console.WriteLine(a + b); -Console.WriteLine(a / b); -Console.WriteLine(a % b); -Console.WriteLine(a > b); -Console.WriteLine(a > 10 && b < 10); -``` diff --git a/content/programovani/1-rocnik/07-retezce.en.md b/content/programovani/1-rocnik/07-retezce.en.md deleted file mode 100644 index 7229ab2..0000000 --- a/content/programovani/1-rocnik/07-retezce.en.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -nazev: Strings -popis: Joining text, length and a slice. ---- diff --git a/content/programovani/1-rocnik/07-retezce.md b/content/programovani/1-rocnik/07-retezce.md deleted file mode 100644 index 044c950..0000000 --- a/content/programovani/1-rocnik/07-retezce.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -id: cs-1-retezce -nazev: Řetězce -popis: Skládání textu, délka a výřez. ---- - -# Výklad - -## Interpolace -*$* - -- $"Ahoj, {jmeno}" dosadí hodnotu do složených závorek. -- Je přehlednější než spojování plusem. -- Do závorek může i výpočet: {vek + 1}. - -> Tip: Bez dolaru před uvozovkami se {jmeno} vypíše doslova. - -## Metody textu -*Length* - -- Length je počet znaků. -- ToUpper vrátí velká písmena a původní text nezmění. -- Substring(0, 2) vezme dva znaky od začátku. - -> Tip: První znak má index 0, ne 1. - -# Kód - -``` -string jmeno = "Anna"; -int vek = 17; -Console.WriteLine($"Ahoj, {jmeno}. Za rok ti bude {vek + 1}."); -Console.WriteLine(jmeno.Length); -Console.WriteLine(jmeno.ToUpper()); -Console.WriteLine(jmeno.Substring(0, 2)); -``` diff --git a/content/programovani/1-rocnik/08-vstup.en.md b/content/programovani/1-rocnik/08-vstup.en.md deleted file mode 100644 index aaa9f2d..0000000 --- a/content/programovani/1-rocnik/08-vstup.en.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -nazev: Console input -popis: Console.ReadLine reads a line. ---- diff --git a/content/programovani/1-rocnik/08-vstup.md b/content/programovani/1-rocnik/08-vstup.md deleted file mode 100644 index ea4349c..0000000 --- a/content/programovani/1-rocnik/08-vstup.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -id: cs-1-vstup -nazev: Vstup z konzole -popis: Console.ReadLine přečte řádek. ---- - -# Výklad - -## ReadLine -*text* - -- ReadLine počká na řádek a vrátí ho jako string. -- V této lekci řádek napište do pole Vstup a pak Spustit. -- Každé další ReadLine vezme další řádek vstupu. - -> Tip: Když vstup necháte prázdný, ReadLine dostane konec a program může spadnout. - -## Číslo ze vstupu -*Parse* - -- ReadLine nikdy nevrací int. Vrací text. -- int.Parse z něj číslo udělá. -- Napište do vstupu třeba 17. - -> Tip: Zkuste ve vstupu Anna a uvidíte chybu. Parse čeká číslo. - -# Kód - -``` -Console.WriteLine("Kolik ti je?"); -string radek = Console.ReadLine(); -int vek = int.Parse(radek); -Console.WriteLine($"Za rok ti bude {vek + 1}."); -``` diff --git a/content/programovani/2-rocnik/01-if.en.md b/content/programovani/2-rocnik/01-if.en.md deleted file mode 100644 index 177d905..0000000 --- a/content/programovani/2-rocnik/01-if.en.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -nazev: If and else -popis: A branch that runs only sometimes. ---- diff --git a/content/programovani/2-rocnik/01-if.md b/content/programovani/2-rocnik/01-if.md deleted file mode 100644 index c235df4..0000000 --- a/content/programovani/2-rocnik/01-if.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -id: cs-2-if -nazev: If a else -popis: Větev, která se spustí jen někdy. ---- - -# Výklad - -## Podmínka -*if* - -- if (vek >= 18) spustí blok ve složených závorkách, jen když je podmínka true. -- else je větev pro opačný případ. -- else if přidá další podmínku mezi ně. - -> Tip: Za if není středník. Středník by podmínku oddělil od bloku. - -## Porovnání -*==* - -- Čísla porovnávejte >, <, >=, <=, == a !=. -- Text se porovnává ==. "Anna" == "anna" je false. -- Do podmínky patří bool, ne přiřazení. - -> Tip: Změňte vek a sledujte, která věta se vypíše. - -# Kód - -``` -int vek = 17; -if (vek >= 18) -{ - Console.WriteLine("plnoletý"); -} -else if (vek >= 15) -{ - Console.WriteLine("téměř"); -} -else -{ - Console.WriteLine("ještě ne"); -} -``` diff --git a/content/programovani/2-rocnik/02-switch.en.md b/content/programovani/2-rocnik/02-switch.en.md deleted file mode 100644 index 54377bb..0000000 --- a/content/programovani/2-rocnik/02-switch.en.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -nazev: Switch -popis: Several branches for one value. ---- diff --git a/content/programovani/2-rocnik/02-switch.md b/content/programovani/2-rocnik/02-switch.md deleted file mode 100644 index d46a17c..0000000 --- a/content/programovani/2-rocnik/02-switch.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -id: cs-2-switch -nazev: Switch -popis: Víc větví podle jedné hodnoty. ---- - -# Výklad - -## Větve -*case* - -- switch vybere case, který se rovná hodnotě. -- break ukončí větev. Bez něj se překlad v klasickém zápisu zastaví. -- default je větev, když nesedí žádný case. - -> Tip: Na známku 1 až 5 se switch hodí víc než řada else if. - -## Nový zápis -*šipka* - -- case 1 => "výborně" je krátká větev bez break. -- Výraz switch umí hodnotu rovnou vrátit. -- V lekci je klasický zápis, ať je vidět break. - -> Tip: Přidejte case 5 a spusťte se znamkou 5. - -# Kód - -``` -int znamka = 2; -switch (znamka) -{ - case 1: - Console.WriteLine("výborně"); - break; - case 2: - Console.WriteLine("chvalitebně"); - break; - default: - Console.WriteLine("jiná známka"); - break; -} -``` diff --git a/content/programovani/2-rocnik/03-while.en.md b/content/programovani/2-rocnik/03-while.en.md deleted file mode 100644 index cc1f71b..0000000 --- a/content/programovani/2-rocnik/03-while.en.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -nazev: While -popis: Repeat while a condition holds. ---- diff --git a/content/programovani/2-rocnik/03-while.md b/content/programovani/2-rocnik/03-while.md deleted file mode 100644 index 37455ca..0000000 --- a/content/programovani/2-rocnik/03-while.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -id: cs-2-while -nazev: While -popis: Opakování, dokud podmínka platí. ---- - -# Výklad - -## Smyčka -*while* - -- Tělo se opakuje, dokud je podmínka true. -- Když podmínku nikdy nezměníte, smyčka neskončí. -- Aplikace dlouhý běh po chvíli zastaví. - -> Tip: i = i + 1 nebo i++ posune čítač. Bez toho se i nemění. - -## Součet -*1 až 4* - -- Začněte součtem 0 a přičítejte i. -- 1+2+3+4 je 10. -- Podmínka i <= 4 pustí i číslo 4 dovnitř. - -> Tip: Změňte 4 na 10. Součet 1 až 10 je 55. - -# Kód - -``` -int i = 1; -int soucet = 0; -while (i <= 4) -{ - soucet = soucet + i; - i++; -} -Console.WriteLine(soucet); -``` diff --git a/content/programovani/2-rocnik/04-for.en.md b/content/programovani/2-rocnik/04-for.en.md deleted file mode 100644 index 757f660..0000000 --- a/content/programovani/2-rocnik/04-for.en.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -nazev: For -popis: A loop with its counter in one place. ---- diff --git a/content/programovani/2-rocnik/04-for.md b/content/programovani/2-rocnik/04-for.md deleted file mode 100644 index 2e6afac..0000000 --- a/content/programovani/2-rocnik/04-for.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -id: cs-2-for -nazev: For -popis: Smyčka s čítačem na jednom místě. ---- - -# Výklad - -## Tři části -*start; podmínka; krok* - -- for (int i = 0; i < 3; i++) má začátek, podmínku a krok. -- i < 3 pustí 0, 1 a 2. Trojku už ne. -- Krok i++ se provede až po těle. - -> Tip: Když potřebujete přesný počet opakování, for je přehlednější než while. - -## Násobilka -*výpis* - -- V těle můžete počítat i * 2. -- WriteLine v těle vypíše jeden řádek na každé opakování. -- Čítač nemusí začínat nulou. - -> Tip: Přepište podmínku na i <= 5 a sledujte další řádek. - -# Kód - -``` -for (int i = 1; i <= 3; i++) -{ - Console.WriteLine($"{i} krát 2 je {i * 2}"); -} -``` diff --git a/content/programovani/2-rocnik/05-pole.en.md b/content/programovani/2-rocnik/05-pole.en.md deleted file mode 100644 index a4664a1..0000000 --- a/content/programovani/2-rocnik/05-pole.en.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -nazev: Arrays -popis: Several values of one type under one name. ---- diff --git a/content/programovani/2-rocnik/05-pole.md b/content/programovani/2-rocnik/05-pole.md deleted file mode 100644 index 4653b09..0000000 --- a/content/programovani/2-rocnik/05-pole.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -id: cs-2-pole -nazev: Pole -popis: Víc hodnot stejného typu pod jedním jménem. ---- - -# Výklad - -## Index -*od nuly* - -- new int[] { 2, 4, 6 } je pole tří čísel. -- První prvek je znamky[0], poslední znamky[2]. -- Length je počet prvků, ne index posledního. - -> Tip: znamky[3] u pole délky 3 spadne. Poslední index je 2. - -## Zápis -*prvku* - -- Do prvku se dá uložit nová hodnota: znamky[1] = 5. -- Ostatní prvky zůstanou. -- Pole má pevnou délku. Přidat čtvrtý prvek nejde, na to je později List. - -> Tip: Vyměňte první známku a spusťte znovu. - -# Kód - -``` -int[] znamky = { 1, 3, 2 }; -Console.WriteLine(znamky[0]); -Console.WriteLine(znamky.Length); -znamky[1] = 5; -Console.WriteLine(znamky[1]); -``` diff --git a/content/programovani/2-rocnik/06-foreach.en.md b/content/programovani/2-rocnik/06-foreach.en.md deleted file mode 100644 index 3a4186e..0000000 --- a/content/programovani/2-rocnik/06-foreach.en.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -nazev: Foreach -popis: Visit every item without an index. ---- diff --git a/content/programovani/2-rocnik/06-foreach.md b/content/programovani/2-rocnik/06-foreach.md deleted file mode 100644 index 1c0a779..0000000 --- a/content/programovani/2-rocnik/06-foreach.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -id: cs-2-foreach -nazev: Foreach -popis: Projít každý prvek bez indexu. ---- - -# Výklad - -## Projítí -*foreach* - -- foreach (int z in znamky) vezme prvky od prvního po poslední. -- z je kopie hodnoty. U int se zápisem do z pole nezmění. -- Když index nepotřebujete, foreach je kratší než for. - -> Tip: Součet ve smyčce přičítá aktuální z. - -## Texty -*string[]* - -- Pole může být i ze stringů. -- Stejný foreach funguje pro oba typy, jen se liší typ prvku. -- Pořadí je pořadí v závorce při vytvoření. - -> Tip: Přidejte do pole třetí jméno. - -# Kód - -``` -string[] jmena = { "Anna", "Eva", "Jan" }; -foreach (string jmeno in jmena) -{ - Console.WriteLine(jmeno); -} -``` diff --git a/content/programovani/2-rocnik/07-metody.en.md b/content/programovani/2-rocnik/07-metody.en.md deleted file mode 100644 index 3b6fe65..0000000 --- a/content/programovani/2-rocnik/07-metody.en.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -nazev: Methods -popis: A named piece of the program you can call. ---- diff --git a/content/programovani/2-rocnik/07-metody.md b/content/programovani/2-rocnik/07-metody.md deleted file mode 100644 index 2c0164a..0000000 --- a/content/programovani/2-rocnik/07-metody.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -id: cs-2-metody -nazev: Metody -popis: Pojmenovaný kus programu, který lze zavolat. ---- - -# Výklad - -## Volání -*jméno()* - -- static void Pozdrav() je metoda bez výsledku. -- Zavolá se Pozdrav(); včetně závorek. -- Bez závorek by to bylo jen jméno, ne volání. - -> Tip: Metodu lze zavolat víckrát a pokaždé udělá totéž. - -## Proč -*jednou* - -- Kód, který se opakuje, patří do metody. -- Jméno metody říká, co dělá: Pozdrav, ne Metoda1. -- void znamená, že nevrací hodnotu. - -> Tip: Přidejte druhé volání Pozdrav(). - -# Kód - -``` -Pozdrav(); -Pozdrav(); - -static void Pozdrav() -{ - Console.WriteLine("Ahoj"); -} -``` diff --git a/content/programovani/2-rocnik/08-navrat.en.md b/content/programovani/2-rocnik/08-navrat.en.md deleted file mode 100644 index 8199f32..0000000 --- a/content/programovani/2-rocnik/08-navrat.en.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -nazev: Parameters and return -popis: A method receives values and can return one. ---- diff --git a/content/programovani/2-rocnik/08-navrat.md b/content/programovani/2-rocnik/08-navrat.md deleted file mode 100644 index 2a9f1cc..0000000 --- a/content/programovani/2-rocnik/08-navrat.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -id: cs-2-navrat -nazev: Parametry a návrat -popis: Metoda dostane hodnoty a může jednu vrátit. ---- - -# Výklad - -## Parametr -*vstup* - -- int a v závorce je parametr. Volající dodá argument. -- Součet(2, 5) uloží 2 do a a 5 do b. -- Jména parametrů platí jen uvnitř metody. - -> Tip: Změňte argumenty a výsledek se změní, metoda ne. - -## return -*výstup* - -- int před jménem je typ výsledku. -- return hodnotu vrátí a metodu ukončí. -- Volající si výsledek může uložit: int s = Soucet(2, 5); - -> Tip: return 0 omylem na začátku by zbytek metody nespustil. - -# Kód - -``` -int s = Soucet(2, 5); -Console.WriteLine(s); -Console.WriteLine(Soucet(10, 1)); - -static int Soucet(int a, int b) -{ - return a + b; -} -``` diff --git a/content/programovani/3-rocnik/01-trida.en.md b/content/programovani/3-rocnik/01-trida.en.md deleted file mode 100644 index 1ac6f34..0000000 --- a/content/programovani/3-rocnik/01-trida.en.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -nazev: Class and object -popis: Your own type and one concrete piece of it. ---- diff --git a/content/programovani/3-rocnik/01-trida.md b/content/programovani/3-rocnik/01-trida.md deleted file mode 100644 index 54fc345..0000000 --- a/content/programovani/3-rocnik/01-trida.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -id: cs-3-trida -nazev: Třída a objekt -popis: Vlastní typ a jeho konkrétní kus. ---- - -# Výklad - -## Třída -*návod* - -- class Zak popisuje, co žák má: jméno a věk. -- new Zak() vytvoří objekt, jeden konkrétní kus. -- Dva new jsou dva objekty. Změna jednoho druhý nemění. - -> Tip: Třída sama o sobě není žák. Je to popis. - -## Pole objektu -*tečka* - -- z.Jmeno se čte a zapisuje přes tečku. -- Na začátek dáme veřejná pole, ať je vidět, komu patří. -- Později je schováme za vlastnost. - -> Tip: Vytvořte druhého žáka a vypište obě jména. - -# Kód - -``` -Zak z = new Zak(); -z.Jmeno = "Anna"; -z.Vek = 17; -Console.WriteLine($"{z.Jmeno}, {z.Vek}"); - -class Zak -{ - public string Jmeno; - public int Vek; -} -``` diff --git a/content/programovani/3-rocnik/02-konstruktor.en.md b/content/programovani/3-rocnik/02-konstruktor.en.md deleted file mode 100644 index 22b38d1..0000000 --- a/content/programovani/3-rocnik/02-konstruktor.en.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -nazev: Constructor -popis: A method that fills the object immediately. ---- diff --git a/content/programovani/3-rocnik/02-konstruktor.md b/content/programovani/3-rocnik/02-konstruktor.md deleted file mode 100644 index dcd171e..0000000 --- a/content/programovani/3-rocnik/02-konstruktor.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -id: cs-3-konstruktor -nazev: Konstruktor -popis: Metoda, která objekt hned naplní. ---- - -# Výklad - -## Jméno třídy -*new Zak* - -- Konstruktor se jmenuje jako třída a nemá návratový typ. -- new Zak("Anna", 17) ho zavolá. -- Prázdný new Zak() přestane fungovat, jakmile napíšete vlastní konstruktor. - -> Tip: Hodnoty patří do new, ne až na další řádky. - -## this -*tento objekt* - -- this.Jmeno je pole objektu. Jmeno bez this by v konstruktoru byl parametr. -- Když se jmenují stejně, this je nutný. -- Mimo konstruktor this často není potřeba. - -> Tip: Přidejte do výpisu věk z konstruktoru. - -# Kód - -``` -Zak z = new Zak("Anna", 17); -Console.WriteLine($"{z.Jmeno}, {z.Vek}"); - -class Zak -{ - public string Jmeno; - public int Vek; - - public Zak(string jmeno, int vek) - { - Jmeno = jmeno; - Vek = vek; - } -} -``` diff --git a/content/programovani/3-rocnik/03-vlastnosti.en.md b/content/programovani/3-rocnik/03-vlastnosti.en.md deleted file mode 100644 index d20739a..0000000 --- a/content/programovani/3-rocnik/03-vlastnosti.en.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -nazev: Properties -popis: get and set instead of a bare field. ---- diff --git a/content/programovani/3-rocnik/03-vlastnosti.md b/content/programovani/3-rocnik/03-vlastnosti.md deleted file mode 100644 index e9cea23..0000000 --- a/content/programovani/3-rocnik/03-vlastnosti.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -id: cs-3-vlastnosti -nazev: Vlastnosti -popis: get a set místo holého pole. ---- - -# Výklad - -## get a set -*tečka zůstává* - -- public string Jmeno { get; set; } se zvenku používá jako pole. -- Uvnitř může set odmítnout špatnou hodnotu. -- get hodnotu vrátí, set ji uloží. - -> Tip: Zápis z.Vek = -1 může set zarazit, holé pole ne. - -## Kontrola -*set* - -- V příkladu set u věku záporné číslo neuloží. -- get pořád vrátí poslední platnou hodnotu. -- Tak se objekt nepokazí zvenku. - -> Tip: Zkuste z.Vek = -3 a vypište věk. Zůstane 17. - -# Kód - -``` -Zak z = new Zak("Anna", 17); -z.Vek = -3; -Console.WriteLine(z.Vek); - -class Zak -{ - public string Jmeno { get; set; } - private int vek; - public int Vek - { - get { return vek; } - set { if (value >= 0) vek = value; } - } - - public Zak(string jmeno, int vek) - { - Jmeno = jmeno; - Vek = vek; - } -} -``` diff --git a/content/programovani/3-rocnik/04-zapouzdreni.en.md b/content/programovani/3-rocnik/04-zapouzdreni.en.md deleted file mode 100644 index 08bb91c..0000000 --- a/content/programovani/3-rocnik/04-zapouzdreni.en.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -nazev: Encapsulation -popis: Private data and public methods. ---- diff --git a/content/programovani/3-rocnik/04-zapouzdreni.md b/content/programovani/3-rocnik/04-zapouzdreni.md deleted file mode 100644 index 27b5b89..0000000 --- a/content/programovani/3-rocnik/04-zapouzdreni.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -id: cs-3-zapouzdreni -nazev: Zapouzdření -popis: Soukromá data a veřejné metody. ---- - -# Výklad - -## private -*schované* - -- private pole vidí jen kód té třídy. -- public metoda je dveře, kterými se s objektem mluví. -- Zvenku z.penize nenapíšete. Zavoláte Pridej. - -> Tip: Když je vše public, kdokoli rozbije pravidla objektu. - -## Metoda -*Pridej* - -- Pridej přičte a vrátí nový stav. -- Záporný vklad lze v metodě odmítnout. -- Výpis stavu jde přes Kolik, ne přes pole. - -> Tip: Zkuste Pridej(-10). Stav se nemá zmenšit. - -# Kód - -``` -Pokladna p = new Pokladna(); -p.Pridej(50); -p.Pridej(-10); -Console.WriteLine(p.Kolik()); - -class Pokladna -{ - private int penize; - - public void Pridej(int castka) - { - if (castka > 0) penize = penize + castka; - } - - public int Kolik() - { - return penize; - } -} -``` diff --git a/content/programovani/3-rocnik/05-dedicnost.en.md b/content/programovani/3-rocnik/05-dedicnost.en.md deleted file mode 100644 index 8e3d992..0000000 --- a/content/programovani/3-rocnik/05-dedicnost.en.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -nazev: Inheritance -popis: A new class takes over a finished one. ---- diff --git a/content/programovani/3-rocnik/05-dedicnost.md b/content/programovani/3-rocnik/05-dedicnost.md deleted file mode 100644 index 6b1029a..0000000 --- a/content/programovani/3-rocnik/05-dedicnost.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -id: cs-3-dedicnost -nazev: Dědičnost -popis: Nová třída převezme hotovou. ---- - -# Výklad - -## base -*: Zak* - -- class Student : Zak znamená, že student je žák a má něco navíc. -- Dostane Jmeno a Vek, aniž by se psaly znovu. -- base(...) zavolá konstruktor předka. - -> Tip: Student umí to, co Zak, a ještě obor. - -## Je -*typ* - -- Student lze uložit do proměnné Zak. Pořád je to student. -- Opačně žák bez oboru studentem není. -- Na specialitu sáhnete, až když máte původní typ. - -> Tip: Vypište i obor. Patří studentovi, ne obecnému žákovi. - -# Kód - -``` -Student s = new Student("Eva", 18, "informatika"); -Console.WriteLine($"{s.Jmeno}, {s.Obor}"); - -class Zak -{ - public string Jmeno { get; set; } - public int Vek { get; set; } - public Zak(string jmeno, int vek) - { - Jmeno = jmeno; - Vek = vek; - } -} - -class Student : Zak -{ - public string Obor { get; set; } - public Student(string jmeno, int vek, string obor) : base(jmeno, vek) - { - Obor = obor; - } -} -``` diff --git a/content/programovani/3-rocnik/06-polymorfismus.en.md b/content/programovani/3-rocnik/06-polymorfismus.en.md deleted file mode 100644 index 61e4f62..0000000 --- a/content/programovani/3-rocnik/06-polymorfismus.en.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -nazev: Polymorphism -popis: The same call, a different answer from the child. ---- diff --git a/content/programovani/3-rocnik/06-polymorfismus.md b/content/programovani/3-rocnik/06-polymorfismus.md deleted file mode 100644 index f2b4bb7..0000000 --- a/content/programovani/3-rocnik/06-polymorfismus.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -id: cs-3-polymorfismus -nazev: Polymorfismus -popis: Stejné volání, jiná odpověď potomka. ---- - -# Výklad - -## virtual a override -*přepsání* - -- virtual u předka dovolí potomkovi metodu vyměnit. -- override u potomka řekne, že jde o tu samou metodu. -- Bez virtual by potomek jen schoval jméno a přes typ předka by se volala stará verze. - -> Tip: Proměnná je Zvire, objekt je Pes. Zavolá se štěk, ne obecné zvíře. - -## Seznam -*víc tvarů* - -- Do pole Zvire lze dát psa i kočku. -- foreach volá Zvuk a každý objekt odpoví po svém. -- Nové zvíře přidáte třídou, ne úpravou smyčky. - -> Tip: Přidejte do pole kočku a třetí řádek výstupu bude mňau. - -# Kód - -``` -Zvire[] zvirata = { new Pes(), new Kocka() }; -foreach (Zvire z in zvirata) -{ - Console.WriteLine(z.Zvuk()); -} - -class Zvire -{ - public virtual string Zvuk() { return "..."; } -} - -class Pes : Zvire -{ - public override string Zvuk() { return "haf"; } -} - -class Kocka : Zvire -{ - public override string Zvuk() { return "mňau"; } -} -``` diff --git a/content/programovani/3-rocnik/07-rozhrani.en.md b/content/programovani/3-rocnik/07-rozhrani.en.md deleted file mode 100644 index 1f39bf6..0000000 --- a/content/programovani/3-rocnik/07-rozhrani.en.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -nazev: Interface -popis: A contract: which methods a type must have. ---- diff --git a/content/programovani/3-rocnik/07-rozhrani.md b/content/programovani/3-rocnik/07-rozhrani.md deleted file mode 100644 index 0caebee..0000000 --- a/content/programovani/3-rocnik/07-rozhrani.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -id: cs-3-rozhrani -nazev: Rozhraní -popis: Smlouva: které metody typ musí mít. ---- - -# Výklad - -## interface -*I* - -- interface nemá hotový kód, jen hlavičky metod. -- class Pes : IMluvici slíbí, že Mluv napíše. -- Jedna třída může splnit víc rozhraní. Dědit může jen jednu třídu. - -> Tip: Jméno rozhraní se často píše s I na začátku: IMluvici. - -## Společný typ -*seznam* - -- Proměnná typu rozhraní udrží kohokoli, kdo smlouvu splnil. -- Pes a Radio nemají společného předka, ale oba umí Mluv. -- Smyčka jim rozumí přes smlouvu, ne přes původ. - -> Tip: Rozhraní neříká, jak metoda funguje. To napíše až třída. - -# Kód - -``` -IMluvici[] veci = { new Pes(), new Radio() }; -foreach (IMluvici v in veci) -{ - Console.WriteLine(v.Mluv()); -} - -interface IMluvici -{ - string Mluv(); -} - -class Pes : IMluvici -{ - public string Mluv() { return "haf"; } -} - -class Radio : IMluvici -{ - public string Mluv() { return "hudba"; } -} -``` diff --git a/content/programovani/3-rocnik/08-enum.en.md b/content/programovani/3-rocnik/08-enum.en.md deleted file mode 100644 index 4fb204b..0000000 --- a/content/programovani/3-rocnik/08-enum.en.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -nazev: Enum -popis: A fixed list of named values. ---- diff --git a/content/programovani/3-rocnik/08-enum.md b/content/programovani/3-rocnik/08-enum.md deleted file mode 100644 index dec3916..0000000 --- a/content/programovani/3-rocnik/08-enum.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -id: cs-3-enum -nazev: Výčet -popis: Pevný seznam pojmenovaných hodnot. ---- - -# Výklad - -## enum -*Den* - -- enum Den { Po, Ut, St } jsou tři pojmenované hodnoty. -- Místo magického čísla 1 píšete Den.Po. -- Překladač nepustí hodnotu, která ve výčtu není. - -> Tip: Čísla 0, 1, 2 by za měsíc nikdo nepřečetl. Jména ano. - -## switch -*přes výčet* - -- switch na enum má case pro každou hodnotu. -- Když přidáte čtvrtek a zapomenete case, překlad na to v novém zápisu upozorní. -- Výčet je typ. Není to string. - -> Tip: Změňte dnes na Den.St. - -# Kód - -``` -Den dnes = Den.Po; -switch (dnes) -{ - case Den.Po: - Console.WriteLine("pondělí"); - break; - case Den.Ut: - Console.WriteLine("úterý"); - break; - default: - Console.WriteLine("jiný den"); - break; -} - -enum Den -{ - Po, - Ut, - St -} -``` diff --git a/content/programovani/4-rocnik/01-vyjimky.en.md b/content/programovani/4-rocnik/01-vyjimky.en.md deleted file mode 100644 index c4750a7..0000000 --- a/content/programovani/4-rocnik/01-vyjimky.en.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -nazev: Exceptions -popis: An error you can catch and explain. ---- diff --git a/content/programovani/4-rocnik/01-vyjimky.md b/content/programovani/4-rocnik/01-vyjimky.md deleted file mode 100644 index 117182a..0000000 --- a/content/programovani/4-rocnik/01-vyjimky.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -id: cs-4-vyjimky -nazev: Výjimky -popis: Chyba, kterou lze chytit a vysvětlit. ---- - -# Výklad - -## try -*pokus* - -- try je kus, který může spadnout. -- catch (Exception e) ho chytí, místo aby spadl celý program. -- e.Message je text chyby. - -> Tip: Bez try by Parse na textu abc program ukončil. - -## finally -*vždy* - -- finally se spustí, ať try prošel, nebo ne. -- Hodí se na úklid. V příkladu jen vypíše, že končíme. -- catch může být víc, pro různé typy chyb. - -> Tip: Změňte abc na 5. catch se přeskočí, finally ne. - -# Kód - -``` -try -{ - int n = int.Parse("abc"); - Console.WriteLine(n); -} -catch (Exception e) -{ - Console.WriteLine("Chyba: " + e.Message); -} -finally -{ - Console.WriteLine("konec"); -} -``` diff --git a/content/programovani/4-rocnik/02-list.en.md b/content/programovani/4-rocnik/02-list.en.md deleted file mode 100644 index 0c8016d..0000000 --- a/content/programovani/4-rocnik/02-list.en.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -nazev: List -popis: A list that can grow. ---- diff --git a/content/programovani/4-rocnik/02-list.md b/content/programovani/4-rocnik/02-list.md deleted file mode 100644 index 16cbf92..0000000 --- a/content/programovani/4-rocnik/02-list.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -id: cs-4-list -nazev: List -popis: Seznam, který umí růst. ---- - -# Výklad - -## Přidávání -*Add* - -- List začne prázdný. Add přidá na konec. -- Count je počet. Indexy jsou zase od nuly. -- Na rozdíl od pole délku dopředu neříkáte. - -> Tip: List potřebuje špičaté závorky s typem prvku. - -## Odebrání -*Remove* - -- Remove("Eva") odebere první Evu. -- RemoveAt(0) odebere podle indexu. -- foreach pak projde, co zůstalo. - -> Tip: Přidejte třetí jméno před odebráním. - -# Kód - -``` -List jmena = new List(); -jmena.Add("Anna"); -jmena.Add("Eva"); -jmena.Remove("Eva"); -foreach (string j in jmena) -{ - Console.WriteLine(j); -} -Console.WriteLine(jmena.Count); -``` diff --git a/content/programovani/4-rocnik/03-slovnik.en.md b/content/programovani/4-rocnik/03-slovnik.en.md deleted file mode 100644 index 40451f5..0000000 --- a/content/programovani/4-rocnik/03-slovnik.en.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -nazev: Dictionary -popis: A value under a key. ---- diff --git a/content/programovani/4-rocnik/03-slovnik.md b/content/programovani/4-rocnik/03-slovnik.md deleted file mode 100644 index 4ff2289..0000000 --- a/content/programovani/4-rocnik/03-slovnik.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -id: cs-4-slovnik -nazev: Slovník -popis: Hodnota pod klíčem. ---- - -# Výklad - -## Klíč -*jednou* - -- Dictionary má klíč text a hodnotu číslo. -- znamky["Anna"] = 1 uloží nebo přepíše. -- Stejný klíč je v slovníku jen jednou. - -> Tip: Pole je podle čísla. Slovník je podle jména, které si zvolíte. - -## Čtení -*ContainsKey* - -- Čtení chybějícího klíče spadne. -- ContainsKey napřed zjistí, jestli klíč je. -- foreach projde dvojice Key a Value. - -> Tip: Zeptejte se na jméno, které v slovníku není, až po ContainsKey. - -# Kód - -``` -Dictionary znamky = new Dictionary(); -znamky["Anna"] = 1; -znamky["Eva"] = 2; -znamky["Anna"] = 3; -if (znamky.ContainsKey("Eva")) -{ - Console.WriteLine(znamky["Eva"]); -} -Console.WriteLine(znamky["Anna"]); -``` diff --git a/content/programovani/4-rocnik/04-linq.en.md b/content/programovani/4-rocnik/04-linq.en.md deleted file mode 100644 index 0b2ec5a..0000000 --- a/content/programovani/4-rocnik/04-linq.en.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -nazev: LINQ -popis: Queries over a list. ---- diff --git a/content/programovani/4-rocnik/04-linq.md b/content/programovani/4-rocnik/04-linq.md deleted file mode 100644 index de4a297..0000000 --- a/content/programovani/4-rocnik/04-linq.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -id: cs-4-linq -nazev: LINQ -popis: Dotazy nad seznamem. ---- - -# Výklad - -## Where -*filtr* - -- Where nechá jen prvky, které splní podmínku. -- n => n >= 10 je krátká funkce: vezmi n a vrať, jestli je aspoň 10. -- Samotné Where ještě nic neprojde. ToList nebo foreach výsledek vezme. - -> Tip: Šipka => není porovnání. Je to zápis malé funkce. - -## Select -*převod* - -- Select z každého prvku udělá jiný. -- OrderBy seřadí. -- Dotaz lze řetězit: Where a pak Select. - -> Tip: Změňte 10 na 12 a dvojka z výpisu zmizí. - -# Kód - -``` -int[] cisla = { 4, 11, 7, 20 }; -var velka = cisla.Where(n => n >= 10).OrderBy(n => n); -foreach (int n in velka) -{ - Console.WriteLine(n); -} -``` diff --git a/content/programovani/4-rocnik/05-soubory.en.md b/content/programovani/4-rocnik/05-soubory.en.md deleted file mode 100644 index f0b0642..0000000 --- a/content/programovani/4-rocnik/05-soubory.en.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -nazev: Files -popis: Writing and reading text. ---- diff --git a/content/programovani/4-rocnik/05-soubory.md b/content/programovani/4-rocnik/05-soubory.md deleted file mode 100644 index bb0133a..0000000 --- a/content/programovani/4-rocnik/05-soubory.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -id: cs-4-soubory -nazev: Soubory -popis: Zápis a čtení textu. ---- - -# Výklad - -## WriteAllText -*jednou* - -- File.WriteAllText zapíše celý soubor. Když existuje, přepíše ho. -- Cesta pozdrav.txt je vedle programu, v jeho složce. -- ReadAllText celý text vrátí jako string. - -> Tip: Na telefonu se soubor nespustí. Na počítači s .NET ano. - -## Řádky -*Append* - -- AppendAllText přidá na konec a soubor nesmaže. -- ReadAllLines vrátí pole řádků. -- Po skončení programu soubor ve složce laboratoře zůstane. - -> Tip: Spusťte dvakrát. Druhý zápis WriteAllText starý text nahradí. - -# Kód - -``` -File.WriteAllText("pozdrav.txt", "Ahoj ze souboru"); -string zpet = File.ReadAllText("pozdrav.txt"); -Console.WriteLine(zpet); -``` diff --git a/content/programovani/4-rocnik/06-generika.en.md b/content/programovani/4-rocnik/06-generika.en.md deleted file mode 100644 index 422ce16..0000000 --- a/content/programovani/4-rocnik/06-generika.en.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -nazev: Generics -popis: One method for several types. ---- diff --git a/content/programovani/4-rocnik/06-generika.md b/content/programovani/4-rocnik/06-generika.md deleted file mode 100644 index dfe9d7d..0000000 --- a/content/programovani/4-rocnik/06-generika.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -id: cs-4-generika -nazev: Generika -popis: Jedna metoda pro víc typů. ---- - -# Výklad - -## T -*typový parametr* - -- static void Vypis(T hodnota) přijme int i string. -- T se doplní při volání podle argumentu. -- Jedna metoda tak nenutí kopírovat kód pro každý typ. - -> Tip: Když metoda s T má umět jen porovnávat, T se omezí. Tady stačí výpis. - -## List -*už ho znáte* - -- List je generická třída. string je dosazený T. -- Stejný List drží čísla a metody jsou stejné. -- Generika hlídá typ. Do List string nedáte. - -> Tip: Zavolejte Vypis s číslem i s textem. - -# Kód - -``` -Vypis(7); -Vypis("ahoj"); - -static void Vypis(T hodnota) -{ - Console.WriteLine(hodnota); -} -``` diff --git a/content/programovani/4-rocnik/07-delegaty.en.md b/content/programovani/4-rocnik/07-delegaty.en.md deleted file mode 100644 index d39c31f..0000000 --- a/content/programovani/4-rocnik/07-delegaty.en.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -nazev: Delegates -popis: A variable that holds a method. ---- diff --git a/content/programovani/4-rocnik/07-delegaty.md b/content/programovani/4-rocnik/07-delegaty.md deleted file mode 100644 index b5b9652..0000000 --- a/content/programovani/4-rocnik/07-delegaty.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -id: cs-4-delegaty -nazev: Delegáty -popis: Proměnná, do které uložíte metodu. ---- - -# Výklad - -## Func -*funkce* - -- Func je metoda, která dostane int a vrátí int. -- x => x * x je taková metoda bez jména. -- Do proměnné ji uložíte a zavoláte později. - -> Tip: Závorky pocet(4) metodu spustí. Bez nich byste ji jen předali dál. - -## Action -*bez výsledku* - -- Action nic nevrací. Hodí se na kroky. -- Metodu můžete předat jiné metodě jako argument. -- Tak se píše i Where z minulé lekce. - -> Tip: Vyměňte x * x za x + 1. - -# Kód - -``` -Func pocet = x => x * x; -Console.WriteLine(pocet(4)); -Action pozdrav = () => Console.WriteLine("ahoj"); -pozdrav(); -``` diff --git a/content/programovani/4-rocnik/08-async.en.md b/content/programovani/4-rocnik/08-async.en.md deleted file mode 100644 index 98da3e9..0000000 --- a/content/programovani/4-rocnik/08-async.en.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -nazev: Async and await -popis: Work that waits without freezing the way you write it. ---- diff --git a/content/programovani/4-rocnik/08-async.md b/content/programovani/4-rocnik/08-async.md deleted file mode 100644 index 9baebaf..0000000 --- a/content/programovani/4-rocnik/08-async.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -id: cs-4-async -nazev: Async a await -popis: Práce, která počká, aniž by zamkla zbytek zápisu. ---- - -# Výklad - -## await -*počkej* - -- await Task.Delay čeká, ale zápis zůstane řádek za řádkem. -- Metoda s await má v hlavičce async a vrací Task. -- V krátkém programu smí await stát i na nejvyšší úrovni. - -> Tip: Delay(300) čeká 300 milisekund. Výpis hotovo přijde až po něm. - -## Task -*slib* - -- Task je slib, že práce doběhne. -- await slib rozbalí. Bez await byste měli slib, ne výsledek. -- Na síť a soubory se await hodí. Na 2 + 2 ne. - -> Tip: Dejte za první výpis ještě jeden await a druhý řádek. - -# Kód - -``` -Console.WriteLine("začátek"); -await Task.Delay(300); -Console.WriteLine("hotovo"); -``` diff --git a/content/programove-vybaveni/1-rocnik/01-software-a-licence.en.md b/content/programove-vybaveni/1-rocnik/01-software-a-licence.en.md deleted file mode 100644 index 77b2182..0000000 --- a/content/programove-vybaveni/1-rocnik/01-software-a-licence.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Software and licences -popis: System and application programs, and the terms for using them. -nazev_cviceni: Quiz: software and licences -nadpis_kvizu: Name the kind of program and the kind of licence ---- diff --git a/content/programove-vybaveni/1-rocnik/01-software-a-licence.md b/content/programove-vybaveni/1-rocnik/01-software-a-licence.md deleted file mode 100644 index e40dee4..0000000 --- a/content/programove-vybaveni/1-rocnik/01-software-a-licence.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: sw-1-software-a-licence -nazev: Software a licence -popis: Systémové a aplikační programy a to, za jakých podmínek se smí používat. -nazev_cviceni: Kvíz: software a licence -nadpis_kvizu: Poznejte druh programu a druh licence ---- - -# Výklad - -## Dva druhy programů -*Software* - -- Software je program. Hardware je zařízení. Samotný počítač bez programu nic neudělá. -- Operační systém řídí počítač: Windows, Linux, macOS. Ve škole pracujeme ve Windows. -- Aplikační software řeší jednu práci: Word dokument, Excel tabulku, prohlížeč web. -- Ovladač je malý program k zařízení. Tiskárna bez ovladače netiskne, i když je zapnutá. - -> Tip: Když program spadne a systém běží dál, spadla aplikace. Když nesvítí plocha, spadl systém. - -## Licence -*Podmínky* - -- Licence říká, kdo program smí nainstalovat a na kolik počítačů. -- Komerční program se kupuje, nebo se platí předplatné. Microsoft 365 je předplatné. -- OEM licence je přivázaná k jednomu počítači. Na nový stroj se nepřetahuje. -- Stažený program bez licence není zdarma. Je to kopie, kterou škola nesmí používat. - -> Tip: Školní účet Microsoft 365 nepatří na domácí počítače navždy. Platí, dokud škola předplatné má. - -## Zdarma není jeden pojem -*Freeware a open source* - -- Freeware je zdarma, ale zdrojový kód nedostanete. Smíte ho používat za podmínek autora. -- Open source má otevřený kód. GPL navíc chce, aby odvozené programy zůstaly otevřené. -- Zkušební verze (shareware) po čase skončí, nebo omezí funkce. Není to trvalá licence. -- Na školní počítač patří jen programy, které škola schválila. Vlastní instalace se hlásí učiteli. - -> Tip: Cena nula neznamená, že smíte program rozdávat dál. I freeware má licenci. - -## Zadání: šest programů -*Cvičení* - -- Do tabulky zapište šest programů ze školního počítače: systém, prohlížeč, Word, Excel a dva další. -- U každého napište, jestli je systémový, nebo aplikační. -- U Wordu a Excelu napište, jaká licence ve škole je: předplatné Microsoft 365, ne domácí krabice. -- Soubor pojmenujte licence.txt a uložte ho do Dokumenty. Zatím nic neinstalujte. - -> Tip: Název systému zjistíte příkazem winver. Okno ukáže edici Windows a verzi. - -# Kvíz - -## Kam patří Microsoft Word? -- Mezi operační systémy -- [x] Mezi aplikační software -- Mezi ovladače tiskárny -- Mezi hardware -> Word řeší jednu práci, dokument. Systém pod ním je Windows. - -## Co znamená OEM licence Windows? -- Smí se přenést na každý další počítač -- [x] Je vázaná na jeden počítač -- Je to totéž co GPL -- Platí jen 14 dní -> OEM se prodává s počítačem a na jiný stroj se nepřesouvá. - -## Čím se freeware liší od open source? -- Freeware má otevřený zdrojový kód -- [x] Freeware je zdarma, ale kód obvykle nedostanete -- Open source se nesmí používat ve škole -- Je to totéž -> Zdarma a otevřený kód jsou dvě různé věci. GPL je otevřená licence, ne jen nulová cena. - -## Který program je operační systém? -- Excel -- [x] Windows -- WordPress -- Power BI -> Windows řídí počítač. Ostatní jsou aplikace, které na systému běží. diff --git a/content/programove-vybaveni/1-rocnik/02-operacni-system.en.md b/content/programove-vybaveni/1-rocnik/02-operacni-system.en.md deleted file mode 100644 index 572309c..0000000 --- a/content/programove-vybaveni/1-rocnik/02-operacni-system.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: The operating system -popis: What the system does between the user and the hardware. -nazev_cviceni: Quiz: the operating system -nadpis_kvizu: Name the role of the system ---- diff --git a/content/programove-vybaveni/1-rocnik/02-operacni-system.md b/content/programove-vybaveni/1-rocnik/02-operacni-system.md deleted file mode 100644 index 352a114..0000000 --- a/content/programove-vybaveni/1-rocnik/02-operacni-system.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: sw-1-operacni-system -nazev: Operační systém -popis: Co systém dělá mezi uživatelem a hardwarem. -nazev_cviceni: Kvíz: operační systém -nadpis_kvizu: Poznejte roli systému ---- - -# Výklad - -## Mezi člověkem a strojem -*Role* - -- Systém spouští programy, hlídá paměť a přiděluje čas procesoru. -- Souborový systém ukládá data na disk. Ve Windows je to NTFS. -- Ovladač si systém načte, aby mluvil s tiskárnou, diskem a sítí. -- Uživatel vidí plochu a okna. Jádro pod tím nevidí a do něj nesahá. - -> Tip: Když dva programy chtějí tiskárnu najednou, rozhodne systém. Samy se nedomluví. - -## Tři systémy -*Windows, Linux, macOS* - -- Školní učebna je Windows. Příkazy a obrazovky v tomto předmětu jsou z Windows. -- Linux je častý na serverech. Stejný dokument v Excelu tam sám od sebe není. -- macOS běží na počítačích Apple. Zkratka Ctrl je tam často Cmd. -- Soubor .docx je dokument Wordu. Není to program a není to systém. - -> Tip: Přípona souboru říká, čím ho otevřít. Systém podle ní vybere aplikaci. - -## Start počítače -*Až po přihlášení* - -- Po zapnutí naběhne firmware, pak systém, pak přihlašovací obrazovka. -- Dokud se nepřihlásíte, pracujete s účtem nikoho. Soubory uživatele jsou zamčené. -- Každý účet má vlastní plochu a složku C:\Users\jméno. -- Vypnutí přes nabídku Start uloží práci systému. Dlouhý stisk tlačítka je až poslední možnost. - -> Tip: Restart po aktualizaci není trest. Systém si domlouvá soubory, které za běhu nevymění. - -## Zadání: jaký systém to je -*Cvičení* - -- Spusťte winver a opište edici a verzi, třeba Windows 11 Pro, verzi z okna. -- Otevřete C:\Users a napište, které složky uživatelů tam jsou. Do cizích nesaháte. -- Najděte jeden ovladač v názvu: ve Správci zařízení rozbalte Monitory nebo Tiskárny. -- Zápis uložte jako system.txt do Dokumenty. Hesla ani sériová čísla nepište. - -> Tip: Správce zařízení je ve Windows devmgmt.msc. Žlutý vykřičník znamená chybějící nebo vadný ovladač. - -# Kvíz - -## Co dělá operační systém s pamětí? -- Nic, paměť si berou programy samy -- [x] Přiděluje ji programům -- Maže ji při každém uložení dokumentu -- Patří do Excelu -> Program požádá, systém přidělí. Dva programy nesmí psát do stejného místa. - -## Jaký souborový systém používá školní Windows na disku? -- [x] NTFS -- Jen názvy souborů bez systému -- SVG -- MySQL -> NTFS drží soubory, oprávnění i větší disky. Názvy složek jsou až uvnitř něj. - -## Kdy smíte sáhnout do složky jiného uživatele v C:\Users? -- Kdykoli, je to jeden počítač -- [x] Nesmíte, je to jeho účet -- Jen když je složka na ploše -- Když má dokument příponu docx -> Každý účet má vlastní soubory. Cizí složka není společný šuplík. - -## Čím zjistíte edici Windows? -- [x] Příkazem winver -- Otevřením Excelu -- Smazáním koše -- Souborem .bat -> winver otevře okno O systému Windows s edicí a verzí. diff --git a/content/programove-vybaveni/1-rocnik/03-soubory-a-slozky.en.md b/content/programove-vybaveni/1-rocnik/03-soubory-a-slozky.en.md deleted file mode 100644 index be64b98..0000000 --- a/content/programove-vybaveni/1-rocnik/03-soubory-a-slozky.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Files and folders -popis: A path, an extension and order in Documents. -nazev_cviceni: Quiz: files -nadpis_kvizu: Build the path and the name ---- diff --git a/content/programove-vybaveni/1-rocnik/03-soubory-a-slozky.md b/content/programove-vybaveni/1-rocnik/03-soubory-a-slozky.md deleted file mode 100644 index 8989f5a..0000000 --- a/content/programove-vybaveni/1-rocnik/03-soubory-a-slozky.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: sw-1-soubory -nazev: Soubory a složky -popis: Cesta, přípona a pořádek v Dokumentech. -nazev_cviceni: Kvíz: soubory -nadpis_kvizu: Sestavte cestu a název ---- - -# Výklad - -## Cesta -*Kde soubor leží* - -- Cesta začíná diskem. C:\Users\novak\Documents\Skola\1-rocnik je složka, ne soubor. -- Zpětné lomítko odděluje složky. Dopředné lomítko je na webu, ne ve Windows. -- Dokumenty jsou %USERPROFILE%\Documents. Na každém účtu to vede jinam, příkaz je stejný. -- Plocha je taky složka. Soubor jen na ploše se ve školním pořádku ztratí. - -> Tip: Do řádku adresy v Průzkumníku vložte cestu a Enter. Nemusíte proklikávat pět složek. - -## Přípona -*Čím se soubor otevře* - -- prihlaska.docx je Word. znamky.xlsx je Excel. poznamka.txt je prostý text. -- Windows přípony schovává. Zapněte Zobrazit, Zobrazit, Přípony názvů souborů. -- Přejmenovat foto.jpg na foto.docx z něj dokument neudělá. Změní se jen štítek. -- Dvojitá přípona faktura.pdf.exe je program, který se tváří jako dokument. Neotevírejte ho. - -> Tip: Když přípony vidíte, podvodný soubor poznáte dřív, než na něj kliknete. - -## Názvy -*Co je zakázané* - -- V názvu nesmí být znaky \ / : * ? " < > |. -- Mezera smí být, ale v dávkových souborech pak název patří do uvozovek. -- Školní název je věcný: 2026-06-12-zadost.docx. Final-final2.docx není název. -- Datum pište rok-měsíc-den. Složka se seřadí od nejstaršího sama. - -> Tip: Kopírování je Ctrl+C, vložení Ctrl+V, přesun začíná Ctrl+X. Přesun z flashky na disk soubor na flashce smaže. - -## Zadání: strom školy -*Cvičení* - -- V Dokumentech založte Skola, v ní 1-rocnik a v ní slozky word, excel a system. -- Do word uložte prázdný soubor poznamka.txt. Příponu ať je vidět. -- Cesta ať končí na \Skola\1-rocnik\word\poznamka.txt. -- Na ploše nic nenechávejte. Koš nevysypávejte, dokud nevíte, co v něm je. - -> Tip: Nová složka je Ctrl+Shift+N. Když se jmenuje Nová složka, hned ji přejmenujte. - -# Kvíz - -## Která cesta vede k souboru v Dokumentech? -- [x] C:\Users\novak\Documents\Skola\1-rocnik\poznamka.txt -- https://skola/poznamka.txt -- poznamka.txt bez složky, to stačí vždy -- C:/Users/novak s obyčejnými lomítky jako jediná správná forma -> Ve Windows se složky oddělují zpětným lomítkem a cesta začíná diskem. - -## Co se stane, když foto.jpg přejmenujete na foto.docx? -- Stane se z něj upravitelný dokument Word -- [x] Změní se přípona, obsah zůstane obrázek -- Soubor se uloží do koše -- Vznikne tabulka Excel -> Přípona je nápověda pro systém. Bajty obrázku se samy nepřepíšou na dokument. - -## Který název je na školní odevzdání nejlepší? -- final2.docx -- [x] 2026-06-12-zadost.docx -- Nový dokument.docx -- ???.docx -> Datum rok-měsíc-den se seřadí a je z něj poznat verze. Otazník v názvu Windows ani nepustí. - -## Proč zapnout zobrazení přípon? -- Aby šly soubory mazat -- [x] Aby byl vidět skutečný typ, třeba pdf.exe -- Protože bez přípony soubor nejde uložit -- Excel to vyžaduje u každé buňky -> Skrytá přípona schová, že faktura.pdf.exe je program. diff --git a/content/programove-vybaveni/1-rocnik/04-instalace-a-aktualizace.en.md b/content/programove-vybaveni/1-rocnik/04-instalace-a-aktualizace.en.md deleted file mode 100644 index 2408177..0000000 --- a/content/programove-vybaveni/1-rocnik/04-instalace-a-aktualizace.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Installation and updates -popis: Where a program comes from and why the system is updated. -nazev_cviceni: Quiz: installation -nadpis_kvizu: Pick a safe source ---- diff --git a/content/programove-vybaveni/1-rocnik/04-instalace-a-aktualizace.md b/content/programove-vybaveni/1-rocnik/04-instalace-a-aktualizace.md deleted file mode 100644 index 4b787c9..0000000 --- a/content/programove-vybaveni/1-rocnik/04-instalace-a-aktualizace.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: sw-1-instalace -nazev: Instalace a aktualizace -popis: Odkud se program bere a proč se systém aktualizuje. -nazev_cviceni: Kvíz: instalace -nadpis_kvizu: Vyberte bezpečný zdroj ---- - -# Výklad - -## Odkud instalovat -*Zdroj* - -- Školní programy berte z Microsoft Store, z balíčku školy, nebo z webu výrobce. -- Odkaz v mailu, tlačítko Stáhnout zdarma na cizím webu a crack nejsou zdroj. -- Instalace chce souhlas správce. Okno Řízení uživatelských účtů se neodklepává poslepu. -- Na plochu nepatří deset instalačních souborů. Po instalaci je smažte, program už je v systému. - -> Tip: Název souboru setup.exe nic neříká. Říká to vydavatel v okně účtů a adresa, odkud soubor přišel. - -## Aktualizace -*Windows Update* - -- Aktualizace zašívá chyby, přes které se do počítače leze. Odkládat ji týdny je riziko. -- Windows Update je v Nastavení, Windows Update. Školní počítač nechte doběhnout. -- Restart po aktualizaci udělejte, když o něj systém požádá. Ne uprostřed testu, ale ten den. -- Word a Excel se v Microsoft 365 aktualizují se sadou Office, ne jen s Windows. - -> Tip: Verze systému z winver se po velké aktualizaci změní. Když se měsíc nemění, aktualizace stojí. - -## Odinstalace -*Aplikace* - -- Program se odebírá v Nastavení, Aplikace, Nainstalované aplikace. Ne smazáním zástupce. -- Zástupce na ploše je jen odkaz. Smazáním ikony program v počítači zůstane. -- Neznámý program, který jste neinstalovali, nejdřív nahlaste. Nemusí to být hra spolužáka. -- Odinstalace nesmaže vaše dokumenty. Smaže program. Dokumenty si před velkým úklidem zkopírujte. - -> Tip: Když v seznamu aplikací Word není a zástupce ano, zástupce vede do prázdna, nebo na jiný disk. - -## Zadání: stav počítače -*Cvičení* - -- Z winver opište verzi. V Windows Update napište, jestli je systém aktuální, nebo něco čeká. -- V nainstalovaných aplikacích najděte Word nebo Microsoft 365 a opište název, jak ho seznam uvádí. -- Najděte jeden program, který nepoznáváte, a zapište ho. Neodinstalovávejte ho bez učitele. -- Uložte stav.txt do Skola\1-rocnik\system. Nic z internetu nestahujte. - -> Tip: Čas poslední aktualizace je ve Windows Update dole v historii. Stačí datum, ne seznam všech záplat. - -# Kvíz - -## Odkud se má školní program instalovat? -- Z odkazu v neznámém mailu -- [x] Z webu výrobce, z Store, nebo z balíčku školy -- Z stránky s nápisem crack -- Z přílohy faktura.pdf.exe -> Výrobce, obchod a škola jsou zdroje. Crack a náhodný mail nejsou. - -## Co udělá smazání zástupce na ploše? -- Odinstaluje program -- [x] Smaže jen odkaz, program zůstane -- Smaže Dokumenty -- Vypne aktualizace -> Zástupce je zkratka. Program se odebírá v Nainstalovaných aplikacích. - -## Proč se Windows Update nenechává měsíc stát? -- Protože jinak nejde otevřít Word -- [x] Záplaty zavírají známé díry -- Protože se jinak smaže plocha -- Aktualizace jen mění tapetu -> Neaktualizovaný systém má chyby, které už jsou veřejně popsané. - -## Kdy odklepnete okno Řízení uživatelských účtů? -- Vždycky, ať instalace pokračuje -- [x] Jen když víte, jaký program a odkud ho spouštíte -- Nikdy, ani u školního balíčku -- Jen v Excelu -> Okno říká, že program chce právo správce. Neznámý vydavatel se neodklepává. diff --git a/content/programove-vybaveni/1-rocnik/05-ucty.en.md b/content/programove-vybaveni/1-rocnik/05-ucty.en.md deleted file mode 100644 index b525df1..0000000 --- a/content/programove-vybaveni/1-rocnik/05-ucty.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: User accounts -popis: A standard user, an administrator and a password that is not the account name. -nazev_cviceni: Quiz: accounts -nadpis_kvizu: Pick the account type and the password ---- diff --git a/content/programove-vybaveni/1-rocnik/05-ucty.md b/content/programove-vybaveni/1-rocnik/05-ucty.md deleted file mode 100644 index fc41b33..0000000 --- a/content/programove-vybaveni/1-rocnik/05-ucty.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: sw-1-ucty -nazev: Uživatelské účty -popis: Běžný uživatel, správce a heslo, které není jméno účtu. -nazev_cviceni: Kvíz: účty -nadpis_kvizu: Vyberte typ účtu a heslo ---- - -# Výklad - -## Dva typy -*Správce a uživatel* - -- Správce smí instalovat programy a měnit systém. Ve škole je to účet učitele nebo správce učebny. -- Běžný uživatel smí pracovat se svými soubory. Systémové složky mu systém zamkne. -- Denní práce nepatří na účet správce. Virus by dostal stejná práva jako vy. -- Nový školní účet pro cvičení se jmenuje zaci a je běžný uživatel, ne správce. - -> Tip: Když systém požádá o heslo správce, běžný účet na to nestačí. To je záměr, ne porucha. - -## Heslo -*Osm znaků* - -- Heslo má aspoň 8 znaků a není to jméno účtu, ani slovo heslo, ani 12345678. -- Do příkazu se heslo nepíše. Příkaz net user zaci * /add se na heslo zeptá a na obrazovce ho neukáže. -- Heslo na papírek na monitor nepatří. Patří do hlavy, nebo do školního sejfu hesel, když ho učitel určí. -- Cizí heslo se nezkouší. Ani když je účet spolužáka odhlášený a počítač je společný. - -> Tip: Hvězdička v net user znamená dotaz na heslo. Heslo napsané za příkazem zůstane v historii příkazů. - -## Vlastní soubory -*Profil* - -- Profil je složka C:\Users\zaci. Jsou v ní Dokumenty, Plocha a Stažené soubory. -- Soubor uložený do Dokumentů tohoto účtu jiný běžný uživatel neotevře. -- Společná složka C:\Users\Public je pro věci, které mají vidět všichni. Úkoly tam nedávejte. -- Odhlášení účet zavře. Vypnutí počítače taky. Přepnutí uživatele nechá první účet otevřený v paměti. - -> Tip: Na sdíleném počítači se odhlašujte. Přepnutí uživatele nechá otevřené dokumenty v paměti. - -## Zadání: účet na papíře -*Cvičení* - -- Napište, jak by se založil běžný účet zaci: příkaz net user zaci * /add spuštěný jako správce. -- Napište heslo, které pravidlům nevyhovuje, a druhé, které má aspoň 8 znaků a není jméno účtu. Skutečné školní heslo nepište. -- Účet nesmí být ve skupině Administrators. Patří mezi běžné Users. -- Uložte ucet.txt do Skola\1-rocnik\system. Účet v systému zakládejte jen když to učitel výslovně řekne. - -> Tip: Kdo jsem, zjistí příkaz whoami. Když vypíše správce, na denní práci jste na špatném účtu. - -# Kvíz - -## Jaký má být cvičný účet zaci? -- Správce, ať jde všechno -- [x] Běžný uživatel -- Účet bez hesla -- Účet hosta sdílený celou třídou bez hesla -> Denní práce běží jako běžný uživatel. Správce je na instalaci a správu, ne na Word. - -## Jak se heslo předá příkazu net user? -- Napíše se za příkaz, ať je v sešitě vidět -- [x] Hvězdičkou, příkaz se zeptá a heslo neukáže -- Do názvu účtu -- Do souboru na plochu -> net user zaci * /add se zeptá. Heslo v příkazu zůstane v historii. - -## Proč se denně nepracuje jako správce? -- Word jinak nejde otevřít -- [x] Program, který spustíte, dostane právo měnit systém -- Správce nemá Dokumenty -- Excel jinak nepočítá -> Škodlivý program dědí vaše práva. U správce smí instalovat a měnit systém. - -## Kam patří osobní úkol? -- Do C:\Users\Public -- [x] Do Dokumentů vlastního účtu -- Do složky Windows -- Na účet spolužáka -> Public vidí každý účet na počítači. Úkol patří do vlastního profilu. diff --git a/content/programove-vybaveni/1-rocnik/06-spravce-uloh.en.md b/content/programove-vybaveni/1-rocnik/06-spravce-uloh.en.md deleted file mode 100644 index b9e7a54..0000000 --- a/content/programove-vybaveni/1-rocnik/06-spravce-uloh.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Task Manager -popis: A process, memory and startup programs. The system is not ended. -nazev_cviceni: Quiz: Task Manager -nadpis_kvizu: Pick what you may end ---- diff --git a/content/programove-vybaveni/1-rocnik/06-spravce-uloh.md b/content/programove-vybaveni/1-rocnik/06-spravce-uloh.md deleted file mode 100644 index 45405b1..0000000 --- a/content/programove-vybaveni/1-rocnik/06-spravce-uloh.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: sw-1-spravce-uloh -nazev: Správce úloh -popis: Proces, paměť a programy po spuštění. Systém se neukončuje. -nazev_cviceni: Kvíz: Správce úloh -nadpis_kvizu: Vyberte, co smíte ukončit ---- - -# Výklad - -## Okno -*Ctrl+Shift+Esc* - -- Správce úloh se otevře Ctrl+Shift+Esc. Nehledá se přes náhodné ikony na ploše. -- Karta Procesy ukáže aplikace a to, co běží na pozadí. -- Sloupec Procesor je v procentech. Sloupec Paměť je v megabajtech. -- Vysoká paměť u prohlížeče s dvaceti kartami je běžná. Vysoká paměť neznámého procesu se hlásí. - -> Tip: Když plocha nereaguje, Ctrl+Shift+Esc často projde i tehdy, když nabídka Start ne. - -## Ukončit se smí aplikace -*Ne systém* - -- Ukončit úlohu smíte u svého Wordu, který nereaguje. Rozpracovaný dokument si předtím uložte, jinak o něj přijdete. -- Proces Systém, Registr a aplikace systému Windows se neukončují. Počítač pak nemusí doběhnout do restartu. -- Neznámý proces nejdřív vyhledejte podle přesného názvu. Ukončení není první krok. -- Restart počítače je čistší než ukončit deset systémových procesů za sebou. - -> Tip: Word, který nereaguje, ukončete a otevřete znovu. Autorecover často dokument vrátí, ale nespoléhejte na něj. - -## Po spuštění -*Co startuje samo* - -- Karta Aplikace po spuštění ukáže programy, které naběhnou s Windows. -- Každý takový program bere čas startu a paměť. Ve škole jich má být málo. -- Vypnutí Teams nebo prohlížeče po spuštění, když ho učitel nechce, je v pořádku. Vypnutí zabezpečení Windows není. -- Změna se projeví po příštím přihlášení, ne vždy hned. - -> Tip: Povolené a zakázané je v posledním sloupci. Zakázaný program v počítači zůstane, jen se sám nespustí. - -## Zadání: jeden pohled -*Cvičení* - -- Otevřete Správce úloh a zapište tři aplikace, které berou nejvíc paměti. Čísla opište. -- Najděte, jestli s Windows startuje něco, co nepoznáváte. Neznámé nevypínejte, jen ho zapište. -- Systémové procesy neukončujte. Když Word nereaguje, ukončete jen Word. -- Uložte procesy.txt do Skola\1-rocnik\system. - -> Tip: Řazení podle paměti je kliknutí na záhlaví sloupce Paměť. První řádek je pak ten nejtěžší. - -# Kvíz - -## Jakou zkratkou se otevře Správce úloh? -- [x] Ctrl+Shift+Esc -- Ctrl+S -- Win+E je Správce úloh -- Alt+F4 na ploše -> Ctrl+Shift+Esc otevře Správce přímo. Win+E je Průzkumník. - -## Co smíte ukončit, když nereaguje vaše práce? -- Proces Systém -- [x] Svůj Word, který nereaguje -- Registr -- Zabezpečení Windows -> Ukončuje se zaseknutá aplikace. Systémové procesy drží počítač. - -## Co dělá vypnutí programu na kartě Po spuštění? -- Odinstaluje ho -- [x] Příště se sám nespustí s Windows -- Smaže Dokumenty -- Zakáže aktualizace -> Program v počítači zůstane. Nenaběhne jen sám při přihlášení. - -## Vysoká paměť u prohlížeče s mnoha kartami znamená co? -- Že se má hned ukončit Systém -- [x] Že prohlížeč prostě drží otevřené karty -- Že je disk NTFS rozbitý -- Že vypršela licence -> Každá karta bere paměť. Neznámý proces je jiný případ než prohlížeč, který jste sami otevřeli. diff --git a/content/programove-vybaveni/1-rocnik/07-zabezpeceni.en.md b/content/programove-vybaveni/1-rocnik/07-zabezpeceni.en.md deleted file mode 100644 index aaec038..0000000 --- a/content/programove-vybaveni/1-rocnik/07-zabezpeceni.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Securing the computer -popis: Antivirus, updates and a file that pretends to be a document. -nazev_cviceni: Quiz: security -nadpis_kvizu: Pick what stays on and what stays closed ---- diff --git a/content/programove-vybaveni/1-rocnik/07-zabezpeceni.md b/content/programove-vybaveni/1-rocnik/07-zabezpeceni.md deleted file mode 100644 index 803fd77..0000000 --- a/content/programove-vybaveni/1-rocnik/07-zabezpeceni.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: sw-1-zabezpeceni -nazev: Zabezpečení počítače -popis: Antivir, aktualizace a soubor, který se tváří jako dokument. -nazev_cviceni: Kvíz: zabezpečení -nadpis_kvizu: Vyberte, co se nezapíná a co se neotvírá ---- - -# Výklad - -## Zabezpečení Windows -*Defender* - -- Školní Windows mají Zabezpečení Windows. Antivir se nevypíná kvůli instalaci hry. -- Ochrana v reálném čase má být zapnutá. Vypnutá ochrana je nález, ne úleva. -- Brána firewall má být zapnutá na školní síti. Vypnutí kvůli jedné hře se nedělá. -- Druhý antivir vedle Defenderu se bez učitele neinstaluje. Dva se perou a oba pak hlídají hůř. - -> Tip: Zabezpečení Windows otevřete z nabídky Start. Zelené fajfky u položek jsou stav, který opisujete do úkolu. - -## Soubory a maily -*Co neotvírat* - -- Příloha faktura.pdf.exe se neotevírá, ani když text mailu zní věcně. -- Odkaz na přihlášení, který nečekáte, se neotvírá. Škola po hesle v mailu nepátrá. -- Flash disk neznámého původu se do školního počítače nestrká. Nejdřív učitel. -- Makro ve Wordu se povoluje, jen když dokument přišel ze školy a učitel řekl proč. - -> Tip: Heslo se neposílá mailem ani do chatu. Kdo ho po vás chce zprávou, nemá ho dostat. - -## Oprávnění k souboru -*NTFS* - -- Pravý klik na složku, Vlastnosti, Zabezpečení ukáže, kdo smí číst a kdo zapisovat. -- Běžný uživatel zapíše do svých Dokumentů. Do C:\Windows nezapíše. -- Odebrat si vlastní právo číst vlastní Dokumenty je chyba. Složka pak nejde otevřít. -- Společná složka Public nemá být místo, kam dáváte test s jménem. - -> Tip: Když soubor nejde uložit, často nemáte právo zápisu. Uložte ho do Dokumentů, ne do Program Files. - -## Zadání: pět kontrol -*Cvičení* - -- Opište, jestli je ochrana v reálném čase zapnutá a jestli firewall hlásí zapnuto. -- Z Windows Update opište, jestli něco čeká na restart. -- Najděte ve stažených souborech, jestli tam není soubor s dvojitou příponou. Neotvírejte ho, zapište název. -- Uložte bezpecnost.txt do Skola\1-rocnik\system. Ochranu nevypínejte. - -> Tip: Když je ochrana vypnutá, nezapínejte ji naslepo třemi kliky v neznámém okně. Řekněte to učiteli, může ji vypínat školní správa. - -# Kvíz - -## Co má být zapnuté v Zabezpečení Windows? -- Nic, antivir zpomaluje Word -- [x] Ochrana v reálném čase a firewall -- Jen spořič obrazovky -- Jen OneDrive -> Antivir i firewall jsou součást školního počítače. Nevypínají se kvůli pohodlí. - -## Který soubor neotevřete? -- poznamka.txt z vlastní složky -- [x] faktura.pdf.exe z mailu -- zadost.docx, kterou jste sami uložili -- znamky.xlsx z hodiny -> Dvojitá přípona exe je program. Mail s fakturou ho nesmí spustit. - -## Kam běžný uživatel smí uložit úkol? -- Do C:\Windows -- [x] Do svých Dokumentů -- Do složky ovladačů -- Přes cizí účet -> Dokumenty vlastního účtu jsou na zápis. Systémové složky ne. - -## Proč se vedle Defenderu bez učitele nedává druhý antivir? -- Windows umí jen jeden a druhý se vždy sám smaže -- [x] Dva antiviry se navzájem ruší -- Defender je freeware bez licence -- Excel pak neumí SUMA -> Dva programy, které hlídají stejné soubory, se blokují. Ve škole stačí Zabezpečení Windows. diff --git a/content/programove-vybaveni/1-rocnik/08-zadani-windows.en.md b/content/programove-vybaveni/1-rocnik/08-zadani-windows.en.md deleted file mode 100644 index 847262b..0000000 --- a/content/programove-vybaveni/1-rocnik/08-zadani-windows.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Assignment: a school account and a tidy disk -popis: Folders, a standard account, updates and protection in one note. -nazev_cviceni: Quiz: the school account -nadpis_kvizu: Check the whole assignment ---- diff --git a/content/programove-vybaveni/1-rocnik/08-zadani-windows.md b/content/programove-vybaveni/1-rocnik/08-zadani-windows.md deleted file mode 100644 index 862c127..0000000 --- a/content/programove-vybaveni/1-rocnik/08-zadani-windows.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: sw-1-zadani-windows -nazev: Zadání: školní účet a pořádek -popis: Složky, běžný účet, aktualizace a ochrana v jednom zápisu. -nazev_cviceni: Kvíz: školní účet -nadpis_kvizu: Zkontrolujte celé zadání ---- - -# Výklad - -## Složky -*Strom* - -- V Dokumentech je Skola\1-rocnik a v ní word, excel a system. -- Na ploše nezůstane pracovní soubor. Plocha není archiv. -- Přípony názvů jsou vidět. poznámka se nejmenuje poznámka.txt.txt. -- Názvy jsou bez znaků \ / : * ? a datum v názvu je rok-měsíc-den. - -> Tip: Cestu opište z řádku adresy. Od oka se lomítka pletou. - -## Účet -*zaci* - -- Cvičný účet zaci je běžný uživatel. Není ve skupině Administrators. -- Heslo má aspoň 8 znaků a nezadává se do příkazu, jen přes hvězdičku v net user zaci * /add. -- Do zápisu nepatří skutečné heslo. Patří tam pravidlo a příkaz bez hesla. -- whoami na denní práci nemá ukázat účet správce. - -> Tip: Účet zakládejte jen pod dohledem. V zápisu stačí postup, když učitel účet na počítači nechce. - -## Stav systému -*Tři řádky* - -- winver: edice a verze. -- Windows Update: aktuální, nebo čeká restart. Datum stačí. -- Zabezpečení Windows: ochrana v reálném čase zapnutá, firewall zapnutý. -- Ze Správce úloh tři nejtěžší aplikace podle paměti. Systémové procesy neukončené. - -> Tip: Když je něco vypnuté, zapište to jako nález. Neopravujte firewall naslepo. - -## Odevzdání -*Jeden soubor* - -- Všechno je v ucto-windows.txt ve složce Skola\1-rocnik\system. -- Jsou tam cesta ke složce word, popis účtu, verze Windows a stav ochrany. -- Není tam heslo, není tam cizí soubor a není tam vypnutý Defender. -- Soubor otevřete znovu a přečtěte ho. Cesta v textu musí po vložení do adresy opravdu vyjít. - -> Tip: Když cesta z textu skončí chybou, složka neexistuje, nebo je v cestě obyčejné lomítko. - -# Kvíz - -## Jaký účet je zaci? -- Správce -- [x] Běžný uživatel mimo skupinu Administrators -- Účet bez hesla v Public -- Sdílený účet celé třídy -> Denní účet není správce. Heslo má a do skupiny Administrators nepatří. - -## Kam se ukládá pracovní soubor? -- Na plochu -- [x] Do Skola\1-rocnik a příslušné složky -- Do C:\Windows -- Do stažených souborů bez názvu -> Plocha se nearchivuje. Strom Skola drží word, excel a system odděleně. - -## Co má být zapnuté? -- Jen spořič -- [x] Ochrana v reálném čase a firewall -- Dva antiviry -- Sdílení celé složky Users -> Defender a firewall zůstávají zapnuté. Do úkolu se opisuje jejich stav. - -## Co v souboru ucto-windows.txt být nesmí? -- Verze z winver -- [x] Skutečné heslo -- Cesta ke složce -- Stav Windows Update -> Heslo se do textového úkolu nepíše. Příkaz ho bere přes hvězdičku, ne do sešitu. diff --git a/content/programove-vybaveni/2-rocnik/01-word-styly.en.md b/content/programove-vybaveni/2-rocnik/01-word-styly.en.md deleted file mode 100644 index 92c3344..0000000 --- a/content/programove-vybaveni/2-rocnik/01-word-styly.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Word: styles -popis: Heading 1, body text and spacing that is not empty lines. -nazev_cviceni: Quiz: styles -nadpis_kvizu: Pick the style and the shortcut ---- diff --git a/content/programove-vybaveni/2-rocnik/01-word-styly.md b/content/programove-vybaveni/2-rocnik/01-word-styly.md deleted file mode 100644 index b0a2f8d..0000000 --- a/content/programove-vybaveni/2-rocnik/01-word-styly.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: sw-2-word-styly -nazev: Word: styly -popis: Nadpis 1, normální text a mezery, které nejsou prázdné řádky. -nazev_cviceni: Kvíz: styly -nadpis_kvizu: Vyberte styl a zkratku ---- - -# Výklad - -## Styl, ne ruční tučné -*Nadpis* - -- Nadpis 1 je styl. Ctrl+Alt+1 ho zapne. Nadpis 2 je Ctrl+Alt+2. -- Tučné a větší písmo místo stylu vypadá jako nadpis, ale obsah z něj Word nesestaví. -- Normální text je styl Normální. Ctrl+Shift+N ho vrátí, když jste omylem v nadpisu. -- V dokumentu jsou nejvýš tři úrovně nadpisů. Čtvrtá je už nepřehledná. - -> Tip: Podokno Styly otevřete z karty Domů. U odstavce je vidět, jaký styl opravdu má. - -## Odstavec -*Mezery ze stylu* - -- Prázdný Enter mezi odstavci se nedělá. Mezera se nastaví ve stylu, třeba 8 bodů za odstavcem. -- Řádkování školního textu je 1,15 nebo 1,5. Ne dvojité přes celou stránku bez důvodu. -- Zarovnání do bloku u delšího textu, vlevo u nadpisu a u krátkého dopisu. -- Stránka je A4. Okraje 2,5 cm ze všech stran, to je předvolba Normální. - -> Tip: Konec stránky je Ctrl+Enter. Řada Enterů na další stránku se při úpravě rozjede. - -## Soubor -*docx a pdf* - -- Pracovní soubor je .docx. Jdou v něm styly i další úpravy. -- Na odevzdání, které se už nemá měnit, je navíc PDF. -- Jednou vyexportované PDF neupravujte dál jako jediný zdroj. Opravte docx a PDF udělejte znovu. -- Název je věcný: 2026-06-12-protokol.docx. Dokument1.docx se neodevzdává. - -> Tip: Soubor, Export, Vytvořit soubor PDF. Před exportem se podívejte na náhled tisku, jestli nadpis nesedí sám na konci stránky. - -## Zadání: dvoustránkový text -*Cvičení* - -- Dokument A4, okraje 2,5 cm, aspoň tři nadpisy stylem Nadpis 1. -- Pod každým nadpisem aspoň jeden odstavec stylem Normální. Žádné prázdné Entery mezi nimi. -- Konec první stránky je Ctrl+Enter, ne deset prázdných řádků. -- Uložte protokol.docx do Skola\1-rocnik\word a k němu protokol.pdf. - -> Tip: Když v navigačním podokně nadpisy nejsou, jsou to jen tučná písma. Označte je a dejte Ctrl+Alt+1. - -# Kvíz - -## Jak se má udělat nadpis, aby z něj šel obsah? -- Tučně a 16 bodů -- [x] Stylem Nadpis 1, zkratka Ctrl+Alt+1 -- Pěti prázdnými Entery nad ním -- Obrázkem textu -> Obsah čte styly. Ruční tučné písmo v obsahu není. - -## Čím se přejde na další stránku? -- Deseti Entery -- [x] Ctrl+Enter -- Mezerou za odstavcem 80 bodů -- Smazáním okrajů -> Ctrl+Enter je konec stránky. Prázdné řádky se při doplnění textu rozjedou. - -## Jaké jsou školní okraje na A4? -- 0 cm, ať se vejde víc -- [x] 2,5 cm, předvolba Normální -- 5 cm vpravo a 0 vlevo -- Okraje se ve Wordu nenastavují -> Normální okraj je 2,5 cm. Text až do kraje papíru tiskárna často ořízne. - -## Který soubor se dál upravuje? -- PDF -- [x] docx -- Jen vytištěná stránka -- Příloha exe -> docx drží styly. PDF je kopie na odevzdání. diff --git a/content/programove-vybaveni/2-rocnik/02-word-tabulka-a-obsah.en.md b/content/programove-vybaveni/2-rocnik/02-word-tabulka-a-obsah.en.md deleted file mode 100644 index 9a94510..0000000 --- a/content/programove-vybaveni/2-rocnik/02-word-tabulka-a-obsah.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Word: a table, a header and a table of contents -popis: A 4 by 3 table, a page number and a contents list from the headings. -nazev_cviceni: Quiz: contents -nadpis_kvizu: Pick where the contents come from ---- diff --git a/content/programove-vybaveni/2-rocnik/02-word-tabulka-a-obsah.md b/content/programove-vybaveni/2-rocnik/02-word-tabulka-a-obsah.md deleted file mode 100644 index ce559e7..0000000 --- a/content/programove-vybaveni/2-rocnik/02-word-tabulka-a-obsah.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: sw-2-word-obsah -nazev: Word: tabulka, záhlaví a obsah -popis: Tabulka 4×3, číslo stránky a obsah z nadpisů. -nazev_cviceni: Kvíz: obsah -nadpis_kvizu: Vyberte, odkud se obsah vezme ---- - -# Výklad - -## Tabulka -*4 řádky a 3 sloupce* - -- Tabulka se vkládá z karty Vložení. Kreslení tužkou od ruky se ve školním protokolu nedělá. -- Školní tabulka má 4 řádky a 3 sloupce: záhlaví a tři záznamy. -- Záhlaví tabulky je tučné a řádek se neopakuje jako obyčejný text pod tabulkou. -- Text v buňce se nezalamuje deseti mezerami. Šířka sloupce se táhne myší. - -> Tip: Když potřebujete řádek navíc, klepněte vpravo od řádku a dejte vložit. Enter v buňce jen zalomí text. - -## Záhlaví a zápatí -*Číslo stránky* - -- Záhlaví je nahoře, zápatí dole. Dvojklik v okraji je otevře. -- V záhlaví je název školy a název dokumentu. V zápatí je číslo stránky. -- Číslo stránky se vloží jako pole. Ručně napsaná jednička se na druhé stránce neposune. -- Záhlaví není nadpis dokumentu. Nadpis zůstává v textu jako Nadpis 1. - -> Tip: Pole čísla stránky má po označení šedé pozadí. Když je to obyčejná číslice, na další stránce se nezmění. - -## Obsah -*Z nadpisů* - -- Obsah je na kartě Reference, Obsah. Word ho složí z Nadpis 1 a Nadpis 2. -- Ručně psaný seznam stránek obsah není. Po vložení odstavce se rozejde. -- Po změně textu se obsah aktualizuje pravým klikem, Aktualizovat pole, a volbou celá tabulka. -- Obsah stojí na začátku, za titulní řádek, na vlastní stránce nebo hned pod názvem. Ne na konci. - -> Tip: Když je obsah prázdný, nadpisy nejsou styly. Ctrl+Alt+1 a obsah aktualizujte znovu. - -## Zadání: protokol s tabulkou -*Cvičení* - -- Vezměte protokol.docx. Přidejte tabulku 4×3: sloupec Jméno, Třída, Stav. -- Tři řádky: Anna Nováková, 1.A, odevzdáno. Druhý a třetí řádek doplňte vlastními jmény. -- Záhlaví s názvem školy, zápatí s číslem stránky, obsah z nadpisů na začátku. -- Uložte znovu docx a nové PDF. Staré PDF přepište, ať neexistují dvě verze. - -> Tip: Aktualizace obsahu se ptá, jestli jen čísla, nebo celá tabulka. Po nových nadpisech berte celou tabulku. - -# Kvíz - -## Jak velká je školní tabulka v tomto úkolu? -- [x] 4 řádky a 3 sloupce -- Jedna buňka -- 10 sloupců bez záhlaví -- Tabulka se ve Wordu nedělá -> Záhlaví plus tři záznamy jsou čtyři řádky. Sloupce jsou Jméno, Třída a Stav. - -## Odkud Word vezme obsah? -- Z tučných vět -- [x] Ze stylů Nadpis 1 a Nadpis 2 -- Z zápatí -- Z Excelu automaticky vždy -> Bez stylů nadpisů je obsah prázdný. Tučné písmo nestačí. - -## Jak se má dostat na stránku číslo? -- Napsat 1 do zápatí ručně -- [x] Vložit pole čísla stránky -- Dát ho do názvu souboru -- Nepsat ho, Word ho do PDF doplní sám i bez pole -> Pole se na každé stránce samo zvýší. Ruční jednička zůstane jednička. - -## Kdy se obsah aktualizuje celý, ne jen čísla stránek? -- [x] Když přibyl nadpis -- Když se jen změnila šířka okraje o milimetr a nadpisy zůstaly -- Po každém písmenu -- Obsah se neaktualizuje nikdy -> Nový nadpis do obsahu přibude jen při aktualizaci celé tabulky. diff --git a/content/programove-vybaveni/2-rocnik/03-word-dopis.en.md b/content/programove-vybaveni/2-rocnik/03-word-dopis.en.md deleted file mode 100644 index 6a953ff..0000000 --- a/content/programove-vybaveni/2-rocnik/03-word-dopis.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Word: a formal letter -popis: Sender, date, subject, greeting, body and signature on one page. -nazev_cviceni: Quiz: the letter -nadpis_kvizu: Put the parts in order ---- diff --git a/content/programove-vybaveni/2-rocnik/03-word-dopis.md b/content/programove-vybaveni/2-rocnik/03-word-dopis.md deleted file mode 100644 index 288e40f..0000000 --- a/content/programove-vybaveni/2-rocnik/03-word-dopis.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: sw-2-word-dopis -nazev: Word: úřední dopis -popis: Odesílatel, datum, věc, oslovení, text a podpis na jedné straně. -nazev_cviceni: Kvíz: dopis -nadpis_kvizu: Seřaďte náležitosti ---- - -# Výklad - -## Náležitosti -*Shora dolů* - -- Vlevo nahoře odesílatel: škola, jméno, adresa. Vpravo datum 12. 6. 2026. -- Pod tím adresát. Pak řádek Věc: žádost o uvolnění z výuky. -- Oslovení, text, rozloučení a jméno s podpisem. Podpis je pod jménem, ne místo něj. -- Celý dopis je jedna strana A4. Druhá stránka s jedním řádkem je chyba. - -> Tip: Datum pište 12. 6. 2026, ne 12/6/26. Český úřední dopis má den, měsíc a rok. - -## Vzhled -*Klidný dopis* - -- Písmo jedno, třeba Calibri 11 nebo 12. V dopise není Nadpis 1 přes celou šířku. -- Řádek Věc je tučný nebo jako krátký nadpis, zbytek je Normální. -- Odstavce mají mezeru za sebou. Mezi oslovením a textem není deset Enterů. -- Okraje 2,5 cm. Text do bloku. Bez obrázku, bez tabulky, bez obsahu. - -> Tip: Když se poslední řádek podpisu sleze na druhou stránku, zkraťte mezeru za odstavcem, nepřidávejte menší okraje než 2 cm. - -## Hromadná pošta -*Až když je řádků víc* - -- Jeden dopis se píše přímo. Hromadná korespondence se vyplatí, když je adresátů aspoň deset. -- Zdroj dat je Excel s řádkem záhlaví: Jmeno, Prijmeni, Trida. -- Word na kartě Korespondence vezme tento sešit a pole vloží do oslovení. -- Sloučený výsledek se ukládá jako nový docx. Zdrojový dopis s poli si nechte zvlášť. - -> Tip: Když Excel nemá záhlaví, první žák se stane názvem sloupce a z hromadné pošty vypadne. - -## Zadání: žádost -*Cvičení* - -- Napište žádost o uvolnění z výuky na 12. 6. 2026. Adresát je ředitel školy, odesílatel jste vy. -- V dokumentu je Věc, oslovení, aspoň dvě věty důvodu a podpis. -- Jedna strana, A4, okraje 2,5 cm. Uložte zadost.docx a zadost.pdf do složky word. -- Hromadnou poštu v tomto úkolu nedělejte. Stačí jeden dopis. - -> Tip: Přečtěte dopis nahlas. Když v něm chybí, o co žádáte a který den, věta důvodu nestačí. - -# Kvíz - -## Kam patří datum v tomto dopisu? -- Dospodu místo podpisu -- [x] Dopravna, 12. 6. 2026 -- Do názvu souboru jako jediné místo -- Do zápatí místo čísla, datum v textu být nesmí -> Datum je vpravo nahoře. Podpis dole je jméno, ne datum. - -## Jak se označí, o co v dopise jde? -- [x] Řádkem Věc -- Stylem Nadpis 3 uprostřed stránky -- Obrázkem razítka -- Obsahem na druhé straně -> Věc je krátký řádek nad oslovením, třeba žádost o uvolnění z výuky. - -## Kdy se použije hromadná korespondence? -- Na jeden dopis řediteli -- [x] Když je stejný dopis pro deset a víc adresátů a data jsou v Excelu -- Na každou tabulku -- Místo PDF -> Jeden dopis se píše ručně. Hromadná pošta bere řádky z Excelu se záhlavím. - -## Jak dlouhý je školní dopis z tohoto zadání? -- [x] Jedna strana A4 -- Přesně tři strany -- Půl stránky a zbytek prázdných Enterů -- Deset stran se styly Nadpis 1 -> Žádost se vejde na jednu stranu. Druhá stránka jen s podpisem je špatně zalomená. diff --git a/content/programove-vybaveni/2-rocnik/04-excel-bunky.en.md b/content/programove-vybaveni/2-rocnik/04-excel-bunky.en.md deleted file mode 100644 index 17e029c..0000000 --- a/content/programove-vybaveni/2-rocnik/04-excel-bunky.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Excel: cells and formulas -popis: The address A1, a formula with an equals sign and a dollar lock. -nazev_cviceni: Quiz: cells -nadpis_kvizu: Complete the formula ---- diff --git a/content/programove-vybaveni/2-rocnik/04-excel-bunky.md b/content/programove-vybaveni/2-rocnik/04-excel-bunky.md deleted file mode 100644 index 9ac18a5..0000000 --- a/content/programove-vybaveni/2-rocnik/04-excel-bunky.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: sw-2-excel-bunky -nazev: Excel: buňky a vzorce -popis: Adresa A1, vzorec se rovnítkem a ukotvení dolarama. -nazev_cviceni: Kvíz: buňky -nadpis_kvizu: Doplňte vzorec ---- - -# Výklad - -## Buňka -*Adresa* - -- Sloupce jsou písmena, řádky čísla. B2 je druhý sloupec a druhý řádek. -- Do buňky patří jedna hodnota. Jméno a třída do jedné buňky nepatří. -- Číslo je číslo, text je text. Jeden apostróf před číslem z něj udělá text a přestane se sčítat. -- Sešit je soubor xlsx. List je záložka dole. Školní sešit má listy Ceník a Součet. - -> Tip: Klik na záhlaví sloupce označí celý sloupec. Na číslo řádku celý řádek. - -## Vzorec -*Rovnítko* - -- Vzorec začíná =. Bez rovnítka je B2*C2 jen text a nic nespočítá. -- V ceníku je v D2 vzorec =B2*C2. B je počet, C je cena, D je částka. -- Český Excel odděluje argumenty funkcí středníkem. Krát je hvězdička, děleno lomítko. -- Vzorec se kopíruje za úchyt v pravém dolním rohu buňky. Neopisuje se do pěti buněk ručně. - -> Tip: Když buňka ukáže vzorec místo výsledku, je sloupec úzký, nebo je buňka text. Zkontrolujte rovnítko. - -## Posun a dolar -*A1 a $A$1* - -- Zkopírování =B2*C2 o řádek níž udělá =B3*C3. Adresy se posunou. -- =$B$2 se neposune ani ve sloupci, ani v řádku. Dolar kotví. -- Sazba DPH v buňce F1 se ve vzorcích bere jako $F$1, ať kopírování neodjede na F2. -- Smazání hodnoty, na kterou vzorec ukazuje, udělá chybu. Vzorec na prázdnou buňku není nula sám od sebe, když čekal číslo a dostal text. - -> Tip: Dolar jen u písmene, $B2, kotví sloupec. Dolar jen u čísla, B$2, kotví řádek. - -## Zadání: ceník -*Cvičení* - -- List Ceník: sloupce Polozka, Pocet, Cena, Castka. Záhlaví v řádku 1, pět položek v řádcích 2 až 6. -- Castka v D2 je =B2*C2 a dolů se táhne. Žádná částka není napsaná ručně. -- Sazba v F1 je 0,21 a v E2 je =D2*$F$1. Po zkopírování dolů pořád ukazuje na F1. -- Uložte cenik.xlsx do Skola\1-rocnik\excel. - -> Tip: Klik na D2 ukáže vzorec v řádku vzorců. Když tam je jen číslo, částka je opsaná a při změně počtu se nehne. - -# Kvíz - -## Čím začíná vzorec? -- Závorkou -- [x] Rovnítkem -- Středníkem -- Dolarama bez rovnítka -> Bez = Excel nic nepočítá. Text B2*C2 zůstane text. - -## Co je v D2, když počet je v B2 a cena v C2? -- [x] =B2*C2 -- B2*C2 bez rovnítka -- =B2+C2 -- Ručně spočítané číslo -> Částka je součin. Sčítání by sečetlo počet s cenou, což není částka. - -## Proč je sazba ve vzorci $F$1? -- [x] Aby se při kopírování dolů adresa neposunula -- Protože dolar je měna tabulky -- Aby vzorec přestal počítat -- $ se v Excelu nesmí -> F1 je jedna buňka pro všechny řádky. Bez dolarů by druhý řádek četl F2. - -## Co udělá zkopírování =B2*C2 o řádek níž? -- Nechá B2 a C2 -- [x] Vznikne =B3*C3 -- Smaže list -- Změní se na text -> Relativní adresa se posune o stejný počet řádků jako kopírování. diff --git a/content/programove-vybaveni/2-rocnik/05-excel-funkce.en.md b/content/programove-vybaveni/2-rocnik/05-excel-funkce.en.md deleted file mode 100644 index 06d600d..0000000 --- a/content/programove-vybaveni/2-rocnik/05-excel-funkce.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Excel: functions -popis: SUM, IF and VLOOKUP. The Czech edition separates arguments with a semicolon. -nazev_cviceni: Quiz: functions -nadpis_kvizu: Pick the right formula ---- diff --git a/content/programove-vybaveni/2-rocnik/05-excel-funkce.md b/content/programove-vybaveni/2-rocnik/05-excel-funkce.md deleted file mode 100644 index 67c6907..0000000 --- a/content/programove-vybaveni/2-rocnik/05-excel-funkce.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: sw-2-excel-funkce -nazev: Excel: funkce -popis: SUMA, KDYŽ a SVYHLEDAT. V české verzi se argumenty oddělují středníkem. -nazev_cviceni: Kvíz: funkce -nadpis_kvizu: Vyberte správný zápis ---- - -# Výklad - -## Souhrny -*SUMA a spol.* - -- SUMA(D2:D6) sečte částky. Průměr je PRŮMĚR, nejmenší MIN, největší MAX. -- POČET spočítá čísla. Prázdnou buňku nepočítá. Text nepočítá. -- Rozsah D2:D6 zahrnuje oba konce. D2:D6 jsou řádky 2 až 6, ne jen 2 a 6. -- Souhrn patří pod tabulku, nebo na list Součet. Nepočítá se na papír a neopisuje se. - -> Tip: Anglický Excel má SUM a čárku. Český má SUMA a středník. Ve škole pište česky, jak to má školní Office. - -## KDYŽ -*Známky* - -- České známky: 1 je nejlepší, 5 je neprospěl. Prospěch je známka 1 až 4. -- =KDYŽ(D2<=4;"prospěl";"neprospěl") vrací text podle známky v D2. -- Středníky oddělují podmínku, větev ano a větev ne. Čárka v české verzi vzorec rozbije. -- Podmínka, která čeká známku aspoň 4 jako úspěch, je obráceně. Čtyřka ještě prochází, pětka ne. - -> Tip: Uvozovky kolem textu ve funkci jsou povinné. Bez nich Excel hledá buňku nebo název. - -## SVYHLEDAT -*Ceník* - -- SVYHLEDAT najde hodnotu v levém sloupci oblasti a vrátí jiný sloupec stejného řádku. -- =SVYHLEDAT(A2;Ceník!$A$2:$C$20;3;NEPRAVDA) hledá A2, oblast je ukotvená, vrátí 3. sloupec, shoda je přesná. -- NEPRAVDA znamená přesnou shodu. PRAVDA by směla vzít nejbližší nižší a u textu plete. -- Hledaná hodnota musí být v prvním sloupci oblasti. Jinak funkce nehledá uprostřed tabulky. - -> Tip: Když funkce vrátí #N/A, hodnota v prvním sloupci není. Zkontrolujte mezeru za jménem a stejný typ, text proti číslu. - -## Zadání: známky a ceník -*Cvičení* - -- Na list Znamky dejte pět žáků, sloupec Znamka a sloupec Stav se vzorcem KDYŽ, prospěl při známce 1 až 4. -- Pod známky SUMA nedávejte, součet známek nic neříká. Dejte PRŮMĚR. -- Na listu Ceník doplňte SVYHLEDAT, který podle kódu položky vrátí cenu. Oblast ukotvěte a dejte NEPRAVDA. -- Uložte znamky.xlsx do složky excel. Oba listy ať jsou v jednom sešitu. - -> Tip: Průměr známek 1,0 až 5,0 vychází jako číslo. Když vyjde 0, počítáte prázdné buňky, nebo máte text místo čísel. - -# Kvíz - -## Jak se v českém Excelu zapíše součet D2 až D6? -- =SUM(D2:D6) -- [x] =SUMA(D2:D6) -- =SUMA(D2,D6) -- SUMA(D2:D6) bez rovnítka -> Česká funkce je SUMA a rozsah je D2:D6. SUM je anglická verze. - -## Který vzorec označí známku 5 jako neprospěl? -- [x] =KDYŽ(D2<=4;"prospěl";"neprospěl") -- =KDYŽ(D2>=4;"prospěl";"neprospěl") -- =KDYŽ(D2<=4,"prospěl","neprospěl") -- =D2<=4 -> Prochází 1 až 4, tedy menší nebo rovno 4. V češtině jsou středníky, ne čárky. - -## Co znamená NEPRAVDA na konci SVYHLEDAT? -- Vypne vzorec -- [x] Chce přesnou shodu -- Sečte sloupec -- Vrátí vždy první řádek -> NEPRAVDA je přesně ta hodnota. PRAVDA bere přibližnou shodu a u kódů položek lže. - -## Proč je oblast Ceník!$A$2:$C$20 ukotvená? -- [x] Aby se při kopírování vzorce dolů neposunula -- Protože jinak nejde uložit xlsx -- Dolar sčítá ceny -- SVYHLEDAT ukotvení zakazuje -> Každý řádek hledá v téže tabulce. Bez dolarů by se oblast sunula dolů s vzorcem. diff --git a/content/programove-vybaveni/2-rocnik/06-excel-grafy.en.md b/content/programove-vybaveni/2-rocnik/06-excel-grafy.en.md deleted file mode 100644 index a159302..0000000 --- a/content/programove-vybaveni/2-rocnik/06-excel-grafy.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Excel: charts -popis: A column chart to compare, a line chart for time. A pie only for parts of a whole. -nazev_cviceni: Quiz: charts -nadpis_kvizu: Pick the chart type ---- diff --git a/content/programove-vybaveni/2-rocnik/06-excel-grafy.md b/content/programove-vybaveni/2-rocnik/06-excel-grafy.md deleted file mode 100644 index 4eda9dd..0000000 --- a/content/programove-vybaveni/2-rocnik/06-excel-grafy.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: sw-2-excel-grafy -nazev: Excel: grafy -popis: Sloupcový graf pro porovnání, spojnicový pro čas. Koláč jen pro podíl celku. -nazev_cviceni: Kvíz: grafy -nadpis_kvizu: Vyberte typ grafu ---- - -# Výklad - -## Který graf -*Typ* - -- Porovnání tříd nebo položek je sloupcový graf. -- Vývoj po měsících je spojnicový. Osa x je čas, zleva doprava. -- Koláč je jen pro podíly jednoho celku, nejvýš pět výsečí. Dvanáct měsíců v koláči nečtěte. -- Dva grafy přes sebe, které říkají totéž, se nedělají. - -> Tip: Když váháte, sloupec je ve škole skoro vždycky bezpečnější než koláč. - -## Co musí být vidět -*Popisky* - -- Graf má název, třeba Tržba po měsících. Název Graf 1 se neodevzdává. -- Osa hodnot má jednotku, Kč nebo počet. Osa kategorií má názvy, ne 1 až 12 bez legendy měsíce, pokud to z dat není jasné. -- Legenda se dá pryč, když je řada jen jedna. Zabírá místo a nic neříká. -- Data grafu jsou v buňkách. Namalovat sloupec obrázkem nejde aktualizovat. - -> Tip: Klik na graf, Vybrat data. Když oblast nesedí, graf kreslí i záhlaví nebo prázdné řádky. - -## Odkud bere čísla -*Tabulka* - -- Nejdřív čísla, potom graf. Graf bez zdroje je obrázek. -- Nula v buňce je nula a v grafu je vidět. Prázdná buňka čáru přeruší. -- Text v číselném sloupci graf vynechá nebo ho položí jako nulu. Čísla nepište s jednotkou Kč v téže buňce. -- Změna čísla v tabulce změní graf. Když ne, graf je kopie jako obrázek. - -> Tip: Kč patří do záhlaví sloupce nebo do názvu osy, ne za číslo do buňky. Jinak je buňka text. - -## Zadání: jeden graf -*Cvičení* - -- Na novém listu Mesice dejte leden až červen a k nim tržbu v Kč, šest čísel. -- Vložte spojnicový graf s názvem Tržba leden až červen. Jednotka ať je v názvu osy nebo v názvu grafu. -- Koláč nedělejte. Legendu jedné řady vypněte. -- Uložte do znamky.xlsx jako další list, nebo do trzba.xlsx ve složce excel. - -> Tip: Náhled tisku ať graf neroztrhne na dvě stránky. Dejte ho pod tabulku, ne přes ni. - -# Kvíz - -## Jaký graf je na tržbu leden až červen? -- Koláč se šesti výsečemi -- [x] Spojnicový -- Náhodný 3D kužel -- Obrázek sloupců vložený z Wordu -> Čas jde zleva doprava ve spojnicovém grafu. Koláč neukáže pořadí měsíců. - -## Kdy je koláč na místě? -- Na dvanáct měsíců -- [x] Na podíly jednoho celku, jen pár výsečí -- Na každou tabulku -- Když chybí název -> Koláč je celek rozdělený na pár dílů. Časová řada do něj nepatří. - -## Kam nepatří Kč? -- Do názvu osy -- [x] Do buňky za číslo, třeba 120 Kč -- Do názvu grafu -- Do záhlaví sloupce -> 120 Kč je text. Graf i SUMA pak číslo nevidí. - -## Co se stane po změně čísla v tabulce, když je graf v pořádku? -- Graf se musí nakreslit znovu ručně -- [x] Sloupec nebo bod se změní sám -- Excel graf smaže -- Změní se licence -> Graf je navázaný na buňky. Obrázek vložený místo grafu se sám nezmění. diff --git a/content/programove-vybaveni/2-rocnik/07-excel-kontingence.en.md b/content/programove-vybaveni/2-rocnik/07-excel-kontingence.en.md deleted file mode 100644 index bb01bed..0000000 --- a/content/programove-vybaveni/2-rocnik/07-excel-kontingence.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Excel: a table, a filter and a pivot -popis: A list as a table, a filter and a total by class. -nazev_cviceni: Quiz: the pivot table -nadpis_kvizu: Say what goes in rows and what goes in values ---- diff --git a/content/programove-vybaveni/2-rocnik/07-excel-kontingence.md b/content/programove-vybaveni/2-rocnik/07-excel-kontingence.md deleted file mode 100644 index 8f91004..0000000 --- a/content/programove-vybaveni/2-rocnik/07-excel-kontingence.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: sw-2-excel-kontingence -nazev: Excel: tabulka, filtr a kontingenční tabulka -popis: Seznam jako tabulka, filtr a součet podle třídy. -nazev_cviceni: Kvíz: kontingenční tabulka -nadpis_kvizu: Řekněte, co patří do řádků a co do hodnot ---- - -# Výklad - -## Tabulka -*Ctrl+T* - -- Seznam se záhlavím se označí a Ctrl+T z něj udělá tabulku. Filtr v záhlaví vznikne sám. -- Záhlaví je jeden řádek: Polozka, Trida, Castka. Dva řádky nadpisů Ctrl+T rozbije. -- Hned pod tabulku se nepíše další text. Souhrn je v řádku souhrnů, nebo na jiném listu. -- Řazení je šipka v záhlaví. Seřadit jen půlku sloupce mimo tabulku rozhodí řádky. - -> Tip: Tabulka dostane na kartě Návrh název, třeba Prodej. Pak se na ni dá odkazovat jménem. - -## Filtr -*Jen 1.A* - -- Filtr Trida = 1.A ostatní řádky schová. Nesmaže je. -- Zrušení filtru je Vybrat vše, nebo Vymazat filtr na kartě Data. -- Řádek souhrnů tabulky sečte jen to, co filtr nechá vidět. -- Obyčejná SUMA přes stejné buňky sečte i řádky, které filtr schoval. Na filtrovaný součet to není. - -> Tip: Když po filtru zmizí skoro všechno, podívejte se, jestli nemáte mezeru v názvu třídy. 1.A a 1.A s mezerou navíc jsou dvě hodnoty. - -## Kontingenční tabulka -*Součet podle třídy* - -- Kontingenční tabulka je na kartě Vložení. Zdroj je tabulka i se záhlavím. -- Do řádků přijde Trida. Do hodnot Součet z Castka. Sloupce nechte prázdné, dokud není druhý rozměr. -- Známky se v kontingenci nesčítají. U známek dejte průměr, u peněz součet. -- Kontingence patří na nový list. Když ji položíte přes zdroj, zdroj přepíšete. - -> Tip: Po změně dat dejte Obnovit. Kontingenční tabulka se sama nehne. - -## Zadání: prodej po třídách -*Cvičení* - -- List Prodej: aspoň 12 řádků, sloupce Polozka, Trida, Castka. Třídy jen 1.A a 1.B. -- Ctrl+T a název tabulky Prodej. Filtr ať umí ukázat jen 1.A a zase všechno. -- Kontingenční tabulka na novém listu: řádky Trida, hodnoty součet Castka. -- Uložte prodej.xlsx do složky Skola\1-rocnik\excel. Ruční součty vedle kontingence nepište. - -> Tip: Když kontingence ukáže Počet místo Součet, v hodnotách počítá buňky. Přepněte souhrn na Součet. - -# Kvíz - -## Co udělá Ctrl+T na seznamu se záhlavím? -- Smaže ho -- [x] Udělá z něj tabulku s filtrem -- Převede ho na PDF -- Uzamkne list heslem -> Tabulka má filtr v záhlaví a jde pojmenovat. Obyčejná oblast to nemá. - -## Co sečte jen řádky, které filtr nechá vidět? -- Obyčejná SUMA přes celou oblast -- [x] Řádek souhrnů tabulky -- Nadpis grafu -- Ručně opsaný součet -> SUMA schované řádky filtru pořád počítá. Řádek souhrnů tabulky bere jen viditelné. - -## Kam v kontingenční tabulce patří Trida a kam Castka? -- Trida do hodnot jako součet, Castka do řádků -- [x] Trida do řádků, součet Castka do hodnot -- Obojí do filtrů a nikam jinam -- Trida do názvu souboru -> Řádky jsou třídy. Hodnoty jsou součet peněz. Součet názvů tříd nedává smysl. - -## Kdy se u známek v kontingenci použije průměr? -- Vždy se známky sčítají -- [x] Když má vyjít průměrná známka, ne součet známek -- Průměr Excel neumí -- Jen u textu -> Součet známek nic neříká. Peníze se sčítají, známky se průměrují. diff --git a/content/programove-vybaveni/2-rocnik/08-zadani-office.en.md b/content/programove-vybaveni/2-rocnik/08-zadani-office.en.md deleted file mode 100644 index 04488f3..0000000 --- a/content/programove-vybaveni/2-rocnik/08-zadani-office.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Assignment: a report and a sheet -popis: A Word letter and an Excel grade sheet in one folder. -nazev_cviceni: Quiz: the Office hand-in -nadpis_kvizu: Check both files ---- diff --git a/content/programove-vybaveni/2-rocnik/08-zadani-office.md b/content/programove-vybaveni/2-rocnik/08-zadani-office.md deleted file mode 100644 index 4c2a906..0000000 --- a/content/programove-vybaveni/2-rocnik/08-zadani-office.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: sw-2-zadani-office -nazev: Zadání: protokol a tabulka -popis: Dopis ve Wordu a známky v Excelu v jedné složce. -nazev_cviceni: Kvíz: odevzdání Office -nadpis_kvizu: Zkontrolujte oba soubory ---- - -# Výklad - -## Word -*Žádost* - -- zadost.docx je jedna strana A4, okraje 2,5 cm, datum 12. 6. 2026 vpravo nahoře. -- Je v ní řádek Věc, oslovení, aspoň dvě věty a podpis. Není v ní obsah ani tabulka. -- K protokolu z dřívějška, pokud ho máte, patří styly Nadpis 1 a PDF. -- PDF se jmenuje stejně jako docx. Dvě verze final a final2 se neodevzdávají. - -> Tip: Náhled tisku má ukázat jednu stránku. Podpis na druhé stránce znamená moc velké mezery. - -## Excel -*Známky* - -- znamky.xlsx má list Znamky: jméno, známka, stav. -- Stav je vzorec =KDYŽ(D2<=4;"prospěl";"neprospěl") nebo se sloupcem známky, který opravdu máte. Známka 5 je neprospěl. -- Pod tabulkou je PRŮMĚR známek, ne jejich součet. -- Čísla jsou čísla. Text 1 nebo 120 Kč ve stejné buňce se nepočítá. - -> Tip: Klik na buňku stavu musí v řádku vzorců ukázat KDYŽ. Opsané slovo prospěl se při změně známky nehne. - -## Kontrola vzorců -*Ne opis* - -- V ceníku, pokud ho přikládáte, je částka =B2*C2 a sazba ukotvená jako $F$1. -- SVYHLEDAT, pokud ho máte, končí na NEPRAVDA a oblast je ukotvená. -- Graf tržby je spojnicový, má název a není to koláč dvanácti měsíců. -- Kontingenční tabulka, pokud je v sešitu, stojí na vlastním listu a sčítá částky po třídách. - -> Tip: Stačí žádost a známky. Ceník, graf a kontingence jsou navíc, ale když je přiložíte, musí sedět. - -## Složka -*Dva hlavní soubory* - -- Ve složce Skola\1-rocnik\word je zadost.docx a zadost.pdf. -- Ve složce Skola\1-rocnik\excel je znamky.xlsx. -- Na ploše tyto soubory nejsou. Přípony jsou vidět. -- Otevřete oba znovu. Datum, věc a aspoň jedna pětka se stavem neprospěl mají být vidět. - -> Tip: Když PDF nejde otevřít, export nedoběhl. Udělejte ho z docx znovu. - -# Kvíz - -## Jaký je školní dopis z tohoto zadání? -- Tři strany se styly a obsahem -- [x] Jedna strana A4 s řádkem Věc a datem 12. 6. 2026 -- Jen tabulka 4×3 -- Prezentace -> Žádost je jeden list. Obsah a Nadpis 1 patří protokolu, ne tomuto dopisu. - -## Který vzorec označí pětku jako neprospěl? -- [x] =KDYŽ(D2<=4;"prospěl";"neprospěl") -- =KDYŽ(D2>=4;"prospěl";"neprospěl") -- napsané slovo prospěl -- =SUMA(D2) -> Prochází známka 1 až 4. Pětka padne do druhé větve. V češtině jsou středníky. - -## Co patří pod sloupec známek? -- Součet známek -- [x] Průměr -- Kontingenční součet peněz -- Nic, známky se mažou -> Součet známek nemá význam. PRŮMĚR ano. - -## Které soubory se odevzdávají jako základ? -- Jen PDF bez docx -- [x] zadost.docx, zadost.pdf a znamky.xlsx -- Jen xlsx na ploše -- prezentace a video -> Word se odevzdává i jako zdroj, i jako PDF. Excel je xlsx, protože v PDF by nebyly vzorce. diff --git a/content/programove-vybaveni/3-rocnik/01-databaze.en.md b/content/programove-vybaveni/3-rocnik/01-databaze.en.md deleted file mode 100644 index e466ba7..0000000 --- a/content/programove-vybaveni/3-rocnik/01-databaze.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: A database -popis: A table, a record, a key. When a sheet is no longer enough. -nazev_cviceni: Quiz: databases -nadpis_kvizu: Name the key and the reason for a database ---- diff --git a/content/programove-vybaveni/3-rocnik/01-databaze.md b/content/programove-vybaveni/3-rocnik/01-databaze.md deleted file mode 100644 index bcda465..0000000 --- a/content/programove-vybaveni/3-rocnik/01-databaze.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: sw-3-databaze -nazev: Databáze -popis: Tabulka, záznam, klíč. Kdy už nestačí Excel. -nazev_cviceni: Kvíz: databáze -nadpis_kvizu: Poznejte klíč a důvod databáze ---- - -# Výklad - -## Excel nestačí -*Vztahy* - -- Excel je výborný na jeden seznam. Jakmile se třída opakuje na každém řádku žáka, začne se název třídy rozcházet. -- Databáze drží věci v samostatných tabulkách a spojuje je klíčem. -- Tabulka tridy má název třídy jednou. Tabulka zaci se na ni jen odkáže. -- Access i MySQL umí totéž v principu. Access je soubor accdb, MySQL je server a příkazy SQL. - -> Tip: Když opravujete 1.A na 1. A v padesáti řádcích Excelu, má to být tabulka tříd, ne opis. - -## Řádek a sloupec -*Záznam a pole* - -- Řádek je záznam, třeba jeden žák. Sloupec je pole, třeba prijmeni. -- Každá hodnota je atomická. Jméno a příjmení nepatří do jedné buňky. -- Primární klíč je hodnota, která se v tabulce neopakuje. U žáka je to id, ne příjmení. -- Cizí klíč je pole, které ukazuje na primární klíč jiné tabulky. trida_id v tabulce zaci ukazuje na id v tridy. - -> Tip: Dva Nováci se smějí jmenovat stejně. Jejich id je různé. Proto příjmení klíč není. - -## Typy -*Číslo, text, datum* - -- id je číslo. Jméno je krátký text. Datum narození je datum, ne text 12.6. -- Ano/ne je samostatný typ, ne text ano. -- Do číselného pole nepatří jednotka. Počet žáků je 28, ne 28 žáků. -- Prázdné pole a nula nejsou totéž. Nula je známá hodnota, prázdno je nevíme. - -> Tip: Text v číselném poli se nepodaří uložit, nebo se sečte špatně. Typ zvolte při založení sloupce. - -## Zadání: návrh na papír -*Cvičení* - -- Navrhněte dvě tabulky: tridy (id, nazev) a zaci (id, jmeno, prijmeni, trida_id). -- U každého pole napište typ. id v obou tabulkách je primární klíč. -- Napište dva řádky tříd, 1.A a 1.B, a tři žáky, z toho Annu Novákovou ve třídě 1.A. -- Soubor navrh.txt uložte k databázím. Access ani MySQL ještě neotevírejte, dokud návrh nesedí. - -> Tip: Šipka vede od trida_id k id tabulky tridy. Opačně by žák byl klíčem třídy, což není. - -# Kvíz - -## Co je primární klíč žáka? -- Příjmení -- [x] id, které se neopakuje -- Název třídy -- První sloupec, ať je v něm cokoli -> Příjmení se opakuje. id jednoho žáka ne. - -## Co je trida_id v tabulce zaci? -- Primární klíč třídy v téže tabulce -- [x] Cizí klíč na tabulku tridy -- Text 1.A opsaný do každého řádku -- Heslo -> Cizí klíč drží jen číslo třídy. Název třídy žije v tabulce tridy jednou. - -## Kdy už je Excel na seznam žáků těsný? -- Jakmile má víc než jeden sloupec -- [x] Když se údaj, třeba název třídy, opakuje a musí zůstat stejný -- Excel nestačí nikdy -- Jakmile je soubor xlsx -> Opakovaný název se rozjede. Databáze ho má v jedné tabulce a ostatní se na ni odkážou. - -## Čím se liší nula a prázdné pole? -- Ničím -- [x] Nula je hodnota, prázdné pole znamená, že hodnota chybí -- Prázdné pole je vždy nula -- Nula je text -> Průměr nulu počítá. Prázdnou buňku často ne. Typ i význam se liší. diff --git a/content/programove-vybaveni/3-rocnik/02-access-tabulky.en.md b/content/programove-vybaveni/3-rocnik/02-access-tabulky.en.md deleted file mode 100644 index 3ee054f..0000000 --- a/content/programove-vybaveni/3-rocnik/02-access-tabulky.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Access: tables and a relationship -popis: An AutoNumber, a foreign key and a one-to-many link without a cascade. -nazev_cviceni: Quiz: Access -nadpis_kvizu: Pick the key type and the cascade ---- diff --git a/content/programove-vybaveni/3-rocnik/02-access-tabulky.md b/content/programove-vybaveni/3-rocnik/02-access-tabulky.md deleted file mode 100644 index c92654e..0000000 --- a/content/programove-vybaveni/3-rocnik/02-access-tabulky.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: sw-3-access-tabulky -nazev: Access: tabulky a vztah -popis: Automatické číslo, cizí klíč a vztah 1:N bez kaskády. -nazev_cviceni: Kvíz: Access -nadpis_kvizu: Vyberte typ klíče a kaskádu ---- - -# Výklad - -## Soubor -*accdb* - -- Databáze Accessu je jeden soubor accdb. Jmenuje se evidence.accdb. -- Tabulku založíte v návrhovém zobrazení, ne jen v datovém listu. V návrhu je vidět typ. -- Tabulka tridy má pole id a nazev. Tabulka zaci má id, jmeno, prijmeni a trida_id. -- Název pole je bez mezery a bez diakritiky: trida_id. Popisek pro lidi se dá nastavit zvlášť. - -> Tip: Datový list je na zapisování řádků. Typ pole se mění v návrhu. Když už v tabulce data jsou, změna typu může selhat. - -## Klíče -*Automatické číslo* - -- id je typ Automatické číslo a je to primární klíč. Access ho doplňuje sám: 1, 2, 3. -- trida_id je typ Číslo, dlouhé celé číslo. Není to automatické číslo. Píšete ho vy, nebo ho vybere vztah. -- nazev, jmeno a prijmeni jsou Krátký text. Délka 50 stačí. -- Dva primární klíče v jedné tabulce školního cvičení nejsou. Stačí id. - -> Tip: Když trida_id necháte jako text, vztah na číselné id třídy Access odmítne. Typy obou konců musí sedět. - -## Vztah 1:N -*Bez kaskády* - -- Jedna třída má víc žáků. Žák má jednu třídu. To je vztah 1:N. -- Ve vztazích přetáhnete tridy.id na zaci.trida_id. -- Zaškrtněte vynucení referenční integrity. Žák se nesmí odkázat na třídu, která neexistuje. -- Kaskádové odstranění nechte vypnuté. Smazání třídy by jinak smazalo i žáky. - -> Tip: Na straně tridy je jednička, na straně zaci je znak nekonečna. Když je to obráceně, táhli jste vztah špatným směrem. - -## Zadání: evidence.accdb -*Cvičení* - -- Založte evidence.accdb s tabulkami tridy a zaci podle návrhu. -- Vložte třídy 1.A a 1.B. Vložte Annu Novákovou s trida_id třídy 1.A a ještě dva žáky. -- Vztah 1:N s referenční integritou, bez kaskádového odstranění. -- Zkuste uložit žáka s trida_id 99. Access ho má odmítnout. Pak to číslo vraťte na platnou třídu. - -> Tip: Když jde uložit trida_id 99, integrita není zapnutá. Otevřete vztahy a vztah vytvořte znovu. - -# Kvíz - -## Jaký typ má id žáka? -- Krátký text, který píšete ručně -- [x] Automatické číslo a primární klíč -- Ano/ne -- Dlouhý text s celým jménem třídy -> Automatické číslo žák nedoplňuje. Access ho dá samo a v tabulce se neopakuje. - -## Jaký typ má trida_id? -- Automatické číslo -- [x] Číslo, dlouhé celé číslo -- Datum -- Ano/ne -> Je to cizí klíč na id třídy, které je taky číslo. Automatické číslo by si vymýšlelo vlastní hodnoty. - -## Co dělá referenční integrita? -- Smaže žáky při smazání třídy -- [x] Nedovolí žáka s třídou, která neexistuje -- Schová tabulku -- Převede accdb na xlsx -> Odkaz musí vést na skutečný řádek. Třída 99 bez řádku v tridy projít nemá. - -## Proč nechat kaskádové odstranění vypnuté? -- Access ho neumí -- [x] Smazání třídy by smazalo i její žáky -- Jinak nejde uložit accdb -- Kvůli Excelu -> Třída a žáci jsou různá data. Smazat třídu omylem a přijít o žáky je špatná pojistka pro školní cvičení. diff --git a/content/programove-vybaveni/3-rocnik/03-access-dotazy.en.md b/content/programove-vybaveni/3-rocnik/03-access-dotazy.en.md deleted file mode 100644 index 721c282..0000000 --- a/content/programove-vybaveni/3-rocnik/03-access-dotazy.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Access: queries -popis: A query that shows only class 1.A, and a criterion in quotes. -nazev_cviceni: Quiz: queries -nadpis_kvizu: Fill in the criterion ---- diff --git a/content/programove-vybaveni/3-rocnik/03-access-dotazy.md b/content/programove-vybaveni/3-rocnik/03-access-dotazy.md deleted file mode 100644 index 679b605..0000000 --- a/content/programove-vybaveni/3-rocnik/03-access-dotazy.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: sw-3-access-dotazy -nazev: Access: dotazy -popis: Dotaz, který ukáže jen třídu 1.A, a kritérium v uvozovkách. -nazev_cviceni: Kvíz: dotazy -nadpis_kvizu: Doplňte kritérium ---- - -# Výklad - -## Dotaz není kopie -*Pohled* - -- Dotaz data nekopíruje do nové tabulky. Přečte je a ukáže výsledek. -- Když ve třídě přibude žák, stejný dotaz ho příště ukáže taky. -- Dotaz se dělá v návrhovém zobrazení. Tabulky se přidají a pole se přetáhnou dolů. -- Uložený dotaz se jmenuje zaci_1A. Dotaz1 se neodevzdává. - -> Tip: Když dotaz otevřete a data změníte, měníte zdrojovou tabulku. Na prohlížení to vadit nemusí, na omyl ano. - -## Kritérium -*1.A* - -- Pod pole nazev z tabulky tridy patří kritérium "1.A" včetně uvozovek. -- Bez uvozovek Access text nepozná a dotaz selže, nebo se zeptá na parametr. -- Číselné kritérium uvozovky nemá. id 1 je prostě 1. -- Chcete-li žáky obou tříd, kritérium 1.A tam nedávejte. Filtr, který tam zbyl z minula, výsledek ořeže. - -> Tip: Řádek Kritéria je filtr. Řádek Zobrazit schová sloupec, který v dotazu být musí, ale ve výsledku ho nechcete. - -## Spojení v dotazu -*Obě tabulky* - -- Do dotazu přidejte tridy i zaci. Access použije vztah, který už máte. -- Ven dejte prijmeni, jmeno a nazev třídy. id ven dávat nemusíte. -- Řazení podle prijmeni je vzestupně. V návrhové mřížce je na to řádek Řadit. -- Žák bez třídy se při vnitřním spojení neukáže. Díky integritě takový řádek stejně nemá vzniknout. - -> Tip: Když se každý žák ukáže dvakrát, tabulky nejsou spojené a Access udělal všechny kombinace. Vraťte vztah. - -## Zadání: jen 1.A -*Cvičení* - -- Dotaz zaci_1A ukáže jméno, příjmení a název třídy, jen pro 1.A, seřazené podle příjmení. -- Anna Nováková v něm je. Žák z 1.B v něm není. -- Uložte dotaz do evidence.accdb. Výsledek nekopírujte do Excelu jako jediný výstup. -- Změňte v tabulce příjmení Anny na Novák a dotaz otevřete znovu. Má ukázat Novák. - -> Tip: Když se zeptá na parametr 1.A, kritérium nemá uvozovky a Access ho bere jako otázku. - -# Kvíz - -## Kam patří podmínka "1.A"? -- Do názvu souboru -- [x] Do řádku Kritéria pod polem nazev -- Do primárního klíče místo id -- Do kaskádového odstranění -> Kritéria filtrují řádky. Pole nazev drží text 1.A. - -## Proč jsou u 1.A uvozovky? -- [x] Access jinak text pochopí jako parametr nebo chybu -- Protože 1.A je číslo -- Uvozovky se v Accessu nepoužívají -- Aby se zapnula kaskáda -> Textové kritérium se píše v uvozovkách. Číslo ne. - -## Co se stane s dotazem, když do třídy 1.A přidáte žáka? -- Dotaz je stará kopie a žáka neukáže -- [x] Po novém otevření ho ukáže -- Access databázi zavře -- Musíte ho opsat do Excelu -> Dotaz čte tabulky. Není to zmrazený export. - -## Proč se žák v dotazu objeví dvakrát u každé třídy? -- Má dva primární klíče -- [x] Tabulky v dotazu nejsou spojené vztahem -- Je seřazený podle příjmení -- Filtr je vypnutý -> Bez spojení Access zkombinuje každý řádek s každým. Vztah tomu zabrání. diff --git a/content/programove-vybaveni/3-rocnik/04-access-formulare.en.md b/content/programove-vybaveni/3-rocnik/04-access-formulare.en.md deleted file mode 100644 index b3cd488..0000000 --- a/content/programove-vybaveni/3-rocnik/04-access-formulare.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Access: a form and a report -popis: Entry through a form and printing through a report. The datasheet is not for users. -nazev_cviceni: Quiz: forms -nadpis_kvizu: Pick what is for entry and what is for print ---- diff --git a/content/programove-vybaveni/3-rocnik/04-access-formulare.md b/content/programove-vybaveni/3-rocnik/04-access-formulare.md deleted file mode 100644 index 37f9b48..0000000 --- a/content/programove-vybaveni/3-rocnik/04-access-formulare.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: sw-3-access-formulare -nazev: Access: formulář a sestava -popis: Zápis přes formulář a tisk přes sestavu. Datový list není pro uživatele. -nazev_cviceni: Kvíz: formulář -nadpis_kvizu: Vyberte, čím se data zadávají a čím tisknou ---- - -# Výklad - -## Formulář -*Jeden žák* - -- Formulář ukáže jeden záznam jako políčka. Datový list ukáže mřížku a tam se běžný uživatel snadno trefí do špatného řádku. -- Formulář Zaci se založí z tabulky zaci. Pole id ať je vidět, ale zamčené. Automatické číslo se nepíše. -- trida_id je lépe rozbalovací seznam, který ukazuje název třídy a ukládá id. -- Formulář se jmenuje frmZaci. Výchozí Formulář1 se neodevzdává. - -> Tip: Rozbalovací seznam bere řádky z tabulky tridy. Viditelný sloupec je nazev, vázaný sloupec je id. - -## Sestava -*Tisk* - -- Sestava je na tisk a na PDF. Formulář je na zápis. Neslouží k tomu totéž. -- Sestava žáků je seskupená podle třídy a v rámci třídy seřazená podle příjmení. -- Záhlaví skupiny ukáže 1.A jednou, ne na každém řádku jako jediný nadpis celé sestavy. -- Do sestavy nepatří tlačítka formuláře. Patří do ní nadpis Evidence žáků a číslo stránky. - -> Tip: Náhled sestavy je před tiskem povinný. Prázdná druhá stránka znamená velkou zápatí nebo prázdný oddíl. - -## Kdo kam smí -*Ne do návrhu* - -- Uživatel, který jen zapisuje žáky, dostane formulář. Návrhové zobrazení ne. -- Mazání záznamu na formuláři je vypnuté, dokud učitel neřekne jinak. -- Sestava se needituje. Když v ní přepíšete jméno, často přepisujete data, a to z sestavy dělat nechcete. -- Záloha je kopie accdb před mazáním. Jediný soubor na ploše záloha není. - -> Tip: Soubor, Uložit jako, a datum v názvu: evidence-2026-06-12.accdb. Pak teprve mažete zkušební řádky. - -## Zadání: formulář a sestava -*Cvičení* - -- frmZaci zapíše jméno, příjmení a třídu. id nejde přepsat. -- Sestava seskupí žáky podle třídy. Anna Nováková je pod 1.A. -- Z formuláře přidejte jednoho žáka do 1.B a v sestavě ho najděte. -- Uložte vše do evidence.accdb. PDF sestavy je evidence-zaci.pdf vedle souboru. - -> Tip: Když v rozbalovacím seznamu vidíte čísla místo 1.A, zobrazujete id. Přepněte šířku sloupců, ať je vidět nazev. - -# Kvíz - -## Čím se ve škole zadává nový žák? -- Přímo v návrhovém zobrazení tabulky -- [x] Formulářem frmZaci -- Přepsáním sestavy -- Excelem místo Accessu bez uložení accdb -> Formulář ukáže jeden záznam a umí seznam tříd. Návrh tabulky je pro autora databáze. - -## K čemu je sestava? -- K mazání sloupců -- [x] K tisku a PDF, seskupenému podle třídy -- K nastavení automatického čísla -- K instalaci Accessu -> Sestava formátuje výstup. Zápis zůstává formuláři. - -## Proč je id na formuláři zamčené? -- [x] Automatické číslo se nepíše ručně -- Access id neumí ukázat -- Jinak nejde sestava -- Protože je to text -> Číslo přidělí Access. Ruční přepsání by rozbilo klíč. - -## Co uděláte před mazáním zkušebních řádků? -- Nic, accdb se sám verzuje -- [x] Kopie souboru s datem v názvu -- Smažete vztah -- Export jen do JPG -> Jedna kopie accdb je záloha. Mazání bez ní nejde vzít zpět tak snadno jako Ctrl+Z ve Wordu. diff --git a/content/programove-vybaveni/3-rocnik/05-mysql-select.en.md b/content/programove-vybaveni/3-rocnik/05-mysql-select.en.md deleted file mode 100644 index 4e04663..0000000 --- a/content/programove-vybaveni/3-rocnik/05-mysql-select.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: MySQL: SELECT -popis: Choosing columns, a WHERE condition and a sort. Text sits in single quotes. -nazev_cviceni: Quiz: SELECT -nadpis_kvizu: Pick the right statement ---- diff --git a/content/programove-vybaveni/3-rocnik/05-mysql-select.md b/content/programove-vybaveni/3-rocnik/05-mysql-select.md deleted file mode 100644 index 2595d1b..0000000 --- a/content/programove-vybaveni/3-rocnik/05-mysql-select.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: sw-3-mysql-select -nazev: MySQL: SELECT -popis: Výběr sloupců, podmínka WHERE a řazení. Text je v jednoduchých uvozovkách. -nazev_cviceni: Kvíz: SELECT -nadpis_kvizu: Vyberte správný příkaz ---- - -# Výklad - -## Databáze skola -*Dvě tabulky* - -- Na serveru je databáze skola. Tabulka tridy má id a nazev. Tabulka zaci má id, jmeno, prijmeni a trida_id. -- Příkazy se píšou v MySQL, ne do Excelu. Středník příkaz ukončí. -- Nejdřív USE skola; ať další příkazy nemíří do jiné databáze. -- Heslo k serveru do sešitu nepatří. Patří učiteli a do klienta, který ho neukazuje v příkazu. - -> Tip: Když klient hlásí, že tabulka neexistuje, jste v jiné databázi, nebo je v názvu překlep. SHOW TABLES; ukáže, co tam je. - -## SELECT -*Jen to, co potřebujete* - -- SELECT prijmeni, jmeno FROM zaci; vrátí dva sloupce všech žáků. -- Hvězdička SELECT * FROM zaci; je na průzkum. Do odevzdaného dotazu vyberte sloupce jménem. -- WHERE trida_id = 1 nechá jen jednu třídu. Číslo je bez uvozovek. -- Text se píše v jednoduchých uvozovkách: WHERE nazev = '1.A'. - -> Tip: Dvojité uvozovky kolem 1.A záleží na režimu serveru. Ve škole pište jednoduché, ty platí spolehlivě. - -## Pořadí -*ORDER BY* - -- ORDER BY prijmeni; seřadí vzestupně, tedy A až Ž. -- ORDER BY prijmeni DESC; je sestupně. -- WHERE patří před ORDER BY. Obrácené pořadí příkazů server odmítne. -- LIMIT 5 vrátí nejvýš pět řádků. Na kontrolu ano, na úplný seznam třídy ne. - -> Tip: Nejdřív FROM, pak WHERE, pak ORDER BY. SELECT je na začátku, i když se sloupce vybírají jako první v hlavě. - -## Zadání: tři dotazy -*Cvičení* - -- Do souboru dotazy.sql napište USE skola; a tři SELECT. -- První: příjmení a jméno všech žáků podle příjmení. -- Druhý: jen žáci s trida_id = 1. -- Třetí: název třídy 1.A z tabulky tridy. Text '1.A' je v jednoduchých uvozovkách. - -> Tip: Každý příkaz ukončete středníkem. Bez něj klient čeká na pokračování. - -# Kvíz - -## Který příkaz vrátí příjmení žáků třídy s id 1? -- [x] SELECT prijmeni FROM zaci WHERE trida_id = 1; -- SELECT prijmeni WHERE trida_id = 1; -- SELECT * FROM tridy WHERE nazev = 1.A; -- WHERE trida_id = 1; -> SELECT říká sloupce, FROM tabulku, WHERE podmínku. Číslo je bez uvozovek. - -## Jak se v podmínce zapíše název třídy? -- nazev = 1.A -- [x] nazev = '1.A' -- nazev = "bez uvozovek a bez čísla" -- nazev := 1.A -> Text patří do jednoduchých uvozovek. Bez nich to není řetězec. - -## Kam patří ORDER BY? -- Před SELECT -- [x] Za WHERE -- Místo FROM -- Do názvu tabulky -> Pořadí je WHERE, potom ORDER BY. SELECT zůstává první. - -## K čemu je ve škole SELECT * ? -- Na odevzdaný tisk všech osobních údajů -- [x] Na rychlý pohled, co v tabulce je -- Místo primárního klíče -- Na smazání řádků -> Hvězdička je průzkum. Odevzdaný dotaz jmenuje sloupce, které mají být vidět. diff --git a/content/programove-vybaveni/3-rocnik/06-mysql-zmeny.en.md b/content/programove-vybaveni/3-rocnik/06-mysql-zmeny.en.md deleted file mode 100644 index a00bb9c..0000000 --- a/content/programove-vybaveni/3-rocnik/06-mysql-zmeny.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: MySQL: INSERT, UPDATE and DELETE -popis: A new row, a change and a delete. An UPDATE or DELETE without WHERE is not written in class. -nazev_cviceni: Quiz: changing data -nadpis_kvizu: Recognise the safe statement ---- diff --git a/content/programove-vybaveni/3-rocnik/06-mysql-zmeny.md b/content/programove-vybaveni/3-rocnik/06-mysql-zmeny.md deleted file mode 100644 index 63fc270..0000000 --- a/content/programove-vybaveni/3-rocnik/06-mysql-zmeny.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: sw-3-mysql-zmeny -nazev: MySQL: INSERT, UPDATE a DELETE -popis: Nový řádek, oprava a smazání. UPDATE a DELETE bez WHERE se ve škole nepíšou. -nazev_cviceni: Kvíz: změny dat -nadpis_kvizu: Poznejte bezpečný příkaz ---- - -# Výklad - -## INSERT -*Nový žák* - -- INSERT INTO zaci (jmeno, prijmeni, trida_id) VALUES ('Anna', 'Nováková', 1); přidá jeden řádek. -- Sloupce v závorce a hodnoty za VALUES musí být ve stejném pořadí a stejném počtu. -- id s automatickým číslem do výčtu nedávejte, server ho doplní. -- Jeden INSERT, jeden žák. Balit pět žáků do nepřehledného příkazu ve cvičení nemusíte. - -> Tip: Když server hlásí neznámý sloupec, název nesedí s tabulkou. SHOW COLUMNS FROM zaci; ukáže pravdu. - -## UPDATE -*Jen jeden řádek* - -- UPDATE zaci SET trida_id = 2 WHERE id = 15; přepíše třídu jen žáku 15. -- Bez WHERE by stejný příkaz přepsat třídu všem. Ve škole se neodevzdává. -- Nejdřív SELECT s stejnou podmínkou WHERE. Až když vidíte jeden správný řádek, pusťte UPDATE. -- SET mění hodnoty. Není to SELECT a nic nevrací kromě počtu ovlivněných řádků. - -> Tip: Klient ukáže, kolik řádků se změnilo. Když vidíte desítky a čekali jste jeden, zastavte se a volejte učitele. Záloha se hodí předtím, ne potom. - -## DELETE -*Také s WHERE* - -- DELETE FROM zaci WHERE id = 15; smaže jeden řádek. -- DELETE FROM zaci; bez WHERE smaže všechny žáky. To není čištění tabulky, to je ztráta dat. -- Smazaný řádek Ctrl+Z v MySQL nevrátí. Vrátí ho záloha, nebo ho vložíte znovu, když znáte hodnoty. -- Mazat třídu, na kterou ještě ukazují žáci, referenční pravidlo nemá dovolit. Nejdřív žáci, nebo třídu nemazat. - -> Tip: Před DELETE udělejte SELECT se stejnou podmínkou. Počet řádků musí být ten, který čekáte, obvykle jeden. - -## Zadání: tři změny na kopii -*Cvičení* - -- Na cvičných datech vložte žáka Petr Svoboda do třídy 1, tedy trida_id 1. -- UPDATE mu změňte třídu na 2, ale jen přes jeho id, které jste předtím přečetli SELECTem. -- Téhož žáka DELETE smažte zase jen podle id. Ostatní žáci v tabulce zůstanou. -- Tři příkazy připojte do dotazy.sql pod komentář, který říká, že UPDATE a DELETE mají WHERE. - -> Tip: Komentář v SQL začíná dvěma pomlčkami. Do příkazu se nepočítá, příštímu čtenáři řekne, proč tam WHERE je. - -# Kvíz - -## Který příkaz přidá Annu do třídy 1? -- [x] INSERT INTO zaci (jmeno, prijmeni, trida_id) VALUES ('Anna', 'Nováková', 1); -- SELECT Anna INTO zaci; -- UPDATE zaci SET Anna; -- DELETE FROM zaci WHERE jmeno = 'Anna'; -> INSERT vkládá řádek. Sloupce a hodnoty drží pořadí. - -## Jak se změní třída jen žáku s id 15? -- UPDATE zaci SET trida_id = 2; -- [x] UPDATE zaci SET trida_id = 2 WHERE id = 15; -- SELECT trida_id = 2; -- INSERT INTO zaci VALUES (15); -> Bez WHERE by se třída přepsala všem. WHERE id = 15 drží jeden řádek. - -## Co udělá DELETE FROM zaci; bez WHERE? -- Nesmaže nic, WHERE je volitelné a server se zeptá -- [x] Smaže všechny řádky v zaci -- Smaže jen poslední řádek -- Jen vypíše žáky -> Bez podmínky je cílem celá tabulka. Ve školním cvičení takový příkaz nepište. - -## Co uděláte těsně před UPDATE? -- DELETE bez WHERE -- [x] SELECT se stejnou podmínkou, ať vidíte ty řádky -- DROP tabulky -- Vypnete integritu -> SELECT ukáže, na koho UPDATE dopadne. Až pak má smysl stejné WHERE použít ke změně. diff --git a/content/programove-vybaveni/3-rocnik/07-mysql-join.en.md b/content/programove-vybaveni/3-rocnik/07-mysql-join.en.md deleted file mode 100644 index b97432f..0000000 --- a/content/programove-vybaveni/3-rocnik/07-mysql-join.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: MySQL: joining tables -popis: An INNER JOIN on trida_id, and why the class name is not repeated on every row. -nazev_cviceni: Quiz: JOIN -nadpis_kvizu: Complete the join ---- diff --git a/content/programove-vybaveni/3-rocnik/07-mysql-join.md b/content/programove-vybaveni/3-rocnik/07-mysql-join.md deleted file mode 100644 index 62e5a1b..0000000 --- a/content/programove-vybaveni/3-rocnik/07-mysql-join.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: sw-3-mysql-join -nazev: MySQL: spojení tabulek -popis: INNER JOIN přes trida_id a proč se název třídy neopakuje v každém řádku. -nazev_cviceni: Kvíz: JOIN -nadpis_kvizu: Doplňte spojení ---- - -# Výklad - -## Jedna pravda -*Název jen jednou* - -- Název 1.A je v tabulce tridy jednou. V zaci je jen trida_id. -- Když by název ležel i u žáka, oprava překlepu znamená projít všechny žáky. -- To je důvod dvou tabulek. Excel to umí jen ručně, databáze vztahem. -- JOIN tabulky spojí ve výsledku dotazu. Nesloučí je do jedné natrvalo. - -> Tip: Po JOIN pořád existují dvě tabulky. Výsledek dotazu je jen pohled pro tento příkaz. - -## INNER JOIN -*Shoda klíčů* - -- INNER JOIN vrátí řádky, kde se klíče sejdou. Žák a jeho třída. -- ON z.trida_id = t.id je podmínka spojení. Není to totéž co WHERE na název. -- Bez ON server buď příkaz odmítne, nebo spojí každý řádek s každým. -- Přezdívky z a t jsou v dotazu proto, aby bylo jasné, která tabulka je která. - -> Tip: WHERE t.nazev = '1.A' přijde až po spojení. Nejdřív se tabulky potkají, pak se filtruje. - -## Celý příkaz -*Jak má vypadat* - -- SELECT z.prijmeni, z.jmeno, t.nazev FROM zaci AS z INNER JOIN tridy AS t ON z.trida_id = t.id; -- WHERE t.nazev = '1.A' z toho udělá jen jednu třídu. -- ORDER BY z.prijmeni výsledek seřadí. -- Sloupce pište s přezdívkou tabulky. Samotné id by bylo nejasné, mají ho obě tabulky. - -> Tip: Když příkaz hlásí nejednoznačný sloupec id, napište z.id nebo t.id. Server nehádá. - -## Zadání: jeden JOIN -*Cvičení* - -- Do dotazy.sql přidejte dotaz, který vypíše příjmení, jméno a název třídy. -- Jen třída 1.A, seřazené podle příjmení. -- Anna Nováková v něm je včetně textu 1.A, ne jen čísla 1. -- Příkaz spusťte dvakrát. Výsledek má být stejný, JOIN data nemění. - -> Tip: Když vidíte číslo místo 1.A, vybíráte trida_id a ne t.nazev. Doplňte sloupec z tabulky tridy. - -# Kvíz - -## Které spojení ukáže žáka i název jeho třídy? -- SELECT * FROM zaci; -- [x] SELECT z.prijmeni, t.nazev FROM zaci AS z INNER JOIN tridy AS t ON z.trida_id = t.id; -- DELETE FROM tridy; -- INSERT INTO tridy VALUES ('1.A'); -> JOIN vezme příjmení z žáků a název z tříd tam, kde se id shoduje. - -## Co patří do ON? -- [x] z.trida_id = t.id -- t.nazev = '1.A' -- ORDER BY z.prijmeni -- USE skola -> ON je shoda klíčů. Filtr na název 1.A je WHERE, ne spojení. - -## Proč není název třídy uložený u každého žáka? -- MySQL to neumí -- [x] Aby se název měnil na jednom místě -- Protože text v MySQL nejde uložit -- Aby nešel JOIN -> Jedna pravda v tabulce tridy. Žáci drží jen číslo. - -## Co JOIN udělá s uloženými tabulkami? -- Sloučí je natrvalo do jedné -- [x] Jen složí výsledek dotazu, tabulky zůstanou dvě -- Smaže cizí klíče -- Převede je na Excel -> Výsledek je odpověď na příkaz. tridy a zaci na serveru zůstávají. diff --git a/content/programove-vybaveni/3-rocnik/08-zadani-databaze.en.md b/content/programove-vybaveni/3-rocnik/08-zadani-databaze.en.md deleted file mode 100644 index b69e293..0000000 --- a/content/programove-vybaveni/3-rocnik/08-zadani-databaze.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Assignment: a student register -popis: Classes, students, a relationship and one query that shows 1.A by name. -nazev_cviceni: Quiz: the register -nadpis_kvizu: Walk the keys and the query ---- diff --git a/content/programove-vybaveni/3-rocnik/08-zadani-databaze.md b/content/programove-vybaveni/3-rocnik/08-zadani-databaze.md deleted file mode 100644 index d3a812b..0000000 --- a/content/programove-vybaveni/3-rocnik/08-zadani-databaze.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: sw-3-zadani-databaze -nazev: Zadání: evidence žáků -popis: Třídy, žáci, vztah a jeden dotaz, který ukáže 1.A jménem. -nazev_cviceni: Kvíz: evidence -nadpis_kvizu: Projděte klíče i dotaz ---- - -# Výklad - -## Struktura -*Dvě tabulky* - -- tridy: id jako klíč, nazev. Řádky 1.A a 1.B. -- zaci: id jako klíč, jmeno, prijmeni, trida_id jako cizí klíč. -- Anna Nováková je ve třídě 1.A. Ve třídě 1.B je aspoň jeden jiný žák. -- Název 1.A není opsaný v tabulce žáků. Je jen v tridy. - -> Tip: Ať děláte Access, nebo MySQL, tahle dvě pole a vztah jsou povinné. Nástroj je obal. - -## Access -*Když odevzdáváte accdb* - -- evidence.accdb má vztah 1:N, referenční integritu a vypnutou kaskádu. -- Dotaz zaci_1A a formulář frmZaci. Sestava je seskupená podle třídy. -- Žák s neexistující třídou nejde uložit. Vyzkoušeno na trida_id 99. -- PDF sestavy leží vedle accdb. - -> Tip: Když učitel otevře jen accdb, formulář a dotaz v něm musí být. Samotné PDF bez souboru nestačí. - -## MySQL -*Když odevzdáváte SQL* - -- dotazy.sql obsahuje SELECT se WHERE, INSERT, UPDATE i DELETE, oba měnící příkazy s WHERE. -- JOIN vypíše příjmení a název 1.A, seřazené podle příjmení. -- V souboru není heslo k serveru a není DELETE bez WHERE. -- Příkazy jdou spustit znovu jen tam, kde to dává smysl. DELETE testovacího žáka v souboru má konkrétní id a komentář. - -> Tip: Odevzdává se text příkazů, ne snímek obrazovky klienta. Snímek smí být navíc. - -## Jedno odevzdání -*Ne obě poloviční* - -- Stačí jeden nástroj, Access nebo MySQL, ale celý: struktura, data, dotaz na 1.A. -- V dotazu je Anna vidět jako 1.A, ne jako holé číslo, pokud je součástí této části zadání JOIN nebo dotaz s názvem. -- Záloha souboru má datum v názvu, třeba evidence-2026-06-12.accdb. -- Do textu úkolu nepište heslo a nepište, že jste kaskádu zapnuli, pokud jste ji zapnout neměli. - -> Tip: Když umíte obojí, odevzdejte jedno pořádně. Dvě rozdělané databáze jsou horší než jedna hotová. - -# Kvíz - -## Kde leží text 1.A? -- V každém řádku žáka jako jediná pravda -- [x] V tabulce tridy, v poli nazev -- V názvu souboru jako jediném místě -- V hesle -> Žák má jen trida_id. Název je v tabulce tříd jednou. - -## Jaký vztah mají třídy a žáci? -- [x] 1:N, jedna třída a víc žáků -- N:N bez třetí tabulky uprostřed školního cvičení -- Žádný, stačí Excel bez klíče -- 1:1, každý žák vlastní tabulku třídy -> Jedna třída, mnoho žáků. Na straně žáků je cizí klíč. - -## Co musí mít UPDATE a DELETE v odevzdaném SQL? -- Žádnou podmínku, ať je příkaz krátký -- [x] WHERE, které trefí jen zamýšlené řádky -- Hvězdičku místo sloupců -- Kaskádu v příkazu SELECT -> Bez WHERE se mění nebo maže celá tabulka. Ve cvičení se to neodevzdává. - -## Co Access odmítne, když je integrita zapnutá? -- Žáka se třídou 1.A -- [x] Žáka s trida_id 99, které v tridy není -- Formulář -- Sestavu podle příjmení -> Cizí klíč musí ukazovat na existující třídu. 99 v tabulce tříd není. diff --git a/content/programove-vybaveni/4-rocnik/01-wordpress.en.md b/content/programove-vybaveni/4-rocnik/01-wordpress.en.md deleted file mode 100644 index d8adbc0..0000000 --- a/content/programove-vybaveni/4-rocnik/01-wordpress.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: WordPress: pages and posts -popis: A school site, a static page and a dated news item. The system is not hand-written HTML for every sentence. -nazev_cviceni: Quiz: WordPress -nadpis_kvizu: Tell a page from a post ---- diff --git a/content/programove-vybaveni/4-rocnik/01-wordpress.md b/content/programove-vybaveni/4-rocnik/01-wordpress.md deleted file mode 100644 index de527c6..0000000 --- a/content/programove-vybaveni/4-rocnik/01-wordpress.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: sw-4-wordpress -nazev: WordPress: stránky a příspěvky -popis: Web školy, statická stránka a datovaná zpráva. Systém není ručně psané HTML každé věty. -nazev_cviceni: Kvíz: WordPress -nadpis_kvizu: Rozlište stránku a příspěvek ---- - -# Výklad - -## Co to je -*Správa obsahu* - -- WordPress je systém pro web. Text se píše v administraci, ne do každé stránky jako do samostatného souboru ve Wordu. -- Školní web se jmenuje Školní den. Název se nastaví v Nastavení, Obecné. -- Administrace je cesta /wp-admin/ na adrese webu. Bez účtu tam nejste. -- Veřejná stránka a administrace jsou dva pohledy. Návštěvník administraci nevidí. - -> Tip: Když se po uložení na webu nic nezměnilo, často jste jen uložili koncept. Zveřejnit je samostatný krok. - -## Stránka a příspěvek -*Dva druhy* - -- Stránka je trvalá: O škole, Kontakt. Nemá datum jako hlavní údaj. -- Příspěvek je zpráva: co se stalo 12. 6. 2026. Řadí se od nejnovějšího. -- Školní den má aspoň jednu stránku O škole a jeden příspěvek o dni otevřených dveří. -- Příspěvek není stránka s jiným názvem. V menu se s nimi pracuje jinak. - -> Tip: V administraci jsou Příspěvky a Stránky dvě samostatné položky. Když novinku přidáte jako stránku, na výpisu zpráv nebude. - -## Adresa -*Trvalý odkaz* - -- Trvalý odkaz v Nastavení, Trvalé odkazy, ať je název příspěvku, ne ?p=123. -- Adresa pak nese slova, třeba /den-otevrenych-dveri/. -- Jednou zveřejněnou adresu neměňte jen kvůli stylu. Odkaz, který už někdo má, by se rozbil. -- Název webu a adresa příspěvku jsou dvě věci. Název je Školní den, adresa je konkrétní článek. - -> Tip: Když škola už odkazy rozeslala, změnu trvalých odkazů nechte na učiteli. Cvičný web si klidně nastavte hned na začátku. - -## Zadání: dvě věci na webu -*Cvičení* - -- Na cvičném webu nastavte název Školní den. -- Zveřejněte stránku O škole, aspoň dvě věty, bez data jako hlavní osy. -- Zveřejněte příspěvek Den otevřených dveří s datem 12. 6. 2026. -- Do souboru web.txt napište adresu stránky a adresu příspěvku. Heslo do souboru nepište. - -> Tip: Koncept se na veřejné stránce neukáže. U obou má být stav Publikováno. - -# Kvíz - -## Čím se liší stránka od příspěvku? -- Ničím, je to stejné tlačítko -- [x] Stránka je trvalá, příspěvek je datovaná zpráva -- Příspěvek nejde zveřejnit -- Stránka musí být v Excelu -> O škole je stránka. Novinka s datem je příspěvek. - -## Kam se nastaví název webu Školní den? -- Do názvu počítače -- [x] Do Nastavení, Obecné -- Do buňky A1 -- Do příkazu DELETE -> Název webu je nastavení WordPressu, ne název souboru Windows. - -## Jaký trvalý odkaz ve cvičení chcete? -- ?p=123 natrvalo -- [x] Název příspěvku ve adrese -- Jen číslo id žáka -- Adresu z Accessu -> Adresa se slovy se čte a pamatuje. Číselný parametr ne. - -## Co napsat do web.txt? -- Heslo správce -- [x] Adresy zveřejněné stránky a příspěvku -- Celou databázi MySQL -- Soubor accdb -> Úkol dokládá, že stránky jsou venku. Heslo do textového souboru nepatří. diff --git a/content/programove-vybaveni/4-rocnik/02-wordpress-role.en.md b/content/programove-vybaveni/4-rocnik/02-wordpress-role.en.md deleted file mode 100644 index bee86a9..0000000 --- a/content/programove-vybaveni/4-rocnik/02-wordpress-role.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: WordPress: users and appearance -popis: An author writes their own news, an editor also edits others. There is one administrator. -nazev_cviceni: Quiz: roles -nadpis_kvizu: Match the role ---- diff --git a/content/programove-vybaveni/4-rocnik/02-wordpress-role.md b/content/programove-vybaveni/4-rocnik/02-wordpress-role.md deleted file mode 100644 index a4d5f49..0000000 --- a/content/programove-vybaveni/4-rocnik/02-wordpress-role.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: sw-4-wordpress-role -nazev: WordPress: uživatelé a vzhled -popis: Autor píše své zprávy, šéfredaktor i cizí. Správce je jeden. -nazev_cviceni: Kvíz: role -nadpis_kvizu: Přiřaďte roli ---- - -# Výklad - -## Role -*Nejmíň práv* - -- Správce instaluje doplňky, mění šablonu a zakládá uživatele. Ve třídě je jeden, účet učitele. -- Šéfredaktor zveřejňuje a upravuje i cizí příspěvky a stránky. Správce to být nemusí. -- Autor zveřejňuje vlastní příspěvky. Cizí ne. Stránky O škole nezakládá. -- Spolužák, který jen přidává novinky, dostane roli Autor. Ne správce. - -> Tip: Přihlášení každého člověka je vlastní účet. Heslo se nepůjčuje, ani když jde o školní cvičení. - -## Šablona a doplňky -*Málo* - -- Šablona je vzhled. Ve cvičení stačí jedna, třeba výchozí, kterou učitel určí. -- Doplněk přidává funkci. Každý doplněk je další věc, která se musí aktualizovat. -- Doplněk z neznámého webu se neinstaluje. Stačí jeden překlep a web běží s cizím kódem. -- Aktualizace WordPressu, šablony a doplňků se dělají v klidný den a po záloze, ne minutu před dnem otevřených dveří. - -> Tip: Neaktivní doplněk, který nepoužíváte, smažte. Vypnutý pořád leží na disku a pořád se může hodit útočníkovi, když v něm je chyba. - -## Menu -*Co návštěvník vidí* - -- Menu má položku O škole na stránku, ne na koncept. -- Příspěvky se často vypisují samy na úvodu. Do menu se nemusí přidávat každý. -- Zkouškový příspěvek s textem test test do veřejného menu nepatří. Smažte ho, nebo ho nechte jako koncept. -- Název v menu a nadpis stránky ať říkají totéž. O škole a O nas jsou dvě stránky, ne jedna. - -> Tip: Náhled v anonymním okně ukáže web bez vašeho přihlášení. To je pohled návštěvníka. - -## Zadání: účet autora -*Cvičení* - -- Založte uživatele redakce s rolí Autor. Heslo mu nastavte mimo sešit, do web.txt ho nepište. -- Ověřte, že tento účet neumí instalovat doplňky. Když umí, je to správce a roli změňte. -- Šablonu neměňte na náhodnou z internetu. Nechte tu, kterou web už má, nebo tu od učitele. -- Do web.txt dopište přihlašovací jméno autora a že role je Autor. Ne heslo. - -> Tip: Uživatelé, Všichni uživatelé, sloupec Role. Autor tam musí být napsaný, nestačí, že to tak bylo v úmyslu. - -# Kvíz - -## Jakou roli dostane spolužák, který jen píše novinky? -- Správce -- [x] Autor -- Jediný účet s vaším heslem -- Roli MySQL -> Autor zveřejní vlastní příspěvek a nesahá na doplňky ani na cizí texty. - -## Kdo smí instalovat doplňky? -- Každý návštěvník -- [x] Správce -- Autor -- Kdokoli s odkazem na článek -> Doplňky mění celý web. To je práce správce, ne autora zprávy. - -## Proč se doplněk nestahuje z náhodného webu? -- WordPress doplňky neumí -- [x] Je to cizí kód, který běží na školním webu -- Protože pak nejde napsat stránku -- Doplňky jsou vždycky v Excelu -> Doplněk je program. Neznámý zdroj do školního webu nepatří. - -## Co do web.txt o účtu redakce nepatří? -- Přihlašovací jméno -- Role Autor -- [x] Heslo -- To, že účet nezvládne instalovat doplňky -> Heslo do textového úkolu nepište. Jméno a role ano. diff --git a/content/programove-vybaveni/4-rocnik/03-power-bi.en.md b/content/programove-vybaveni/4-rocnik/03-power-bi.en.md deleted file mode 100644 index fb41b75..0000000 --- a/content/programove-vybaveni/4-rocnik/03-power-bi.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Power BI: data from Excel -popis: One workbook, one table, a chart by class. The same data is not loaded twice. -nazev_cviceni: Quiz: Power BI -nadpis_kvizu: Pick the source and the visual ---- diff --git a/content/programove-vybaveni/4-rocnik/03-power-bi.md b/content/programove-vybaveni/4-rocnik/03-power-bi.md deleted file mode 100644 index e3c9d21..0000000 --- a/content/programove-vybaveni/4-rocnik/03-power-bi.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: sw-4-power-bi -nazev: Power BI: data z Excelu -popis: Jeden sešit, jedna tabulka, graf podle třídy. Stejná data se nenačítají dvakrát. -nazev_cviceni: Kvíz: Power BI -nadpis_kvizu: Vyberte zdroj a vizuál ---- - -# Výklad - -## Soubor -*pbix* - -- Power BI Desktop ukládá práci do pbix. Není to xlsx a není to obrázek grafu. -- Na odevzdání vedle pbix patří PDF stránky sestavy, ať ji otevře i člověk bez Power BI. -- Zdroj je prodej.xlsx, tabulka Prodej se sloupci Polozka, Trida, Castka. -- Načtení je Načíst data, Excel, a vybere se tabulka Prodej, ne celý sešit naslepo dvakrát. - -> Tip: Když v modelu vidíte Prodej a Prodej (2), tabulka se načetla dvakrát. Jednu odeberte, než postavíte graf. - -## Model -*Jedna řádka, jedna skutečnost* - -- Každý řádek je jeden prodej: položka, třída, částka. Součet v tomtéž sloupci navíc řádek souhrnu být nemá. -- Řádek souhrnů z Excelu do Power BI nepatří. Součet si spočítá vizuál. -- Trida je text 1.A a 1.B. Castka je číslo bez Kč v buňce. -- Když Excel opravíte, v Power BI dejte Obnovit. Sám se o uložení xlsx nedozví. - -> Tip: Sloupec, který Power BI bere jako text, se nesčítá. Často je v něm mezera nebo Kč. V Excelu ho opravte a obnovte. - -## Vizuál -*Sloupec a karta* - -- Sloupcový graf: osa Trida, hodnota součet Castka. Porovnání dvou tříd. -- Karta ukáže jedno číslo, celkový součet Castka. -- Koláč pro dvě třídy je zbytečný. Pro dvanáct měsíců byl špatně už v Excelu. -- Průřez, anglicky slicer, na pole Trida nechte na příští lekci. Teď ať graf ukáže obě třídy. - -> Tip: Když graf ukáže počet řádků místo součtu korun, v hodnotách je Počet. Přepněte souhrn na Součet. - -## Zadání: první pbix -*Cvičení* - -- prodej.pbix načte tabulku Prodej jednou. -- Na stránce jsou sloupcový graf podle třídy a karta s celkovou částkou. -- Obnovte data potom, co v Excelu změníte jednu částku. Karta se musí pohnout. -- Uložte pbix do složky Skola\1-rocnik\excel a vedle něj prodej.pdf. - -> Tip: PDF je snímek sestavy. pbix je práce, ve které jde vizuál opravit. Odevzdávají se oba. - -# Kvíz - -## Jaký soubor je pracovní v Power BI? -- xlsx jako jediný -- [x] pbix -- pdf jako jediný -- accdb -> pbix drží model a vizuály. Excel je zdroj. PDF je náhled na odevzdání. - -## Jak se mají načíst data prodeje? -- [x] Tabulka Prodej jednou -- Tentýž list dvakrát -- Jako obrázek grafu z Excelu -- Přepisem do Wordu -> Jedna tabulka v modelu. Druhá kopie téhož zdroje mate součty. - -## Jaký vizuál porovná částku tříd 1.A a 1.B? -- Koláč s dvanácti díly -- [x] Sloupcový graf, osa Trida, součet Castka -- Karta bez popisku a bez čísla -- Průřez místo grafu jako jediný prvek -> Dvě kategorie a jejich součet jsou sloupce. Karta je jen jedno číslo celkem. - -## Co uděláte v Power BI potom, co změníte číslo v Excelu? -- Nic, pbix se mění sám v tu vteřinu -- [x] Obnovit -- Smazat pbix a začít ve Wordu -- Převést Castka na text -> Power BI si data při načtení vezme. Další změna Excelu se projeví až po obnovení. diff --git a/content/programove-vybaveni/4-rocnik/04-power-bi-prurez.en.md b/content/programove-vybaveni/4-rocnik/04-power-bi-prurez.en.md deleted file mode 100644 index 29027c6..0000000 --- a/content/programove-vybaveni/4-rocnik/04-power-bi-prurez.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Power BI: a slicer and a report -popis: A class slicer filters the whole page. A filter on one visual leaves the others. -nazev_cviceni: Quiz: the slicer -nadpis_kvizu: Say what the slicer affects ---- diff --git a/content/programove-vybaveni/4-rocnik/04-power-bi-prurez.md b/content/programove-vybaveni/4-rocnik/04-power-bi-prurez.md deleted file mode 100644 index c2e7f08..0000000 --- a/content/programove-vybaveni/4-rocnik/04-power-bi-prurez.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: sw-4-power-bi-prurez -nazev: Power BI: průřez a sestava -popis: Průřez třídy přefiltruje celou stránku. Filtr jednoho vizuálu ostatní nechá. -nazev_cviceni: Kvíz: průřez -nadpis_kvizu: Řekněte, co průřez ovlivní ---- - -# Výklad - -## Průřez -*Celá stránka* - -- Průřez na pole Trida je ovládací prvek na plátně. Čtenář klikne na 1.A. -- Sloupcový graf i karta se mají změnit. Celková částka pak není celá škola, ale jen 1.A. -- Když se karta nehne, průřez na ni není napojený, nebo karta bere jinou tabulku. -- Výběr se zruší gumou na průřezu, nebo volbou všech tříd. Data se tím nesmažou. - -> Tip: Průřez filtruje. Není to nový součet uložený do Excelu. - -## Filtr vizuálu -*Jen jeden graf* - -- Filtr v podokně konkrétního vizuálu ovlivní jen ten vizuál. -- Školní sestava pro porovnání tříd filtr vizuálu nepotřebuje. Má ukázat obě, dokud čtenář nezvolí průřez. -- Filtr stránky schová třídu všem vizuálům na stránce, i bez klikání. Na odevzdání ho nenechávejte zapnutý omylem. -- Než sestavu vyexportujete, zrušte výběr průřezu, pokud má PDF ukázat celou školu. - -> Tip: PDF zachytí průřez tak, jak je zrovna vybraný. Vybraná 1.A v PDF už druhou třídu neukáže. - -## Stránka -*Jedna otázka* - -- Stránka se jmenuje Prodej. Název Stránka 1 se neodevzdává. -- Nadpis na plátně říká Prodej po třídách. Graf má popisky tříd. -- Na jedné stránce jsou nejvýš průřez, jeden graf a jedna karta. Druhý graf se stejným obsahem je navíc. -- Barvy nechte klidné. Červená a zelená těsně vedle sebe se špatně čte. - -> Tip: Zobrazte sestavu na projektoru, nebo aspoň v celém okně. Drobný popisek, který na vašem monitoru ujde, vzadu ve třídě zanikne. - -## Zadání: stránka s průřezem -*Cvičení* - -- Na stránku Prodej přidejte průřez Trida. -- Klik na 1.A změní graf i kartu. Po zrušení výběru je zase vidět celý součet. -- PDF vyexportujte bez vybrané třídy, ať ukazuje 1.A i 1.B. -- pbix uložte znovu. V modelu je tabulka Prodej pořád jen jednou. - -> Tip: Když průřez nabízí prázdný řádek, v Excelu je prázdný řádek tabulky. Smažte ho ve zdroji a obnovte. - -# Kvíz - -## Co má průřez na Trida změnit? -- Jen barvu pozadí -- [x] Graf i kartu na stránce -- Soubor xlsx na disku -- Heslo k WordPressu -> Průřez filtruje vizuály na stránce. Karta s celkovou částkou se musí změnit taky. - -## Čím se liší filtr jednoho vizuálu od průřezu? -- Ničím -- [x] Filtr vizuálu platí jen pro něj, průřez je ovládání pro stránku -- Filtr vizuálu smaže Excel -- Průřez nejde zrušit -> Průřez je na plátně pro čtenáře. Filtr v podokně vizuálu ostatní grafy nechá. - -## Jaké PDF se odevzdává, když mají být vidět obě třídy? -- S vybranou jen 1.A -- [x] Bez výběru v průřezu -- Prázdná stránka -- Jen karta bez grafu a bez tříd -> PDF drží aktuální výběr. Než ho uděláte, výběr zrušte. - -## Jak se má stránka jmenovat? -- Stránka 1 -- [x] Prodej -- pbix -- DELETE -> Název říká, co na stránce je. Výchozí Stránka 1 se neodevzdává. diff --git a/content/programove-vybaveni/4-rocnik/05-batch.en.md b/content/programove-vybaveni/4-rocnik/05-batch.en.md deleted file mode 100644 index bbfeb4d..0000000 --- a/content/programove-vybaveni/4-rocnik/05-batch.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Batch files -popis: A bat file that creates the school folders and deletes nothing. -nazev_cviceni: Quiz: batch -nadpis_kvizu: Pick the safe command ---- diff --git a/content/programove-vybaveni/4-rocnik/05-batch.md b/content/programove-vybaveni/4-rocnik/05-batch.md deleted file mode 100644 index b110c71..0000000 --- a/content/programove-vybaveni/4-rocnik/05-batch.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: sw-4-batch -nazev: Dávkové soubory -popis: Soubor bat, který založí složky školy a nic nemaže. -nazev_cviceni: Kvíz: batch -nadpis_kvizu: Vyberte bezpečný příkaz ---- - -# Výklad - -## Soubor bat -*Příkazy za sebou* - -- Dávkový soubor je text s příponou bat. Příkazový řádek ho spustí řádek po řádku. -- První řádek cvičení je @echo off, ať se příkazy nevypisují podruhé do okna. -- rem je komentář. Do příkazu se nepočítá. -- Soubor se jmenuje slozky.bat a leží v Dokumentech, ne na cizím flash disku, kterému nerozumíte. - -> Tip: Dvojklik spustí bat v té složce, kde soubor je. Neznámý bat z mailu se nespouští, stejně jako pdf.exe. - -## Složky -*mkdir* - -- mkdir založí složku. Když už existuje, příkaz ohlásí chybu a pokračuje se dál, složku nesmaže. -- set "ROOT=%USERPROFILE%\Documents\Skola" uloží cestu. %USERPROFILE% je složka účtu, u každého jiná. -- mkdir "%ROOT%\1-rocnik\word" založí i mezistupně, když je napíšete takto v nových Windows. Když ne, založte nejdřív 1-rocnik a pak word. -- Uvozovky kolem cesty jsou povinné v okamžiku, kdy v cestě je mezera. V Documents mezera není, v názvu účtu být může. - -> Tip: echo Hotovo vypíše větu. pause nechá okno otevřené, ať výsledek přečtete. Bez pause dvojklik okno hned zavře. - -## Co se nepouští -*del* - -- del smaže soubor. Ve školním bat na založení složek žádný del není. -- Příkaz, který maže podle masky celý disk, se nepíše ani z legrace. Obnova není Ctrl+Z. -- cd /d přejde na jiný disk a složku. Než něco mažete, echo vypíše, kde jste. V tomto cvičení nemažete. -- Bat, kterému nerozumíte řádek po řádku, nespouštějte. Krátký soubor se čte celý. - -> Tip: Když chcete zkusit del, zkuste ho na jeden soubor test.txt, který jste sami právě vytvořili. Ne na složku Windows. - -## Zadání: slozky.bat -*Cvičení* - -- slozky.bat nastaví ROOT na %USERPROFILE%\Documents\Skola a založí 1-rocnik\word, 1-rocnik\excel a 1-rocnik\system. -- Na konci je echo s cestou a pause. Není tam del. -- Spusťte ho jednou. Složky v Průzkumníku opravdu jsou. -- Spusťte ho podruhé. Smí ohlásit, že složka už existuje. Nemá nic smazat. - -> Tip: Úprava bat je v Poznámkovém bloku, ne ve Wordu. Word do něj doplní formátování a příkazový řádek pak řádek nepochopí. - -# Kvíz - -## Co má být první řádek školního bat? -- del C:\ -- [x] @echo off -- formát disku -- heslo účtu -> @echo off jen ztiší opisování příkazů. Nic nemaže. - -## Co dělá mkdir? -- Smaže složku -- [x] Založí složku -- Otevře Word -- Změní heslo -> mkdir je make directory. Mazání je jiný příkaz a v tomto cvičení není. - -## Kam ukazuje %USERPROFILE%? -- Na stejnou složku na všech účtech počítače -- [x] Na profil přihlášeného účtu -- Na web WordPressu -- Na tabulku tridy -> Každý účet má vlastní profil. Stejný bat tedy založí Skola v Dokumentech toho, kdo ho spustil. - -## Který bat ve cvičení nespouštíte? -- Ten, který jen zakládá složky a na konci čeká -- [x] Neznámý soubor z mailu -- slozky.bat, který jste sami přečetli -- Soubor, který ohlásí, že složka už existuje -> Dávka je program. Z mailu se nespouští, stejně jako soubor s příponou exe. diff --git a/content/programove-vybaveni/4-rocnik/06-uzivatele-a-skupiny.en.md b/content/programove-vybaveni/4-rocnik/06-uzivatele-a-skupiny.en.md deleted file mode 100644 index 840ca87..0000000 --- a/content/programove-vybaveni/4-rocnik/06-uzivatele-a-skupiny.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Users and groups in Windows -popis: The zaci account is in Users. It is not in Administrators. -nazev_cviceni: Quiz: groups -nadpis_kvizu: Put the account in the right group ---- diff --git a/content/programove-vybaveni/4-rocnik/06-uzivatele-a-skupiny.md b/content/programove-vybaveni/4-rocnik/06-uzivatele-a-skupiny.md deleted file mode 100644 index 75a3c74..0000000 --- a/content/programove-vybaveni/4-rocnik/06-uzivatele-a-skupiny.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: sw-4-uzivatele -nazev: Uživatelé a skupiny ve Windows -popis: Účet zaci je ve Users. Ve skupině Administrators není. -nazev_cviceni: Kvíz: skupiny -nadpis_kvizu: Zařaďte účet do skupiny ---- - -# Výklad - -## Skupina -*Práva najednou* - -- Skupina sdružuje účty, které mají mít stejná práva. Neměníte právo každému účtu zvlášť po jednom souboru. -- Users jsou běžní uživatelé. Administrators smí měnit systém a instalovat. -- Účet zaci patří do Users. Do Administrators ne. -- Nový účet je často v Users sám. Práce navíc je nestrkat ho mezi správce, ne dopisovat Users. - -> Tip: Kdo je správce, vypíše net localgroup Administrators. Jméno zaci v tom seznamu být nemá. - -## Příkazy -*Bez hesla v řádku* - -- net user zaci * /add účet založí a na heslo se zeptá. Hvězdička znamená dotaz, ne heslo zapsané do bat. -- net user zaci vypíše účet. Je tam vidět, jestli je aktivní. -- net localgroup Users zaci /add ho přidá do Users, kdyby tam nebyl. -- net localgroup Administrators zaci /delete ho ze správců odebere, pokud tam omylem je. Příkaz chce spustit správce. - -> Tip: lusrmgr.msc otevře stejné účty v okně, ale jen ve Windows Pro, Education a Enterprise. V edici Home toto okno není a zůstává net user. - -## Kdo příkaz spouští -*Správce* - -- Běžný uživatel účet nezaloží. Okno se musí spustit jako správce, nebo systém požádá o souhlas. -- Souhlas správce není důvod založit účet rovnou jako správce. zaci zůstává běžný. -- whoami na účtu zaci nesmí skončit na Administrators. -- Cvičný účet se po hodině dá odebrat: net user zaci /delete. Nejdřív si ověřte, že nemaže účet učitele. - -> Tip: Jméno účtu zaci je cvičné. Účet, který se jmenuje jako učitel nebo správce, se nedeaktivuje a nemaže. - -## Zadání: zápis, ne cizí účty -*Cvičení* - -- Do ucty.txt napište příkaz, kterým se zaci založí, včetně hvězdičky místo hesla. -- Napište, v které skupině má být a ve které být nemá. -- Pokud učitel dovolí, účet opravdu založte a net localgroup Administrators opište. zaci v seznamu není. -- Heslo do ucty.txt nepište. Cizí účty na počítači neměňte. - -> Tip: Když lusrmgr.msc hlásí, že neexistuje, máte edici Home. Použijte net user a do zápisu napište, že grafické okno v této edici není. - -# Kvíz - -## Do které skupiny patří zaci? -- Administrators -- [x] Users -- Do žádné, účet bez skupiny smí instalovat -- Do skupiny hesel -> Běžná práce je skupina Users. Správci jsou Administrators. - -## Jak se účet založí, aniž by heslo zůstalo v příkazu? -- [x] net user zaci * /add -- net user zaci heslo123 /add -- mkdir zaci -- DELETE FROM zaci -> Hvězdička se zeptá. Heslo napsané v příkazu zůstane v historii. - -## Kde lusrmgr.msc není? -- Ve Windows Pro -- [x] Ve Windows Home -- Ve Windows Education -- Ve Windows Enterprise -> Grafická správa účtů je v Pro, Education a Enterprise. Home ji nemá. - -## Co whoami nesmí ukázat při denní práci na účtu zaci? -- Že jde o běžného uživatele -- [x] Že účet je ve skupině Administrators -- Název počítače -- To, že účet existuje -> Denní účet není správce. whoami to prozradí dřív, než něco nainstalujete. diff --git a/content/programove-vybaveni/4-rocnik/07-zasady.en.md b/content/programove-vybaveni/4-rocnik/07-zasady.en.md deleted file mode 100644 index a14b512..0000000 --- a/content/programove-vybaveni/4-rocnik/07-zasady.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Local policy -popis: A minimum password of 8 characters and a lock after 300 seconds. A school domain overrides the local policy. -nazev_cviceni: Quiz: policy -nadpis_kvizu: Fill in the value and the command ---- diff --git a/content/programove-vybaveni/4-rocnik/07-zasady.md b/content/programove-vybaveni/4-rocnik/07-zasady.md deleted file mode 100644 index f850445..0000000 --- a/content/programove-vybaveni/4-rocnik/07-zasady.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: sw-4-zasady -nazev: Místní zásady -popis: Minimální heslo 8 znaků a zámek po 300 sekundách. Doména školy místní zásadu přebije. -nazev_cviceni: Kvíz: zásady -nadpis_kvizu: Doplňte hodnotu a příkaz ---- - -# Výklad - -## Kde se zásady berou -*gpedit* - -- Místní zásady otevře gpedit.msc. Je ve Windows Pro, Education a Enterprise, v edici Home není. -- Konfigurace počítače platí pro stroj. Konfigurace uživatele platí pro účty, které se přihlásí. -- Školní cvičení mění dvě věci: délku hesla a zámek při nečinnosti. Ostatní zásady nechte být. -- Když je počítač v doméně školy, doménová zásada vyhraje nad místní. Místní změna se pak jakoby ztratí a není to chyba klikání. - -> Tip: Než něco změníte, napište si původní hodnotu. Vrátit Neznámé číslo zpět nejde, když jste si ho nezapsali. - -## Heslo -*Osm znaků* - -- Cesta vede přes Konfigurace počítače, Nastavení systému Windows, Nastavení zabezpečení, Zásady účtů, Zásady hesel. -- Minimální délka hesla se nastaví na 8. -- Nula znamená, že heslo smí být prázdné. To školní účet nechce. -- Zásada neopraví heslo, které už je krátké, dokud ho uživatel příště nemění. Platí pro nová hesla. - -> Tip: Heslo v zásadě nenastavujete. Nastavujete pravidlo. Samotné heslo účtu zaci se zadává při net user, ne tady. - -## Zámek -*300 sekund* - -- Nečinnost: Konfigurace počítače, Nastavení systému Windows, Nastavení zabezpečení, Místní zásady, Možnosti zabezpečení. -- Položka Interaktivní přihlášení: limit nečinnosti počítače se nastaví na 300 sekund, tedy 5 minut. -- Nula nebo nenastaveno znamená, že tato zásada zámek nevynucuje. -- Po pěti minutách bez myši a klávesnice se má počítač zamknout, ne vypnout a ne smazat Dokumenty. - -> Tip: Zámek je Win+L hned. Zásada totéž udělá sama, když odejdete od stroje a zapomenete. - -## Zadání: dvě hodnoty -*Cvičení* - -- Pokud gpedit.msc máte, nastavte minimální délku hesla na 8 a limit nečinnosti na 300 sekund. Původní hodnoty si zapište. -- gpupdate /force zásady načte hned, bez čekání na restart. Příkaz chce okno spuštěné jako správce. -- Do zasady.txt napište obě hodnoty a jestli je počítač v doméně. Heslo nepište. -- V edici Home napište, že gpedit.msc v ní není, a hodnoty jen popište. Nevymýšlejte, že jste je nastavili. - -> Tip: Když po gpupdate hodnota v gpedit zůstane a systém se nechová podle ní, počítač je v doméně a doména místní číslo přebíjí. - -# Kvíz - -## Jaká je školní minimální délka hesla? -- 0 -- [x] 8 -- 300 -- Prázdné heslo -> Osm znaků je pravidlo z první hodiny o účtech. Nula by prázdné heslo dovolila. - -## Na kolik sekund se nastaví limit nečinnosti? -- 5 -- [x] 300 -- 8 -- Na nulu, ať se počítač nezamyká -> 300 sekund je pět minut. Číslo 5 by bylo pět sekund, to v této položce není. - -## Čím se místní zásady načtou hned? -- Smazáním účtu zaci -- [x] gpupdate /force -- mkdir -- SELECT * FROM zaci -> gpupdate zásady znovu načte. Bez něj si počítač může počkat na své vlastní obnovení. - -## Co platí, když je počítač v doméně školy a místní heslo nastavíte jinak? -- Vždy vyhraje místní gpedit -- [x] Vyhraje doménová zásada -- Hesla se vypnou -- WordPress přestane běžet -> Doména je nad místním počítačem. Místní změna, která jí odporuje, se neuplatní. diff --git a/content/programove-vybaveni/4-rocnik/08-maturitni-zadani.en.md b/content/programove-vybaveni/4-rocnik/08-maturitni-zadani.en.md deleted file mode 100644 index fdca7fe..0000000 --- a/content/programove-vybaveni/4-rocnik/08-maturitni-zadani.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Exam assignment -popis: Folders, a letter, grades, a register, a site, a report and an account with a password rule. -nazev_cviceni: Quiz: the whole assignment -nadpis_kvizu: Walk the hand-in ---- diff --git a/content/programove-vybaveni/4-rocnik/08-maturitni-zadani.md b/content/programove-vybaveni/4-rocnik/08-maturitni-zadani.md deleted file mode 100644 index ef404a3..0000000 --- a/content/programove-vybaveni/4-rocnik/08-maturitni-zadani.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: sw-4-maturita -nazev: Maturitní zadání -popis: Složky, dopis, známky, evidence, web, sestava a účet s zásadou hesla. -nazev_cviceni: Kvíz: celé zadání -nadpis_kvizu: Projdi odevzdání ---- - -# Výklad - -## Systém -*Složky a účet* - -- slozky.bat založí Skola\1-rocnik\word, excel a system v Dokumentech toho účtu, který ho spustí. -- V bat není del a není v něm heslo. Je v něm @echo off, mkdir a pause. -- Účet zaci je běžný uživatel ve skupině Users, není v Administrators. -- Minimální délka hesla je 8 znaků. Zámek po nečinnosti je 300 sekund, pokud edice Windows zásady má. - -> Tip: Do textového souboru patří příkazy a hodnoty. Skutečné heslo ne. - -## Office -*Dopis a známky* - -- zadost.docx je jedna strana, datum 12. 6. 2026, řádek Věc, k tomu PDF. -- znamky.xlsx počítá stav vzorcem KDYŽ. Známka 5 je neprospěl, 1 až 4 prospěl. -- Pod známkami je průměr, ne součet. -- prodej.xlsx a prodej.pbix: tabulka načtená jednou, průřez třídy, PDF bez výběru, ať jsou vidět obě třídy. - -> Tip: pbix bez xlsx zdroje učitel neobnoví. Xlsx vedle pbix nechte. - -## Data a web -*Evidence a Školní den* - -- Access nebo MySQL: tabulky tridy a zaci, vztah 1:N, Anna Nováková ve třídě 1.A. -- Dotaz ukáže název 1.A, ne jen číslo. UPDATE a DELETE, pokud jsou v SQL, mají WHERE. -- WordPress: název Školní den, stránka O škole, příspěvek s datem, účet autora. Správce je jeden. -- V textech o webu a účtech není heslo. - -> Tip: Stačí jeden databázový nástroj, ale celý. Access s integritou, nebo SQL s JOINem. - -## Složka odevzdání -*Pořádek* - -- Všechno leží pod Skola, ne na ploše a ne v Stažených. -- Přípony jsou vidět. Názvy nemají final2. -- Na obhajobu otevřete nejdřív bat a složky, pak Excel a Power BI, pak databázi a nakonec web. -- U každé části umíte říct, kdo smí heslo, kdo smí instalovat a proč pětka není prospěl. - -> Tip: Když se zeptají, proč zaci není správce, odpověď je: denní účet nemá právo měnit systém. - -# Kvíz - -## Co slozky.bat nesmí obsahovat? -- mkdir -- @echo off -- [x] del přes celý disk nebo cizí složky -- pause -> Cvičení složky zakládá. Mazání do něj nepatří a neznámé mazání už vůbec ne. - -## Jaký je stav známky 5? -- prospěl -- [x] neprospěl -- průměr -- 1.A -> Prochází 1 až 4. Pětka je neprospěl. Rozhoduje vzorec KDYŽ, ne rukou psaný text. - -## Jakou roli má účet, který ve WordPressu jen píše novinky? -- Správce -- [x] Autor -- Jediný sdílený účet učitele -- Administrators ve Windows -> Autor zveřejní vlastní příspěvek. Doplňky a uživatele spravuje jeden správce. - -## Jaké jsou dvě hodnoty zásad? -- Heslo 0 znaků a zámek 8 sekund -- [x] Heslo aspoň 8 znaků a zámek po 300 sekundách -- Heslo v souboru bat a zámek vypnutý -- 300 znaků hesla a 8 sekund -> Osm znaků je délka hesla. 300 sekund je pět minut nečinnosti. diff --git a/content/technicka-grafika/1-rocnik/01-format-a-meritko.en.md b/content/technicka-grafika/1-rocnik/01-format-a-meritko.en.md deleted file mode 100644 index 2de20d7..0000000 --- a/content/technicka-grafika/1-rocnik/01-format-a-meritko.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Sheet size, scale and the title block -popis: A sizes, drawing scale and the title block. -nazev_cviceni: Quiz: sheet and scale -nadpis_kvizu: Check the sheet, the scale and the title block ---- diff --git a/content/technicka-grafika/1-rocnik/01-format-a-meritko.md b/content/technicka-grafika/1-rocnik/01-format-a-meritko.md deleted file mode 100644 index 2ef74ba..0000000 --- a/content/technicka-grafika/1-rocnik/01-format-a-meritko.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: tg-1-format-a-meritko -nazev: Formát, měřítko a razítko -popis: Řada A, měřítko výkresu a popisové pole. -nazev_cviceni: Kvíz: formát a měřítko -nadpis_kvizu: Ověřte si formát, měřítko a razítko ---- - -# Výklad - -## Řada formátů A -*Papír* - -- Základní formát A4 má 210 × 297 mm. Delší strana je na výšku. -- A3 vznikne složením dvou A4: 297 × 420 mm. -- A2 je 420 × 594 mm. Každý větší formát má dvojnásobnou plochu. -- Na škole se součást kreslí nejčastěji na A4 nebo A3. - -> Tip: kratší strana většího formátu je delší stranou menšího. A3 je na šířku, A4 na výšku. - -## Co znamená měřítko -*Měřítko* - -- Měřítko 1:1 znamená, že výkres je ve skutečné velikosti. -- Měřítko 1:2 zmenšuje kresbu na polovinu. Měřítko 2:1 ji zvětšuje na dvojnásobek. -- Kóta se vždy píše ve skutečném rozměru, ne v rozměru nakreslené čáry. -- Do razítka se měřítko zapíše tak, jak se kreslilo, třeba 1:2. - -> Tip: díra o průměru 20 mm má na výkresu 1:2 čáru dlouhou 10 mm, ale kóta říká 20. - -## Popisové pole -*Razítko* - -- Razítko je v pravém dolním rohu. Čte se zprava, když je výkres ve správné poloze. -- Patří do něj název, měřítko, materiál, datum a jméno. -- Číslo výkresu a název součásti se nesmí vyměnit za ozdobný text. -- Rámeček je od okraje papíru odsazený, na školním A4 obvykle o 5 až 10 mm. - -> Tip: než začnete kreslit součást, vyhraďte si hladinu pro rámeček a razítko. - -## Zadání: rámeček A4 -*Cvičení* - -- Nakreslete obdélník 210 × 297 a dovnitř rámeček odsazený o 10 mm od každého okraje. -- Vpravo dole vyhraďte razítko 180 × 40 mm, které lícuje s vnitřním rámečkem. -- Do razítka vepište název Destička, měřítko 1:1 a své jméno. -- Soubor uložte jako A4-ramecek.dwg, jednotky milimetry. - -> Tip: vnitřní rámeček má 190 × 277 mm. Levý dolní roh dejte do bodu 0,0. - - -# Kvíz - -## Jaké rozměry má formát A4? -- 297 × 420 mm -- [x] 210 × 297 mm -- 420 × 594 mm -- 148 × 210 mm -> A3 je 297 × 420 mm. A4 je polovina této plochy, 210 × 297 mm. - -## Co se stane s kótou na výkresu v měřítku 1:2? -- Píše se polovina skutečného rozměru -- [x] Píše se skutečný rozměr -- Kóty se vynechají -- Měřítko se do razítka nepíše -> Kresba je poloviční, číslo na kótě zůstává skutečné. Měřítko 1:2 je v razítku. - -## Kam se na výkresu umísťuje razítko? -- Doprostřed plochy -- [x] Do pravého dolního rohu -- Nad součást, vlevo -- Mimo rámeček -> Razítko lícuje s vnitřním rámečkem vpravo dole, aby šlo výkres složit a razítko zůstalo navrchu. - -## Jak je velký vnitřní rámeček A4 při odsazení 10 mm? -- 210 × 297 mm -- [x] 190 × 277 mm -- 200 × 287 mm -- 180 × 40 mm -> Od 210 i od 297 se odečte 10 mm z každé strany, tedy 20 mm. 190 × 277 mm. diff --git a/content/technicka-grafika/1-rocnik/02-druhy-car.en.md b/content/technicka-grafika/1-rocnik/02-druhy-car.en.md deleted file mode 100644 index afc6ade..0000000 --- a/content/technicka-grafika/1-rocnik/02-druhy-car.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Line types and line weights -popis: Outlines, hidden edges, centrelines and dimensions. -nazev_cviceni: Quiz: lines -nadpis_kvizu: Name the line ---- diff --git a/content/technicka-grafika/1-rocnik/02-druhy-car.md b/content/technicka-grafika/1-rocnik/02-druhy-car.md deleted file mode 100644 index 542e176..0000000 --- a/content/technicka-grafika/1-rocnik/02-druhy-car.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: tg-1-druhy-car -nazev: Druhy a tloušťky čar -popis: Obrys, skryté hrany, osy a kóty podle normy. -nazev_cviceni: Kvíz: čáry -nadpis_kvizu: Poznejte druh čáry ---- - -# Výklad - -## Tlustá plná čára -*Obrys* - -- Viditelné hrany a obrysy se kreslí souvislou tlustou čarou. -- V AutoCADu jí patří vlastní hladina, třeba OBRYS, s tloušťkou 0,5 mm. -- Tloušťka se nastavuje na hladině, ne u každé čáry zvlášť. -- Obrys nesmí být stejně tenký jako kóta, jinak se výkres nedá číst. - -> Tip: hladinu OBRYS nastavte jako aktuální dřív, než začnete kreslit tvar. - -## Tenké čáry -*Kóty a hrany* - -- Kóty, odkazy, šrafy a pomocné čáry jsou souvislé a tenké, kolem 0,25 mm. -- Skryté hrany, které z daného pohledu nejsou vidět, jsou čárkované a tenké. -- Osa díry nebo válce je čerchovaná: dlouhá čárka, tečka, dlouhá čárka. -- Osa přesahuje obrys jen o kousek, nepřetahuje se přes celý výkres. - -> Tip: čárkovaná čára je skrytá hrana. Čerchovaná je osa. Nejsou totéž. - -## Jak to nastavit v AutoCADu -*Hladiny* - -- Příkaz `_LAYER` otevře správce hladin. Založte OBRYS, SKRYTE, OSA a KOTA. -- U SKRYTE zvolte typ čáry DASHED, u OSA typ CENTER. -- Typ čáry se načítá příkazem `_LINETYPE`. Bez načtení ho hladina nenabídne. -- Měřítko typu čáry `_LTSCALE` zvětší nebo zmenší mezery v čárkování, ať je čára čitelná. - -> Tip: když čárkování vypadá jako plná čára, je LTSCALE moc velké nebo moc malé. - -## Zadání: tři čáry jedné díry -*Cvičení* - -- Nakreslete obdélník 60 × 40 tlustou plnou čarou. -- Svislou osu veďte středem a nechte ji přesáhnout obrys o 3 mm na každou stranu. -- Jednu zadní hranu, která z pohledu není vidět, nakreslete tenkou čárkovanou čarou. -- Každý druh čáry musí ležet na své hladině. - -> Tip: osa dlouhá 46 mm při výšce tělesa 40 mm přesahuje o 3 mm nahoře i dole. - - -# Kvíz - -## Jakou čarou se kreslí viditelný obrys? -- Tenkou čárkovanou -- [x] Tlustou plnou -- Tenkou čerchovanou -- Tlustou čerchovanou -> Viditelné hrany jsou souvislé a tlustší než kóty, osy i skryté hrany. - -## Co znamená tenká čárkovaná čára? -- Osu díry -- [x] Skrytou hranu -- Obrys -- Šrafu -> Čárkovaná čára je hrana, kterou v daném pohledu nevidíme. Osa je čerchovaná. - -## Jakou čarou se kreslí osa válce? -- Tlustou plnou -- Tenkou čárkovanou -- [x] Tenkou čerchovanou -- Vlnovkou -> Osa je dlouhá čárka, tečka, dlouhá čára. V AutoCADu je to typ CENTER. - -## Proč má mít obrys vlastní hladinu? -- Aby šel smazat jen razítko -- [x] Aby měla tloušťka a typ čáry jedno místo -- Hladiny v AutoCADu nejsou -- Obrys se kreslí jen od ruky -> Tloušťka i typ se nastaví na hladině. Všechny obrysy je pak mají stejné. diff --git a/content/technicka-grafika/1-rocnik/03-prostredi-autocadu.en.md b/content/technicka-grafika/1-rocnik/03-prostredi-autocadu.en.md deleted file mode 100644 index 2d39a07..0000000 --- a/content/technicka-grafika/1-rocnik/03-prostredi-autocadu.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: The AutoCAD workspace -popis: Model space, the command line, units and limits. -nazev_cviceni: Quiz: the workspace -nadpis_kvizu: Check the first drawing setup ---- diff --git a/content/technicka-grafika/1-rocnik/03-prostredi-autocadu.md b/content/technicka-grafika/1-rocnik/03-prostredi-autocadu.md deleted file mode 100644 index 7a16b82..0000000 --- a/content/technicka-grafika/1-rocnik/03-prostredi-autocadu.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: tg-1-prostredi -nazev: Prostředí AutoCADu -popis: Model, příkazový řádek, jednotky a meze. -nazev_cviceni: Kvíz: prostředí -nadpis_kvizu: Ověřte si první nastavení výkresu ---- - -# Výklad - -## Kam se kreslí -*Model* - -- Součást se kreslí v modelu. Papír, rámeček a výřezy patří až do rozvržení. -- Příkazový řádek je dole. Čte se pořád: AutoCAD se ptá na další bod. -- Stisk Enter nebo mezerník zopakuje poslední příkaz. -- Esc příkaz zruší. Neukládejte rozpracovaný příkaz klávesou Esc uprostřed bodu. - -> Tip: když AutoCAD „nic nedělá“, podívejte se, na co se příkazový řádek ptá. - -## Příkaz, který funguje vždy -*Podtržítko* - -- Český AutoCAD má přeložené příkazy. Úsečka se jmenuje ÚSEČKA. -- Mezinárodní jméno se píše s podtržítkem: `_LINE`. Funguje v každé jazykové verzi. -- Na pásu karet je stejný příkaz pod ikonou. Ikona i text dělají totéž. -- V těchto lekcích je u každého kroku mezinárodní příkaz. Naučte se ho psát. - -> Tip: `_LINE` a ÚSEČKA spustí stejné kreslení. Podtržítko se hodí, když čeština na klávesnici zlobí. - -## Jednotky a meze -*Milimetry* - -- `_UNITS` nastavte na desetinné milimetry. Úhly nechte ve stupních. -- Přesnost 0 stačí na celé milimetry, 0,0 když budete potřebovat desetinu. -- `_LIMITS` určí levý dolní a pravý horní roh kreslicí plochy, třeba 0,0 a 420,297. -- `_ZOOM` a volba All ukáže celé meze. Kolečko myši přibližuje ke kurzoru. - -> Tip: nový výkres začněte jednotkami. Přepočet z palců na milimetry uprostřed práce nic nespraví. - -## Zadání: prázdný výkres A3 -*Cvičení* - -- Založte soubor v milimetrech a nastavte meze 0,0 až 420,297. -- Příkazem `_RECTANG` nakreslete obrys papíru z bodu 0,0 do bodu 420,297. -- Přibližte vše příkazem `_ZOOM` a volbou Extents. -- Uložte soubor jako A3-prazdny.dwg. - -> Tip: Extents přiblíží to, co je nakreslené. All přiblíží meze, i když jsou prázdné. - - -# Kvíz - -## Kde se kreslí tvar součásti? -- V rozvržení, přes razítko -- [x] V modelu -- Jen na pásu karet -- V příkazu PLOT -> Model je prostor součásti. Rozvržení je papír, na který se model později vloží výřezem. - -## Co udělá příkaz `_LINE` v českém AutoCADu? -- Nastaví jednotky -- [x] Spustí kreslení úsečky -- Smaže poslední čáru -- Otevře hladiny -> Podtržítko volá mezinárodní příkaz. `_LINE` je úsečka, ať je AutoCAD v jakémkoli jazyce. - -## Jakou jednotku má školní výkres? -- Palec -- [x] Milimetr -- Metr -- Pixel -> `_UNITS` nastavte na desetinné milimetry dřív, než zadáte první rozměr. - -## Co ukáže `_ZOOM` s volbou Extents? -- Celé nastavené meze, i prázdné -- [x] Všechno, co je nakreslené -- Jen razítko -- Poslední příkaz -> Extents orámuje nakreslené objekty. All ukáže meze výkresu. diff --git a/content/technicka-grafika/1-rocnik/04-souradnice.en.md b/content/technicka-grafika/1-rocnik/04-souradnice.en.md deleted file mode 100644 index 95648e1..0000000 --- a/content/technicka-grafika/1-rocnik/04-souradnice.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Coordinates -popis: Absolute points, relative moves and polar entry. -nazev_cviceni: Quiz: coordinates -nadpis_kvizu: Find the next point ---- diff --git a/content/technicka-grafika/1-rocnik/04-souradnice.md b/content/technicka-grafika/1-rocnik/04-souradnice.md deleted file mode 100644 index 626ba0c..0000000 --- a/content/technicka-grafika/1-rocnik/04-souradnice.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: tg-1-souradnice -nazev: Souřadnice -popis: Absolutní bod, relativní posun a polární zápis. -nazev_cviceni: Kvíz: souřadnice -nadpis_kvizu: Dopočítejte další bod ---- - -# Výklad - -## Absolutní souřadnice -*Od počátku* - -- Bod 40,25 leží 40 mm vpravo a 25 mm nahoru od počátku 0,0. -- Čárka odděluje X a Y. Desetinná čárka v čísle se v AutoCADu píše tečkou: 10.5 -- Osa X míří vpravo, osa Y nahoru. Tak je natočený model při startu. -- Absolutní bod nezávisí na tom, kde jste skončili minule. - -> Tip: když se výkres „rozjede“ mimo papír, někdo zadal absolutní bod místo posunu. - -## Relativní souřadnice -*Zavináč* - -- `@30,0` znamená 30 mm vpravo od posledního bodu, výška se nemění. -- `@0,40` je 40 mm nahoru. `@-20,0` je 20 mm doleva. -- Zavináč se píše před čísla. Bez něj AutoCAD čte absolutní bod. -- Při kreslení `_LINE` se tak skládá tvar bod za bodem. - -> Tip: obdélník 70 × 40 z bodu 10,10: `@70,0` pak `@0,40` pak `@-70,0` a zavřít volbou Close. - -## Polární souřadnice -*Délka a úhel* - -- `@50<90` je úsečka dlouhá 50 mm směrem 90 stupňů, tedy kolmo nahoru. -- Úhel se měří od kladné osy X proti směru hodinových ručiček. -- `@40<0` míří vpravo, `@40<180` vlevo, `@40<270` dolů. -- Špičatá závorka se píše bez mezery. Mezera by příkaz ukončila. - -> Tip: úhel 45 stupňů je šikmo vpravo nahoru. Délka je vždy skutečná, ne průmět. - -## Zadání: obdélník ze souřadnic -*Cvičení* - -- Spusťte `_LINE` v bodě 20,20. -- Pokračujte `@80,0`, potom `@0,50`, potom `@-80,0`. -- Útvar zavřete volbou Close, ne ručním bodem. -- Změřte `_DIST` mezi levým dolním a pravým horním rohem. Má vyjít 94,3 mm, tedy přepona 80 a 50. - -> Tip: Close spojí poslední bod s prvním. Ruční bod 20,20 nemusí trefit počátek a obrys zůstane otevřený. - - -# Kvíz - -## Co znamená zápis `@0,40`? -- Bod 0,40 od počátku výkresu -- [x] 40 mm nahoru od posledního bodu -- 40 mm vpravo od počátku -- Úhel 40 stupňů -> Zavináč čte posun od posledního bodu. Nula v X a 40 v Y je čistě nahoru. - -## Kam míří `@60<180`? -- 60 mm nahoru -- [x] 60 mm doleva -- 180 mm vpravo -- Do počátku -> Úhel 180 stupňů je záporná osa X, tedy doleva. 60 je délka úsečky. - -## Jak AutoCAD pozná desetinné číslo? -- Čárkou: 10,5,0 -- [x] Tečkou: 10.5 -- Zlomkem 21/2 -- Mezerou 10 5 -> Čárka odděluje X a Y. Desetina se píše tečkou, třeba 10.5,20. - -## Proč útvar zavřít volbou Close? -- Aby se smazala první úsečka -- [x] Aby se poslední bod trefil do prvního -- Close nastaví měřítko -- Close je totéž co Esc -> Ručně opsaný první bod často mine o zlomek milimetru a obrys nejde vyšrafovat. diff --git a/content/technicka-grafika/1-rocnik/05-zakladni-entity.en.md b/content/technicka-grafika/1-rocnik/05-zakladni-entity.en.md deleted file mode 100644 index 2ca03d0..0000000 --- a/content/technicka-grafika/1-rocnik/05-zakladni-entity.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Lines, circles, arcs and rectangles -popis: The four commands every part starts with. -nazev_cviceni: Quiz: basic objects -nadpis_kvizu: Pick the right command ---- diff --git a/content/technicka-grafika/1-rocnik/05-zakladni-entity.md b/content/technicka-grafika/1-rocnik/05-zakladni-entity.md deleted file mode 100644 index e41ea6b..0000000 --- a/content/technicka-grafika/1-rocnik/05-zakladni-entity.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: tg-1-zakladni-entity -nazev: Úsečka, kružnice, oblouk a obdélník -popis: Čtyři příkazy, kterými začíná každá součást. -nazev_cviceni: Kvíz: základní entity -nadpis_kvizu: Vyberte správný příkaz ---- - -# Výklad - -## Úsečka a obdélník -*Hrany* - -- `_LINE` chce první a další bod. Končí se Enterem, zavření obrysu volbou Close. -- `_RECTANG` chce dva protilehlé rohy. Z bodu 0,0 a `@90,40` vznikne obdélník 90 × 40. -- Obdélník je jedna uzavřená křivka. Úsečky jsou samostatné objekty. -- Uzavřená křivka se později líp šrafuje a vysouvá do 3D. - -> Tip: když budete tvar vysouvat, kreslete ho jako `_RECTANG` nebo uzavřenou `_PLINE`, ne jako čtyři volné úsečky. - -## Kružnice -*Díry* - -- `_CIRCLE` se nejčastěji zadá středem a poloměrem. -- Volba D přepne na průměr. U díry Ø12 je průměr 12 a poloměr 6. -- Střed díry se kótuje, ne její okraj. Okraj je důsledek průměru. -- Víc stejných děr se nekreslí znovu: první se zkopíruje nebo rozloží do pole. - -> Tip: v zadání Ø znamená průměr. Do příkazu s poloměrem dáte polovinu. - -## Oblouk -*Zaoblení z příkazu* - -- `_ARC` umí oblouk třemi body nebo středem, počátkem a úhlem. -- Zaoblení rohu ale nedělejte obloukem od ruky. Na to je později `_FILLET`. -- Oblouk má směr. Špatné pořadí bodů ho vyklenu na druhou stranu. -- U drážky se oblouk často nahradí `_PLINE` s volbou Arc uprostřed úseček. - -> Tip: tři body oblouku zadávejte v pořadí, v jakém oblouk plyne. Prostřední bod je na oblouku, ne střed kružnice. - -## Zadání: destička s dírou -*Cvičení* - -- `_RECTANG` z 0,0 do `@90,50`. -- Střed destičky je 45,25. Tam `_CIRCLE`, volba D, průměr 16. -- Osu svislou i vodorovnou nechte přesáhnout obrys o 3 mm. Patří na hladinu OSA. -- Uložte jako desticka-90x50.dwg. - -> Tip: polovina z 90 je 45 a polovina z 50 je 25. Střed neměřte od oka. - - -# Kvíz - -## Čím nakreslíte obdélník 90 × 40 jedním objektem? -- Čtyřmi úsečkami `_LINE` -- [x] `_RECTANG` a druhým rohem `@90,40` -- `_CIRCLE` s poloměrem 90 -- `_ARC` o úhlu 90 -> `_RECTANG` chce dva rohy. Relativní `@90,40` je šířka a výška od prvního rohu. - -## Zadání říká díra Ø12. Jaký poloměr má kružnice? -- 12 -- [x] 6 -- 24 -- 3 -> Průměr je 12, poloměr je polovina. V `_CIRCLE` buď poloměr 6, nebo volba D a průměr 12. - -## Kde leží střed destičky 90 × 50, která začíná v 0,0? -- 90,50 -- [x] 45,25 -- 0,0 -- 25,45 -> Střed je v polovině šířky a polovině výšky. - -## Kdy dát přednost uzavřené křivce před čtyřmi úsečkami? -- Nikdy, úsečka je přesnější -- [x] Když se obrys bude šrafovat nebo vysouvat -- Jen u razítka -- Když je tvar otevřený -> Šrafa i vysunutí potřebují uzavřenou oblast. Čtyři úsečky, které se netrefí, oblast neutvoří. diff --git a/content/technicka-grafika/1-rocnik/06-uchopeni-a-orto.en.md b/content/technicka-grafika/1-rocnik/06-uchopeni-a-orto.en.md deleted file mode 100644 index 08596b5..0000000 --- a/content/technicka-grafika/1-rocnik/06-uchopeni-a-orto.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Snaps, ortho and polar tracking -popis: How to hit an endpoint and draw square. -nazev_cviceni: Quiz: precise drawing -nadpis_kvizu: Pick the snap and the toggle ---- diff --git a/content/technicka-grafika/1-rocnik/06-uchopeni-a-orto.md b/content/technicka-grafika/1-rocnik/06-uchopeni-a-orto.md deleted file mode 100644 index c9f7f0e..0000000 --- a/content/technicka-grafika/1-rocnik/06-uchopeni-a-orto.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: tg-1-uchopeni -nazev: Úchop, orto a polární trasování -popis: Jak trefit konec čáry a kreslit kolmo. -nazev_cviceni: Kvíz: přesné kreslení -nadpis_kvizu: Vyberte úchop a přepínač ---- - -# Výklad - -## Úchopy -*Koncový bod* - -- Úchop přitáhne kurzor ke geometrii. Bez něj minuta minete konec čáry. -- Zapíná se klávesou F3 nebo v stavovém řádku. Nastavení je `_OSNAP`. -- Na začátek stačí koncový bod, střed a střed kružnice. -- Kolmice a tečna se hodí, až budete napojovat čáru na kružnici. - -> Tip: úchop Střed u úsečky je její polovina. Střed u kružnice je její osa. Jsou to dva různé úchopy. - -## Orto a polární úhel -*F8 a F10* - -- Orto, klávesa F8, pustí kurzor jen vodorovně a svisle. -- Polární trasování F10 drží i šikmé úhly, obvykle po 45 nebo po 15 stupních. -- Orto a volné šikmé kreslení nejdou dohromady. Na šikmou čáru orto vypněte. -- Délku při zapnutém ortu napište jen číslem a Enter. Směr určuje myš. - -> Tip: vodorovná čára dlouhá 40 mm je F8, kurzor doprava, napsat 40 a Enter. Nemusíte počítat druhý bod. - -## Proč se výkres rozpadne -*Minutí* - -- Dvě čáry, které se „téměř“ dotýkají, nejdou oříznout ani vyšrafovat. -- Mezera vznikne, když kliknete vedle koncového bodu a úchop je vypnutý. -- `_ZOOM` na roh ukáže mezeru, která na celém výkresu není vidět. -- Opravený roh se napojí úchopem, ne posunem od oka. - -> Tip: než odevzdáte výkres, přibližte každý roh. Mezera menší než milimetr na tisku vynikne. - -## Zadání: kříž přesně ve středu -*Cvičení* - -- Nakreslete obdélník 80 × 60 z bodu 0,0. -- Svislou osu veďte z úchopu Střed dolní hrany do úchopu Střed horní hrany. -- Vodorovnou osu veďte ze Středu levé hrany do Středu pravé. -- Osy se mají protnout v bodě 40,30. Ověřte to `_ID`. - -> Tip: `_ID` vypíše souřadnice úchopu. Když průsečík není 40,30, jedna osa minula střed hrany. - - -# Kvíz - -## Která klávesa zapíná úchopy? -- F8 -- [x] F3 -- F10 -- Esc -> F3 jsou úchopy, F8 je orto, F10 je polární trasování. - -## Co dělá orto? -- Chytá konce čar -- [x] Drží kreslení ve vodorovném a svislém směru -- Nastaví milimetry -- Maže poslední úsečku -> Se zapnutým ortem kurzor neuhne do šikma. Délku pak stačí napsat číslem. - -## Proč dvě čáry, které se na obrazovce dotýkají, nejdou vyšrafovat? -- Šrafa vyžaduje kóty -- [x] Mezi nimi je mezera, konec minul úchop -- Hladina OSA to zakazuje -- Orto je zapnuté -> Od oka minutý konec nechá škvíru. Přiblížení a úchop Koncový bod ji ukážou. - -## Který úchop najde polovinu úsečky? -- Střed kružnice -- [x] Střed -- Koncový bod -- Kolmice -> Úchop Střed na úsečce je její polovina. Na kružnici je to jiný úchop, střed kružnice. diff --git a/content/technicka-grafika/1-rocnik/07-posun-kopie-otoceni.en.md b/content/technicka-grafika/1-rocnik/07-posun-kopie-otoceni.en.md deleted file mode 100644 index 0409703..0000000 --- a/content/technicka-grafika/1-rocnik/07-posun-kopie-otoceni.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Move, copy, rotate and mirror -popis: Change a finished shape instead of drawing it again. -nazev_cviceni: Quiz: editing -nadpis_kvizu: Match the command to the task ---- diff --git a/content/technicka-grafika/1-rocnik/07-posun-kopie-otoceni.md b/content/technicka-grafika/1-rocnik/07-posun-kopie-otoceni.md deleted file mode 100644 index 611ca1a..0000000 --- a/content/technicka-grafika/1-rocnik/07-posun-kopie-otoceni.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: tg-1-posun-kopie -nazev: Posun, kopie, otočení a zrcadlení -popis: Úprava hotového tvaru místo kreslení znovu. -nazev_cviceni: Kvíz: úpravy -nadpis_kvizu: Vyberte příkaz podle zadání ---- - -# Výklad - -## Posun a kopie -*Z místa na místo* - -- `_MOVE` objekt odnese. Na původním místě nic nezůstane. -- `_COPY` nechá vzor a přidá další. Ptá se na základní bod a pak na nové body. -- Základní bod vyberte úchopem, třeba roh nebo střed. Od oka se kopie rozjede. -- Víc kopií za sebou vznikne opakovaným zadáním dalšího bodu, bez nového příkazu. - -> Tip: posun o 30 mm doprava je základní bod kdekoli, druhý bod `@30,0`. - -## Otočení -*Kolem bodu* - -- `_ROTATE` chce základní bod a úhel. Kladný úhel je proti směru hodin. -- 90 otočí doleva, -90 nebo 270 doprava. -- Volba Reference vezme současný úhel hrany a řekne, jaký má být nový. -- Otáčí se kolem vybraného bodu, ne kolem středu obrazovky. - -> Tip: díru v rohu otočíte kolem středu destičky, ne kolem středu díry, jinak odjede z rozteče. - -## Zrcadlení -*Souměrnost* - -- `_MIRROR` chce dva body osy zrcadlení. Osa nemusí být nakreslená předem. -- Svislá osa jsou dva body se stejným X. Vodorovná dva body se stejným Y. -- Na otázku, zda smazat zdroj, dejte Ne, když má zůstat obě poloviny. -- Text se při zrcadlení může otočit naruby. Proměnná MIRRTEXT s hodnotou 0 nechá text čitelný. - -> Tip: souměrnou součást nakreslete z poloviny a zrcadlete. Druhou polovinu neobkreslujte. - -## Zadání: druhá díra zrcadlem -*Cvičení* - -- Destička 100 × 40, levý dolní roh v 0,0. -- Díru Ø10 dejte středem do bodu 20,20. -- Zrcadlete ji přes svislou osu destičky. Osa prochází body 50,0 a 50,40. -- Zdroj nemažte. Druhá díra má střed v 80,20. - -> Tip: 100 minus 20 je 80. Zrcadlo kolem x = 50 převede 20 na 80 a výšku 20 nechá. - - -# Kvíz - -## Čím odnesete objekt, aby na původním místě nezůstal? -- `_COPY` -- [x] `_MOVE` -- `_MIRROR` -- `_ROTATE` -> Kopie zdroj nechá. Posun ho přestěhuje. - -## Jaký úhel otočí tvar o 90 stupňů ve směru hodin? -- 90 -- [x] -90 -- 180 -- 45 -> Kladný úhel jde proti hodinám. Po směru hodin je záporný, tedy -90. - -## Přes co se zrcadlí díra se středem 20,20 na destičce široké 100? -- Přes bod 0,0 -- [x] Přes svislou osu x = 50 -- Přes vodorovnou osu y = 20 -- Přes hranu x = 100 -> Osa souměrnosti destičky je uprostřed šířky. 20 a 80 jsou od ní stejně daleko. - -## Co má být základní bod posunu? -- Libovolné místo vedle objektu, od oka -- [x] Úchop, třeba roh nebo střed -- Vždy počátek 0,0 -- Střed obrazovky -> Úchop podrží rozměr. Kliknutí vedle rohu posune tvar o neznámý kousek navíc. diff --git a/content/technicka-grafika/1-rocnik/08-zadani-desticka.en.md b/content/technicka-grafika/1-rocnik/08-zadani-desticka.en.md deleted file mode 100644 index 1920b3e..0000000 --- a/content/technicka-grafika/1-rocnik/08-zadani-desticka.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Assignment: a plate -popis: The whole first-year drawing on one part. -nazev_cviceni: Quiz: the plate -nadpis_kvizu: Check the finished drawing ---- diff --git a/content/technicka-grafika/1-rocnik/08-zadani-desticka.md b/content/technicka-grafika/1-rocnik/08-zadani-desticka.md deleted file mode 100644 index 08464d1..0000000 --- a/content/technicka-grafika/1-rocnik/08-zadani-desticka.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: tg-1-zadani-desticka -nazev: Zadání: destička -popis: Celý výkres z prvního ročníku na jedné součásti. -nazev_cviceni: Kvíz: destička -nadpis_kvizu: Zkontrolujte hotový výkres ---- - -# Výklad - -## Co se odevzdává -*Zadání* - -- Destička 120 × 70 mm, tloušťka se nekreslí, jde o jeden pohled. -- Čtyři díry Ø8. Středy jsou 15 mm od levého i pravého kraje a 15 mm od dolního i horního kraje. -- Uprostřed je podélná drážka 40 × 16 se zaoblenými konci. Zatím stačí obdélník, zaoblení přijde ve druháku. -- Výkres je na A4, měřítko 1:1, rámeček a razítko z první lekce. - -> Tip: středy děr jsou body 15,15, pak 105,15, pak 15,55 a 105,55. 120 minus 15 je 105, 70 minus 15 je 55. - -## Hladiny a čáry -*Pořádek* - -- OBRYS je tlustá plná čára. OSA je tenká čerchovaná. KOTA zatím nechte prázdnou. -- Každá díra má svislou i vodorovnou osu, která přesahuje obrys o 3 mm. -- Destička má jednu vodorovnou a jednu svislou osu souměrnosti přes celý tvar. -- Skryté hrany tu nejsou. Pohled je zepředu a díry jsou průchozí, jejich okraj je vidět. - -> Tip: průchozí díra v tomto pohledu není čárkovaná. Čárkovaná by byla hrana schovaná za materiálem. - -## Postup -*Po řadě* - -- Nejdřív rámeček a razítko, potom obrys `_RECTANG` 120 × 70. -- Jednu díru `_CIRCLE` o průměru 8 a další tři `_COPY` nebo dvě `_MIRROR`. -- Drážku `_RECTANG` 40 × 16 se středem ve středu destičky. Její levý dolní roh je 40,27. -- Osy dokreslete úchopem Střed. `_DIST` mezi protilehlými dírami ve vodorovném směru má být 90. - -> Tip: střed destičky je 60,35. Drážka sahá 20 mm doleva a doprava a 8 mm nahoru a dolů. - -## Kontrola před odevzdáním -*Co musí sedět* - -- V razítku je název Destička, měřítko 1:1 a materiál, třeba ocel. -- Žádná čára obrysu neleží na hladině OSA a žádná osa není plná. -- Přiblížené rohy nemají mezeru. Kružnice se dotýká svých os ve středu. -- Soubor se jmenuje desticka-120x70.dwg a je v milimetrech. - -> Tip: vypněte hladinu OBRYS. Zůstat mají jen osy a rámeček. Zapněte ji zpět a totéž udělejte s OSA. - - -# Kvíz - -## Kde leží střed pravé horní díry? -- 15,15 -- [x] 105,55 -- 120,70 -- 60,35 -> Od pravého kraje 15 mm je x = 105. Od horního kraje 15 mm je y = 55. - -## Jaká je vodorovná rozteč levé a pravé díry? -- 120 -- 15 -- [x] 90 -- 105 -> 105 minus 15 je 90. Tolik má ukázat `_DIST` mezi středy. - -## Kam patří obrys destičky? -- Na hladinu OSA -- [x] Na hladinu OBRYS, tlustou plnou čarou -- Čárkovaně, protože díry jsou průchozí -- Do razítka -> Viditelný obrys je tlustá plná čára. Osa je samostatná hladina. - -## Proč se průchozí díra v tomto pohledu nekreslí čárkovaně? -- Čárkovaná čára je zakázaná -- [x] Její okraj je z pohledu vidět -- Díra se kreslí jen osou -- Měřítko je 1:2 -> Čárkovaně se kreslí hrana, kterou materiál zakrývá. Okraj díry v čelním pohledu vidíme. diff --git a/content/technicka-grafika/2-rocnik/01-orez-a-ekvidistanta.en.md b/content/technicka-grafika/2-rocnik/01-orez-a-ekvidistanta.en.md deleted file mode 100644 index 0b5fb23..0000000 --- a/content/technicka-grafika/2-rocnik/01-orez-a-ekvidistanta.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Trim, extend and offset -popis: Fix lines that overshoot, and keep a constant gap. -nazev_cviceni: Quiz: trim and offset -nadpis_kvizu: Pick the command and the distance ---- diff --git a/content/technicka-grafika/2-rocnik/01-orez-a-ekvidistanta.md b/content/technicka-grafika/2-rocnik/01-orez-a-ekvidistanta.md deleted file mode 100644 index d132ae3..0000000 --- a/content/technicka-grafika/2-rocnik/01-orez-a-ekvidistanta.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: tg-2-orez-ekvidistanta -nazev: Ořez, prodloužení a ekvidistanta -popis: Úprava čar, které přesahují nebo mají stálý odstup. -nazev_cviceni: Kvíz: ořez a odstup -nadpis_kvizu: Vyberte příkaz a vzdálenost ---- - -# Výklad - -## Ořez a prodloužení -*Na hranu* - -- `_TRIM` uřízne kus objektu po hraně, kterou vyberete jako řeznou. -- V novějším AutoCADu stačí Enter bez výběru hran a řeže se o všechno, co čára protíná. -- `_EXTEND` dělá opak: natáhne čáru až k vybrané hraně. -- Maže se ta část, na kterou kliknete. Klik na špatnou stranu uřízne to, co mělo zůstat. - -> Tip: když ořez „nebere“, čáry se ve skutečnosti neprotínají. Přibližte roh a napojte ho úchopem. - -## Ekvidistanta -*Stálý odstup* - -- `_OFFSET` vytvoří rovnoběžnou křivku v zadané vzdálenosti. -- Hodí se na tloušťku stěny, rámeček i osazení. Zadáte vzdálenost a stranu. -- U kružnice vznikne soustředná kružnice. Průměr se změní o dvojnásobek odstupu. -- Ekvidistanta obdélníku udělá menší nebo větší obdélník se stejnými rohy, ne se zaoblením. - -> Tip: stěna tlustá 8 mm je ekvidistanta obrysu o 8 mm dovnitř. U kružnice Ø40 tak vznikne Ø24. - -## Co neřeže -*Otevřený roh* - -- Ořez potřebuje průsečík. Dvě čáry, které se jen míjejí, se neoříznou. -- Nejdřív je prodlužte nebo je nakreslete znovu s úchopem, teprve pak řežte. -- Ekvidistanta otevřené křivky zůstane otevřená. Rohy se samy nedovřou. -- Po ořezu zkontrolujte, že nezůstaly pahýly kratší než milimetr. Ty `_ERASE` smaže. - -> Tip: pahýl po ořezu je pořád objekt. Na tisku udělá tečku, která do výkresu nepatří. - -## Zadání: rámeček stěny -*Cvičení* - -- Vnější obdélník 100 × 60. Ekvidistantou o 8 mm dovnitř udělejte vnitřní obrys. -- Vnitřní obdélník má tedy 84 × 44. -- Čáry, které po dalších úpravách přesáhnou vnější roh, ořízněte. -- Oba obrysy nechte na hladině OBRYS. Kóty zatím nepřidávejte. - -> Tip: 100 minus dvakrát 8 je 84. 60 minus 16 je 44. Když vnitřek vyjde jinak, odstup šel ven, ne dovnitř. - - -# Kvíz - -## Který příkaz uřízne přesahující kus čáry? -- `_OFFSET` -- [x] `_TRIM` -- `_EXTEND` -- `_MOVE` -> Ořez bere kus za řeznou hranou. Prodloužení čáru naopak natahuje. - -## Ekvidistanta kružnice Ø40 o 8 mm dovnitř má průměr? -- 32 -- [x] 24 -- 48 -- 8 -> Poloměr klesne o 8, průměr o 16. 40 minus 16 je 24. - -## Proč ořez na dvou čarách nic neudělá? -- Orto je zapnuté -- [x] Čáry se neprotínají -- Chybí razítko -- Objekt je kružnice -> Bez průsečíku není kde řezat. Nejdřív čáry napojte, potom řežte. - -## Vnitřní obrys obdélníku 100 × 60 po ekvidistantě 8 mm dovnitř je? -- 100 × 60 -- 92 × 52 -- [x] 84 × 44 -- 108 × 68 -> Z šířky i výšky se ubere 8 mm z každé strany, tedy 16 mm. 84 × 44. diff --git a/content/technicka-grafika/2-rocnik/02-zaobleni-a-zkoseni.en.md b/content/technicka-grafika/2-rocnik/02-zaobleni-a-zkoseni.en.md deleted file mode 100644 index 30afc38..0000000 --- a/content/technicka-grafika/2-rocnik/02-zaobleni-a-zkoseni.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Fillets and chamfers -popis: A corner by a radius or by two distances. -nazev_cviceni: Quiz: corners -nadpis_kvizu: Work out the corner ---- diff --git a/content/technicka-grafika/2-rocnik/02-zaobleni-a-zkoseni.md b/content/technicka-grafika/2-rocnik/02-zaobleni-a-zkoseni.md deleted file mode 100644 index 17e40f1..0000000 --- a/content/technicka-grafika/2-rocnik/02-zaobleni-a-zkoseni.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: tg-2-zaobleni-zkoseni -nazev: Zaoblení a zkosení -popis: Roh poloměrem nebo dvěma vzdálenostmi. -nazev_cviceni: Kvíz: rohy -nadpis_kvizu: Dopočítejte roh ---- - -# Výklad - -## Zaoblení -*Poloměr* - -- `_FILLET` spojí dvě úsečky obloukem. Volba R nastaví poloměr. -- Poloměr 8 znamená oblouk o poloměru 8 mm, ne průměr. -- R0 ostrý roh jen napojí, oblouk nevznikne. Hodí se na nedotažené čáry. -- Příkaz si poloměr pamatuje. Než zaoblíte jiný roh, R zkontrolujte. - -> Tip: u drážky se zaobleným koncem je poloměr polovina šířky drážky. Drážka 16 mm má R8. - -## Zkosení -*Dvě vzdálenosti* - -- `_CHAMFER` srazí roh úsečkou. Volba D zadá dvě vzdálenosti od vrcholu. -- Stejné vzdálenosti 2 a 2 srazí roh pod 45 stupňů, pokud jsou hrany kolmé. -- Různé vzdálenosti, třeba 2 a 4, dají šikminu, která není 45 stupňů. -- Zkosení se kótuje délkou a úhlem, nebo oběma délkami. Ne poloměrem. - -> Tip: na výkresu je zkosení 2 × 45°. V příkazu jsou to vzdálenosti 2 a 2, ne úhel napsaný místo D. - -## Kdy který roh -*Dílec* - -- Zaoblení bývá tam, kde se obrábí frézou nebo kde ostrá hrana vadí. -- Zkosení bývá na hraně díry a na konci hřídele, aby díl navedl protikus. -- Na jednom rohu nedávejte zaoblení i zkosení. Zadání říká jen jedno. -- Po zaoblení se změní délka rovné hrany. Kóta rovné části už není celá šířka. - -> Tip: hrana dlouhá 40 mm se dvěma zaobleními R5 na koncích má rovný úsek 30 mm. - -## Zadání: drážka a sražení -*Cvičení* - -- Obdélník 80 × 30. Na obou kratších koncích `_FILLET` s R8, na obou dlouhých hranách. -- Vznikne oválná drážka: rovný střed je dlouhý 64 mm, šířka zůstane 30? Pozor, R8 na výšce 30 nejde, šířka drážky musí být 16. -- Překreslete tvar jako drážku 64 × 16 a konce zaoblete R8. -- Jeden vnější roh destičky 80 × 50 mimo drážku srazte `_CHAMFER` 2 a 2. - -> Tip: poloměr zaoblení konce drážky se rovná polovině její šířky. 16 / 2 = 8. - - -# Kvíz - -## Co nastaví `_FILLET` volbou R8? -- Zkosení 8 × 8 -- [x] Oblouk o poloměru 8 mm -- Průměr 8 -- Osazení o 8 mm -> R je poloměr oblouku. Průměr oblouku by byl 16. - -## Jak v příkazu zadáte zkosení 2 × 45° na kolmém rohu? -- R2 -- [x] Vzdálenosti 2 a 2 -- Úhel 45 místo obou vzdáleností, bez délek -- Ekvidistantu 2 -> Stejné vzdálenosti na kolmých hranách dají 45 stupňů. Do příkazu patří délky. - -## Jaký poloměr má konec drážky široké 16 mm? -- 16 -- [x] 8 -- 4 -- 32 -> Konec je půlkruh. Jeho poloměr je polovina šířky. - -## Co udělá zaoblení R0? -- Smaže roh -- [x] Napojí čáry ostrým rohem -- Udělá kružnici -- Nastaví měřítko -> Nulový poloměr je způsob, jak dvě minuté čáry spojit do ostrého rohu. diff --git a/content/technicka-grafika/2-rocnik/03-hladiny.en.md b/content/technicka-grafika/2-rocnik/03-hladiny.en.md deleted file mode 100644 index ecdd7b2..0000000 --- a/content/technicka-grafika/2-rocnik/03-hladiny.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Layers -popis: Colour, linetype and weight in one place. -nazev_cviceni: Quiz: layers -nadpis_kvizu: Decide which layer an object belongs on ---- diff --git a/content/technicka-grafika/2-rocnik/03-hladiny.md b/content/technicka-grafika/2-rocnik/03-hladiny.md deleted file mode 100644 index 6a93333..0000000 --- a/content/technicka-grafika/2-rocnik/03-hladiny.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: tg-2-hladiny -nazev: Hladiny -popis: Barva, typ čáry a tloušťka na jednom místě. -nazev_cviceni: Kvíz: hladiny -nadpis_kvizu: Rozhodněte, co patří na kterou hladinu ---- - -# Výklad - -## Proč hladiny -*Pořádek* - -- Hladina nese barvu, typ čáry i tloušťku. Objekt, který na ní vznikne, je zdědí. -- Obrys, osa, skrytá hrana, šrafa, kóta a rámeček jsou samostatné hladiny. -- Vypnutá hladina na obrazovce zmizí, ale tisknout se pořád může. Zmrazená se netiskne a nepřepočítává. -- Zamčená hladina je vidět, ale nejde omylem posunout. - -> Tip: kóty nikdy nekreslete na OBRYS. Až budete obrys měnit, kóty by odjely s ním. - -## Aktuální hladina -*Než kliknete* - -- Nový objekt padne na aktuální hladinu. Je to ta, která je ve správci vybraná jako současná. -- `_LAYER` založí hladinu. Poklepáním ji nastavíte jako aktuální. -- Objekt na špatné hladině přesuňte ve vlastnostech, příkaz `_PROPERTIES` nebo horní lišta. -- Barvu a typ čáry nechte ByLayer. Barva nastavená na objektu se se hladinou přestane řídit. - -> Tip: ByLayer znamená „ber to, co říká hladina“. Je to výchozí a na školním výkresu má tak zůstat. - -## Názvy, které obstojí -*Úmluva* - -- OBRYS, OSA, SKRYTE, SRAFA, KOTA, RAM, TEXT. Krátce a bez mezer. -- OBRYS je bílá nebo černá, tloušťka 0,50. Ostatní tenké, 0,25, každá svou barvou. -- SKRYTE má typ DASHED, OSA typ CENTER. Ostatní Continuous. -- Hladinu 0 nemažte a nekreslete na ni součást. Je systémová. - -> Tip: hladina 0 je schovaná v blocích. Součást na ní se později špatně barví. - -## Zadání: šest hladin -*Cvičení* - -- V souboru destičky založte OBRYS, OSA, SKRYTE, SRAFA, KOTA a RAM. -- Obrys přesuňte na OBRYS, osy na OSA, rámeček na RAM. -- OSA musí mít typ CENTER a po `_LTSCALE` 0,5 nebo 1 musí být čerchování vidět. -- Vypněte OBRYS. Na obrazovce smí zůstat osy a rámeček, nic z tvaru. - -> Tip: když osa vypadá plně, typ čáry není načtený, nebo je LTSCALE mimo rozumné měřítko. - - -# Kvíz - -## Kam patří kóta? -- Na hladinu OBRYS -- [x] Na vlastní hladinu KOTA -- Na hladinu 0 -- Kamkoli, hladina je jen barva pozadí -> Kóta má vlastní tenkou čáru a při úpravě obrysu nesmí odjet s ním. - -## Co znamená ByLayer? -- Objekt barvu hladiny ignoruje -- [x] Objekt si bere barvu a typ čáry z hladiny -- Hladina je zamčená -- Objekt se netiskne -> ByLayer je správné nastavení. Barva „natvrdo“ na objektu se hladinou už neřídí. - -## Čím se liší vypnutá a zmrazená hladina? -- Ničím -- [x] Zmrazená se navíc netiskne a výkres ji nepočítá -- Vypnutá se nedá znovu zapnout -- Zmrazená je vidět červeně -> Vypnutí je jen obrazovka. Zmrazení hladinu vyřadí i z tisku a z přepočtu. - -## Proč nekreslit součást na hladinu 0? -- Hladina 0 nejde použít -- [x] Je systémová a v blocích se chová jinak -- Nepouští tlusté čáry -- Smí na ni jen razítko -> Hladina 0 má zvláštní roli uvnitř bloků. Součást patří na pojmenované hladiny. diff --git a/content/technicka-grafika/2-rocnik/04-srafy.en.md b/content/technicka-grafika/2-rocnik/04-srafy.en.md deleted file mode 100644 index 7619115..0000000 --- a/content/technicka-grafika/2-rocnik/04-srafy.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Hatches -popis: Sectioned material, hatch scale and a closed boundary. -nazev_cviceni: Quiz: hatches -nadpis_kvizu: Decide what gets hatched ---- diff --git a/content/technicka-grafika/2-rocnik/04-srafy.md b/content/technicka-grafika/2-rocnik/04-srafy.md deleted file mode 100644 index 300909f..0000000 --- a/content/technicka-grafika/2-rocnik/04-srafy.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: tg-2-srafy -nazev: Šrafy -popis: Řez materiálem, měřítko šrafy a uzavřená oblast. -nazev_cviceni: Kvíz: šrafy -nadpis_kvizu: Rozhodněte, co se šrafuje ---- - -# Výklad - -## Co šrafa říká -*Materiál* - -- Šrafa v řezu znamená materiál, který řezná rovina proťala. -- Ocel se na školním výkresu šrafuje tenkými čarami pod 45 stupňů. -- Dva sousední díly mají šrafu na opačnou stranu, nebo jinou rozteč. -- Díra, drážka a prázdno se nešrafují. Není tam materiál. - -> Tip: šrafa pod 45 stupni nesmí být rovnoběžná s obrysem. Když je obrys šikmý, úhel šrafy změňte. - -## Příkaz -*Uzavřená oblast* - -- `_HATCH` a vzor ANSI31. Klikněte dovnitř uzavřené oblasti. -- Oblast musí být dovřená. Mezera v rohu šrafu zastaví nebo ji vylije ven. -- Měřítko vzoru zvětší rozteč čar. Moc hustá šrafa na tisku zčerná. -- Šrafa patří na hladinu SRAFA, tenkou čarou. Ne na OBRYS. - -> Tip: asociativní šrafa se přizpůsobí, když obrys později natáhnete. Na školní práci ji nechte zapnutou. - -## Co se v podélném řezu nešrafuje -*Výjimky* - -- Hřídel, žebro, šroub a pero v podélném řezu zůstávají bez šrafy. -- V příčném řezu se tatáž hřídel šrafuje. Rozhoduje směr řezu, ne součást. -- Tenká stěna řezaná podélně se šrafuje. Žebro ne, aby nepůsobilo jako plný kus. -- Obrys šrafované plochy je pořád tlustá čára. Šrafa ho nenahrazuje. - -> Tip: podélný řez hřídele ukáže osazení obrysem. Šrafa by z hřídele udělala zdánlivě plný hranol. - -## Zadání: řez destičkou -*Cvičení* - -- Destičku 80 × 20 v řezu A-A vyšrafujte ANSI31, měřítko tak, aby rozteč byla zhruba 2 až 3 mm. -- Díru Ø10 uprostřed nešrafujte. Šrafa končí na její hraně. -- Šrafu dejte na hladinu SRAFA. Vypnutím této hladiny musí zmizet jen šrafa, obrys zůstane. -- Když šrafa vyteče ven, najděte mezeru v obrysu a roh napojte. - -> Tip: jedna oblast vlevo od díry a jedna vpravo. Obě mohou být jedna šrafa, pokud příkaz umí víc oblastí. - - -# Kvíz - -## Co znamená šrafa v řezu? -- Skrytou hranu -- [x] Materiál proťatý řeznou rovinou -- Závit -- Měřítko 1:2 -> Šrafuje se jen to, co řez skutečně prochází. Díra je prázdná. - -## Jaký vzor se na škole používá pro ocel? -- Plná výplň -- [x] ANSI31, tenké čáry pod 45 stupňů -- Tečkování -- Čerchovaná osa -> ANSI31 je běžný strojařský vzor. Úhel změňte, jen když by splynul s obrysem. - -## Proč šrafa vyteče mimo součást? -- Je zapnuté orto -- [x] Obrys není uzavřený -- Chybí kóta -- Hladina je ByLayer -> I malá mezera v rohu oblast otevře. Napojte roh a šrafu opakujte. - -## Šrafuje se hřídel v podélném řezu? -- Ano, vždy -- [x] Ne -- Jen když má drážku -- Jen ve 3D -> Hřídel, žebro a šroub se v podélném řezu nechávají prázdné. V příčném řezu se hřídel šrafuje. diff --git a/content/technicka-grafika/2-rocnik/05-koty-linearni.en.md b/content/technicka-grafika/2-rocnik/05-koty-linearni.en.md deleted file mode 100644 index 46918a3..0000000 --- a/content/technicka-grafika/2-rocnik/05-koty-linearni.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Linear dimensions -popis: The real size, extension lines and a dimension style. -nazev_cviceni: Quiz: linear dimensions -nadpis_kvizu: Read the dimension correctly ---- diff --git a/content/technicka-grafika/2-rocnik/05-koty-linearni.md b/content/technicka-grafika/2-rocnik/05-koty-linearni.md deleted file mode 100644 index 20556d0..0000000 --- a/content/technicka-grafika/2-rocnik/05-koty-linearni.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: tg-2-koty-linearni -nazev: Lineární kóty -popis: Skutečný rozměr, pomocné čáry a styl kót. -nazev_cviceni: Kvíz: lineární kóty -nadpis_kvizu: Přečtěte kótu správně ---- - -# Výklad - -## Co kóta říká -*Skutečný rozměr* - -- Kóta je skutečný rozměr součásti, ne délka čáry na papíře. -- Na výkresu 1:2 je čára poloviční a číslo zůstává celé. -- `_DIMLINEAR` chce počátek první pomocné čáry, druhé a polohu kótovací čáry. -- Body chytejte úchopem. Kóta z bodu vedle rohu je o milimetr špatně a tváří se přesně. - -> Tip: číslo na kótě nepřepisujte ručně. Když nesedí, je špatně geometrie, ne text. - -## Vzhled -*Čitelné číslo* - -- Pomocné čáry odstupují od obrysu asi o 1 mm a přesahují kótovací čáru. -- Sousední kóty mají stejný odstup, třeba 10 mm od obrysu a 7 mm mezi sebou. -- Číslo se píše nad kótovací čáru, ne přes obrys. Kóta neprotíná šrafu, když to jde jinak. -- `_DIMSTYLE` nastaví šipky, písmo a jednotky jednou pro celý výkres. - -> Tip: výška písma na A4 bývá 3,5 mm. Menší text se na tisku nedá číst. - -## Řetězec a základna -*Víc rozměrů* - -- Řetězec klade kóty za sebou. Součet dílčích kót má dát celkový rozměr. -- Kóta od základny měří všechno od jedné hrany. Hodí se na rozteče od dorazu. -- Celkový rozměr a součet dílčích se na jedné hraně neopakují bez důvodu. -- Kóta patří tam, odkud se rozměr bude vyrábět, ne doprostřed šrafy. - -> Tip: 20 + 45 + 15 = 80. Když součet nesedí s celkovou kótou, jedna pomocná čára minula roh. - -## Zadání: destička 120 × 70 -*Cvičení* - -- Okótujte šířku 120 a výšku 70. -- Vodorovně přidejte 15 od levého kraje ke středu díry a 90 mezi středy děr. -- Svisle 15 od dolní hrany ke středu díry. -- Všechny kóty na hladinu KOTA. `_DIST` mezi rohy musí ukázat stejná čísla jako kóty. - -> Tip: kótujte středy děr, ne jejich okraje. Okraj určí až kóta průměru. - - -# Kvíz - -## Co se píše do lineární kóty na výkresu 1:2? -- Polovina skutečného rozměru -- [x] Skutečný rozměr -- Dvojnásobek -- Měřítko 1:2 místo čísla -> Měřítko mění délku čáry na papíře. Číslo kóty je rozměr součásti. - -## Proč nepřepisovat text kóty ručně? -- AutoCAD to zakazuje vždy -- [x] Špatné číslo skrývá chybu geometrie -- Text musí být v palcích -- Kóta by zmizela z hladiny -> Správná kóta měří geometrii. Ruční text 120 na čáře dlouhé 119 je lež. - -## Od čeho se kótuje poloha díry? -- Od okraje kružnice -- [x] Od středu -- Od osy razítka -- Od nejbližší šrafy -> Výroba potřebuje střed. Průměr díry je samostatná kóta. - -## Co má platit pro řetězec 20, 45 a 15 na součásti dlouhé 80? -- Součet má být 100 -- [x] Součet má být 80 -- Celková kóta se vynechá vždy -- Řetězec se kreslí čerchovaně -> 20 + 45 + 15 = 80. Nesoulad znamená minutý úchop na některé pomocné čáře. diff --git a/content/technicka-grafika/2-rocnik/06-koty-prumeru-a-uhlu.en.md b/content/technicka-grafika/2-rocnik/06-koty-prumeru-a-uhlu.en.md deleted file mode 100644 index 9b60f02..0000000 --- a/content/technicka-grafika/2-rocnik/06-koty-prumeru-a-uhlu.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Diameter, radius and angle dimensions -popis: The diameter symbol, a fillet radius and a chamfer angle. -nazev_cviceni: Quiz: diameter and angle -nadpis_kvizu: Match the symbol to the size ---- diff --git a/content/technicka-grafika/2-rocnik/06-koty-prumeru-a-uhlu.md b/content/technicka-grafika/2-rocnik/06-koty-prumeru-a-uhlu.md deleted file mode 100644 index 17ce4d0..0000000 --- a/content/technicka-grafika/2-rocnik/06-koty-prumeru-a-uhlu.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: tg-2-koty-prumeru -nazev: Kóty průměru, poloměru a úhlu -popis: Značka průměru, poloměr zaoblení a úhel zkosení. -nazev_cviceni: Kvíz: průměr a úhel -nadpis_kvizu: Doplňte značku ke správnému rozměru ---- - -# Výklad - -## Průměr a poloměr -*Díra a oblouk* - -- `_DIMDIAMETER` kótuje kružnici. Před číslo patří značka průměru. -- `_DIMRADIUS` kótuje oblouk. Před číslo patří R. -- Díra má kótu průměru, i když jste ji kreslili poloměrem. Výroba vrtá průměrem. -- Zaoblení rohu má kótu poloměru. Jedno R na výkresu platí pro všechny stejné rohy, když to poznámka říká. - -> Tip: díru Ø8 nekótujte jako R4. Nástroj se jmenuje podle průměru. - -## Úhel -*Zkosení a klín* - -- `_DIMANGULAR` měří úhel mezi dvěma úsečkami nebo obloukem. -- Zkosení 2 × 45° se často zapíše poznámkou, ne obloukovou kótou v každém rohu. -- Úhel se měří ve stupních. 45 stupňů je polovina pravého úhlu. -- Kóta úhlu nesmí překrýt číslo sousední délky. Odsuňte ji dál od vrcholu. - -> Tip: pravý úhel se na strojařském výkresu obvykle nekótuje. 90 stupňů se předpokládá. - -## Kolik desetin -*Přesnost* - -- Školní kóta celého milimetru nemá zbytečné desetinné nuly, pokud styl neříká jinak. -- Průměr a poloměr zaokrouhlete stejně jako délky. Nemíchejte 8 a 8,00 bez důvodu. -- `_DIMSTYLE` nastaví přesnost i značky najednou. Neupravujte každou kótu ručně. -- Kóta, která ukazuje 7,99 místo 8, minula střed. Geometrii opravte, text ne. - -> Tip: 7,99 je skoro jistě úchop vedle středu. `_ID` středu díry to ukáže. - -## Zadání: díra a roh -*Cvičení* - -- Na destičce okótujte díru Ø8 příkazem `_DIMDIAMETER`. -- Zaoblení R8 na drážce okótujte `_DIMRADIUS` jednou. K ostatním stejné poznámkou. -- Zkosení 2 × 45° zapište k příslušné hraně. -- Žádná kóta průměru nesmí ukazovat 4 ani R8 u díry, která se vrtá. - -> Tip: čtyři stejné díry se kótují jednou, s poznámkou 4× Ø8, plus rozteč středů. - - -# Kvíz - -## Jak se kótuje vrtaná díra o průměru 8 mm? -- R8 -- R4 -- [x] Ø8 -- 8 bez značky, jako délka -> Vrták se volí podle průměru. Poloměr by výrobce přepočítával a snadno spletl. - -## Co znamená R8? -- Průměr 8 -- [x] Poloměr zaoblení 8 mm -- Rozteč 8 mm -- Tloušťka čáry 8 -> R je poloměr oblouku. U díry se R nepoužívá. - -## Kóta díry ukazuje 7,99. Co s tím? -- Přepsat text na 8 -- [x] Opravit geometrii, střed minul úchop -- Smazat všechny kóty -- Změnit měřítko na 1:2 -> Text by lež zakryl. Střed díry má ležet přesně tam, kde ho kóty polohy uvádějí. - -## Jak jednou kótou popsat čtyři stejné díry Ø8? -- Čtyřikrát opsat Ø8 -- [x] 4× Ø8 a rozteč středů -- Jen jednu díru a ostatní nechat bez kóty -- R4 krát čtyři -> Počet, průměr a poloha středů stačí. Opakovat stejnou kótu u každé díry výkres zanáší. diff --git a/content/technicka-grafika/2-rocnik/07-pole.en.md b/content/technicka-grafika/2-rocnik/07-pole.en.md deleted file mode 100644 index 23f02f0..0000000 --- a/content/technicka-grafika/2-rocnik/07-pole.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Rectangular and polar arrays -popis: Repeating holes in a row or on a circle. -nazev_cviceni: Quiz: arrays -nadpis_kvizu: Work out the spacing and the count ---- diff --git a/content/technicka-grafika/2-rocnik/07-pole.md b/content/technicka-grafika/2-rocnik/07-pole.md deleted file mode 100644 index c0f8fd0..0000000 --- a/content/technicka-grafika/2-rocnik/07-pole.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: tg-2-pole -nazev: Obdélníkové a polární pole -popis: Opakování děr v řadě nebo na kružnici. -nazev_cviceni: Kvíz: pole -nadpis_kvizu: Dopočítejte rozteč a počet ---- - -# Výklad - -## Obdélníkové pole -*Řady a sloupce* - -- `_ARRAYRECT` rozkopíruje objekt do řádků a sloupců. -- Zadává se počet sloupců, počet řádků a rozteč, ne celkový rozměr. -- Rozteč 30 při třech sloupcích dá od první osy ke třetí 60 mm. -- Pole může zůstat svázané. Úprava jedné díry se propíše do ostatních. - -> Tip: tři díry v řadě mají dvě mezery. Celková délka je dvojnásobek rozteče, ne trojnásobek. - -## Polární pole -*Na kružnici* - -- `_ARRAYPOLAR` chce střed otáčení, počet prvků a úhel vyplnění. -- Čtyři díry po 360 stupních jsou po 90 stupních. -- Vzorová díra musí ležet na roztečné kružnici dřív, než pole spustíte. -- Střed pole je střed příruby, ne střed první díry. - -> Tip: roztečná kružnice Ø60 má poloměr 30. Vzorová díra leží třeba v bodě 30,0. - -## Roztečná kružnice se nekreslí tlustě -*Osa* - -- Kružnice, na které leží středy děr, je tenká čerchovaná osa. -- Není to hrana součásti a nepatří na OBRYS. -- Kótuje se jejím průměrem, často jako Ø60, a počtem děr. -- Samotné díry mají svou kótu průměru jen jednou. - -> Tip: na výkresu čtete 4× Ø8 na Ø60. Osm je díra, 60 je kružnice středů. - -## Zadání: čtyři díry na kružnici -*Cvičení* - -- Příruba je kružnice Ø80, střed 0,0. -- Vzorovou díru Ø8 dejte středem do 30,0. -- `_ARRAYPOLAR` kolem 0,0, čtyři prvky, 360 stupňů. -- Roztečnou kružnici Ø60 dejte na hladinu OSA. Ověřte `_DIST` mezi sousedními středy. - -> Tip: sousední středy svírají 90 stupňů na poloměru 30. Vzdálenost je 30 × √2, asi 42,4 mm. - - -# Kvíz - -## Tři díry v řadě mají rozteč 30. Jak daleko je první osa od třetí? -- 30 -- 90 -- [x] 60 -- 120 -> Mezi třemi dírami jsou dvě mezery. 2 × 30 = 60. - -## Kam se umísťuje vzorová díra pro pole na Ø60? -- Do středu příruby -- [x] Na poloměr 30 od středu -- 60 mm od středu -- Kamkoli, pole si poloměr dopočítá -> Ø60 znamená poloměr 30. Střed vzorové díry musí na této kružnici už ležet. - -## Čím je nakreslená kružnice středů děr? -- Tlustým obrysem -- [x] Tenkou čerchovanou osou -- Šrafou -- Kótovací čarou -> Není to hrana materiálu. Je to osa rozteče a patří na hladinu OSA. - -## Co znamená zápis 4× Ø8 na Ø60? -- Čtyři díry o průměru 60 -- [x] Čtyři díry Ø8, jejich středy leží na Ø60 -- Osazení 4 mm -- Zkosení 8 × 60 -> První průměr je díra, druhý je roztečná kružnice. diff --git a/content/technicka-grafika/2-rocnik/08-zadani-priruba.en.md b/content/technicka-grafika/2-rocnik/08-zadani-priruba.en.md deleted file mode 100644 index 1bb0ae0..0000000 --- a/content/technicka-grafika/2-rocnik/08-zadani-priruba.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Assignment: a flange -popis: A drawing with an offset, a hole pattern, a hatch and dimensions. -nazev_cviceni: Quiz: the flange -nadpis_kvizu: Check the flange before you hand it in ---- diff --git a/content/technicka-grafika/2-rocnik/08-zadani-priruba.md b/content/technicka-grafika/2-rocnik/08-zadani-priruba.md deleted file mode 100644 index 6c75f73..0000000 --- a/content/technicka-grafika/2-rocnik/08-zadani-priruba.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: tg-2-zadani-priruba -nazev: Zadání: příruba -popis: Výkres s ekvidistantou, polem děr, šrafou a kótami. -nazev_cviceni: Kvíz: příruba -nadpis_kvizu: Zkontrolujte přírubu před odevzdáním ---- - -# Výklad - -## Tvar -*Rozměry* - -- Příruba Ø100, střed 0,0. Středová díra Ø40. -- Čtyři díry Ø9 na roztečné kružnici Ø70, po 90 stupních. -- Vnější hrana má zkosení 1 × 45°, které v tomto pohledu vidíte jako tenkou kružnici Ø98. -- Tloušťka příruby 12 mm se okótuje v druhém pohledu nebo v řezu. V čelním pohledu je kružnice. - -> Tip: rozteč Ø70 znamená vzorovou díru ve vzdálenosti 35 mm od středu. - -## Řez -*Aby byla vidět tloušťka* - -- Druhý pohled je řez přes osu. Ukáže tloušťku 12 a průchod díry Ø40. -- V řezu se šrafuje materiál příruby. Díra Ø40 zůstane prázdná. -- Díry Ø9 v tomto řezu nemusí vyjít všechny. Řezná rovina bere dvě protilehlé, nebo žádnou, podle úhlu. -- Zvolte řez rovinou, která prochází dvěma protilehlými dírami Ø9, ať je v řezu vidět i jejich průchod. - -> Tip: rovina pod úhlem 0 stupňů vezme díry na ose X. Jejich průchod je Ø9 skrz tloušťku 12. - -## Kóty a hladiny -*Jednou* - -- Kóty: Ø100, Ø40, 4× Ø9 na Ø70, tloušťka 12, zkosení 1 × 45°. -- OBRYS, OSA, SRAFA, KOTA, RAM. Typy čar jako ve druháku. -- Razítko: Příruba, 1:1, ocel. -- Formát A4 na šířku nebo A3, když se řez vedle čela nevejde čitelně. - -> Tip: kóta 4× Ø9 se neopakuje u každé díry. Roztečná kružnice má vlastní kótu Ø70. - -## Kontrola -*Před tiskem* - -- `_DIST` od středu k ose díry Ø9 je 35. -- Šrafa nezasahuje do díry Ø40 ani do děr Ø9. -- Vypnutí hladiny KOTA nechá čistý tvar. Čísla nezmizí z obrysu, protože na něm nemají být. -- Soubor priruba.dwg, jednotky milimetry, žádná kóta přepsaná ručně. - -> Tip: když kóta Ø100 ukazuje 99,9, vnější kružnice nemá průměr 100. Opravte kružnici, ne text. - - -# Kvíz - -## Jak daleko od středu leží osa díry na roztečné kružnici Ø70? -- 70 -- [x] 35 -- 9 -- 100 -> Rozteč se kótuje průměrem. Poloměr, tedy vzdálenost středu díry, je 35. - -## Jak jednou kótou popsat čtyři malé díry? -- Ø9 -- Ø70 -- [x] 4× Ø9 -- R4,5 -> Počet krát průměr. Poloha je až kóta roztečné kružnice. - -## Co se v řezu příruby nešrafuje? -- Těleso příruby -- [x] Průchod díry Ø40 -- Obrys -- Razítko se šrafuje vždy -> Šrafuje se materiál. Díra je prázdná, šrafa končí na její hraně. - -## Kóta vnějšího průměru ukazuje 99,9. Co uděláte? -- Přepíšete ji na 100 -- [x] Opravíte kružnici na Ø100 -- Změníte měřítko na 1:2 -- Smažete řez -> Kóta měří geometrii. Ruční text by zakryl, že kružnice je špatně. diff --git a/content/technicka-grafika/3-rocnik/01-pohledy.en.md b/content/technicka-grafika/3-rocnik/01-pohledy.en.md deleted file mode 100644 index a25979f..0000000 --- a/content/technicka-grafika/3-rocnik/01-pohledy.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Views and first-angle projection -popis: Front, top and side views the way they are drawn here. -nazev_cviceni: Quiz: views -nadpis_kvizu: Put the view in the right place ---- diff --git a/content/technicka-grafika/3-rocnik/01-pohledy.md b/content/technicka-grafika/3-rocnik/01-pohledy.md deleted file mode 100644 index f247128..0000000 --- a/content/technicka-grafika/3-rocnik/01-pohledy.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: tg-3-pohledy -nazev: Pohledy a evropské promítání -popis: Nárys, půdorys a bokorys tak, jak se kreslí u nás. -nazev_cviceni: Kvíz: pohledy -nadpis_kvizu: Umístěte pohled na správné místo ---- - -# Výklad - -## Tři základní pohledy -*Nárys* - -- Nárys je pohled zepředu. Vybírá se tak, aby ukázal tvar co nejlíp. -- Půdorys je pohled shora. Bokorys je pohled zleva. -- V evropském promítání leží půdorys pod nárysem, ne nad ním. -- Bokorys zleva leží vpravo od nárysu. Předmět si představte překlopený k vám. - -> Tip: americké promítání má půdorys nahoře. Na českém školním výkresu se nekreslí. - -## Co se v pohledu opakuje -*Stejná hrana* - -- Výška nárysu a výška bokorysu je stejné číslo. Šířka nárysu a šířka půdorysu taky. -- Hloubka půdorysu se rovná šířce bokorysu. Pomůže si 45stupňová pomocná čára. -- Skrytá hrana se v pohledu, kde není vidět, kreslí tenkou čárkovanou čarou. -- Hrana, která v daném pohledu splývá s obrysem, se podruhé nekreslí. - -> Tip: když je nárys vysoký 40, bokorys nemůže být vysoký 36. Někde chybí hrana nebo měřítko. - -## Zarovnání -*Jedna osa* - -- Pohledy se zarovnají. Svislé hrany nárysu a půdorysu leží na stejných svislicích. -- Vodorovné hrany nárysu a bokorysu leží na stejných vodorovných přímkách. -- Mezi pohledy nechte mezeru na kóty, třeba 30 až 40 mm. Pohledy se nesmí překrývat. -- Osa souměrnosti prochází všemi pohledy, ve kterých je součást souměrná. - -> Tip: `_XLINE` pod 45 stupňů přenese hloubku z půdorysu do bokorysu. Po dokreslení ji smažte nebo dejte na pomocnou hladinu. - -## Zadání: kvádr s osazením -*Cvičení* - -- Kvádr 60 × 40 × 30. Zepředu je na něm osazení: pravá část je o 10 mm nižší, v délce 20 mm. -- Nárys je 60 široký a 30 vysoký. Půdorys pod ním je 60 × 40. -- Bokorys vpravo je 40 široký a 30 vysoký. Osazení v něm vyjde jako skrytá nebo viditelná hrana podle směru. -- Pohledy zarovnejte. Výška 30 musí sedět v nárysu i v bokorysu. - -> Tip: osazení dlouhé 20 a nižší o 10 znamená, že v nárysu je horní hrana 40 mm v plné výšce a 20 mm ve výšce 20. - - -# Kvíz - -## Kam se v evropském promítání kreslí půdorys? -- Nad nárys -- [x] Pod nárys -- Vlevo od nárysu -- Místo bokorysu -> Evropské promítání klade pohled shora pod pohled zepředu. Nahoře by byl americký zvyk. - -## Co musí mít nárys a bokorys společné? -- Šířku -- [x] Výšku -- Hloubku jako jediné číslo bez převodu -- Razítko -> Výška předmětu je v obou pohledech stejná. Hloubka se přenáší mezi půdorysem a bokorysem. - -## Jak se kreslí hrana, kterou v daném pohledu není vidět? -- Tlustou plnou -- [x] Tenkou čárkovanou -- Čerchovanou osou -- Nezobrazuje se nikdy -> Skrytá hrana je čárkovaná. Vynechat ji smíte jen tam, kde by výkres zbytečně zanesla a norma to dovolí. - -## Kvádr je vysoký 30. Jak vysoký je jeho bokorys? -- 40 -- [x] 30 -- 60 -- Podle měřítka jinak -> Výška se mezi nárysem a bokorysem nemění. Měřítko je pro celý výkres jedno. diff --git a/content/technicka-grafika/3-rocnik/02-rezy.en.md b/content/technicka-grafika/3-rocnik/02-rezy.en.md deleted file mode 100644 index 3b30d5d..0000000 --- a/content/technicka-grafika/3-rocnik/02-rezy.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Sections and cross-sections -popis: The cutting plane, the arrows and what gets hatched. -nazev_cviceni: Quiz: sections -nadpis_kvizu: Read the cutting plane ---- diff --git a/content/technicka-grafika/3-rocnik/02-rezy.md b/content/technicka-grafika/3-rocnik/02-rezy.md deleted file mode 100644 index 0845683..0000000 --- a/content/technicka-grafika/3-rocnik/02-rezy.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: tg-3-rezy -nazev: Řezy a průřezy -popis: Řezná rovina, šipky a co se šrafuje. -nazev_cviceni: Kvíz: řezy -nadpis_kvizu: Přečtěte řeznou rovinu ---- - -# Výklad - -## Úplný řez -*Rovina A-A* - -- Řez ukáže vnitřek, který by jinak byl samá čárkovaná čára. -- Řezná rovina se v pohledu označí tlustou čerchovanou čarou se šipkami a písmeny, třeba A. -- Obraz řezu se popíše A-A. Šipky říkají, kterým směrem se díváme. -- Materiál proťatý rovinou se šrafuje. Prázdné díry ne. - -> Tip: šipky řezu míří na plochu, kterou uvidíte. Obrácené šipky otočí celý obraz. - -## Poloviční řez -*Souměrná součást* - -- Souměrná součást smí mít půl pohledu a půl řezu v jednom obrazu. -- Dělí je osa. Pohled bývá nad osou nebo vlevo, řez pod osou nebo vpravo. -- Na ose mezi polovinou pohledu a řezu se nekreslí tlustý obrys. -- Skryté hrany v neřezané polovině se často vynechají, protože řez už vnitřek ukázal. - -> Tip: hřídel s dírou na ose je typický poloviční řez. Nahoře obrys, dole díra a šrafa. - -## Co řezem není -*Průřez* - -- Průřez ukáže jen tvar v řezné rovině, bez toho, co leží za ní. -- Řez ukáže i hrany za rovinou. Proto je na řezu víc čar než na průřezu. -- Tenký průřez se smí nakreslit přímo do pohledu, pootočený na místě. -- Žebro řezané podélně se nešrafuje ani v úplném řezu. - -> Tip: když za rovinou vidíte další osazení, je to řez. Když je tam jen vyšrafovaný profil, je to průřez. - -## Zadání: pouzdro -*Cvičení* - -- Pouzdro je válec Ø50, díra Ø30, délka 40. Nakreslete nárys jako úplný řez A-A osou. -- V řezu vyšrafujte mezikruží. Díra Ø30 zůstane prázdná po celé délce 40. -- Šipky A umístěte do půdorysu nebo do místa, odkud je rovina jasná. -- Kóty Ø50, Ø30 a 40. Hřídel to není, šrafa tu být má. - -> Tip: tloušťka stěny je (50 − 30) / 2 = 10 mm. V řezu je vidět vlevo i vpravo od díry. - - -# Kvíz - -## Co říkají šipky u řezné roviny? -- Tloušťku čáry -- [x] Směr pohledu na řez -- Měřítko šrafy -- Počet děr -> Obraz řezu je to, co bychom viděli ve směru šipek. Obrácené šipky obraz otočí. - -## Šrafuje se díra Ø30 v řezu pouzdra? -- Ano, je uprostřed -- [x] Ne, není tam materiál -- Jen v měřítku 1:2 -- Jen když je pouzdro z oceli -> Šrafuje se stěna. Průchozí díra zůstane bílá. - -## Čím se liší průřez od řezu? -- Průřez se nešrafuje -- [x] Průřez neukazuje hrany za řeznou rovinou -- Řez nemá písmena -- Průřez je vždy v měřítku 2:1 -> Řez dokreslí i to, co leží za rovinou. Průřez je jen proťatý tvar. - -## Kam se u souměrného polovičního řezu kreslí řez? -- Přes celý obraz -- [x] Jen na jednu stranu od osy -- Mimo pohled, bez označení -- Do razítka -> Druhá polovina zůstane pohledem. Dělí je osa, ne tlustá hrana. diff --git a/content/technicka-grafika/3-rocnik/03-bloky.en.md b/content/technicka-grafika/3-rocnik/03-bloky.en.md deleted file mode 100644 index f9b3ccc..0000000 --- a/content/technicka-grafika/3-rocnik/03-bloky.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Blocks -popis: A repeated part as one object with a base point. -nazev_cviceni: Quiz: blocks -nadpis_kvizu: Insert the block correctly ---- diff --git a/content/technicka-grafika/3-rocnik/03-bloky.md b/content/technicka-grafika/3-rocnik/03-bloky.md deleted file mode 100644 index 933c73f..0000000 --- a/content/technicka-grafika/3-rocnik/03-bloky.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: tg-3-bloky -nazev: Bloky -popis: Opakovaný díl jako jeden objekt se základním bodem. -nazev_cviceni: Kvíz: bloky -nadpis_kvizu: Vložte blok správně ---- - -# Výklad - -## K čemu blok je -*Jeden díl* - -- Blok je pojmenovaná skupina objektů, která se vkládá jako jeden kus. -- Šroub, značka nebo razítko se nekreslí pokaždé znovu. -- Úprava definice bloku se propíše do všech vložení. Kopie by zůstaly staré. -- Blok patří do výkresu. `_WBLOCK` ho navíc uloží do vlastního souboru. - -> Tip: čtyři stejné šrouby jsou čtyři vložení jednoho bloku, ne čtyři překreslené šrouby. - -## Základní bod -*Kam se chytá* - -- `_BLOCK` se zeptá na jméno, základní bod a objekty. -- Základní bod je místo, za které budete blok vkládat. U šroubu třeba průsečík osy a dosedací plochy. -- Špatný základní bod posune každé vložení o stejnou chybu. -- Objekty bloku nedávejte na hladinu 0, pokud nemají přebírat barvu místa vložení. Na škole nechte jejich vlastní hladiny. - -> Tip: základní bod chytejte úchopem. Bod „někde u šroubu“ se při vložení mine o několik milimetrů. - -## Vložení -*Místo, měřítko, úhel* - -- `_INSERT` vybere jméno, bod vložení, měřítko a otočení. -- Měřítko 1 a úhel 0 vloží blok tak, jak byl nakreslen. -- Měřítko 2 ho zvětší. Na výkresu 1:1 se měřítko bloku nemění, mění se až měřítko výřezu. -- Rozbití bloku příkazem `_EXPLODE` z něj zase udělá obyčejné čáry. Dělejte to jen když máte měnit jediné vložení. - -> Tip: rozbitý blok se už neaktualizuje s definicí. Rozbijte ho, jen když opravdu chcete výjimku. - -## Zadání: šroub M8 jako blok -*Cvičení* - -- V nárysu nakreslete zjednodušený šroub: dřík Ø8 dlouhý 20 a hlava široká 13 vysoká 5,5. -- Základní bod dejte na osu, do dosedací plochy pod hlavou. -- Blok pojmenujte SROUB-M8 a vložte ho dvakrát, po 40 mm. -- Změňte délku dříku v definici na 25. Obě vložení se musí prodloužit. - -> Tip: dosedací plocha je rozhraní hlavy a dříku. Od ní se měří, jak hluboko šroub sedí. - - -# Kvíz - -## Čím se liší blok od obyčejné kopie? -- Ničím -- [x] Úprava definice se propíše do všech vložení -- Blok nejde otočit -- Kopie zabere méně místa -> Kopie jsou nezávislé. Vložení bloku sdílejí jednu definici. - -## Co je základní bod bloku? -- Střed razítka -- [x] Bod, za který se blok vkládá -- Vždy 0,0 výkresu -- Pravý horní roh objektů -> Špatný základní bod posune každé vložení. Chytejte ho úchopem na osu nebo na dosedací plochu. - -## Kdy blok rozbít příkazem `_EXPLODE`? -- Vždy po vložení -- [x] Jen když jedno vložení má být výjimka -- Aby se zmenšil soubor -- Před každým tiskem -> Rozbitý blok se s definicí už neaktualizuje. Ostatní vložení nechte celé. - -## Měřítko vložení 1 na výkresu 1:1 znamená? -- Blok se kreslí poloviční -- [x] Blok se vloží ve velikosti, v jaké byl nakreslen -- Blok se převrátí -- Měřítko razítka se změní na 1:2 -> Měřítko výkresu řeší až výřez na papíře. Blok součásti nechte v měřítku 1. diff --git a/content/technicka-grafika/3-rocnik/04-atributy-a-kusovnik.en.md b/content/technicka-grafika/3-rocnik/04-atributy-a-kusovnik.en.md deleted file mode 100644 index b19bfc1..0000000 --- a/content/technicka-grafika/3-rocnik/04-atributy-a-kusovnik.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Attributes and the parts list -popis: Text in a block that changes with every insert. -nazev_cviceni: Quiz: attributes -nadpis_kvizu: Read the parts list ---- diff --git a/content/technicka-grafika/3-rocnik/04-atributy-a-kusovnik.md b/content/technicka-grafika/3-rocnik/04-atributy-a-kusovnik.md deleted file mode 100644 index 03df34e..0000000 --- a/content/technicka-grafika/3-rocnik/04-atributy-a-kusovnik.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: tg-3-atributy -nazev: Atributy a kusovník -popis: Text v bloku, který se mění s každým vložením. -nazev_cviceni: Kvíz: atributy -nadpis_kvizu: Přečtěte kusovník ---- - -# Výklad - -## Atribut je popisek bloku -*Značka* - -- Atribut je text uložený v bloku. Při každém vložení se zeptá znovu. -- `_ATTDEF` založí značku, výzvu a výchozí hodnotu. Značka je třeba OZN. -- Do bloku se atribut vloží spolu s geometrií. Samotný atribut na výkresu nic neopakuje. -- Hodnotu už vloženého bloku změníte `_ATTEDIT` nebo dvojklikem, ne přepsáním čáry. - -> Tip: značka OZN není text, který se tiskne. Tiskne se hodnota, třeba 1 nebo M8×20. - -## Kusovník -*Co je na výkresu* - -- Kusovník je tabulka nad razítkem. Řádek je jedna položka sestavy. -- Sloupce bývají pozice, název, počet, materiál nebo norma a rozměr. -- Pozice v kolečku na výkresu musí souhlasit s řádkem tabulky. -- Počet se počítá z vložení, ne od oka. Dva stejné šrouby jsou počet 2, ne dva řádky. - -> Tip: tabulku `_TABLE` dejte na hladinu TEXT nebo RAM. Čáry tabulky nejsou obrys součásti. - -## Pořadí -*Nejdřív definice* - -- Nejdřív nakreslete díl, přidejte atribut, teprve pak z toho udělejte blok. -- Atribut přidaný až po vytvoření bloku se do starých vložení sám nedostane. -- `_BATTMAN` nebo nové definování bloku vložení srovná. Na škole je jistější blok založit znovu. -- Výchozí hodnota atributu je nápověda. U šroubu třeba M8×20, a při vložení ji smíte změnit. - -> Tip: prázdná hodnota v kusovníku znamená, že jste při vložení výzvu odklepli bez textu. - -## Zadání: tři položky -*Cvičení* - -- Sestava má přírubu (pozice 1, 1 kus, ocel), šroub M8×20 (pozice 2, 4 kusy) a matici M8 (pozice 3, 4 kusy). -- Šroub je blok s atributem OZN. Čtyři vložení mají stejnou hodnotu. -- Kusovník nad razítkem má tři řádky. Pozice 2 má počet 4, ne 1. -- Odkazové čáry z koleček 1, 2 a 3 míří na správný díl a nekříží se bez důvodu. - -> Tip: čtyři matice jsou pořád jedna položka. Do tabulky nepište čtyři řádky se stejným šroubem. - - -# Kvíz - -## Co se při vložení bloku s atributem ptá znovu? -- Barva hladiny -- [x] Hodnota atributu, třeba označení -- Základní bod definice -- Měřítko výkresu -> Geometrie bloku zůstává. Mění se text, který jste založili jako atribut. - -## Čtyři stejné šrouby v kusovníku jsou? -- Čtyři řádky -- [x] Jeden řádek s počtem 4 -- Pozice 1 až 4 -- Atribut bez bloku -> Stejný díl je jedna položka. Počet říká, kolikrát je vložený. - -## Kdy se atribut musí založit? -- Až po tisku -- [x] Před vytvořením bloku, spolu s geometrií -- Jen v razítku -- Atribut nejde uložit do bloku -> Atribut přidaný později se do existující definice sám nepřidá. - -## Kam patří kusovník? -- Přes nárys -- [x] Nad razítko -- Na hladinu OBRYS -- Mimo rámeček -> Čte se spolu s razítkem. Čáry tabulky nejsou hrany součásti. diff --git a/content/technicka-grafika/3-rocnik/05-rozvrzeni-a-vyrezy.en.md b/content/technicka-grafika/3-rocnik/05-rozvrzeni-a-vyrezy.en.md deleted file mode 100644 index 14a29ca..0000000 --- a/content/technicka-grafika/3-rocnik/05-rozvrzeni-a-vyrezy.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Layouts and viewports -popis: The sheet of paper that looks into the model. -nazev_cviceni: Quiz: viewports -nadpis_kvizu: Set the viewport scale ---- diff --git a/content/technicka-grafika/3-rocnik/05-rozvrzeni-a-vyrezy.md b/content/technicka-grafika/3-rocnik/05-rozvrzeni-a-vyrezy.md deleted file mode 100644 index 0f26aa9..0000000 --- a/content/technicka-grafika/3-rocnik/05-rozvrzeni-a-vyrezy.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: tg-3-rozvrzeni -nazev: Rozvržení a výřezy -popis: Papír, na kterém leží pohled do modelu. -nazev_cviceni: Kvíz: výřezy -nadpis_kvizu: Nastavte měřítko výřezu ---- - -# Výklad - -## Model a papír -*Dva prostory* - -- V modelu je součást v milimetrech 1:1. Papír je rozvržení, záložka nad příkazovým řádkem. -- Na papír přijde rámeček, razítko a výřez. Výřez je okno do modelu. -- Dvojklik dovnitř výřezu přepne do modelu. Dvojklik ven vrátí papír. -- Kóty součásti nechte v modelu. Razítko kreslete v rozvržení, ať má na papíře stálou velikost. - -> Tip: rámeček nakreslený v modelu se při změně měřítka výřezu zmenší spolu se součástí. Proto patří na papír. - -## Měřítko výřezu -*1:2 na papíře* - -- Výřez má vlastní měřítko. Součást v modelu zůstává 1:1. -- Měřítko 1:2 znamená, že 1 mm na papíře je 2 mm na součásti. -- Ve stavovém řádku výřezu se měřítko vybírá ze seznamu. Starší zápis je `_ZOOM` a `1/2xp`. -- Výřez zamkněte, ať kolečko myši měřítko omylem nerozhodí. - -> Tip: nezamčený výřez je nejčastější důvod, proč ráno výkres není 1:1, i když včera byl. - -## Co je vidět -*Hladiny ve výřezu* - -- Hladinu lze ve výřezu zmrazit a v modelu ji nechat. Pomocné čáry tak na papír nejdou. -- Rámeček výřezu dejte na hladinu VYREZ a tu před tiskem vypněte. Na papíře zůstane jen obsah. -- Jeden výkres smí mít víc výřezů: čelo, řez, detail v jiném měřítku. -- Detail 2:1 je druhý výřez. V razítku se pak píše měřítko hlavní, detail má vlastní popisku. - -> Tip: detail zvětšený 2:1 nekreslete znovu. Je to stejný model v druhém výřezu. - -## Zadání: A3 a měřítko 1:2 -*Cvičení* - -- Rozvržení nastavte na A3 na šířku. Rámeček a razítko nakreslete v rozvržení. -- Výřez ukazuje přírubu Ø100 v měřítku 1:2. Na papíře má mít průměr 50 mm. -- Výřez zamkněte. Hladinu jeho rámečku vypněte. -- `_DIST` na papíře přes průměr příruby má ukázat 50, ne 100. - -> Tip: měření v rozvržení, mimo výřez, čte milimetry papíru. 100 mm součásti v měřítku 1:2 je na papíře 50 mm. - - -# Kvíz - -## Kde se kreslí tvar součásti v měřítku 1:1? -- V rozvržení -- [x] V modelu -- V razítku -- V hladině VYREZ -> Model zůstává skutečný. Měřítko pro papír nastavuje až výřez. - -## Součást Ø100 ve výřezu 1:2 má na papíře průměr? -- 100 mm -- [x] 50 mm -- 200 mm -- 1 mm -> 1:2 zmenšuje na polovinu. Kóta ve modelu pořád říká 100. - -## Proč výřez zamknout? -- Aby nešel tisknout -- [x] Aby kolečko myši nezměnilo měřítko -- Zamknutí smaže model -- Aby šel rámeček smazat -> Nezamčený výřez se při zoomu rozhodí a výkres už není v měřítku z razítka. - -## Kam patří rámeček a razítko? -- Do modelu, na hladinu OBRYS -- [x] Do rozvržení -- Do definice bloku šroubu -- Mimo papír -> V rozvržení mají stálou velikost bez ohledu na měřítko výřezu. diff --git a/content/technicka-grafika/3-rocnik/06-tisk.en.md b/content/technicka-grafika/3-rocnik/06-tisk.en.md deleted file mode 100644 index 2111b75..0000000 --- a/content/technicka-grafika/3-rocnik/06-tisk.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Plotting and PDF -popis: The sheet, the plot area and a black pen. -nazev_cviceni: Quiz: plotting -nadpis_kvizu: Choose the plotter settings ---- diff --git a/content/technicka-grafika/3-rocnik/06-tisk.md b/content/technicka-grafika/3-rocnik/06-tisk.md deleted file mode 100644 index 9294a6f..0000000 --- a/content/technicka-grafika/3-rocnik/06-tisk.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: tg-3-tisk -nazev: Tisk a PDF -popis: Papír, oblast tisku a černobílé pero. -nazev_cviceni: Kvíz: tisk -nadpis_kvizu: Vyberte nastavení plotru ---- - -# Výklad - -## Plotr -*Na papír nebo do PDF* - -- `_PLOT` tiskne aktuální rozvržení. Oblast tisku nechte Layout, ne Extents. -- Tiskárna DWG To PDF uloží výkres, který jde odevzdat bez posunu měřítka. -- Formát papíru musí sedět s rozvržením. A3 v tisku a A4 v rozvržení ořízne razítko. -- Měřítko tisku z rozvržení je 1:1. Měřítko součásti už drží výřez. - -> Tip: tisk 1:2 z rozvržení, které už má výřez 1:2, zmenší výkres podruhé. Na papíře bude 1:4. - -## Pero -*Černá čára* - -- Tabulka per monochrome.ctb tiskne vše černě a tloušťku bere z hladin. -- Barevný tisk ve škole nechte jen na náhled. Odevzdává se černobílý výkres. -- Tloušťka obrysu 0,5 mm a tenká čára 0,25 mm musí být v tabulce nebo na hladině vidět. -- Náhled tisku ukáže, jestli razítko neleze z papíru. Bez náhledu netiskněte. - -> Tip: když je na PDF všechno vlásečnicové, tloušťky hladin se netisknou. V `_PLOT` je zapněte. - -## Co do PDF nepatří -*Čistý výkres* - -- Rámeček výřezu je vypnutý. Pomocné konstrukce taky. -- Kóty jsou čitelné a nejsou přes šrafu, pokud to šlo jinak. -- PDF pojmenujte jako výkres, třeba priruba-A3.pdf, ne Plot1.pdf. -- Vytiskněte i kontrolní kópii na papír, když učitel odevzdání na papíře chce. - -> Tip: otevřete PDF a změřte rámeček A3. Má mít 420 × 297 mm. Jinak je špatně formát nebo měřítko tisku. - -## Zadání: PDF příruby -*Cvičení* - -- Rozvržení A3, výřez 1:1 nebo 1:2 podle toho, co se vejde i s kótami. -- `_PLOT`, tiskárna DWG To PDF, oblast Layout, měřítko 1:1, pero monochrome.ctb. -- Náhled zkontroluje, že razítko je celé a šrafa není černá plocha. -- Soubor uložte jako priruba-A3.pdf vedle dwg. - -> Tip: hustá šrafa v náhledu znamená velké měřítko vzoru nebo malé. Vraťte se do `_HATCH` a rozteč zvětšete. - - -# Kvíz - -## Jaké měřítko tisku se dává při tisku rozvržení? -- Stejné jako měřítko výřezu, znovu -- [x] 1:1 -- Fit to paper -- 2:1, ať je výkres větší -> Měřítko součásti už má výřez. Tisk papíru je 1:1, jinak se měřítko zdvojí. - -## K čemu je monochrome.ctb? -- Zvětší písmo -- [x] Tiskne černě a dodrží tloušťky -- Zamkne výřez -- Smaže hladinu OSA -> Barevné čáry na obrazovce jsou pro práci. Odevzdává se černý výkres s tlustým obrysem. - -## Proč nenechat oblast tisku na Extents? -- Extents je rychlejší -- [x] Vzalo by i objekty mimo papír a rozhodilo by měřítko -- Extents netiskne kóty -- Extents vyžaduje 3D -> Layout tiskne papír tak, jak jste ho složili. Extents hledá vše nakreslené a měřítko si dopočítá samo. - -## Co má mít rámeček A3 v hotovém PDF? -- 210 × 297 mm -- [x] 420 × 297 mm -- 100 × 70 mm -- Libovolný rozměr, rozhoduje obrazovka -> A3 je 420 × 297 mm. Když PDF vyjde menší, je špatně formát papíru nebo měřítko tisku. diff --git a/content/technicka-grafika/3-rocnik/07-izometrie.en.md b/content/technicka-grafika/3-rocnik/07-izometrie.en.md deleted file mode 100644 index 609e526..0000000 --- a/content/technicka-grafika/3-rocnik/07-izometrie.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Isometric drawing -popis: A pictorial view that does not shrink edges the way perspective does. -nazev_cviceni: Quiz: isometrics -nadpis_kvizu: Pick the axis and the ellipse ---- diff --git a/content/technicka-grafika/3-rocnik/07-izometrie.md b/content/technicka-grafika/3-rocnik/07-izometrie.md deleted file mode 100644 index 3dda985..0000000 --- a/content/technicka-grafika/3-rocnik/07-izometrie.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: tg-3-izometrie -nazev: Izometrie -popis: Názorný obraz, ve kterém se rozměry nezkreslují stejně jako v perspektivě. -nazev_cviceni: Kvíz: izometrie -nadpis_kvizu: Vyberte osu a elipsu ---- - -# Výklad - -## Tři osy -*120 stupňů* - -- Izometrie má tři osy po 120 stupních. Svislá zůstává svislá. -- Délky se nanášejí ve skutečné velikosti. Není to perspektiva, hrany se do dálky nezkracují. -- `_ISODRAFT` přepne kreslicí rovinu. F5 cyklí mezi levou, pravou a horní rovinou. -- Orto v izometrii drží čáry podél aktuálních os, ne podél obyčejného X a Y. - -> Tip: než nakreslíte hranu, podívejte se, která izorovina svítí. Čára v špatné rovině neleží na stěně. - -## Kružnice je elipsa -*Isokružnice* - -- Kružnice v izometrii se kreslí jako elipsa. `_ELLIPSE` a volba Isocircle. -- Nejdřív F5 na rovinu, ve které kružnice leží. Horní díra chce horní rovinu. -- Průměr se zadává skutečný. Elipsa ho zobrazí zkoseně, kóta zůstává Ø. -- Obyčejná kružnice `_CIRCLE` v izometrii je chyba. Na papíře by byla pořád kulatá a neladila by s osami. - -> Tip: díra na horní stěně a díra na přední stěně jsou dvě různě natočené elipsy. F5 mezi nimi přepněte. - -## K čemu izometrie je -*Názornost* - -- Izometrie nenahrazuje nárys a řez. Výrobu řídí okótované pohledy. -- Na školní práci bývá izometrie v rohu, bez kót nebo jen s hlavními. -- Skryté hrany se v izometrii často vynechají, ať obraz zůstane čitelný. -- Tlustý obrys nechte na viditelných hranách. Osy děr smíte naznačit tenčeji. - -> Tip: když se izometrie neshoduje s nárysem, platí nárys. Izometrii překreslete. - -## Zadání: kvádr s dírou -*Cvičení* - -- V izometrii nakreslete kvádr 60 × 40 × 30. -- Na horní stěně je díra Ø16 uprostřed. Použijte isokružnici v horní rovině. -- Soustředně naznačte tenčí elipsu, jen pokud by šlo o zahloubení. Tady zahloubení není. -- Porovnejte rozměry s nárysem téhož kvádru. 60, 40 a 30 musí sedět na obou. - -> Tip: střed horní stěny najdete v polovině šířky a hloubky. Elipsa se středem v rohu je špatně. - - -# Kvíz - -## Čím se v izometrii kreslí kružnice? -- `_CIRCLE` -- [x] `_ELLIPSE` s volbou Isocircle -- `_ARC` o 360 stupňů -- `_POLYGON` -> Obyčejná kružnice zůstane kulatá a s izometrickými osami neladí. - -## Co přepíná klávesa F5 při zapnutém `_ISODRAFT`? -- Hladiny -- [x] Izorovina: levá, pravá, horní -- Měřítko tisku -- Orto -> Každá stěna má vlastní natočení elipsy. F5 vybere stěnu, na kterou kreslíte. - -## Zkracují se v izometrii hrany směrem dozadu? -- Ano, jako v perspektivě -- [x] Ne, délky se nanášejí skutečné -- Jen svislé -- Jen při měřítku 1:2 -> Izometrie není perspektiva. Hrana dlouhá 60 mm se nanese jako 60 mm. - -## Co platí, když izometrie nesedí s nárysem? -- Platí izometrie, je názornější -- [x] Platí okótovaný nárys -- Oba se nechají a učitel si vybere -- Smaže se razítko -> Výrobu určují pohledy a kóty. Izometrie je doplněk a musí se jim přizpůsobit. diff --git a/content/technicka-grafika/3-rocnik/08-zadani-pouzdro.en.md b/content/technicka-grafika/3-rocnik/08-zadani-pouzdro.en.md deleted file mode 100644 index 64e0b7f..0000000 --- a/content/technicka-grafika/3-rocnik/08-zadani-pouzdro.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Assignment: a sleeve -popis: A sectioned front view, a second view, dimensions and an A3 plot. -nazev_cviceni: Quiz: the sleeve -nadpis_kvizu: Check the sleeve drawing ---- diff --git a/content/technicka-grafika/3-rocnik/08-zadani-pouzdro.md b/content/technicka-grafika/3-rocnik/08-zadani-pouzdro.md deleted file mode 100644 index f6d3a4f..0000000 --- a/content/technicka-grafika/3-rocnik/08-zadani-pouzdro.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: tg-3-zadani-pouzdro -nazev: Zadání: pouzdro -popis: Nárys v řezu, půdorys, kóty a tisk na A3. -nazev_cviceni: Kvíz: pouzdro -nadpis_kvizu: Zkontrolujte výkres pouzdra ---- - -# Výklad - -## Tvar -*Rozměry* - -- Pouzdro je dutý válec. Vnější Ø60, díra Ø36, délka 80. -- Na pravém konci je osazení: vnější Ø48 v délce 20. Díra Ø36 jde skrz. -- Na Ø60 jsou čtyři díry M6 do hloubky 12, na roztečné kružnici Ø48. Nejsou průchozí. -- Závit M6 se v nárysu kreslí zjednodušeně: velký průměr tenkou čarou, malý tlustou, v délce 12 mm. - -> Tip: rozteč děr M6 je Ø48, tedy 24 mm od osy. Hloubka 12 není délka pouzdra. - -## Pohledy -*Řez a bok* - -- Nárys je úplný řez osou. Šrafuje se stěna, díra Ø36 zůstane prázdná. -- Půdorys nebo bokorys ukáže čtyři díry M6 na Ø48. Jednu okótujte 4× M6 a hloubku 12. -- Evropské promítání: druhý pohled pod nárysem nebo vpravo, zarovnaný. -- Izometrii přidejte vpravo dole, bez kót, ať je tvar jasný. - -> Tip: v řezu osou jsou vidět dvě protilehlé díry M6, pokud rovina A-A jimi prochází. Hloubka 12 se kótuje tady. - -## Výkres -*A3* - -- Model 1:1. Rozvržení A3, měřítko výřezu 1:1, tisk 1:1, monochrome.ctb. -- Hladiny OBRYS, OSA, SKRYTE, SRAFA, KOTA, ZAVIT, RAM. -- Razítko: Pouzdro, ocel, 1:1. Kóty Ø60, Ø36, Ø48, délka 80, osazení 20 a Ø48, 4× M6 hloubka 12. -- Závitová hladina je tenká. Není to obrys válce. - -> Tip: malý průměr závitu M6 je zhruba 5 mm. Tenká čára velkého průměru je 6 mm. Neměňte je za Ø36. - -## Kontrola -*Odevzdání* - -- Stěna v řezu má tloušťku (60 − 36) / 2 = 12 mm. -- Osazení dlouhé 20 nešrafujte jinak než zbytek stěny. Je to pořád jeden kus. -- PDF priruba nahraďte souborem pouzdro-A3.pdf. Razítko je celé na papíře. -- Žádná kóta není přepsaná. `_DIST` přes vnější průměr dá 60. - -> Tip: dva kusy by měly opačný sklon šrafy. Tady je kus jeden, šrafa má jeden směr. - - -# Kvíz - -## Jaká je tloušťka stěny pouzdra Ø60 s dírou Ø36? -- 24 mm -- [x] 12 mm -- 36 mm -- 6 mm -> Rozdíl průměrů je 24 mm materiálu na obě strany. Na jednu stěnu připadá 12 mm. - -## Jak se zjednodušeně kreslí závit M6? -- Obě čáry tlusté -- [x] Velký průměr tenkou čarou, malý tlustou -- Jen osou -- Šrafou ANSI31 -> Tenká čára je velký průměr 6 mm. Tlustá je malý průměr, u M6 zhruba 5 mm. - -## Kam patří čtyři díry M6? -- Průchozí skrz Ø36 -- [x] Do hloubky 12 mm na roztečné kružnici Ø48 -- Na osazení Ø48 jako drážka -- Do razítka -> Nejsou to průchozí díry hlavní dutiny. Hloubka 12 a rozteč Ø48 jsou v zadání. - -## Proč má šrafa pouzdra jeden směr? -- Dva směry jsou zakázané vždy -- [x] Je to jeden kus -- Řez je poloviční -- Měřítko je 1:2 -> Opačný sklon by říkal, že se dotýkají dva díly. Osazení je pořád totéž pouzdro. diff --git a/content/technicka-grafika/4-rocnik/01-prostor-3d.en.md b/content/technicka-grafika/4-rocnik/01-prostor-3d.en.md deleted file mode 100644 index b7db361..0000000 --- a/content/technicka-grafika/4-rocnik/01-prostor-3d.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Model space in 3D -popis: Axes, the user coordinate system and orbiting the model. -nazev_cviceni: Quiz: space -nadpis_kvizu: Find the axis and the AutoCAD edition ---- diff --git a/content/technicka-grafika/4-rocnik/01-prostor-3d.md b/content/technicka-grafika/4-rocnik/01-prostor-3d.md deleted file mode 100644 index 2c94303..0000000 --- a/content/technicka-grafika/4-rocnik/01-prostor-3d.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: tg-4-prostor -nazev: Modelový prostor ve 3D -popis: Osy, uživatelský souřadný systém a obíhání kolem modelu. -nazev_cviceni: Kvíz: prostor -nadpis_kvizu: Najděte osu a verzi AutoCADu ---- - -# Výklad - -## Tři osy -*X, Y, Z* - -- K ose X a Y přibude Z. Na obrazovce při startu míří Z k vám. -- Pravidlo pravé ruky: prsty od X k Y, palec ukazuje Z. -- `_BOX` a další tělesa potřebují plný AutoCAD. Verze LT tělesa nevytvoří. -- 2D výkres z dřívějška zůstává. 3D model je druhý soubor, nebo stejný model v jiném pohledu. - -> Tip: když příkaz `_BOX` AutoCAD nezná, máte LT. Tělesa v ní nejdou. - -## Pohled -*Orbit* - -- ViewCube v rohu nebo `_ORBIT` otáčí pohled. Model se neotáčí, otáčí se kamera. -- Přední, horní a levý pohled odpovídají nárysu, půdorysu a bokorysu. -- `_UCS` posune a natočí souřadnice. Nová tělesa vznikají vůči aktuálnímu UCS. -- `_UCS` a volba World vrátí původní osy. Ztracený UCS je nejčastější zmatek ve 3D. - -> Tip: než vysunete profil, zkontrolujte ikonu os. Z má trčet z plochy, kterou vysouváte. - -## Drát a stínování -*Ať něco vidíte* - -- Drátový model ukáže všechny hrany, i zadní. Na začátku se v něm líp trefuje. -- Stínovaný pohled schová zadní hrany. Přepíná se `_VSCURRENT` nebo nabídkou pohledu. -- Zoom kolečkem pořád platí. Výřez na papír přijde až v lekci o výkresu z modelu. -- Jednotky zůstávají milimetry. Těleso 60 × 40 × 30 je v tomtéž souboru jako 2D profil. - -> Tip: ztracený model najdete `_ZOOM` Extents. Často leží daleko od počátku, protože UCS byl posunutý. - -## Zadání: tři osy a kvádr -*Cvičení* - -- V novém souboru v milimetrech nakreslete `_BOX` se základnou 60 × 40 a výškou 30, roh v 0,0,0. -- Přepněte na přední, horní a levý pohled. V každém má být vidět jiná dvojice rozměrů. -- `_UCS` World a `_DIST` mezi dvěma rohy podél X má dát 60. -- Uložte jako kvadr-60x40x30.dwg. LT na tento soubor nestačí. - -> Tip: přední pohled ukáže 60 × 30, horní 60 × 40, levý 40 × 30. - - -# Kvíz - -## Který AutoCAD umí tělesa `_BOX`? -- Každá verze včetně LT -- [x] Plný AutoCAD, ne LT -- Jen verze na Mac bez příkazů -- Žádný, tělesa jsou v jiném programu -> LT je 2D. Příkaz `_BOX` v ní není. - -## Co dělá `_ORBIT`? -- Otočí těleso v souřadnicích -- [x] Otočí pohled kamery -- Nastaví měřítko tisku -- Smaže osu Z -> Model zůstane. Změní se, odkud se na něj díváte. - -## Co vrátí souřadnice do původního směru? -- `_ZOOM` Extents -- [x] `_UCS` a volba World -- Vypnutí hladiny 0 -- `_PLOT` -> Posunutý UCS nechá nová tělesa „ležet na boku“. World je výchozí osy výkresu. - -## Co ukáže přední pohled na kvádr 60 × 40 × 30, když 30 je výška? -- 60 × 40 -- [x] 60 × 30 -- 40 × 30 -- Jen osu Z -> Přední pohled je šířka a výška. Hloubka 40 je v půdorysu a v bokorysu. diff --git a/content/technicka-grafika/4-rocnik/02-telesa-a-vysunuti.en.md b/content/technicka-grafika/4-rocnik/02-telesa-a-vysunuti.en.md deleted file mode 100644 index 8684db3..0000000 --- a/content/technicka-grafika/4-rocnik/02-telesa-a-vysunuti.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Solids and extrude -popis: A box, a cylinder and a profile pulled up by a height. -nazev_cviceni: Quiz: extrude -nadpis_kvizu: Pick the profile and the height ---- diff --git a/content/technicka-grafika/4-rocnik/02-telesa-a-vysunuti.md b/content/technicka-grafika/4-rocnik/02-telesa-a-vysunuti.md deleted file mode 100644 index d115dcf..0000000 --- a/content/technicka-grafika/4-rocnik/02-telesa-a-vysunuti.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: tg-4-vysunuti -nazev: Tělesa a vysunutí -popis: Kvádr, válec a profil tažený o výšku. -nazev_cviceni: Kvíz: vysunutí -nadpis_kvizu: Vyberte profil a výšku ---- - -# Výklad - -## Hotová tělesa -*Kvádr a válec* - -- `_BOX` chce roh nebo střed základny, půdorys a výšku. -- `_CYLINDER` chce střed, poloměr nebo průměr a výšku. -- Výška se měří ve směru osy Z aktuálního UCS. -- Tato tělesa jsou plná. Nejsou to stěny z ploch. - -> Tip: válec Ø40 a výška 25 má v příkazu buď poloměr 20, nebo volbu průměru 40. - -## Vysunutí profilu -*Z 2D do výšky* - -- `_EXTRUDE` vezme uzavřenou křivku nebo oblast a táhne ji o výšku. -- Profil musí být zavřený. Čtyři nenapojené úsečky vysunout nejdou. -- Kladná výška jde ve směru Z. Záporná na opačnou stranu. -- `_PRESSPULL` umí přitáhnout uzavřenou oblast, na kterou kliknete, bez předchozího výběru. - -> Tip: obdélník 80 × 50 vysunutý o 12 je destička z druháku, teď jako těleso. - -## Profil nejdřív ve 2D -*Plocha* - -- Profil nakreslete v rovině, ze které chcete táhnout. Nejčastěji půdorys, Z ven z obrazovky. -- `_REGION` z uzavřené křivky udělá jednu plochu. Vysouvá se spolehlivěji než volné čáry. -- Po vysunutí profil smíte smazat, nebo ho nechte na hladině PROFIL a tu zmrazte. -- Jeden profil, jedna výška. Osazení vznikne až druhým tělesem a booleanem v další lekci. - -> Tip: otevřená křivka se vysune na plochu, ne na těleso. Pro součást potřebujete těleso. - -## Zadání: destička jako těleso -*Cvičení* - -- Profil 120 × 70, `_EXTRUDE` o 10 mm. To je tloušťka destičky. -- Díru zatím nekreslete. Ověřte `_MASSPROP`: objem má být 120 × 70 × 10 = 84 000 mm³. -- Přední pohled ukáže 120 × 10. Horní pohled 120 × 70. -- Uložte jako desticka-3d.dwg. - -> Tip: když objem vyjde dvojnásobek, výška je 20 místo 10. Kóta textu to nespraví, `_MASSPROP` čte model. - - -# Kvíz - -## Jaký poloměr má `_CYLINDER` o průměru 40? -- 40 -- [x] 20 -- 80 -- 10 -> Příkaz bez přepnutí bere poloměr. Průměr je volba, nebo napište polovinu. - -## Co `_EXTRUDE` potřebuje, aby vzniklo těleso? -- Otevřenou úsečku -- [x] Uzavřený profil -- Razítko -- Už hotový válec -> Neuzavřený profil vytvoří jen plochu. Těleso má mít objem. - -## Kam míří kladná výška vysunutí? -- Vždy doprava na obrazovce -- [x] Ve směru osy Z aktuálního UCS -- Do záporného X -- Do razítka -> Špatně natočený UCS vysune destičku „na bok“. Před příkazem zkontrolujte osy. - -## Objem destičky 120 × 70 × 10 mm je? -- 840 mm³ -- [x] 84 000 mm³ -- 200 mm³ -- 12 000 mm³ -> 120 × 70 = 8 400, krát 10 je 84 000. `_MASSPROP` má ukázat totéž. diff --git a/content/technicka-grafika/4-rocnik/03-rotace.en.md b/content/technicka-grafika/4-rocnik/03-rotace.en.md deleted file mode 100644 index 4f4c6b4..0000000 --- a/content/technicka-grafika/4-rocnik/03-rotace.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Revolving a profile -popis: A part symmetric about an axis is the section spun around. -nazev_cviceni: Quiz: revolve -nadpis_kvizu: Pick the profile and the axis ---- diff --git a/content/technicka-grafika/4-rocnik/03-rotace.md b/content/technicka-grafika/4-rocnik/03-rotace.md deleted file mode 100644 index 9a77666..0000000 --- a/content/technicka-grafika/4-rocnik/03-rotace.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: tg-4-rotace -nazev: Rotace profilu -popis: Součást souměrná podle osy vznikne otočením řezu. -nazev_cviceni: Kvíz: rotace -nadpis_kvizu: Vyberte profil a osu ---- - -# Výklad - -## Kdy rotovat -*Místo skládání válců* - -- `_REVOLVE` otočí uzavřený profil kolem osy o zadaný úhel. -- 360 stupňů udělá plné rotační těleso. 180 udělá polovinu. -- Hodí se na hřídel, pouzdro, přírubu a každou součást souměrnou podle osy. -- Profil je polovina řezu. Osa rotace je osa součásti a profil ji smí jen lemovat, ne křížit. - -> Tip: pouzdro z třetího ročníku je jeden profil stěny otočený o 360 stupňů, ne válec minus válec. Oba postupy jsou správně, rotace je u čistě rotačního dílu kratší. - -## Profil -*Polovina* - -- Nakreslete jen polovinu řezu, vpravo od osy. Uzavřete ho. -- U pouzdra Ø60 / Ø36 dlouhého 80 je profil obdélník 12 × 80. Dvanáct je tloušťka stěny. -- Osa je svislá hrana díry. Profil se osy dotýká jen vnější? Ne: vnitřní hrana profilu je o poloměr díry od osy. -- Vnitřní hrana leží 18 mm od osy, vnější 30 mm. Šířka profilu je 12 mm. - -> Tip: 36 / 2 = 18 a 60 / 2 = 30. Profil je pás mezi těmito poloměry. - -## Osa a úhel -*360* - -- Osu vyberte dva body, nebo jednu úsečku nakreslenou na hladině OSA. -- Úhel 360. Menší úhel nechá výseč a na školní hřídeli bývá omyl. -- Profil nesmí osu křížit. Křížení AutoCAD odmítne, nebo udělá těleso, které se protíná samo. -- Po rotaci profil zmrazte. V řezu ho zase použijete jako kontrolu. - -> Tip: když vznikne plný válec bez díry, profil začínal na ose. Vnitřní hrana musí být 18 mm od osy, ne 0. - -## Zadání: pouzdro rotací -*Cvičení* - -- Osa je úsečka z 0,0 do 0,80. -- Profil: obdélník s rohy 18,0 a 30,80. -- `_REVOLVE` o 360 stupňů kolem této osy. -- `_MASSPROP` objem mezikruží: π × (30² − 18²) × 80. Má vyjít zhruba 144 764 mm³. - -> Tip: 900 − 324 = 576, krát π je asi 1 810, krát 80 je asi 144 800. Řád tisíců, ne desítek. - - -# Kvíz - -## Jaký úhel udělá plné rotační těleso? -- 90 -- 180 -- [x] 360 -- 45 -> Polovina otáčky je výseč. Uzavřené pouzdro potřebuje celých 360 stupňů. - -## Kde leží vnitřní hrana profilu pouzdra Ø36? -- Na ose -- [x] 18 mm od osy -- 36 mm od osy -- 60 mm od osy -> Poloměr díry je polovina průměru. Profil díru ohraničuje, nesmí začínat na ose, jinak díra zmizí. - -## Co se stane, když profil osu kříží? -- Vznikne správné pouzdro -- [x] AutoCAD rotaci odmítne, nebo těleso protne samo sebe -- Profil se jen posune -- Vznikne šrafa -> Osa smí být hranou profilu, ne smí jím procházet skrz. - -## Proč rotovat pouzdro místo skládání dvou válců? -- Jinak to nejde -- [x] U rotačního dílu stačí jeden profil -- Rotace umí i hranaté osazení bez profilu -- `_REVOLVE` funguje i v LT -> Oba postupy jsou správně. Rotace je kratší, když je součást souměrná podle osy. LT ji neumí. diff --git a/content/technicka-grafika/4-rocnik/04-boolean.en.md b/content/technicka-grafika/4-rocnik/04-boolean.en.md deleted file mode 100644 index e6fc00f..0000000 --- a/content/technicka-grafika/4-rocnik/04-boolean.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Union, subtract and intersect -popis: Solids add and subtract like sets. -nazev_cviceni: Quiz: booleans -nadpis_kvizu: Pick the order of the solids ---- diff --git a/content/technicka-grafika/4-rocnik/04-boolean.md b/content/technicka-grafika/4-rocnik/04-boolean.md deleted file mode 100644 index b833fe4..0000000 --- a/content/technicka-grafika/4-rocnik/04-boolean.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: tg-4-boolean -nazev: Sjednocení, rozdíl a průnik -popis: Tělesa se sčítají a odečítají jako množiny. -nazev_cviceni: Kvíz: boolean -nadpis_kvizu: Vyberte pořadí těles ---- - -# Výklad - -## Sjednocení -*Jeden kus* - -- `_UNION` slepí tělesa, která se dotýkají nebo pronikají, v jeden objekt. -- Osazení na hřídeli jsou dva válce. Po sjednocení je to jedna součást. -- Tělesa, která se nedotýkají, sjednocení také spojí do jedné skupiny, ale výrobek to není. -- Než sjednotíte, zkontrolujte přesah. Mezera 0,01 mm nechá dva kusy. - -> Tip: `_INTERFERE` ukáže, jestli se dvě tělesa opravdu pronikají, nebo se jen zdají dotýkat. - -## Rozdíl -*Díra* - -- `_SUBTRACT` nejdřív vyberete těleso, které má zůstat, potvrdíte, a teprve pak těleso, které se odečte. -- Obrácené pořadí smaže součást a nechá díru jako váleček. To je nejčastější chyba. -- Díra Ø10 je válec Ø10 delší, než je tloušťka stěny, ať rozdíl prořízne celou stěnu. -- Válec díry po rozdílu zmizí. Nemusíte ho mazat ručně. - -> Tip: válec díry nechte o milimetr přečuhovat z obou stran. Jinak na stěně zůstane blanka. - -## Průnik -*Společný objem* - -- `_INTERSECT` nechá jen objem, který mají tělesa společný. Zbytek zmizí. -- Hodí se, když potřebujete tvar daný dvěma podmínkami, třeba válec seříznutý kvádrem. -- Na běžnou díru průnik není. Díra je rozdíl. -- Po průniku zůstanou obě původní tělesa pryč. Když je budete potřebovat, předem je zkopírujte. - -> Tip: sjednocení přidá, rozdíl ubere, průnik nechá jen překryv. U díry je to vždy rozdíl. - -## Zadání: destička s dírou -*Cvičení* - -- Destička `_BOX` 120 × 70 × 10. -- Válec Ø16, střed v 60,35, výška od -1 do 11, ať prochází skrz. -- `_SUBTRACT`: nejdřív destička, potom válec. -- `_MASSPROP` objem: 84 000 minus objem válce v tloušťce 10. Válec Ø16 a výška 10 má objem π × 8² × 10 ≈ 2 011. Výsledek je asi 81 989 mm³. - -> Tip: když zmizela destička a zbyl váleček, pořadí rozdílu bylo obrácené. Vraťte krok zpět. - - -# Kvíz - -## Jakým pořadím vznikne díra? -- Nejdřív válec, potom destička -- [x] Nejdřív destička, potom válec -- `_UNION` -- `_INTERSECT` -> První výběr zůstává. Druhý se odečte. Obrácené pořadí nechá jen váleček. - -## Proč má válec díry přečnívat z destičky? -- Aby šel okótovat -- [x] Aby ve stěně nezůstala blanka -- Přečnívat nesmí, rozdíl by selhal -- Aby vznikl závit -> Válec zarovnaný přesně s plochou někdy nechá tenkou slupku. Milimetr přesahu ji odstraní. - -## Který příkaz slepí dva dotýkající se válce hřídele? -- `_SUBTRACT` -- [x] `_UNION` -- `_INTERSECT` -- `_REVOLVE` -> Osazení je jeden kus. Sjednocení z dvou válců udělá jedno těleso. - -## Co nechá `_INTERSECT`? -- Součet objemů -- [x] Jen společný překryv -- Díru -- Původní tělesa vedle výsledku -> Zbytek obou těles zmizí. Před průnikem si je zkopírujte, pokud je ještě budete potřebovat. diff --git a/content/technicka-grafika/4-rocnik/05-rez-a-flatshot.en.md b/content/technicka-grafika/4-rocnik/05-rez-a-flatshot.en.md deleted file mode 100644 index cd46853..0000000 --- a/content/technicka-grafika/4-rocnik/05-rez-a-flatshot.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Sectioning a solid and Flatshot -popis: From the model back to lines for the drawing. -nazev_cviceni: Quiz: the model section -nadpis_kvizu: Decide what lands on the sheet ---- diff --git a/content/technicka-grafika/4-rocnik/05-rez-a-flatshot.md b/content/technicka-grafika/4-rocnik/05-rez-a-flatshot.md deleted file mode 100644 index c8f2f53..0000000 --- a/content/technicka-grafika/4-rocnik/05-rez-a-flatshot.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: tg-4-rez-modelu -nazev: Řez tělesem a plochý snímek -popis: Z modelu zpátky čáry pro výkres. -nazev_cviceni: Kvíz: řez modelu -nadpis_kvizu: Vyberte, co vznikne na papíře ---- - -# Výklad - -## Řezná rovina -*Uvnitř tělesa* - -- `_SECTIONPLANE` položí rovinu řezu. Živé zobrazení ukáže řez, aniž by těleso rozřízlo natrvalo. -- `_SLICE` těleso rozřízne doopravdy. Polovinu můžete nechat, nebo smazat. -- Na školní výkres řežte živě nebo si před `_SLICE` těleso zkopírujte. Původní model budete ještě potřebovat. -- Řez osou pouzdra má ukázat stěnu 12 mm a díru Ø36, stejně jako ruční řez ve třetím ročníku. - -> Tip: rovina, která mine osu, ukáže jinou tloušťku stěny. U pouzdra veďte řez osou. - -## Plochý snímek -*Čáry z pohledu* - -- `_FLATSHOT` promítne aktuální pohled do čar v rovině XY. -- Viditelné hrany dá na jednu hladinu, skryté na druhou. Skryté pak přepněte na čárkované. -- Než příkaz spustíte, nastavte pohled: přední pro nárys, horní pro půdorys. -- Snímek je 2D. Dá se kótovat jako výkres z druháku. Model vedle něj nechte nedotčený. - -> Tip: plochý snímek pořízený v šikmém pohledu není nárys. Nejdřív srovnejte pohled, potom foťte. - -## Co snímek neudělá -*Kóty a šrafa* - -- Snímek neumí šrafu řezu ani kóty. Ty doplníte vy, na hladiny SRAFA a KOTA. -- Neumí ani razítko. To patří do rozvržení. -- Čáry snímku bývají na nových hladinách. Přesuňte je na OBRYS a SKRYTE, ať platí školní tloušťky. -- Když model potom změníte, snímek se sám neopraví. Po úpravě modelu ho vytvořte znovu. - -> Tip: výkresové pohledy z pozdější lekce se na rozdíl od snímku umí s modelem aktualizovat. Snímek je rychlá kontrola. - -## Zadání: nárys z tělesa -*Cvičení* - -- Otevřete pouzdro z rotace. Přední pohled, `_FLATSHOT`, viditelné hrany na OBRYS. -- Do řezu osou doplňte šrafu stěny ručně, nebo použijte živý řez a z něj čáry. -- Okótujte Ø60, Ø36 a délku 80. Čísla musí sedět s `_MASSPROP` a s poloměry profilu. -- Snímek nesmí zůstat šikmo. Nárys je v rovině, díra je obdélník 36 × 80 uvnitř obdélníku 60 × 80. - -> Tip: v nárysu řezu jsou dvě vodorovné čáry díry. Jejich vzdálenost je 36. - - -# Kvíz - -## Čím rozříznete těleso natrvalo? -- `_FLATSHOT` -- [x] `_SLICE` -- `_ORBIT` -- `_PLOT` -> Živá řezná rovina model nechá celý. `_SLICE` ho rozdělí. Předtím si nechte kopii. - -## Co musí předcházet plochému snímku nárysu? -- Tisk -- [x] Srovnaný přední pohled -- Rozbití tělesa -- Šrafa -> Snímek promítne to, co právě vidíte. Šikmý orbit není nárys. - -## Doplní `_FLATSHOT` kóty? -- Ano, z hladiny KOTA -- [x] Ne -- Jen průměry -- Jen když je měřítko 1:1 -> Snímek jsou čáry. Kóty, šrafu a razítko dodáte vy. - -## Jak daleko jsou v nárysu řezu pouzdra od sebe čáry díry Ø36? -- 18 -- 60 -- [x] 36 -- 12 -> V řezu je díra obdélník. Jeho výška je průměr, ne poloměr. diff --git a/content/technicka-grafika/4-rocnik/06-zobrazeni.en.md b/content/technicka-grafika/4-rocnik/06-zobrazeni.en.md deleted file mode 100644 index 3a7cfc8..0000000 --- a/content/technicka-grafika/4-rocnik/06-zobrazeni.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Visual styles -popis: Wireframe, hidden lines and shading for checking the shape. -nazev_cviceni: Quiz: display -nadpis_kvizu: Pick a style for the task ---- diff --git a/content/technicka-grafika/4-rocnik/06-zobrazeni.md b/content/technicka-grafika/4-rocnik/06-zobrazeni.md deleted file mode 100644 index 687c0a4..0000000 --- a/content/technicka-grafika/4-rocnik/06-zobrazeni.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: tg-4-zobrazeni -nazev: Vizuální styly -popis: Drát, skryté hrany a stínování pro kontrolu tvaru. -nazev_cviceni: Kvíz: zobrazení -nadpis_kvizu: Vyberte styl podle úkolu ---- - -# Výklad - -## Drát a skryté hrany -*Kontrola* - -- Drátový model ukáže každou hranu. Hodí se, když saháte na zadní vrchol. -- Styl skrytých hran schová, co je za materiálem. Tvar se čte jako na fotografii bez stínu. -- `_VSCURRENT` styly přepíná. Na pásu karet je stejná nabídka u pohledu. -- Styl nemění těleso. Špatně odečtená díra zůstane špatně v každém stylu. - -> Tip: nejdřív drát, ať trefíte hranu, potom skryté hrany, ať zkontrolujete, že díra opravdu prochází. - -## Stínování -*Objem* - -- Konceptuální nebo stínovaný styl ukáže, jestli je díra průchozí, nebo je to jen namalovaná kružnice. -- Barva tělesa se bere z hladiny. OBRYS a těleso smí mít vlastní hladinu MODEL. -- Materiál a render na škole stačí náznak. Odevzdává se výkres, ne obrázek. -- Stínování zpomalí otáčení. Na slabším počítači se vraťte do drátu, než budete modelovat dál. - -> Tip: když v řezu vidíte dno díry, válec byl krátký. Rozdíl stěnu neprošel. - -## Řezy bez rozbití -*Pohled* - -- Živý řez v kombinaci se stínováním je nejrychlejší kontrola tloušťky stěny. -- Pohled uložte `_VIEW`, ať se k němu vrátíte. Název třeba REZ-AA. -- Izometrický stínovaný pohled smí přijít na výkres jako názorný doplněk, ne jako jediný obraz. -- Barvy na obrazovce pořád tiskněte černě. Styl zobrazení není tabulka per. - -> Tip: uložený pohled nese i styl. Když REZ-AA otevřete a je z něj drát, někdo styl přepsal. - -## Zadání: tři kontroly destičky -*Cvičení* - -- Destičku s dírou Ø16 zobrazte jako drát, jako skryté hrany a stínovaně. -- Ve stínovaném horním pohledu musí být skrz díru vidět. Když není, opakujte rozdíl. -- Uložte pohled HORNI a pohled PREDNI. -- Do výkresu tyto pohledy zatím nevkládejte. Jde o kontrolu modelu. - -> Tip: díra, která ve stínu má dno stejné barvy jako destička, je slepá. Výška válce byla menší než 10 mm. - - -# Kvíz - -## Který styl nechá vidět i zadní hrany? -- Stínovaný -- [x] Drátový -- Skryté hrany -- Monochrome.ctb -> Drát nekryje nic. Skryté hrany a stín zadní geometrii schovají. - -## Změní vizuální styl objem tělesa? -- Ano, stín ubere materiál -- [x] Ne -- Jen u rozdílu -- Jen při tisku -> Styl je způsob kresby na obrazovce. `_MASSPROP` zůstane stejný. - -## Co máte vidět skrz průchozí díru ve stínovaném pohledu? -- Dno stejné barvy -- [x] Prostor za destičkou -- Šrafu ANSI31 -- Razítko -> Dno znamená, že válec díry byl krátký a rozdíl stěnu neprošel. - -## Čím se na papír dostane černá čára, když je model na obrazovce modrý? -- Vizuálním stylem -- [x] Tabulkou per při tisku -- Smazáním hladiny -- `_ORBIT` -> Barva na monitoru je pracovní. monochrome.ctb z ní na PDF udělá černou. diff --git a/content/technicka-grafika/4-rocnik/07-vykres-z-modelu.en.md b/content/technicka-grafika/4-rocnik/07-vykres-z-modelu.en.md deleted file mode 100644 index 4ad88b7..0000000 --- a/content/technicka-grafika/4-rocnik/07-vykres-z-modelu.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: A drawing from the 3D model -popis: A front view and a section that update with the model. -nazev_cviceni: Quiz: model views -nadpis_kvizu: Tie the sheet to the solid ---- diff --git a/content/technicka-grafika/4-rocnik/07-vykres-z-modelu.md b/content/technicka-grafika/4-rocnik/07-vykres-z-modelu.md deleted file mode 100644 index 00b0c55..0000000 --- a/content/technicka-grafika/4-rocnik/07-vykres-z-modelu.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: tg-4-vykres-z-modelu -nazev: Výkres z 3D modelu -popis: Nárys a řez, které se s modelem aktualizují. -nazev_cviceni: Kvíz: pohledy z modelu -nadpis_kvizu: Propojte výkres s tělesem ---- - -# Výklad - -## Základní pohled -*Z tělesa* - -- V rozvržení příkaz základního pohledu vezme těleso a položí na papír nárys, půdorys nebo izometrii. -- Měřítko pohledu nastavíte jako u výřezu, třeba 1:1 nebo 1:2. -- Odvozené pohledy se položí nad, pod nebo vedle. Drží evropské promítání, když ho tak nastavíte. -- Pohled je svázaný s modelem. Změna tělesa a aktualizace pohledu přepíše čáry. - -> Tip: plochý snímek se sám neopraví. Pohled z modelu ano. Na maturitní výkres použijte pohled. - -## Řez pohledu -*A-A* - -- Z základního pohledu uděláte řez tažením řezné čáry. Písmena A doplní AutoCAD, nebo je přepište na A. -- Šrafu řezu nastavte na ANSI31 a školní měřítko. Hřídel v podélném řezu pořád nešrafujte, i když to AutoCAD nabídne. -- Skryté čáry v pohledu vypněte, pokud řez vnitřek ukázal. Výkres zůstane čistý. -- Kóty klikejte na pohled, ne do modelu naslepo. Berou rozměr z tělesa. - -> Tip: kóta napojená na pohled se po aktualizaci přepočítá. Kóta nakreslená vedle jako obyčejná čára ne. - -## Papír -*A3* - -- Rámeček a razítko jsou v rozvržení, měřítko 1:1 vůči papíru. -- Tisk je Layout, 1:1, monochrome.ctb, jako ve třetím ročníku. -- Izometrický pohled bez kót smí být třetí obraz. Nesmí být jediný. -- Než odevzdáte, aktualizujte pohledy. Starý pohled lže, když jste model mezitím změnili. - -> Tip: ve stromu nebo přes aktualizaci pohledu uvidíte, jestli je obraz aktuální. Nevěřte čáře, která přežila smazanou díru. - -## Zadání: pouzdro na A3 -*Cvičení* - -- Z 3D pouzdra vytvořte nárys jako řez A-A a půdorys nebo bokorys s roztečí, pokud na modelu díry jsou. -- Měřítko 1:1, formát A3. Kóty Ø60, Ø36 a 80. -- Změňte v modelu délku na 90, aktualizujte pohled a přesvědčte se, že kóta délky ukáže 90. -- Vraťte délku na 80, ať odevzdáte zadání, ne zkoušku. PDF pojmenujte pouzdro-z-modelu.pdf. - -> Tip: když po změně modelu kóta zůstane 80, není napojená na pohled. Smažte ji a okótujte znovu. - - -# Kvíz - -## Čím se pohled z modelu liší od `_FLATSHOT`? -- Ničím -- [x] Po změně tělesa se dá aktualizovat -- Umí jen izometrii -- Funguje v LT -> Snímek je jednorázová kopie čar. Pohled zůstává svázaný s tělesem. - -## Kam patří rámeček výkresu z modelu? -- Dovnitř tělesa -- [x] Do rozvržení -- Na hladinu OBRYS modelu -- Do definice bloku -> Papír má vlastní měřítko. Rámeček v modelu by se zmenšil s pohledem. - -## Co uděláte po změně délky pouzdra v modelu? -- Nic, kóty se nemění nikdy -- [x] Aktualizujete pohled -- Smažete razítko -- Přepnete na LT -> Neaktualizovaný pohled ukazuje starý tvar. Kóta napojená na něj se přepočítá spolu s ním. - -## Jaké měřítko má tisk tohoto rozvržení? -- 1:2, protože model je velký -- [x] 1:1 -- Podle `_MASSPROP` -- Fit -> Měřítko obrazu drží pohled. Tisk papíru je 1:1, jinak se měřítko zdvojí. diff --git a/content/technicka-grafika/4-rocnik/08-maturitni-zadani.en.md b/content/technicka-grafika/4-rocnik/08-maturitni-zadani.en.md deleted file mode 100644 index 5bfcb04..0000000 --- a/content/technicka-grafika/4-rocnik/08-maturitni-zadani.en.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -nazev: Exam assignment -popis: From a sketch through the model to a PDF that stands on its own. -nazev_cviceni: Quiz: the exam piece -nadpis_kvizu: Walk the whole drawing ---- diff --git a/content/technicka-grafika/4-rocnik/08-maturitni-zadani.md b/content/technicka-grafika/4-rocnik/08-maturitni-zadani.md deleted file mode 100644 index 19d47ea..0000000 --- a/content/technicka-grafika/4-rocnik/08-maturitni-zadani.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: tg-4-maturitni-zadani -nazev: Maturitní zadání -popis: Od náčrtu přes model po PDF, které obstojí samo. -nazev_cviceni: Kvíz: maturita -nadpis_kvizu: Projdete celý výkres ---- - -# Výklad - -## Součást -*Přírubové pouzdro* - -- Dutý válec Ø70 / Ø40, délka 60. Na jednom konci příruba Ø110 tlustá 12. -- Čtyři díry Ø11 na roztečné kružnici Ø90 v přírubě. Jsou průchozí skrz přírubu, ne skrz celé pouzdro. -- Vnitřní hrana díry Ø40 má zkosení 1 × 45° na straně příruby. -- Materiál ocel. Jednotky milimetry. Model 1:1. - -> Tip: tloušťka stěny válce je (70 − 40) / 2 = 15 mm. Příruba přesahuje válec o (110 − 70) / 2 = 20 mm. - -## Model -*Pořadí* - -- Profil řezu rotujte, nebo složte válec Ø70, válec příruby Ø110 výšky 12 a odečtěte díru Ø40. -- Čtyři díry Ø11 vzniknou polárním polem válce na poloměru 45 a rozdílem od příruby. -- Válec díry Ø11 musí být delší než 12 mm, ať je díra průchozí. Do dutiny Ø40 díra Ø11 nezasahuje, leží v materiálu příruby. -- `_MASSPROP` spočítejte orientačně a porovnejte s ručním odhadem. Řád objemu je statisíce mm³, ne tisíce. - -> Tip: rozteč Ø90 je poloměr 45. Díra se středem na poloměru 55 by už ležela mimo přírubu Ø110. - -## Výkres -*A3, 1:1* - -- Nárys je řez A-A osou. Půdorys ukáže čtyři díry. Izometrie bez kót je doplněk. -- Kóty: Ø110, Ø70, Ø40, tloušťka příruby 12, délka 60, 4× Ø11 na Ø90, zkosení 1 × 45°. -- Hladiny OBRYS, OSA, SRAFA, KOTA, RAM. Šrafa jen v řezu, jeden směr, díry prázdné. -- Razítko: Přírubové pouzdro, ocel, 1:1, jméno. Tisk A3, Layout, 1:1, monochrome.ctb. - -> Tip: evropské promítání. Půdorys pod nárysem. Čtyři díry se kótují jednou. - -## Než odevzdáte -*Kontrola* - -- Každá kóta se dá z modelu ověřit. Žádný text není přepsaný. -- Vypnutá hladina KOTA nechá čistý tvar. Vypnutá SRAFA nechá obrys řezu. -- PDF se jmenuje prirubove-pouzdro-A3.pdf a rámeček má 420 × 297 mm. -- Soubor dwg odevzdejte spolu s PDF. Bez modelu výkres nejde opravit. - -> Tip: otevřete PDF na celou stránku. Když je razítko useknuté nebo šrafa černá, tisk opakujte. Na obrazovce AutoCADu to vidět nebylo. - - -# Kvíz - -## Jaká je tloušťka stěny válce Ø70 s dírou Ø40? -- 30 mm -- [x] 15 mm -- 40 mm -- 12 mm -> Rozdíl průměrů je 30 mm na obě strany. Jedna stěna má 15 mm. 12 mm je tloušťka příruby, ne stěny. - -## Kam patří čtyři díry Ø11? -- Skrz celou délku 60 -- [x] Skrz přírubu tlustou 12, na Ø90 -- Do díry Ø40 -- Na osu jako závit M11 -> Leží v materiálu příruby mezi Ø70 a Ø110. Rozteč 90, poloměr 45. - -## Jaké měřítko má model i tisk tohoto výkresu? -- Model 1:2, tisk 1:2 -- [x] Model 1:1, tisk rozvržení 1:1 -- Model 2:1, tisk Fit -- Měřítko se do razítka nepíše -> Součást i papír jsou ve skutečných milimetrech. Měřítko pohledu je 1:1, protože se A3 vejde. - -## Co odevzdáváte spolu s PDF? -- Jen izometrii -- [x] I soubor dwg -- Rozbitý blok razítka -- Výkres bez kót, kóty jsou v PDF -> Z PDF už model neopravíte. DwG je práce, PDF je odevzdaný tisk. diff --git a/ios/Graduately/AppModel.swift b/ios/Graduately/AppModel.swift index 9d324ec..5d7d419 100644 --- a/ios/Graduately/AppModel.swift +++ b/ios/Graduately/AppModel.swift @@ -234,86 +234,6 @@ final class AppModel: ObservableObject { refresh() } - func markTg(_ id: Int) { - progress.markTg(id) - refresh() - } - - func markTg2(_ id: Int) { - progress.markTg2(id) - refresh() - } - - func markTg3(_ id: Int) { - progress.markTg3(id) - refresh() - } - - func markPg(_ id: Int) { - progress.markPg(id) - refresh() - } - - func markPg2(_ id: Int) { - progress.markPg2(id) - refresh() - } - - func markPg3(_ id: Int) { - progress.markPg3(id) - refresh() - } - - func markPg4(_ id: Int) { - progress.markPg4(id) - refresh() - } - - func markSw(_ id: Int) { - progress.markSw(id) - refresh() - } - - func markSw2(_ id: Int) { - progress.markSw2(id) - refresh() - } - - func markSw3(_ id: Int) { - progress.markSw3(id) - refresh() - } - - func markSw4(_ id: Int) { - progress.markSw4(id) - refresh() - } - - func markTg4(_ id: Int) { - progress.markTg4(id) - refresh() - } - - func markCs(_ id: Int) { - progress.markCs(id) - refresh() - } - - func markCs2(_ id: Int) { - progress.markCs2(id) - refresh() - } - - func markCs3(_ id: Int) { - progress.markCs3(id) - refresh() - } - - func markCs4(_ id: Int) { - progress.markCs4(id) - refresh() - } - func markMat0(_ id: Int) { progress.markMat0(id) refresh() diff --git a/ios/Graduately/Data/Content.swift b/ios/Graduately/Data/Content.swift index dafa975..7480e01 100644 --- a/ios/Graduately/Data/Content.swift +++ b/ios/Graduately/Data/Content.swift @@ -59,22 +59,6 @@ final class Content { let fyz2: [J] let fyz3: [J] let fyz4: [J] - let tg: [J] - let tg2: [J] - let tg3: [J] - let tg4: [J] - let pg: [J] - let pg2: [J] - let pg3: [J] - let pg4: [J] - let sw: [J] - let sw2: [J] - let sw3: [J] - let sw4: [J] - let cs: [J] - let cs2: [J] - let cs3: [J] - let cs4: [J] let mat0: [J] let mat: [J] let mat2: [J] @@ -141,22 +125,6 @@ final class Content { fyz2 = raw.arr("fyz2") fyz3 = raw.arr("fyz3") fyz4 = raw.arr("fyz4") - tg = raw.arr("tg") - tg2 = raw.arr("tg2") - tg3 = raw.arr("tg3") - tg4 = raw.arr("tg4") - pg = raw.arr("pg") - pg2 = raw.arr("pg2") - pg3 = raw.arr("pg3") - pg4 = raw.arr("pg4") - sw = raw.arr("sw") - sw2 = raw.arr("sw2") - sw3 = raw.arr("sw3") - sw4 = raw.arr("sw4") - cs = raw.arr("cs") - cs2 = raw.arr("cs2") - cs3 = raw.arr("cs3") - cs4 = raw.arr("cs4") mat0 = raw.arr("mat0") mat = raw.arr("mat") mat2 = raw.arr("mat2") @@ -219,22 +187,6 @@ final class Content { func fyz2Lesson(_ id: Int) -> J? { fyz2.first { $0.int("id") == id } } func fyz3Lesson(_ id: Int) -> J? { fyz3.first { $0.int("id") == id } } func fyz4Lesson(_ id: Int) -> J? { fyz4.first { $0.int("id") == id } } - func tgLesson(_ id: Int) -> J? { tg.first { $0.int("id") == id } } - func tg2Lesson(_ id: Int) -> J? { tg2.first { $0.int("id") == id } } - func tg3Lesson(_ id: Int) -> J? { tg3.first { $0.int("id") == id } } - func tg4Lesson(_ id: Int) -> J? { tg4.first { $0.int("id") == id } } - func pgLesson(_ id: Int) -> J? { pg.first { $0.int("id") == id } } - func pg2Lesson(_ id: Int) -> J? { pg2.first { $0.int("id") == id } } - func pg3Lesson(_ id: Int) -> J? { pg3.first { $0.int("id") == id } } - func pg4Lesson(_ id: Int) -> J? { pg4.first { $0.int("id") == id } } - func swLesson(_ id: Int) -> J? { sw.first { $0.int("id") == id } } - func sw2Lesson(_ id: Int) -> J? { sw2.first { $0.int("id") == id } } - func sw3Lesson(_ id: Int) -> J? { sw3.first { $0.int("id") == id } } - func sw4Lesson(_ id: Int) -> J? { sw4.first { $0.int("id") == id } } - func csLesson(_ id: Int) -> J? { cs.first { $0.int("id") == id } } - func cs2Lesson(_ id: Int) -> J? { cs2.first { $0.int("id") == id } } - func cs3Lesson(_ id: Int) -> J? { cs3.first { $0.int("id") == id } } - func cs4Lesson(_ id: Int) -> J? { cs4.first { $0.int("id") == id } } func mat0Lesson(_ id: Int) -> J? { mat0.first { $0.int("id") == id } } func matLesson(_ id: Int) -> J? { mat.first { $0.int("id") == id } } func mat2Lesson(_ id: Int) -> J? { mat2.first { $0.int("id") == id } } diff --git a/ios/Graduately/Data/ProgressStore.swift b/ios/Graduately/Data/ProgressStore.swift index f77c330..ddbf220 100644 --- a/ios/Graduately/Data/ProgressStore.swift +++ b/ios/Graduately/Data/ProgressStore.swift @@ -94,38 +94,6 @@ final class ProgressStore { func markFyz3(_ id: Int) { mark("fyz3.\(id)") } func fyz4Done(_ id: Int) -> Bool { done("fyz4.\(id)") } func markFyz4(_ id: Int) { mark("fyz4.\(id)") } - func tgDone(_ id: Int) -> Bool { done("tg.\(id)") } - func markTg(_ id: Int) { mark("tg.\(id)") } - func tg2Done(_ id: Int) -> Bool { done("tg2.\(id)") } - func markTg2(_ id: Int) { mark("tg2.\(id)") } - func tg3Done(_ id: Int) -> Bool { done("tg3.\(id)") } - func markTg3(_ id: Int) { mark("tg3.\(id)") } - func tg4Done(_ id: Int) -> Bool { done("tg4.\(id)") } - func markTg4(_ id: Int) { mark("tg4.\(id)") } - func pgDone(_ id: Int) -> Bool { done("pg.\(id)") } - func markPg(_ id: Int) { mark("pg.\(id)") } - func pg2Done(_ id: Int) -> Bool { done("pg2.\(id)") } - func markPg2(_ id: Int) { mark("pg2.\(id)") } - func pg3Done(_ id: Int) -> Bool { done("pg3.\(id)") } - func markPg3(_ id: Int) { mark("pg3.\(id)") } - func pg4Done(_ id: Int) -> Bool { done("pg4.\(id)") } - func markPg4(_ id: Int) { mark("pg4.\(id)") } - func swDone(_ id: Int) -> Bool { done("sw.\(id)") } - func markSw(_ id: Int) { mark("sw.\(id)") } - func sw2Done(_ id: Int) -> Bool { done("sw2.\(id)") } - func markSw2(_ id: Int) { mark("sw2.\(id)") } - func sw3Done(_ id: Int) -> Bool { done("sw3.\(id)") } - func markSw3(_ id: Int) { mark("sw3.\(id)") } - func sw4Done(_ id: Int) -> Bool { done("sw4.\(id)") } - func markSw4(_ id: Int) { mark("sw4.\(id)") } - func csDone(_ id: Int) -> Bool { done("cs.\(id)") } - func markCs(_ id: Int) { mark("cs.\(id)") } - func cs2Done(_ id: Int) -> Bool { done("cs2.\(id)") } - func markCs2(_ id: Int) { mark("cs2.\(id)") } - func cs3Done(_ id: Int) -> Bool { done("cs3.\(id)") } - func markCs3(_ id: Int) { mark("cs3.\(id)") } - func cs4Done(_ id: Int) -> Bool { done("cs4.\(id)") } - func markCs4(_ id: Int) { mark("cs4.\(id)") } func mat0Done(_ id: Int) -> Bool { done("mat0.\(id)") } func markMat0(_ id: Int) { mark("mat0.\(id)") } func matDone(_ id: Int) -> Bool { done("mat.\(id)") } @@ -320,134 +288,6 @@ func summarize(_ content: Content, _ p: ProgressStore) -> ProgressSum { sum.doneUnits += 1 } } - for l in content.tg { - sum.totalEx += 1 - sum.openUnits += 1 - if p.tgDone(l.int("id")) { - sum.doneEx += 1 - sum.doneUnits += 1 - } - } - for l in content.tg2 { - sum.totalEx += 1 - sum.openUnits += 1 - if p.tg2Done(l.int("id")) { - sum.doneEx += 1 - sum.doneUnits += 1 - } - } - for l in content.tg3 { - sum.totalEx += 1 - sum.openUnits += 1 - if p.tg3Done(l.int("id")) { - sum.doneEx += 1 - sum.doneUnits += 1 - } - } - for l in content.tg4 { - sum.totalEx += 1 - sum.openUnits += 1 - if p.tg4Done(l.int("id")) { - sum.doneEx += 1 - sum.doneUnits += 1 - } - } - for l in content.pg { - sum.totalEx += 1 - sum.openUnits += 1 - if p.pgDone(l.int("id")) { - sum.doneEx += 1 - sum.doneUnits += 1 - } - } - for l in content.pg2 { - sum.totalEx += 1 - sum.openUnits += 1 - if p.pg2Done(l.int("id")) { - sum.doneEx += 1 - sum.doneUnits += 1 - } - } - for l in content.pg3 { - sum.totalEx += 1 - sum.openUnits += 1 - if p.pg3Done(l.int("id")) { - sum.doneEx += 1 - sum.doneUnits += 1 - } - } - for l in content.pg4 { - sum.totalEx += 1 - sum.openUnits += 1 - if p.pg4Done(l.int("id")) { - sum.doneEx += 1 - sum.doneUnits += 1 - } - } - for l in content.sw { - sum.totalEx += 1 - sum.openUnits += 1 - if p.swDone(l.int("id")) { - sum.doneEx += 1 - sum.doneUnits += 1 - } - } - for l in content.sw2 { - sum.totalEx += 1 - sum.openUnits += 1 - if p.sw2Done(l.int("id")) { - sum.doneEx += 1 - sum.doneUnits += 1 - } - } - for l in content.sw3 { - sum.totalEx += 1 - sum.openUnits += 1 - if p.sw3Done(l.int("id")) { - sum.doneEx += 1 - sum.doneUnits += 1 - } - } - for l in content.sw4 { - sum.totalEx += 1 - sum.openUnits += 1 - if p.sw4Done(l.int("id")) { - sum.doneEx += 1 - sum.doneUnits += 1 - } - } - for l in content.cs { - sum.totalEx += 1 - sum.openUnits += 1 - if p.csDone(l.int("id")) { - sum.doneEx += 1 - sum.doneUnits += 1 - } - } - for l in content.cs2 { - sum.totalEx += 1 - sum.openUnits += 1 - if p.cs2Done(l.int("id")) { - sum.doneEx += 1 - sum.doneUnits += 1 - } - } - for l in content.cs3 { - sum.totalEx += 1 - sum.openUnits += 1 - if p.cs3Done(l.int("id")) { - sum.doneEx += 1 - sum.doneUnits += 1 - } - } - for l in content.cs4 { - sum.totalEx += 1 - sum.openUnits += 1 - if p.cs4Done(l.int("id")) { - sum.doneEx += 1 - sum.doneUnits += 1 - } - } for l in content.mat0 { sum.totalEx += 1 sum.openUnits += 1 diff --git a/ios/Graduately/Route.swift b/ios/Graduately/Route.swift index a85395c..b6290a6 100644 --- a/ios/Graduately/Route.swift +++ b/ios/Graduately/Route.swift @@ -111,54 +111,6 @@ enum Route: Hashable { case fyz4Map case fyz4Lesson(Int) case fyz4Ex(Int) - case tgYears - case tgMap - case tgLesson(Int) - case tgEx(Int) - case tg2Map - case tg2Lesson(Int) - case tg2Ex(Int) - case tg3Map - case tg3Lesson(Int) - case tg3Ex(Int) - case tg4Map - case tg4Lesson(Int) - case tg4Ex(Int) - case pgYears - case pgMap - case pgLesson(Int) - case pgEx(Int) - case pg2Map - case pg2Lesson(Int) - case pg2Ex(Int) - case pg3Map - case pg3Lesson(Int) - case pg3Ex(Int) - case pg4Map - case pg4Lesson(Int) - case pg4Ex(Int) - case swYears - case swMap - case swLesson(Int) - case swEx(Int) - case sw2Map - case sw2Lesson(Int) - case sw2Ex(Int) - case sw3Map - case sw3Lesson(Int) - case sw3Ex(Int) - case sw4Map - case sw4Lesson(Int) - case sw4Ex(Int) - case csYears - case csMap - case csLesson(Int) - case cs2Map - case cs2Lesson(Int) - case cs3Map - case cs3Lesson(Int) - case cs4Map - case cs4Lesson(Int) case czechMap case mluvnice case mluvEx(Int) @@ -272,54 +224,6 @@ enum Route: Hashable { case .fyz4Map: return "fyz4map" case .fyz4Lesson(let id): return "fyz4unit\(id)" case .fyz4Ex(let id): return "fyz4ex\(id)" - case .tgYears: return "tgyears" - case .tgMap: return "tgmap" - case .tgLesson(let id): return "tgunit\(id)" - case .tgEx(let id): return "tgex\(id)" - case .tg2Map: return "tg2map" - case .tg2Lesson(let id): return "tg2unit\(id)" - case .tg2Ex(let id): return "tg2ex\(id)" - case .tg3Map: return "tg3map" - case .tg3Lesson(let id): return "tg3unit\(id)" - case .tg3Ex(let id): return "tg3ex\(id)" - case .tg4Map: return "tg4map" - case .tg4Lesson(let id): return "tg4unit\(id)" - case .tg4Ex(let id): return "tg4ex\(id)" - case .pgYears: return "pgyears" - case .pgMap: return "pgmap" - case .pgLesson(let id): return "pgunit\(id)" - case .pgEx(let id): return "pgex\(id)" - case .pg2Map: return "pg2map" - case .pg2Lesson(let id): return "pg2unit\(id)" - case .pg2Ex(let id): return "pg2ex\(id)" - case .pg3Map: return "pg3map" - case .pg3Lesson(let id): return "pg3unit\(id)" - case .pg3Ex(let id): return "pg3ex\(id)" - case .pg4Map: return "pg4map" - case .pg4Lesson(let id): return "pg4unit\(id)" - case .pg4Ex(let id): return "pg4ex\(id)" - case .swYears: return "swyears" - case .swMap: return "swmap" - case .swLesson(let id): return "swunit\(id)" - case .swEx(let id): return "swex\(id)" - case .sw2Map: return "sw2map" - case .sw2Lesson(let id): return "sw2unit\(id)" - case .sw2Ex(let id): return "sw2ex\(id)" - case .sw3Map: return "sw3map" - case .sw3Lesson(let id): return "sw3unit\(id)" - case .sw3Ex(let id): return "sw3ex\(id)" - case .sw4Map: return "sw4map" - case .sw4Lesson(let id): return "sw4unit\(id)" - case .sw4Ex(let id): return "sw4ex\(id)" - case .csYears: return "csyears" - case .csMap: return "csmap" - case .csLesson(let id): return "csunit\(id)" - case .cs2Map: return "cs2map" - case .cs2Lesson(let id): return "cs2unit\(id)" - case .cs3Map: return "cs3map" - case .cs3Lesson(let id): return "cs3unit\(id)" - case .cs4Map: return "cs4map" - case .cs4Lesson(let id): return "cs4unit\(id)" case .czechMap: return "czechmap" case .mluvnice: return "mluvnice" case .mluvEx(let n): return "mluve\(n)" @@ -544,102 +448,6 @@ enum Route: Hashable { return [.fyzYears, .fyz4Map, .fyz4Lesson(id)] case .fyz4Ex(let id): return [.fyzYears, .fyz4Map, .fyz4Lesson(id), .fyz4Ex(id)] - case .tgYears: - return [.tgYears] - case .tgMap: - return [.tgYears, .tgMap] - case .tgLesson(let id): - return [.tgYears, .tgMap, .tgLesson(id)] - case .tgEx(let id): - return [.tgYears, .tgMap, .tgLesson(id), .tgEx(id)] - case .tg2Map: - return [.tgYears, .tg2Map] - case .tg2Lesson(let id): - return [.tgYears, .tg2Map, .tg2Lesson(id)] - case .tg2Ex(let id): - return [.tgYears, .tg2Map, .tg2Lesson(id), .tg2Ex(id)] - case .tg3Map: - return [.tgYears, .tg3Map] - case .tg3Lesson(let id): - return [.tgYears, .tg3Map, .tg3Lesson(id)] - case .tg3Ex(let id): - return [.tgYears, .tg3Map, .tg3Lesson(id), .tg3Ex(id)] - case .tg4Map: - return [.tgYears, .tg4Map] - case .tg4Lesson(let id): - return [.tgYears, .tg4Map, .tg4Lesson(id)] - case .tg4Ex(let id): - return [.tgYears, .tg4Map, .tg4Lesson(id), .tg4Ex(id)] - case .pgYears: - return [.pgYears] - case .pgMap: - return [.pgYears, .pgMap] - case .pgLesson(let id): - return [.pgYears, .pgMap, .pgLesson(id)] - case .pgEx(let id): - return [.pgYears, .pgMap, .pgLesson(id), .pgEx(id)] - case .pg2Map: - return [.pgYears, .pg2Map] - case .pg2Lesson(let id): - return [.pgYears, .pg2Map, .pg2Lesson(id)] - case .pg2Ex(let id): - return [.pgYears, .pg2Map, .pg2Lesson(id), .pg2Ex(id)] - case .pg3Map: - return [.pgYears, .pg3Map] - case .pg3Lesson(let id): - return [.pgYears, .pg3Map, .pg3Lesson(id)] - case .pg3Ex(let id): - return [.pgYears, .pg3Map, .pg3Lesson(id), .pg3Ex(id)] - case .pg4Map: - return [.pgYears, .pg4Map] - case .pg4Lesson(let id): - return [.pgYears, .pg4Map, .pg4Lesson(id)] - case .pg4Ex(let id): - return [.pgYears, .pg4Map, .pg4Lesson(id), .pg4Ex(id)] - case .swYears: - return [.swYears] - case .swMap: - return [.swYears, .swMap] - case .swLesson(let id): - return [.swYears, .swMap, .swLesson(id)] - case .swEx(let id): - return [.swYears, .swMap, .swLesson(id), .swEx(id)] - case .sw2Map: - return [.swYears, .sw2Map] - case .sw2Lesson(let id): - return [.swYears, .sw2Map, .sw2Lesson(id)] - case .sw2Ex(let id): - return [.swYears, .sw2Map, .sw2Lesson(id), .sw2Ex(id)] - case .sw3Map: - return [.swYears, .sw3Map] - case .sw3Lesson(let id): - return [.swYears, .sw3Map, .sw3Lesson(id)] - case .sw3Ex(let id): - return [.swYears, .sw3Map, .sw3Lesson(id), .sw3Ex(id)] - case .sw4Map: - return [.swYears, .sw4Map] - case .sw4Lesson(let id): - return [.swYears, .sw4Map, .sw4Lesson(id)] - case .sw4Ex(let id): - return [.swYears, .sw4Map, .sw4Lesson(id), .sw4Ex(id)] - case .csYears: - return [.csYears] - case .csMap: - return [.csYears, .csMap] - case .csLesson(let id): - return [.csYears, .csMap, .csLesson(id)] - case .cs2Map: - return [.csYears, .cs2Map] - case .cs2Lesson(let id): - return [.csYears, .cs2Map, .cs2Lesson(id)] - case .cs3Map: - return [.csYears, .cs3Map] - case .cs3Lesson(let id): - return [.csYears, .cs3Map, .cs3Lesson(id)] - case .cs4Map: - return [.csYears, .cs4Map] - case .cs4Lesson(let id): - return [.csYears, .cs4Map, .cs4Lesson(id)] case .czechMap: return [.czechMap] case .mluvnice: @@ -700,26 +508,6 @@ func routeFromPage(_ page: String) -> Route? { case "fyz2map": return .fyz2Map case "fyz3map": return .fyz3Map case "fyz4map": return .fyz4Map - case "tgyears": return .tgYears - case "tgmap": return .tgMap - case "tg2map": return .tg2Map - case "tg3map": return .tg3Map - case "tg4map": return .tg4Map - case "pgyears": return .pgYears - case "pgmap": return .pgMap - case "pg2map": return .pg2Map - case "pg3map": return .pg3Map - case "pg4map": return .pg4Map - case "swyears": return .swYears - case "swmap": return .swMap - case "sw2map": return .sw2Map - case "sw3map": return .sw3Map - case "sw4map": return .sw4Map - case "csyears": return .csYears - case "csmap": return .csMap - case "cs2map": return .cs2Map - case "cs3map": return .cs3Map - case "cs4map": return .cs4Map case "czechmap": return .czechMap case "mluvnice": return .mluvnice case "readinglist": return .readingList @@ -829,90 +617,6 @@ func routeFromPage(_ page: String) -> Route? { if let m = page.wholeMatch(of: /fyzex(\d+)/), let n = Int(m.1) { return .fyzEx(n) } - if let m = page.wholeMatch(of: /sw4unit(\d+)/), let n = Int(m.1) { - return .sw4Lesson(n) - } - if let m = page.wholeMatch(of: /sw4ex(\d+)/), let n = Int(m.1) { - return .sw4Ex(n) - } - if let m = page.wholeMatch(of: /sw3unit(\d+)/), let n = Int(m.1) { - return .sw3Lesson(n) - } - if let m = page.wholeMatch(of: /sw3ex(\d+)/), let n = Int(m.1) { - return .sw3Ex(n) - } - if let m = page.wholeMatch(of: /sw2unit(\d+)/), let n = Int(m.1) { - return .sw2Lesson(n) - } - if let m = page.wholeMatch(of: /sw2ex(\d+)/), let n = Int(m.1) { - return .sw2Ex(n) - } - if let m = page.wholeMatch(of: /swunit(\d+)/), let n = Int(m.1) { - return .swLesson(n) - } - if let m = page.wholeMatch(of: /swex(\d+)/), let n = Int(m.1) { - return .swEx(n) - } - if let m = page.wholeMatch(of: /pg4unit(\d+)/), let n = Int(m.1) { - return .pg4Lesson(n) - } - if let m = page.wholeMatch(of: /pg4ex(\d+)/), let n = Int(m.1) { - return .pg4Ex(n) - } - if let m = page.wholeMatch(of: /pg3unit(\d+)/), let n = Int(m.1) { - return .pg3Lesson(n) - } - if let m = page.wholeMatch(of: /pg3ex(\d+)/), let n = Int(m.1) { - return .pg3Ex(n) - } - if let m = page.wholeMatch(of: /pg2unit(\d+)/), let n = Int(m.1) { - return .pg2Lesson(n) - } - if let m = page.wholeMatch(of: /pg2ex(\d+)/), let n = Int(m.1) { - return .pg2Ex(n) - } - if let m = page.wholeMatch(of: /pgunit(\d+)/), let n = Int(m.1) { - return .pgLesson(n) - } - if let m = page.wholeMatch(of: /pgex(\d+)/), let n = Int(m.1) { - return .pgEx(n) - } - if let m = page.wholeMatch(of: /tg4unit(\d+)/), let n = Int(m.1) { - return .tg4Lesson(n) - } - if let m = page.wholeMatch(of: /tg4ex(\d+)/), let n = Int(m.1) { - return .tg4Ex(n) - } - if let m = page.wholeMatch(of: /tg3unit(\d+)/), let n = Int(m.1) { - return .tg3Lesson(n) - } - if let m = page.wholeMatch(of: /tg3ex(\d+)/), let n = Int(m.1) { - return .tg3Ex(n) - } - if let m = page.wholeMatch(of: /tg2unit(\d+)/), let n = Int(m.1) { - return .tg2Lesson(n) - } - if let m = page.wholeMatch(of: /tg2ex(\d+)/), let n = Int(m.1) { - return .tg2Ex(n) - } - if let m = page.wholeMatch(of: /tgunit(\d+)/), let n = Int(m.1) { - return .tgLesson(n) - } - if let m = page.wholeMatch(of: /tgex(\d+)/), let n = Int(m.1) { - return .tgEx(n) - } - if let m = page.wholeMatch(of: /cs4unit(\d+)/), let n = Int(m.1) { - return .cs4Lesson(n) - } - if let m = page.wholeMatch(of: /cs3unit(\d+)/), let n = Int(m.1) { - return .cs3Lesson(n) - } - if let m = page.wholeMatch(of: /cs2unit(\d+)/), let n = Int(m.1) { - return .cs2Lesson(n) - } - if let m = page.wholeMatch(of: /csunit(\d+)/), let n = Int(m.1) { - return .csLesson(n) - } if let m = page.wholeMatch(of: /lit4unit(\d+)/), let n = Int(m.1) { return .lit4Lesson(n) } diff --git a/ios/Graduately/UI/Components.swift b/ios/Graduately/UI/Components.swift index e0aaf2a..5c74383 100644 --- a/ios/Graduately/UI/Components.swift +++ b/ios/Graduately/UI/Components.swift @@ -50,47 +50,109 @@ enum MacChrome { static let pageInset: CGFloat = 28 static let cardPadding: CGFloat = 22 static let listRowMinHeight: CGFloat = 52 - static let homeTileMin: CGFloat = 260 - static let homeTileHeight: CGFloat = 172 + static let homeTileMin: CGFloat = 240 + static let homeTileHeight: CGFloat = 168 static let pathNode: CGFloat = 84 - /// Pages stop growing here so cards and text keep their shape on wide displays. - static let contentWidth: CGFloat = 1240 - static let readableWidth: CGFloat = 860 - static let actionWidth: CGFloat = 520 } -/// Fixed-height cards in as many columns as fit, centred and capped in width. +enum MacGrid { + /// Picks a column count that fills the width and keeps tiles wider than they are tall. + static func columns(width: CGFloat, height: CGFloat, count: Int, minWidth: CGFloat, minHeight: CGFloat, spacing: CGFloat) -> Int { + guard count > 0, width > 0 else { return 1 } + let maxCols = max(1, min(count, Int((width + spacing) / (minWidth + spacing)))) + var best = maxCols + var bestScore = CGFloat.greatestFiniteMagnitude + let offeredH = height > 1 ? height : minHeight * CGFloat(count) + for cols in 1...maxCols { + let rows = Int(ceil(Double(count) / Double(cols))) + let tileW = (width - spacing * CGFloat(cols - 1)) / CGFloat(cols) + if tileW + 0.5 < minWidth { continue } + let needed = CGFloat(rows) * minHeight + spacing * CGFloat(max(rows - 1, 0)) + let tileH = max(minHeight, (offeredH - spacing * CGFloat(max(rows - 1, 0))) / CGFloat(rows)) + let aspect = tileH / max(tileW, 1) + let rem = count % cols + let ragged = rem == 0 ? 0 : CGFloat(1.5) + let lonely = rem == 1 ? CGFloat(1.4) : 0 + let tooTall = max(0, aspect - 1.05) * 3 + let overflow = max(0, needed - offeredH) + let score = abs(aspect - 0.78) * 2 + ragged + lonely + tooTall + overflow / 180 + if score < bestScore { + bestScore = score + best = cols + } + } + return best + } + + static func contentHeight(width: CGFloat, height: CGFloat, count: Int, minWidth: CGFloat, minHeight: CGFloat, spacing: CGFloat) -> CGFloat { + let cols = columns(width: width, height: height, count: count, minWidth: minWidth, minHeight: minHeight, spacing: spacing) + let rows = max(1, Int(ceil(Double(max(count, 1)) / Double(cols)))) + return CGFloat(rows) * minHeight + spacing * CGFloat(max(rows - 1, 0)) + } +} + +struct MacHeaderHeight: PreferenceKey { + static var defaultValue: CGFloat = 0 + static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) { + value = max(value, nextValue()) + } +} + +/// Card grid that grows into the space it is given and scrolls only when the +/// minimum tile size no longer fits. struct MacFillGrid: View { var count: Int var minWidth: CGFloat = 240 var minHeight: CGFloat = 148 var spacing: CGFloat = 16 var inset: CGFloat = 28 - var maxTileWidth: CGFloat = 340 + /// Home embeds the grid in its own scroll view. A second scroller here + /// swallows the wheel once a banner (the changelog) makes the page taller. + var scrolls = true @ViewBuilder var content: (Int) -> Content var body: some View { GeometryReader { geo in - let available = max(geo.size.width - inset * 2, minWidth) - let fit = max(1, Int((available + spacing) / (minWidth + spacing))) - let cols = max(1, min(count, fit)) - let width = min(available, CGFloat(cols) * maxTileWidth + CGFloat(cols - 1) * spacing) - ScrollView { - LazyVGrid( - columns: Array(repeating: GridItem(.flexible(), spacing: spacing, alignment: .top), count: cols), - alignment: .leading, - spacing: spacing - ) { - ForEach(0.. 1 + HStack(spacing: spacing) { + ForEach(0.. 0 { - HStack(spacing: 10) { - ProgressBar(value: Double(progress.done) / Double(progress.total)) - Text("\(progress.done) / \(progress.total)") - .font(.subheadline.monospacedDigit()) - .foregroundStyle(.secondary) - } - } } - .padding(20) + .padding(22) .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) - .softSurface(cornerRadius: 20) - .contentShape(RoundedRectangle(cornerRadius: 20, style: .continuous)) + .softSurface(cornerRadius: 22) } } #endif -/// Flat capsule bar. Unlike ProgressView it shows nothing at zero. -struct ProgressBar: View { - let value: Double - var height: CGFloat = 8 - - var body: some View { - GeometryReader { geo in - ZStack(alignment: .leading) { - Capsule().fill(Color.primary.opacity(0.08)) - if value > 0 { - Capsule() - .fill(Color.accentColor) - .frame(width: max(height, geo.size.width * min(value, 1))) - } - } - } - .frame(height: height) - .animation(Motion.settle, value: value) - } -} - -struct ProgressRing: View { - let value: Double - var lineWidth: CGFloat = 12 - @ViewBuilder var label: () -> Label - - var body: some View { - ZStack { - Circle().stroke(Color.primary.opacity(0.08), lineWidth: lineWidth) - if value > 0 { - Circle() - .trim(from: 0, to: min(value, 1)) - .stroke(Color.accentColor, style: StrokeStyle(lineWidth: lineWidth, lineCap: .round)) - .rotationEffect(.degrees(-90)) - } - label() - } - .animation(Motion.settle, value: value) - } -} - struct FlowLayout: Layout { var spacing: CGFloat = 6 @@ -570,28 +574,15 @@ extension View { #endif } - /// Leading-aligned content for exercise screens; on the Mac a centred readable column. + /// Full-width, leading-aligned content for exercise screens. func exerciseContent() -> some View { - #if os(macOS) - frame(maxWidth: MacChrome.readableWidth, alignment: .leading) - .padding(.horizontal, MacChrome.pageInset) - .padding(.vertical, 28) - .frame(maxWidth: .infinity) - #else frame(maxWidth: .infinity, alignment: .leading) + #if os(macOS) + .padding(.horizontal, MacChrome.pageInset) + .padding(.vertical, 20) + #else .padding() - #endif - } - - /// Caps a Mac page at [width] and centres it; no-op on iOS. - @ViewBuilder - func macPage(_ width: CGFloat? = nil) -> some View { - #if os(macOS) - frame(maxWidth: width ?? MacChrome.contentWidth) - .frame(maxWidth: .infinity) - #else - self - #endif + #endif } /// macOS content lists use the inset style so they sit under the floating @@ -645,8 +636,7 @@ struct BottomAction: View { }()) #if os(macOS) .padding(.top, 12) - .padding(.bottom, 14) - .frame(maxWidth: MacChrome.actionWidth) + .padding(.bottom, 10) .frame(maxWidth: .infinity) #else .padding(.top, 8) @@ -655,11 +645,10 @@ struct BottomAction: View { } } -/// Primary + secondary text sized for desktop lists, with optional exercise progress. +/// Primary + secondary text sized for desktop lists. struct ListRowLabel: View { let title: String var subtitle: String? = nil - var progress: (done: Int, total: Int)? = nil var body: some View { VStack(alignment: .leading, spacing: 3) { @@ -676,25 +665,6 @@ struct ListRowLabel: View { #endif .foregroundStyle(.secondary) } - if let progress, progress.total > 0 { - ProgressLine(done: progress.done, total: progress.total) - .padding(.top, 4) - } - } - } -} - -/// Slim bar with "done / total" beside it, for list rows. -struct ProgressLine: View { - let done: Int - let total: Int - - var body: some View { - HStack(spacing: 8) { - ProgressBar(value: total == 0 ? 0 : Double(done) / Double(total), height: 5) - Text("\(done) / \(total)") - .font(.caption.monospacedDigit()) - .foregroundStyle(.secondary) } } } @@ -709,10 +679,6 @@ func subjectSymbol(_ icon: String) -> String { case "flask": return "flask.fill" case "bolt": return "bolt.fill" case "function": return "function" - case "ruler": return "ruler.fill" - case "code": return "chevron.left.forwardslash.chevron.right" - case "brush": return "paintbrush.fill" - case "apps": return "square.grid.2x2.fill" default: return "lock.fill" } } diff --git a/ios/Graduately/UI/Exercises.swift b/ios/Graduately/UI/Exercises.swift index fb4ccea..e71f134 100644 --- a/ios/Graduately/UI/Exercises.swift +++ b/ios/Graduately/UI/Exercises.swift @@ -12,9 +12,21 @@ struct ExerciseScaffold: View { var body: some View { let p = vm.palette - ScrollView { - VStack(alignment: .leading, spacing: 8) { content() } - .exerciseContent() + Group { + #if os(macOS) + GeometryReader { geo in + ScrollView { + VStack(alignment: .leading, spacing: 8) { content() } + .exerciseContent() + .frame(maxWidth: .infinity, minHeight: geo.size.height, alignment: .center) + } + } + #else + ScrollView { + VStack(alignment: .leading, spacing: 8) { content() } + .exerciseContent() + } + #endif } .scrollDismissesKeyboard(.interactively) .detailScreen(title, subtitle: sub) diff --git a/ios/Graduately/UI/ExercisesMore.swift b/ios/Graduately/UI/ExercisesMore.swift index 783dd4d..4987c01 100644 --- a/ios/Graduately/UI/ExercisesMore.swift +++ b/ios/Graduately/UI/ExercisesMore.swift @@ -952,105 +952,6 @@ struct ChoiceLessonScreen: View { } } -struct TgQuizScreen: View { - @ObservedObject var vm: AppModel - let year: Int - let id: Int - - var body: some View { - let lesson: J? = { - switch year { - case 2: return vm.content.tg2Lesson(id) - case 3: return vm.content.tg3Lesson(id) - case 4: return vm.content.tg4Lesson(id) - default: return vm.content.tgLesson(id) - } - }() - if let lesson { - let spec = J([ - "type": "choice", - "title": vm.tr(lesson.str("exTitleKey")), - "sub": lesson.str("quizHeadKey"), - "questions": lesson.rawArray("quiz"), - ]) - DispatchExercise(vm: vm, spec: spec, titleFallback: vm.tr(lesson.str("exTitleKey"))) { - switch year { - case 2: vm.markTg2(id) - case 3: vm.markTg3(id) - case 4: vm.markTg4(id) - default: vm.markTg(id) - } - } - } - } -} - -struct PgQuizScreen: View { - @ObservedObject var vm: AppModel - let year: Int - let id: Int - - var body: some View { - let lesson: J? = { - switch year { - case 2: return vm.content.pg2Lesson(id) - case 3: return vm.content.pg3Lesson(id) - case 4: return vm.content.pg4Lesson(id) - default: return vm.content.pgLesson(id) - } - }() - if let lesson { - let spec = J([ - "type": "choice", - "title": vm.tr(lesson.str("exTitleKey")), - "sub": lesson.str("quizHeadKey"), - "questions": lesson.rawArray("quiz"), - ]) - DispatchExercise(vm: vm, spec: spec, titleFallback: vm.tr(lesson.str("exTitleKey"))) { - switch year { - case 2: vm.markPg2(id) - case 3: vm.markPg3(id) - case 4: vm.markPg4(id) - default: vm.markPg(id) - } - } - } - } -} - -struct SwQuizScreen: View { - @ObservedObject var vm: AppModel - let year: Int - let id: Int - - var body: some View { - let lesson: J? = { - switch year { - case 2: return vm.content.sw2Lesson(id) - case 3: return vm.content.sw3Lesson(id) - case 4: return vm.content.sw4Lesson(id) - default: return vm.content.swLesson(id) - } - }() - if let lesson { - let spec = J([ - "type": "choice", - "title": vm.tr(lesson.str("exTitleKey")), - "sub": lesson.str("quizHeadKey"), - "questions": lesson.rawArray("quiz"), - ]) - DispatchExercise(vm: vm, spec: spec, titleFallback: vm.tr(lesson.str("exTitleKey"))) { - switch year { - case 2: vm.markSw2(id) - case 3: vm.markSw3(id) - case 4: vm.markSw4(id) - default: vm.markSw(id) - } - } - } - } -} - struct FyzQuizScreen: View { @ObservedObject var vm: AppModel let year: Int diff --git a/ios/Graduately/UI/PathMap.swift b/ios/Graduately/UI/PathMap.swift index 5c7e4e4..3271b2e 100644 --- a/ios/Graduately/UI/PathMap.swift +++ b/ios/Graduately/UI/PathMap.swift @@ -8,8 +8,6 @@ struct MapNode: Identifiable { let current: Bool var finish: Bool = false var destination: Route? - /// Glyph for a node that has no number, such as a side branch. - var symbol: String? = nil } private struct NodePos { @@ -258,8 +256,6 @@ struct PathMap: View { .overlay { if node.locked { Circle().strokeBorder(palette.lockedBorder, lineWidth: 1) - } else if !node.current && !node.done { - Circle().strokeBorder(palette.accent.opacity(0.55), lineWidth: 2.5) } } if node.finish { @@ -302,13 +298,6 @@ struct PathMap: View { #else .font(.headline.weight(.black)) #endif - } else if let symbol = node.symbol { - Image(systemName: symbol) - #if os(macOS) - .font(.title3.weight(.semibold)) - #else - .font(.body.weight(.semibold)) - #endif } Image(systemName: "checkmark") #if os(macOS) @@ -326,14 +315,6 @@ struct PathMap: View { .font(.headline.weight(.black)) #endif .foregroundStyle(node.current ? palette.onAccent : palette.text) - } else if let symbol = node.symbol { - Image(systemName: symbol) - #if os(macOS) - .font(.title2.weight(.semibold)) - #else - .font(.headline.weight(.semibold)) - #endif - .foregroundStyle(node.current ? palette.onAccent : palette.text) } } .frame(width: nodeSize, height: nodeSize) diff --git a/ios/Graduately/UI/Screens.swift b/ios/Graduately/UI/Screens.swift index d4535b2..3113582 100644 --- a/ios/Graduately/UI/Screens.swift +++ b/ios/Graduately/UI/Screens.swift @@ -1,10 +1,10 @@ import SwiftUI -#if os(macOS) -import AppKit -#endif struct PracticeHome: View { @ObservedObject var vm: AppModel + #if os(macOS) + @State private var homeHeader: CGFloat = 280 + #endif var body: some View { #if os(macOS) @@ -18,124 +18,111 @@ struct PracticeHome: View { private var macHome: some View { let sum = summarize(vm.content, vm.progress) let pct = sum.totalEx == 0 ? 0 : Double(sum.doneEx) / Double(sum.totalEx) - let open = vm.content.subjects.filter { $0.bool("open") } - let soon = vm.content.subjects.filter { !$0.bool("open") } - return ScrollView { - VStack(alignment: .leading, spacing: 28) { - if vm.showChangelog { - ChangelogCard(vm: vm) - } - welcomeCard(sum: sum, pct: pct) - VStack(alignment: .leading, spacing: 14) { - Text(vm.tr("subjects_title")) - .font(.title2.weight(.semibold)) - LazyVGrid( - columns: [GridItem(.adaptive(minimum: MacChrome.homeTileMin), spacing: 16, alignment: .top)], - alignment: .leading, - spacing: 16 - ) { - ForEach(Array(open.enumerated()), id: \.offset) { _, s in - subjectTile(s) + let subjects = vm.content.subjects + return GeometryReader { geo in + let width = max(geo.size.width - MacChrome.pageInset * 2, MacChrome.homeTileMin) + let offered = max(geo.size.height - homeHeader - 20 - MacChrome.pageInset * 2, MacChrome.homeTileHeight) + let minGrid = MacGrid.contentHeight( + width: width, + height: offered, + count: subjects.count, + minWidth: MacChrome.homeTileMin, + minHeight: MacChrome.homeTileHeight, + spacing: 16 + ) + let gridH = max(minGrid, geo.size.height - homeHeader - 20 - MacChrome.pageInset * 2) + ScrollView { + VStack(alignment: .leading, spacing: 20) { + VStack(alignment: .leading, spacing: 16) { + if vm.showChangelog { + ChangelogCard(vm: vm) } - } - } - if !soon.isEmpty { - VStack(alignment: .leading, spacing: 12) { - Text(vm.tr("subjects_soon")) - .font(.headline) - .foregroundStyle(.secondary) - FlowLayout(spacing: 10) { - ForEach(Array(soon.enumerated()), id: \.offset) { _, s in - Label(vm.tr(s.str("key")), systemImage: "lock.fill") - .font(.body) + GlassCard { + VStack(alignment: .leading, spacing: 12) { + Text(vm.tr("welcome_title")) + .font(.largeTitle.bold()) + Text(vm.tr(Self.welcomeBodyKey)) + .font(.title3) + .foregroundStyle(.secondary) + .fixedSize(horizontal: false, vertical: true) + ProgressView(value: pct) + .animation(Motion.settle, value: pct) + Text(vm.fmt("stats_ex_fmt", sum.doneEx, sum.totalEx)) + .font(.subheadline) .foregroundStyle(.secondary) - .padding(.horizontal, 14) - .padding(.vertical, 9) - .background(Color.primary.opacity(0.05), in: Capsule()) } } + Text(vm.tr("subjects_title")) + .font(.title2.weight(.semibold)) } + .fixedSize(horizontal: false, vertical: true) + .background { + GeometryReader { proxy in + Color.clear.preference(key: MacHeaderHeight.self, value: proxy.size.height) + } + } + MacFillGrid( + count: subjects.count, + minWidth: MacChrome.homeTileMin, + minHeight: MacChrome.homeTileHeight, + spacing: 16, + inset: 0, + scrolls: false + ) { index in + subjectTile(subjects[index]) + } + .frame(height: gridH) } + .padding(MacChrome.pageInset) + .frame(maxWidth: .infinity, minHeight: geo.size.height, alignment: .topLeading) } - .padding(MacChrome.pageInset) - .macPage() + .onPreferenceChange(MacHeaderHeight.self) { homeHeader = $0 } } .navigationTitle("Graduately") } - private func welcomeCard(sum: ProgressSum, pct: Double) -> some View { - GlassCard { - HStack(alignment: .center, spacing: 32) { - VStack(alignment: .leading, spacing: 12) { - Text(vm.tr("welcome_title")) - .font(.system(size: 34, weight: .bold)) - .fixedSize(horizontal: false, vertical: true) - Text(vm.tr(Self.welcomeBodyKey)) - .font(.title3) - .foregroundStyle(.secondary) - .fixedSize(horizontal: false, vertical: true) - } - .frame(maxWidth: .infinity, alignment: .leading) - ProgressRing(value: pct) { - VStack(spacing: 2) { - Text(vm.fmt("stats_pct_fmt", Int((pct * 100).rounded(.down)))) - .font(.system(size: 26, weight: .bold, design: .rounded)) - .monospacedDigit() - Text(vm.fmt("stats_ex_fmt", sum.doneEx, sum.totalEx)) - .font(.subheadline.monospacedDigit()) - .foregroundStyle(.secondary) - } - } - .frame(width: 132, height: 132) - } - .padding(.vertical, 6) - } - } - @ViewBuilder private func subjectTile(_ s: J) -> some View { + let open = s.bool("open") let dest = s.strOrNull("target").flatMap(routeFromPage) - if let dest, dest != .subjects, dest != .welcome { - NavigationLink(value: dest) { - subjectTileBody(s) + let part = subjectSum(vm, s) + let progress = open && part.totalEx > 0 ? Double(part.doneEx) / Double(part.totalEx) : 0 + Group { + if open, let dest, dest != .subjects, dest != .welcome { + NavigationLink(value: dest) { + subjectTileBody(s, open: true, progress: progress, part: part) + } + .buttonStyle(PressScaleStyle()) + } else { + subjectTileBody(s, open: false, progress: 0, part: part) } - .buttonStyle(PressScaleStyle()) - } else { - subjectTileBody(s) } } - private func subjectTileBody(_ s: J) -> some View { - let part = subjectSum(vm, s) - let progress = part.totalEx > 0 ? Double(part.doneEx) / Double(part.totalEx) : 0 - return VStack(alignment: .leading, spacing: 14) { - HStack(alignment: .center) { - SubjectIcon(icon: s.str("icon"), open: true, size: 40) - Spacer(minLength: 0) - Image(systemName: "chevron.right") - .font(.body.weight(.semibold)) - .foregroundStyle(.tertiary) - } + private func subjectTileBody(_ s: J, open: Bool, progress: Double, part: ProgressSum) -> some View { + VStack(alignment: .leading, spacing: 16) { + SubjectIcon(icon: s.str("icon"), open: open, size: 44) Text(vm.tr(s.str("key"))) .font(.title3.weight(.semibold)) - .foregroundStyle(.primary) + .foregroundStyle(open ? .primary : .secondary) .multilineTextAlignment(.leading) - .lineLimit(2) Spacer(minLength: 0) - ProgressBar(value: progress) - HStack { + if open && part.totalEx > 0 { + ProgressView(value: progress) + .animation(Motion.settle, value: progress) Text(vm.fmt("stats_ex_fmt", part.doneEx, part.totalEx)) - Spacer(minLength: 0) - Text(vm.fmt("stats_pct_fmt", Int((progress * 100).rounded(.down)))) + .font(.subheadline) + .foregroundStyle(.secondary) + .monospacedDigit() + } else if !open { + Text(vm.tr("stats_locked")) + .font(.subheadline) + .foregroundStyle(.secondary) } - .font(.subheadline.monospacedDigit()) - .foregroundStyle(.secondary) } - .padding(20) - .frame(maxWidth: .infinity, alignment: .topLeading) - .frame(height: MacChrome.homeTileHeight) + .padding(22) + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) .softSurface(cornerRadius: 22) - .contentShape(RoundedRectangle(cornerRadius: 22, style: .continuous)) } #endif @@ -173,28 +160,16 @@ struct PracticeHome: View { } Section(vm.tr("subjects_title")) { - ForEach(Array(vm.content.subjects.filter { $0.bool("open") }.enumerated()), id: \.offset) { _, s in + ForEach(Array(vm.content.subjects.enumerated()), id: \.offset) { _, s in + let open = s.bool("open") let dest = s.strOrNull("target").flatMap(routeFromPage) - if let dest, dest != .subjects, dest != .welcome { + if open, let dest, dest != .subjects, dest != .welcome { NavigationLink(value: dest) { subjectLabel(s) } } else { subjectLabel(s) - } - } - } - - let soon = vm.content.subjects.filter { !$0.bool("open") } - if !soon.isEmpty { - Section(vm.tr("subjects_soon")) { - ForEach(Array(soon.enumerated()), id: \.offset) { _, s in - Label { - Text(vm.tr(s.str("key"))) - } icon: { - SubjectIcon(icon: s.str("icon"), open: false) - } - .foregroundStyle(.secondary) + .foregroundStyle(.secondary) } } } @@ -204,17 +179,15 @@ struct PracticeHome: View { } private func subjectLabel(_ s: J) -> some View { - let part = subjectSum(vm, s) - return Label { - VStack(alignment: .leading, spacing: 6) { + Label { + VStack(alignment: .leading, spacing: 2) { Text(vm.tr(s.str("key"))) - if part.totalEx > 0 { - ProgressLine(done: part.doneEx, total: part.totalEx) + if !s.bool("open") { + Text(vm.tr("stats_locked")).font(.caption).foregroundStyle(.secondary) } } - .padding(.vertical, 2) } icon: { - SubjectIcon(icon: s.str("icon"), open: true) + SubjectIcon(icon: s.str("icon"), open: s.bool("open")) } } #endif @@ -450,8 +423,7 @@ struct SettingsScreen: View { } } .padding(MacChrome.pageInset) - .frame(maxWidth: MacChrome.contentWidth, maxHeight: .infinity, alignment: .topLeading) - .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top) + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) .navigationTitle(vm.tr("settings_title")) } @@ -594,8 +566,7 @@ struct StatsScreen: View { } } .padding(MacChrome.pageInset) - .frame(maxWidth: MacChrome.contentWidth, maxHeight: .infinity, alignment: .topLeading) - .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top) + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) .navigationTitle(vm.tr("stats_title")) } @@ -693,76 +664,6 @@ struct StatsScreen: View { } } -/// Done and total exercises behind one card of a years screen, or nil when there is no count. -func routeProgress(_ vm: AppModel, _ r: Route) -> (done: Int, total: Int)? { - let c = vm.content - let p = vm.progress - func tally(_ lessons: [J], _ done: (Int) -> Bool) -> (done: Int, total: Int) { - (lessons.filter { done($0.int("id")) }.count, lessons.count) - } - switch r { - case .netMap: return tally(c.netLessons, p.netDone) - case .net2Map: return tally(c.itLessons("net2")) { p.courseDone("net2", $0) } - case .net3Map: return tally(c.itLessons("net3")) { p.courseDone("net3", $0) } - case .net4Map: return tally(c.itLessons("net4")) { p.courseDone("net4", $0) } - case .hwMap: return tally(c.hw, p.hwDone) - case .hw2Map: return tally(c.itLessons("hw2")) { p.courseDone("hw2", $0) } - case .hw3Map: return tally(c.itLessons("hw3")) { p.courseDone("hw3", $0) } - case .hw4Map: return tally(c.itLessons("hw4")) { p.courseDone("hw4", $0) } - case .onMap: return tally(c.on, p.onDone) - case .on2Map: return tally(c.on2, p.on2Done) - case .on3Map: return tally(c.on3, p.on3Done) - case .on4Map: return tally(c.on4, p.on4Done) - case .enMap(let year): return tally(c.enYear(year)) { p.enDone(year, $0) } - case .deMap(let year): return tally(c.deYear(year)) { p.deDone(year, $0) } - case .roadmap: - var done = 0 - var total = 0 - for u in c.german where u.bool("unlocked") { - let n = u.strs("names").count - total += n - done += (0.. ProgressSum { var sum = ProgressSum() switch s.str("target") { @@ -812,30 +713,6 @@ private func subjectSum(_ vm: AppModel, _ s: J) -> ProgressSum { + vm.content.mat2.filter { vm.progress.mat2Done($0.int("id")) }.count + vm.content.mat3.filter { vm.progress.mat3Done($0.int("id")) }.count + vm.content.mat4.filter { vm.progress.mat4Done($0.int("id")) }.count - case "csyears", "csmap", "cs2map", "cs3map", "cs4map": - sum.totalEx = vm.content.cs.count + vm.content.cs2.count + vm.content.cs3.count + vm.content.cs4.count - sum.doneEx = vm.content.cs.filter { vm.progress.csDone($0.int("id")) }.count - + vm.content.cs2.filter { vm.progress.cs2Done($0.int("id")) }.count - + vm.content.cs3.filter { vm.progress.cs3Done($0.int("id")) }.count - + vm.content.cs4.filter { vm.progress.cs4Done($0.int("id")) }.count - case "pgyears", "pgmap", "pg2map", "pg3map", "pg4map": - sum.totalEx = vm.content.pg.count + vm.content.pg2.count + vm.content.pg3.count + vm.content.pg4.count - sum.doneEx = vm.content.pg.filter { vm.progress.pgDone($0.int("id")) }.count - + vm.content.pg2.filter { vm.progress.pg2Done($0.int("id")) }.count - + vm.content.pg3.filter { vm.progress.pg3Done($0.int("id")) }.count - + vm.content.pg4.filter { vm.progress.pg4Done($0.int("id")) }.count - case "swyears", "swmap", "sw2map", "sw3map", "sw4map": - sum.totalEx = vm.content.sw.count + vm.content.sw2.count + vm.content.sw3.count + vm.content.sw4.count - sum.doneEx = vm.content.sw.filter { vm.progress.swDone($0.int("id")) }.count - + vm.content.sw2.filter { vm.progress.sw2Done($0.int("id")) }.count - + vm.content.sw3.filter { vm.progress.sw3Done($0.int("id")) }.count - + vm.content.sw4.filter { vm.progress.sw4Done($0.int("id")) }.count - case "tgyears", "tgmap", "tg2map", "tg3map", "tg4map": - sum.totalEx = vm.content.tg.count + vm.content.tg2.count + vm.content.tg3.count + vm.content.tg4.count - sum.doneEx = vm.content.tg.filter { vm.progress.tgDone($0.int("id")) }.count - + vm.content.tg2.filter { vm.progress.tg2Done($0.int("id")) }.count - + vm.content.tg3.filter { vm.progress.tg3Done($0.int("id")) }.count - + vm.content.tg4.filter { vm.progress.tg4Done($0.int("id")) }.count case "fyzyears", "fyzmap", "fyz2map", "fyz3map", "fyz4map": sum.totalEx = vm.content.fyz.count + vm.content.fyz2.count + vm.content.fyz3.count + vm.content.fyz4.count sum.doneEx = vm.content.fyz.filter { vm.progress.fyzDone($0.int("id")) }.count @@ -906,7 +783,6 @@ struct SearchScreen: View { } } .padding(MacChrome.pageInset) - .macPage() } } .navigationTitle(vm.tr("search")) @@ -1139,86 +1015,6 @@ private func buildSearch(_ vm: AppModel) -> [Hit] { add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "fyz4unit\(l.int("id"))", extra: "fyzika") add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "fyz4ex\(l.int("id"))") } - add(vm.tr("Programové vybavení"), vm.tr("search_lesson"), "swyears", extra: "office windows excel mysql") - add(vm.tr("sw_year1"), vm.tr("search_lesson"), "swmap", extra: "rocnik") - add(vm.tr("sw_year2"), vm.tr("search_lesson"), "sw2map", extra: "rocnik") - add(vm.tr("sw_year3"), vm.tr("search_lesson"), "sw3map", extra: "rocnik") - add(vm.tr("sw_year4"), vm.tr("search_lesson"), "sw4map", extra: "rocnik") - for l in vm.content.sw { - add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "swunit\(l.int("id"))", extra: "windows") - add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "swex\(l.int("id"))") - } - for l in vm.content.sw2 { - add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "sw2unit\(l.int("id"))", extra: "word excel") - add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "sw2ex\(l.int("id"))") - } - for l in vm.content.sw3 { - add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "sw3unit\(l.int("id"))", extra: "access mysql") - add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "sw3ex\(l.int("id"))") - } - for l in vm.content.sw4 { - add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "sw4unit\(l.int("id"))", extra: "wordpress") - add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "sw4ex\(l.int("id"))") - } - add(vm.tr("Prezentační grafika"), vm.tr("search_lesson"), "pgyears", extra: "photoshop premiere illustrator") - add(vm.tr("pg_year1"), vm.tr("search_lesson"), "pgmap", extra: "rocnik") - add(vm.tr("pg_year2"), vm.tr("search_lesson"), "pg2map", extra: "rocnik") - add(vm.tr("pg_year3"), vm.tr("search_lesson"), "pg3map", extra: "rocnik") - add(vm.tr("pg_year4"), vm.tr("search_lesson"), "pg4map", extra: "rocnik") - for l in vm.content.pg { - add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "pgunit\(l.int("id"))", extra: "photoshop") - add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "pgex\(l.int("id"))") - } - for l in vm.content.pg2 { - add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "pg2unit\(l.int("id"))", extra: "photoshop") - add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "pg2ex\(l.int("id"))") - } - for l in vm.content.pg3 { - add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "pg3unit\(l.int("id"))", extra: "premiere") - add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "pg3ex\(l.int("id"))") - } - for l in vm.content.pg4 { - add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "pg4unit\(l.int("id"))", extra: "illustrator") - add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "pg4ex\(l.int("id"))") - } - add(vm.tr("Technická grafika"), vm.tr("search_lesson"), "tgyears", extra: "autocad grafika") - add(vm.tr("tg_year1"), vm.tr("search_lesson"), "tgmap", extra: "rocnik") - add(vm.tr("tg_year2"), vm.tr("search_lesson"), "tg2map", extra: "rocnik") - add(vm.tr("tg_year3"), vm.tr("search_lesson"), "tg3map", extra: "rocnik") - add(vm.tr("tg_year4"), vm.tr("search_lesson"), "tg4map", extra: "rocnik") - for l in vm.content.tg { - add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "tgunit\(l.int("id"))", extra: "autocad") - add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "tgex\(l.int("id"))") - } - for l in vm.content.tg2 { - add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "tg2unit\(l.int("id"))", extra: "autocad") - add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "tg2ex\(l.int("id"))") - } - for l in vm.content.tg3 { - add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "tg3unit\(l.int("id"))", extra: "autocad") - add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "tg3ex\(l.int("id"))") - } - for l in vm.content.tg4 { - add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "tg4unit\(l.int("id"))", extra: "autocad") - add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "tg4ex\(l.int("id"))") - } - add(vm.tr("Programování"), vm.tr("search_lesson"), "csyears", extra: "csharp c#") - add(vm.tr("cs_year1"), vm.tr("search_lesson"), "csmap", extra: "rocnik") - add(vm.tr("cs_year2"), vm.tr("search_lesson"), "cs2map", extra: "rocnik") - add(vm.tr("cs_year3"), vm.tr("search_lesson"), "cs3map", extra: "rocnik") - add(vm.tr("cs_year4"), vm.tr("search_lesson"), "cs4map", extra: "rocnik") - for l in vm.content.cs { - add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "csunit\(l.int("id"))", extra: "csharp") - } - for l in vm.content.cs2 { - add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "cs2unit\(l.int("id"))", extra: "csharp") - } - for l in vm.content.cs3 { - add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "cs3unit\(l.int("id"))", extra: "csharp") - } - for l in vm.content.cs4 { - add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "cs4unit\(l.int("id"))", extra: "csharp") - } add(vm.tr("Chemie"), vm.tr("search_lesson"), "chemmap", extra: "chemie") add(vm.tr("Biologie"), vm.tr("search_lesson"), "biomap", extra: "biologie") for l in vm.content.chem { @@ -1262,7 +1058,7 @@ struct RoadmapScreen: View { vm.progress.germanDone(u.int("id"), $0 + 1) } return MapNode( - id: "unit-\(i)", + id: u.str("page"), label: u.str("title"), locked: !unlocked, done: done, @@ -1340,10 +1136,9 @@ struct UnitMapScreen: View { id: "vocab-\(unitId)", label: vm.tr("Vokabeltraining"), locked: false, - done: vm.progress.vocabDone(unitId), + done: false, current: false, - destination: .vocab(unitId), - symbol: "character.book.closed.fill" + destination: .vocab(unitId) ) ) : nil @@ -1411,9 +1206,9 @@ struct NetYearsScreen: View { ("net_year3", "net3_sub", .net3Map), ("net_year4", "net4_sub", .net4Map), ] - MacFillGrid(count: years.count, minWidth: 260, minHeight: 200) { i in + MacFillGrid(count: years.count, minWidth: 260, minHeight: 180) { i in NavigationLink(value: years[i].2) { - MacLinkCard(title: vm.tr(years[i].0), subtitle: vm.tr(years[i].1), badge: "\(i + 1).", progress: routeProgress(vm, years[i].2)) + MacLinkCard(title: vm.tr(years[i].0), subtitle: vm.tr(years[i].1), badge: "\(i + 1).") } .buttonStyle(PressScaleStyle()) } @@ -1422,16 +1217,16 @@ struct NetYearsScreen: View { #else List { NavigationLink(value: Route.netMap) { - ListRowLabel(title: vm.tr("net_year1"), subtitle: vm.tr("net_sub"), progress: routeProgress(vm, Route.netMap)) + ListRowLabel(title: vm.tr("net_year1"), subtitle: vm.tr("net_sub")) } NavigationLink(value: Route.net2Map) { - ListRowLabel(title: vm.tr("net_year2"), subtitle: vm.tr("net2_sub"), progress: routeProgress(vm, Route.net2Map)) + ListRowLabel(title: vm.tr("net_year2"), subtitle: vm.tr("net2_sub")) } NavigationLink(value: Route.net3Map) { - ListRowLabel(title: vm.tr("net_year3"), subtitle: vm.tr("net3_sub"), progress: routeProgress(vm, Route.net3Map)) + ListRowLabel(title: vm.tr("net_year3"), subtitle: vm.tr("net3_sub")) } NavigationLink(value: Route.net4Map) { - ListRowLabel(title: vm.tr("net_year4"), subtitle: vm.tr("net4_sub"), progress: routeProgress(vm, Route.net4Map)) + ListRowLabel(title: vm.tr("net_year4"), subtitle: vm.tr("net4_sub")) } } .navigationTitle(vm.tr("net_years_title")) @@ -1452,9 +1247,9 @@ struct HwYearsScreen: View { ("hw_year3", "hw3_sub", .hw3Map), ("hw_year4", "hw4_sub", .hw4Map), ] - MacFillGrid(count: years.count, minWidth: 260, minHeight: 200) { i in + MacFillGrid(count: years.count, minWidth: 260, minHeight: 180) { i in NavigationLink(value: years[i].2) { - MacLinkCard(title: vm.tr(years[i].0), subtitle: vm.tr(years[i].1), badge: "\(i + 1).", progress: routeProgress(vm, years[i].2)) + MacLinkCard(title: vm.tr(years[i].0), subtitle: vm.tr(years[i].1), badge: "\(i + 1).") } .buttonStyle(PressScaleStyle()) } @@ -1463,16 +1258,16 @@ struct HwYearsScreen: View { #else List { NavigationLink(value: Route.hwMap) { - ListRowLabel(title: vm.tr("hw_year1"), subtitle: vm.tr("hw_sub"), progress: routeProgress(vm, Route.hwMap)) + ListRowLabel(title: vm.tr("hw_year1"), subtitle: vm.tr("hw_sub")) } NavigationLink(value: Route.hw2Map) { - ListRowLabel(title: vm.tr("hw_year2"), subtitle: vm.tr("hw2_sub"), progress: routeProgress(vm, Route.hw2Map)) + ListRowLabel(title: vm.tr("hw_year2"), subtitle: vm.tr("hw2_sub")) } NavigationLink(value: Route.hw3Map) { - ListRowLabel(title: vm.tr("hw_year3"), subtitle: vm.tr("hw3_sub"), progress: routeProgress(vm, Route.hw3Map)) + ListRowLabel(title: vm.tr("hw_year3"), subtitle: vm.tr("hw3_sub")) } NavigationLink(value: Route.hw4Map) { - ListRowLabel(title: vm.tr("hw_year4"), subtitle: vm.tr("hw4_sub"), progress: routeProgress(vm, Route.hw4Map)) + ListRowLabel(title: vm.tr("hw_year4"), subtitle: vm.tr("hw4_sub")) } } .navigationTitle(vm.tr("Technické vybavení")) @@ -1494,9 +1289,9 @@ struct DeHomeScreen: View { ("3", "de_year3", "de_y3_sub", .deMap(3)), ("4", "de_year4", "de_y4_sub", .deMap(4)), ] - MacFillGrid(count: rows.count, minWidth: 260, minHeight: 200) { i in + MacFillGrid(count: rows.count, minWidth: 260, minHeight: 180) { i in NavigationLink(value: rows[i].3) { - MacLinkCard(title: vm.tr(rows[i].1), subtitle: vm.tr(rows[i].2), badge: rows[i].0, progress: routeProgress(vm, rows[i].3)) + MacLinkCard(title: vm.tr(rows[i].1), subtitle: vm.tr(rows[i].2), badge: rows[i].0) } .buttonStyle(PressScaleStyle()) } @@ -1505,11 +1300,11 @@ struct DeHomeScreen: View { #else List { NavigationLink(value: Route.roadmap) { - ListRowLabel(title: vm.tr("de_book_title"), subtitle: vm.tr("de_book_sub"), progress: routeProgress(vm, Route.roadmap)) + ListRowLabel(title: vm.tr("de_book_title"), subtitle: vm.tr("de_book_sub")) } ForEach(1...4, id: \.self) { year in NavigationLink(value: Route.deMap(year)) { - ListRowLabel(title: vm.tr("de_year\(year)"), subtitle: vm.tr("de_y\(year)_sub"), progress: routeProgress(vm, Route.deMap(year))) + ListRowLabel(title: vm.tr("de_year\(year)"), subtitle: vm.tr("de_y\(year)_sub")) } } } @@ -1530,9 +1325,9 @@ struct EnYearsScreen: View { ("en_year3", "en_y3_sub", .enMap(3)), ("en_year4", "en_y4_sub", .enMap(4)), ] - MacFillGrid(count: years.count, minWidth: 260, minHeight: 200) { i in + MacFillGrid(count: years.count, minWidth: 260, minHeight: 180) { i in NavigationLink(value: years[i].2) { - MacLinkCard(title: vm.tr(years[i].0), subtitle: vm.tr(years[i].1), badge: "\(i + 1).", progress: routeProgress(vm, years[i].2)) + MacLinkCard(title: vm.tr(years[i].0), subtitle: vm.tr(years[i].1), badge: "\(i + 1).") } .buttonStyle(PressScaleStyle()) } @@ -1542,7 +1337,7 @@ struct EnYearsScreen: View { List { ForEach(1...4, id: \.self) { year in NavigationLink(value: Route.enMap(year)) { - ListRowLabel(title: vm.tr("en_year\(year)"), subtitle: vm.tr("en_y\(year)_sub"), progress: routeProgress(vm, Route.enMap(year))) + ListRowLabel(title: vm.tr("en_year\(year)"), subtitle: vm.tr("en_y\(year)_sub")) } } } @@ -1564,9 +1359,9 @@ struct OnYearsScreen: View { ("on_year3", "on3_sub", .on3Map), ("on_year4", "on4_sub", .on4Map), ] - MacFillGrid(count: years.count, minWidth: 260, minHeight: 200) { i in + MacFillGrid(count: years.count, minWidth: 260, minHeight: 180) { i in NavigationLink(value: years[i].2) { - MacLinkCard(title: vm.tr(years[i].0), subtitle: vm.tr(years[i].1), badge: "\(i + 1).", progress: routeProgress(vm, years[i].2)) + MacLinkCard(title: vm.tr(years[i].0), subtitle: vm.tr(years[i].1), badge: "\(i + 1).") } .buttonStyle(PressScaleStyle()) } @@ -1575,16 +1370,16 @@ struct OnYearsScreen: View { #else List { NavigationLink(value: Route.onMap) { - ListRowLabel(title: vm.tr("on_year1"), subtitle: vm.tr("on_sub"), progress: routeProgress(vm, Route.onMap)) + ListRowLabel(title: vm.tr("on_year1"), subtitle: vm.tr("on_sub")) } NavigationLink(value: Route.on2Map) { - ListRowLabel(title: vm.tr("on_year2"), subtitle: vm.tr("on2_sub"), progress: routeProgress(vm, Route.on2Map)) + ListRowLabel(title: vm.tr("on_year2"), subtitle: vm.tr("on2_sub")) } NavigationLink(value: Route.on3Map) { - ListRowLabel(title: vm.tr("on_year3"), subtitle: vm.tr("on3_sub"), progress: routeProgress(vm, Route.on3Map)) + ListRowLabel(title: vm.tr("on_year3"), subtitle: vm.tr("on3_sub")) } NavigationLink(value: Route.on4Map) { - ListRowLabel(title: vm.tr("on_year4"), subtitle: vm.tr("on4_sub"), progress: routeProgress(vm, Route.on4Map)) + ListRowLabel(title: vm.tr("on_year4"), subtitle: vm.tr("on4_sub")) } } .navigationTitle(vm.tr("Občanská nauka")) @@ -1730,15 +1525,12 @@ struct SlidesScreen: View { .padding(.horizontal) .padding(.top, 8) .padding(.bottom, 4) - #if os(macOS) - .macPage(MacChrome.actionWidth) - #endif } } private func slidePage(_ slide: J) -> some View { ScrollView { - SlideBody(slide: slide) + slideStack(slide) .padding(.horizontal, slideInset) .padding(.top, 22) .padding(.bottom, 28) @@ -1754,15 +1546,6 @@ struct SlidesScreen: View { 16 #endif } -} - -/// One explanation slide: label, title, tip and numbered points. -struct SlideBody: View { - let slide: J - - var body: some View { - slideStack(slide) - } private func slideStack(_ slide: J) -> some View { VStack(alignment: .leading, spacing: 18) { @@ -1891,9 +1674,9 @@ struct LitYearsScreen: View { ("lit_year3", "lit3_sub", .lit3Map), ("lit_year4", "lit4_sub", .lit4Map), ] - MacFillGrid(count: years.count, minWidth: 260, minHeight: 200) { i in + MacFillGrid(count: years.count, minWidth: 260, minHeight: 180) { i in NavigationLink(value: years[i].2) { - MacLinkCard(title: vm.tr(years[i].0), subtitle: vm.tr(years[i].1), badge: "\(i + 1).", progress: routeProgress(vm, years[i].2)) + MacLinkCard(title: vm.tr(years[i].0), subtitle: vm.tr(years[i].1), badge: "\(i + 1).") } .buttonStyle(PressScaleStyle()) } @@ -1902,16 +1685,16 @@ struct LitYearsScreen: View { #else List { NavigationLink(value: Route.litMap) { - ListRowLabel(title: vm.tr("lit_year1"), subtitle: vm.tr("lit_sub"), progress: routeProgress(vm, Route.litMap)) + ListRowLabel(title: vm.tr("lit_year1"), subtitle: vm.tr("lit_sub")) } NavigationLink(value: Route.lit2Map) { - ListRowLabel(title: vm.tr("lit_year2"), subtitle: vm.tr("lit2_sub"), progress: routeProgress(vm, Route.lit2Map)) + ListRowLabel(title: vm.tr("lit_year2"), subtitle: vm.tr("lit2_sub")) } NavigationLink(value: Route.lit3Map) { - ListRowLabel(title: vm.tr("lit_year3"), subtitle: vm.tr("lit3_sub"), progress: routeProgress(vm, Route.lit3Map)) + ListRowLabel(title: vm.tr("lit_year3"), subtitle: vm.tr("lit3_sub")) } NavigationLink(value: Route.lit4Map) { - ListRowLabel(title: vm.tr("lit_year4"), subtitle: vm.tr("lit4_sub"), progress: routeProgress(vm, Route.lit4Map)) + ListRowLabel(title: vm.tr("lit_year4"), subtitle: vm.tr("lit4_sub")) } } .navigationTitle(vm.tr("Literatura")) @@ -1933,9 +1716,9 @@ struct MatYearsScreen: View { ("mat_year3", "mat3_sub", .mat3Map, "3."), ("mat_year4", "mat4_sub", .mat4Map, "4."), ] - MacFillGrid(count: years.count, minWidth: 260, minHeight: 200) { i in + MacFillGrid(count: years.count, minWidth: 260, minHeight: 180) { i in NavigationLink(value: years[i].2) { - MacLinkCard(title: vm.tr(years[i].0), subtitle: vm.tr(years[i].1), badge: years[i].3, progress: routeProgress(vm, years[i].2)) + MacLinkCard(title: vm.tr(years[i].0), subtitle: vm.tr(years[i].1), badge: years[i].3) } .buttonStyle(PressScaleStyle()) } @@ -1944,19 +1727,19 @@ struct MatYearsScreen: View { #else List { NavigationLink(value: Route.mat0Map) { - ListRowLabel(title: vm.tr("mat0_year"), subtitle: vm.tr("mat0_sub"), progress: routeProgress(vm, Route.mat0Map)) + ListRowLabel(title: vm.tr("mat0_year"), subtitle: vm.tr("mat0_sub")) } NavigationLink(value: Route.matMap) { - ListRowLabel(title: vm.tr("mat_year1"), subtitle: vm.tr("mat_sub"), progress: routeProgress(vm, Route.matMap)) + ListRowLabel(title: vm.tr("mat_year1"), subtitle: vm.tr("mat_sub")) } NavigationLink(value: Route.mat2Map) { - ListRowLabel(title: vm.tr("mat_year2"), subtitle: vm.tr("mat2_sub"), progress: routeProgress(vm, Route.mat2Map)) + ListRowLabel(title: vm.tr("mat_year2"), subtitle: vm.tr("mat2_sub")) } NavigationLink(value: Route.mat3Map) { - ListRowLabel(title: vm.tr("mat_year3"), subtitle: vm.tr("mat3_sub"), progress: routeProgress(vm, Route.mat3Map)) + ListRowLabel(title: vm.tr("mat_year3"), subtitle: vm.tr("mat3_sub")) } NavigationLink(value: Route.mat4Map) { - ListRowLabel(title: vm.tr("mat_year4"), subtitle: vm.tr("mat4_sub"), progress: routeProgress(vm, Route.mat4Map)) + ListRowLabel(title: vm.tr("mat_year4"), subtitle: vm.tr("mat4_sub")) } } .navigationTitle(vm.tr("Matematika")) @@ -1966,170 +1749,6 @@ struct MatYearsScreen: View { } } -struct CsYearsScreen: View { - @ObservedObject var vm: AppModel - - var body: some View { - #if os(macOS) - let years: [(String, String, Route)] = [ - ("cs_year1", "cs_sub", .csMap), - ("cs_year2", "cs2_sub", .cs2Map), - ("cs_year3", "cs3_sub", .cs3Map), - ("cs_year4", "cs4_sub", .cs4Map), - ] - MacFillGrid(count: years.count, minWidth: 260, minHeight: 200) { i in - NavigationLink(value: years[i].2) { - MacLinkCard(title: vm.tr(years[i].0), subtitle: vm.tr(years[i].1), badge: "\(i + 1).", progress: routeProgress(vm, years[i].2)) - } - .buttonStyle(PressScaleStyle()) - } - .navigationTitle(vm.tr("Programování")) - .navigationSubtitle(vm.tr("cs_years_sub")) - #else - List { - NavigationLink(value: Route.csMap) { - ListRowLabel(title: vm.tr("cs_year1"), subtitle: vm.tr("cs_sub"), progress: routeProgress(vm, Route.csMap)) - } - NavigationLink(value: Route.cs2Map) { - ListRowLabel(title: vm.tr("cs_year2"), subtitle: vm.tr("cs2_sub"), progress: routeProgress(vm, Route.cs2Map)) - } - NavigationLink(value: Route.cs3Map) { - ListRowLabel(title: vm.tr("cs_year3"), subtitle: vm.tr("cs3_sub"), progress: routeProgress(vm, Route.cs3Map)) - } - NavigationLink(value: Route.cs4Map) { - ListRowLabel(title: vm.tr("cs_year4"), subtitle: vm.tr("cs4_sub"), progress: routeProgress(vm, Route.cs4Map)) - } - } - .navigationTitle(vm.tr("Programování")) - .navigationSubtitle(vm.tr("cs_years_sub")) - .appListStyle() - #endif - } -} - -struct SwYearsScreen: View { - @ObservedObject var vm: AppModel - - var body: some View { - #if os(macOS) - let years: [(String, String, Route)] = [ - ("sw_year1", "sw_sub", .swMap), - ("sw_year2", "sw2_sub", .sw2Map), - ("sw_year3", "sw3_sub", .sw3Map), - ("sw_year4", "sw4_sub", .sw4Map), - ] - MacFillGrid(count: years.count, minWidth: 260, minHeight: 200) { i in - NavigationLink(value: years[i].2) { - MacLinkCard(title: vm.tr(years[i].0), subtitle: vm.tr(years[i].1), badge: "\(i + 1).", progress: routeProgress(vm, years[i].2)) - } - .buttonStyle(PressScaleStyle()) - } - .navigationTitle(vm.tr("Programové vybavení")) - .navigationSubtitle(vm.tr("sw_years_sub")) - #else - List { - NavigationLink(value: Route.swMap) { - ListRowLabel(title: vm.tr("sw_year1"), subtitle: vm.tr("sw_sub"), progress: routeProgress(vm, Route.swMap)) - } - NavigationLink(value: Route.sw2Map) { - ListRowLabel(title: vm.tr("sw_year2"), subtitle: vm.tr("sw2_sub"), progress: routeProgress(vm, Route.sw2Map)) - } - NavigationLink(value: Route.sw3Map) { - ListRowLabel(title: vm.tr("sw_year3"), subtitle: vm.tr("sw3_sub"), progress: routeProgress(vm, Route.sw3Map)) - } - NavigationLink(value: Route.sw4Map) { - ListRowLabel(title: vm.tr("sw_year4"), subtitle: vm.tr("sw4_sub"), progress: routeProgress(vm, Route.sw4Map)) - } - } - .navigationTitle(vm.tr("Programové vybavení")) - .navigationSubtitle(vm.tr("sw_years_sub")) - .appListStyle() - #endif - } -} - -struct PgYearsScreen: View { - @ObservedObject var vm: AppModel - - var body: some View { - #if os(macOS) - let years: [(String, String, Route)] = [ - ("pg_year1", "pg_sub", .pgMap), - ("pg_year2", "pg2_sub", .pg2Map), - ("pg_year3", "pg3_sub", .pg3Map), - ("pg_year4", "pg4_sub", .pg4Map), - ] - MacFillGrid(count: years.count, minWidth: 260, minHeight: 200) { i in - NavigationLink(value: years[i].2) { - MacLinkCard(title: vm.tr(years[i].0), subtitle: vm.tr(years[i].1), badge: "\(i + 1).", progress: routeProgress(vm, years[i].2)) - } - .buttonStyle(PressScaleStyle()) - } - .navigationTitle(vm.tr("Prezentační grafika")) - .navigationSubtitle(vm.tr("pg_years_sub")) - #else - List { - NavigationLink(value: Route.pgMap) { - ListRowLabel(title: vm.tr("pg_year1"), subtitle: vm.tr("pg_sub"), progress: routeProgress(vm, Route.pgMap)) - } - NavigationLink(value: Route.pg2Map) { - ListRowLabel(title: vm.tr("pg_year2"), subtitle: vm.tr("pg2_sub"), progress: routeProgress(vm, Route.pg2Map)) - } - NavigationLink(value: Route.pg3Map) { - ListRowLabel(title: vm.tr("pg_year3"), subtitle: vm.tr("pg3_sub"), progress: routeProgress(vm, Route.pg3Map)) - } - NavigationLink(value: Route.pg4Map) { - ListRowLabel(title: vm.tr("pg_year4"), subtitle: vm.tr("pg4_sub"), progress: routeProgress(vm, Route.pg4Map)) - } - } - .navigationTitle(vm.tr("Prezentační grafika")) - .navigationSubtitle(vm.tr("pg_years_sub")) - .appListStyle() - #endif - } -} - -struct TgYearsScreen: View { - @ObservedObject var vm: AppModel - - var body: some View { - #if os(macOS) - let years: [(String, String, Route)] = [ - ("tg_year1", "tg_sub", .tgMap), - ("tg_year2", "tg2_sub", .tg2Map), - ("tg_year3", "tg3_sub", .tg3Map), - ("tg_year4", "tg4_sub", .tg4Map), - ] - MacFillGrid(count: years.count, minWidth: 260, minHeight: 200) { i in - NavigationLink(value: years[i].2) { - MacLinkCard(title: vm.tr(years[i].0), subtitle: vm.tr(years[i].1), badge: "\(i + 1).", progress: routeProgress(vm, years[i].2)) - } - .buttonStyle(PressScaleStyle()) - } - .navigationTitle(vm.tr("Technická grafika")) - .navigationSubtitle(vm.tr("tg_years_sub")) - #else - List { - NavigationLink(value: Route.tgMap) { - ListRowLabel(title: vm.tr("tg_year1"), subtitle: vm.tr("tg_sub"), progress: routeProgress(vm, Route.tgMap)) - } - NavigationLink(value: Route.tg2Map) { - ListRowLabel(title: vm.tr("tg_year2"), subtitle: vm.tr("tg2_sub"), progress: routeProgress(vm, Route.tg2Map)) - } - NavigationLink(value: Route.tg3Map) { - ListRowLabel(title: vm.tr("tg_year3"), subtitle: vm.tr("tg3_sub"), progress: routeProgress(vm, Route.tg3Map)) - } - NavigationLink(value: Route.tg4Map) { - ListRowLabel(title: vm.tr("tg_year4"), subtitle: vm.tr("tg4_sub"), progress: routeProgress(vm, Route.tg4Map)) - } - } - .navigationTitle(vm.tr("Technická grafika")) - .navigationSubtitle(vm.tr("tg_years_sub")) - .appListStyle() - #endif - } -} - struct FyzYearsScreen: View { @ObservedObject var vm: AppModel @@ -2141,9 +1760,9 @@ struct FyzYearsScreen: View { ("fyz_year3", "fyz3_sub", .fyz3Map), ("fyz_year4", "fyz4_sub", .fyz4Map), ] - MacFillGrid(count: years.count, minWidth: 260, minHeight: 200) { i in + MacFillGrid(count: years.count, minWidth: 260, minHeight: 180) { i in NavigationLink(value: years[i].2) { - MacLinkCard(title: vm.tr(years[i].0), subtitle: vm.tr(years[i].1), badge: "\(i + 1).", progress: routeProgress(vm, years[i].2)) + MacLinkCard(title: vm.tr(years[i].0), subtitle: vm.tr(years[i].1), badge: "\(i + 1).") } .buttonStyle(PressScaleStyle()) } @@ -2152,16 +1771,16 @@ struct FyzYearsScreen: View { #else List { NavigationLink(value: Route.fyzMap) { - ListRowLabel(title: vm.tr("fyz_year1"), subtitle: vm.tr("fyz_sub"), progress: routeProgress(vm, Route.fyzMap)) + ListRowLabel(title: vm.tr("fyz_year1"), subtitle: vm.tr("fyz_sub")) } NavigationLink(value: Route.fyz2Map) { - ListRowLabel(title: vm.tr("fyz_year2"), subtitle: vm.tr("fyz2_sub"), progress: routeProgress(vm, Route.fyz2Map)) + ListRowLabel(title: vm.tr("fyz_year2"), subtitle: vm.tr("fyz2_sub")) } NavigationLink(value: Route.fyz3Map) { - ListRowLabel(title: vm.tr("fyz_year3"), subtitle: vm.tr("fyz3_sub"), progress: routeProgress(vm, Route.fyz3Map)) + ListRowLabel(title: vm.tr("fyz_year3"), subtitle: vm.tr("fyz3_sub")) } NavigationLink(value: Route.fyz4Map) { - ListRowLabel(title: vm.tr("fyz_year4"), subtitle: vm.tr("fyz4_sub"), progress: routeProgress(vm, Route.fyz4Map)) + ListRowLabel(title: vm.tr("fyz_year4"), subtitle: vm.tr("fyz4_sub")) } } .navigationTitle(vm.tr("Fyzika")) @@ -2176,15 +1795,15 @@ struct SciMapScreen: View { var body: some View { #if os(macOS) - MacFillGrid(count: 2, minWidth: 260, minHeight: 200) { i in + MacFillGrid(count: 2, minWidth: 260, minHeight: 180) { i in if i == 0 { NavigationLink(value: Route.chemMap) { - MacLinkCard(title: vm.tr("Chemie"), subtitle: vm.tr("chem_sub"), systemImage: "flask.fill", progress: routeProgress(vm, .chemMap)) + MacLinkCard(title: vm.tr("Chemie"), subtitle: vm.tr("chem_sub"), systemImage: "flask.fill") } .buttonStyle(PressScaleStyle()) } else { NavigationLink(value: Route.bioMap) { - MacLinkCard(title: vm.tr("Biologie"), subtitle: vm.tr("bio_sub"), systemImage: "leaf.fill", progress: routeProgress(vm, .bioMap)) + MacLinkCard(title: vm.tr("Biologie"), subtitle: vm.tr("bio_sub"), systemImage: "leaf.fill") } .buttonStyle(PressScaleStyle()) } @@ -2195,14 +1814,14 @@ struct SciMapScreen: View { List { NavigationLink(value: Route.chemMap) { Label { - ListRowLabel(title: vm.tr("Chemie"), subtitle: vm.tr("chem_sub"), progress: routeProgress(vm, .chemMap)) + ListRowLabel(title: vm.tr("Chemie"), subtitle: vm.tr("chem_sub")) } icon: { Image(systemName: "flask.fill") } } NavigationLink(value: Route.bioMap) { Label { - ListRowLabel(title: vm.tr("Biologie"), subtitle: vm.tr("bio_sub"), progress: routeProgress(vm, .bioMap)) + ListRowLabel(title: vm.tr("Biologie"), subtitle: vm.tr("bio_sub")) } icon: { Image(systemName: "leaf.fill") } @@ -2220,21 +1839,21 @@ struct CzechMapScreen: View { var body: some View { #if os(macOS) - MacFillGrid(count: 3, minWidth: 260, minHeight: 200) { i in + MacFillGrid(count: 3, minWidth: 260, minHeight: 180) { i in switch i { case 1: NavigationLink(value: Route.mluvnice) { - MacLinkCard(title: vm.tr("Mluvnice"), subtitle: vm.tr("mluv_sub"), systemImage: "textformat", progress: routeProgress(vm, .mluvnice)) + MacLinkCard(title: vm.tr("Mluvnice"), systemImage: "textformat") } .buttonStyle(PressScaleStyle()) case 2: NavigationLink(value: Route.readingList) { - MacLinkCard(title: vm.tr("Maturitní četba"), subtitle: vm.tr("reading_sub"), systemImage: "books.vertical") + MacLinkCard(title: vm.tr("Maturitní četba"), systemImage: "books.vertical") } .buttonStyle(PressScaleStyle()) default: NavigationLink(value: Route.litYears) { - MacLinkCard(title: vm.tr("Literatura"), subtitle: vm.tr("lit_years_sub"), systemImage: "book.closed", progress: routeProgress(vm, .litYears)) + MacLinkCard(title: vm.tr("Literatura"), systemImage: "book.closed") } .buttonStyle(PressScaleStyle()) } @@ -2245,21 +1864,21 @@ struct CzechMapScreen: View { List { NavigationLink(value: Route.litYears) { Label { - ListRowLabel(title: vm.tr("Literatura"), subtitle: vm.tr("lit_years_sub"), progress: routeProgress(vm, .litYears)) + Text(vm.tr("Literatura")) } icon: { Image(systemName: "book.closed") } } NavigationLink(value: Route.mluvnice) { Label { - ListRowLabel(title: vm.tr("Mluvnice"), subtitle: vm.tr("mluv_sub"), progress: routeProgress(vm, .mluvnice)) + Text(vm.tr("Mluvnice")) } icon: { Image(systemName: "textformat") } } NavigationLink(value: Route.readingList) { Label { - ListRowLabel(title: vm.tr("Maturitní četba"), subtitle: vm.tr("reading_sub")) + Text(vm.tr("Maturitní četba")) } icon: { Image(systemName: "books.vertical") } @@ -3189,262 +2808,6 @@ struct RouteDestination: View { } case .fyz4Ex(let id): FyzQuizScreen(vm: vm, year: 4, id: id) - case .csYears: - CsYearsScreen(vm: vm) - case .csMap: - LessonListScreen( - vm: vm, - title: vm.tr("cs_year1"), - subtitle: vm.tr("cs_sub"), - rows: vm.content.cs.map { l in - let id = l.int("id") - return LessonRow(id: "c\(id)", title: vm.tr(l.str("titleKey")), done: vm.progress.csDone(id), destination: .csLesson(id)) - } - ) - case .csLesson(let id): - if let l = vm.content.csLesson(id) { - CodeLessonScreen(vm: vm, lesson: l, onSuccess: { vm.markCs(id) }) - } - case .cs2Map: - LessonListScreen( - vm: vm, - title: vm.tr("cs_year2"), - subtitle: vm.tr("cs2_sub"), - rows: vm.content.cs2.map { l in - let id = l.int("id") - return LessonRow(id: "c2\(id)", title: vm.tr(l.str("titleKey")), done: vm.progress.cs2Done(id), destination: .cs2Lesson(id)) - } - ) - case .cs2Lesson(let id): - if let l = vm.content.cs2Lesson(id) { - CodeLessonScreen(vm: vm, lesson: l, onSuccess: { vm.markCs2(id) }) - } - case .cs3Map: - LessonListScreen( - vm: vm, - title: vm.tr("cs_year3"), - subtitle: vm.tr("cs3_sub"), - rows: vm.content.cs3.map { l in - let id = l.int("id") - return LessonRow(id: "c3\(id)", title: vm.tr(l.str("titleKey")), done: vm.progress.cs3Done(id), destination: .cs3Lesson(id)) - } - ) - case .cs3Lesson(let id): - if let l = vm.content.cs3Lesson(id) { - CodeLessonScreen(vm: vm, lesson: l, onSuccess: { vm.markCs3(id) }) - } - case .cs4Map: - LessonListScreen( - vm: vm, - title: vm.tr("cs_year4"), - subtitle: vm.tr("cs4_sub"), - rows: vm.content.cs4.map { l in - let id = l.int("id") - return LessonRow(id: "c4\(id)", title: vm.tr(l.str("titleKey")), done: vm.progress.cs4Done(id), destination: .cs4Lesson(id)) - } - ) - case .cs4Lesson(let id): - if let l = vm.content.cs4Lesson(id) { - CodeLessonScreen(vm: vm, lesson: l, onSuccess: { vm.markCs4(id) }) - } - case .swYears: - SwYearsScreen(vm: vm) - case .swMap: - LessonListScreen( - vm: vm, - title: vm.tr("sw_year1"), - subtitle: vm.tr("sw_sub"), - rows: vm.content.sw.map { l in - let id = l.int("id") - return LessonRow(id: "s\(id)", title: vm.tr(l.str("titleKey")), done: vm.progress.swDone(id), destination: .swLesson(id)) - } - ) - case .swLesson(let id): - if let l = vm.content.swLesson(id) { - SlidesScreen(vm: vm, title: vm.tr(l.str("titleKey")), subtitle: vm.tr(l.str("subKey")), slides: l.arr("slides"), next: .swEx(id)) - } - case .swEx(let id): - SwQuizScreen(vm: vm, year: 1, id: id) - case .sw2Map: - LessonListScreen( - vm: vm, - title: vm.tr("sw_year2"), - subtitle: vm.tr("sw2_sub"), - rows: vm.content.sw2.map { l in - let id = l.int("id") - return LessonRow(id: "s2\(id)", title: vm.tr(l.str("titleKey")), done: vm.progress.sw2Done(id), destination: .sw2Lesson(id)) - } - ) - case .sw2Lesson(let id): - if let l = vm.content.sw2Lesson(id) { - SlidesScreen(vm: vm, title: vm.tr(l.str("titleKey")), subtitle: vm.tr(l.str("subKey")), slides: l.arr("slides"), next: .sw2Ex(id)) - } - case .sw2Ex(let id): - SwQuizScreen(vm: vm, year: 2, id: id) - case .sw3Map: - LessonListScreen( - vm: vm, - title: vm.tr("sw_year3"), - subtitle: vm.tr("sw3_sub"), - rows: vm.content.sw3.map { l in - let id = l.int("id") - return LessonRow(id: "s3\(id)", title: vm.tr(l.str("titleKey")), done: vm.progress.sw3Done(id), destination: .sw3Lesson(id)) - } - ) - case .sw3Lesson(let id): - if let l = vm.content.sw3Lesson(id) { - SlidesScreen(vm: vm, title: vm.tr(l.str("titleKey")), subtitle: vm.tr(l.str("subKey")), slides: l.arr("slides"), next: .sw3Ex(id)) - } - case .sw3Ex(let id): - SwQuizScreen(vm: vm, year: 3, id: id) - case .sw4Map: - LessonListScreen( - vm: vm, - title: vm.tr("sw_year4"), - subtitle: vm.tr("sw4_sub"), - rows: vm.content.sw4.map { l in - let id = l.int("id") - return LessonRow(id: "s4\(id)", title: vm.tr(l.str("titleKey")), done: vm.progress.sw4Done(id), destination: .sw4Lesson(id)) - } - ) - case .sw4Lesson(let id): - if let l = vm.content.sw4Lesson(id) { - SlidesScreen(vm: vm, title: vm.tr(l.str("titleKey")), subtitle: vm.tr(l.str("subKey")), slides: l.arr("slides"), next: .sw4Ex(id)) - } - case .sw4Ex(let id): - SwQuizScreen(vm: vm, year: 4, id: id) - case .pgYears: - PgYearsScreen(vm: vm) - case .pgMap: - LessonListScreen( - vm: vm, - title: vm.tr("pg_year1"), - subtitle: vm.tr("pg_sub"), - rows: vm.content.pg.map { l in - let id = l.int("id") - return LessonRow(id: "p\(id)", title: vm.tr(l.str("titleKey")), done: vm.progress.pgDone(id), destination: .pgLesson(id)) - } - ) - case .pgLesson(let id): - if let l = vm.content.pgLesson(id) { - SlidesScreen(vm: vm, title: vm.tr(l.str("titleKey")), subtitle: vm.tr(l.str("subKey")), slides: l.arr("slides"), next: .pgEx(id)) - } - case .pgEx(let id): - PgQuizScreen(vm: vm, year: 1, id: id) - case .pg2Map: - LessonListScreen( - vm: vm, - title: vm.tr("pg_year2"), - subtitle: vm.tr("pg2_sub"), - rows: vm.content.pg2.map { l in - let id = l.int("id") - return LessonRow(id: "p2\(id)", title: vm.tr(l.str("titleKey")), done: vm.progress.pg2Done(id), destination: .pg2Lesson(id)) - } - ) - case .pg2Lesson(let id): - if let l = vm.content.pg2Lesson(id) { - SlidesScreen(vm: vm, title: vm.tr(l.str("titleKey")), subtitle: vm.tr(l.str("subKey")), slides: l.arr("slides"), next: .pg2Ex(id)) - } - case .pg2Ex(let id): - PgQuizScreen(vm: vm, year: 2, id: id) - case .pg3Map: - LessonListScreen( - vm: vm, - title: vm.tr("pg_year3"), - subtitle: vm.tr("pg3_sub"), - rows: vm.content.pg3.map { l in - let id = l.int("id") - return LessonRow(id: "p3\(id)", title: vm.tr(l.str("titleKey")), done: vm.progress.pg3Done(id), destination: .pg3Lesson(id)) - } - ) - case .pg3Lesson(let id): - if let l = vm.content.pg3Lesson(id) { - SlidesScreen(vm: vm, title: vm.tr(l.str("titleKey")), subtitle: vm.tr(l.str("subKey")), slides: l.arr("slides"), next: .pg3Ex(id)) - } - case .pg3Ex(let id): - PgQuizScreen(vm: vm, year: 3, id: id) - case .pg4Map: - LessonListScreen( - vm: vm, - title: vm.tr("pg_year4"), - subtitle: vm.tr("pg4_sub"), - rows: vm.content.pg4.map { l in - let id = l.int("id") - return LessonRow(id: "p4\(id)", title: vm.tr(l.str("titleKey")), done: vm.progress.pg4Done(id), destination: .pg4Lesson(id)) - } - ) - case .pg4Lesson(let id): - if let l = vm.content.pg4Lesson(id) { - SlidesScreen(vm: vm, title: vm.tr(l.str("titleKey")), subtitle: vm.tr(l.str("subKey")), slides: l.arr("slides"), next: .pg4Ex(id)) - } - case .pg4Ex(let id): - PgQuizScreen(vm: vm, year: 4, id: id) - case .tgYears: - TgYearsScreen(vm: vm) - case .tgMap: - LessonListScreen( - vm: vm, - title: vm.tr("tg_year1"), - subtitle: vm.tr("tg_sub"), - rows: vm.content.tg.map { l in - let id = l.int("id") - return LessonRow(id: "t\(id)", title: vm.tr(l.str("titleKey")), done: vm.progress.tgDone(id), destination: .tgLesson(id)) - } - ) - case .tgLesson(let id): - if let l = vm.content.tgLesson(id) { - SlidesScreen(vm: vm, title: vm.tr(l.str("titleKey")), subtitle: vm.tr(l.str("subKey")), slides: l.arr("slides"), next: .tgEx(id)) - } - case .tgEx(let id): - TgQuizScreen(vm: vm, year: 1, id: id) - case .tg2Map: - LessonListScreen( - vm: vm, - title: vm.tr("tg_year2"), - subtitle: vm.tr("tg2_sub"), - rows: vm.content.tg2.map { l in - let id = l.int("id") - return LessonRow(id: "t2\(id)", title: vm.tr(l.str("titleKey")), done: vm.progress.tg2Done(id), destination: .tg2Lesson(id)) - } - ) - case .tg2Lesson(let id): - if let l = vm.content.tg2Lesson(id) { - SlidesScreen(vm: vm, title: vm.tr(l.str("titleKey")), subtitle: vm.tr(l.str("subKey")), slides: l.arr("slides"), next: .tg2Ex(id)) - } - case .tg2Ex(let id): - TgQuizScreen(vm: vm, year: 2, id: id) - case .tg3Map: - LessonListScreen( - vm: vm, - title: vm.tr("tg_year3"), - subtitle: vm.tr("tg3_sub"), - rows: vm.content.tg3.map { l in - let id = l.int("id") - return LessonRow(id: "t3\(id)", title: vm.tr(l.str("titleKey")), done: vm.progress.tg3Done(id), destination: .tg3Lesson(id)) - } - ) - case .tg3Lesson(let id): - if let l = vm.content.tg3Lesson(id) { - SlidesScreen(vm: vm, title: vm.tr(l.str("titleKey")), subtitle: vm.tr(l.str("subKey")), slides: l.arr("slides"), next: .tg3Ex(id)) - } - case .tg3Ex(let id): - TgQuizScreen(vm: vm, year: 3, id: id) - case .tg4Map: - LessonListScreen( - vm: vm, - title: vm.tr("tg_year4"), - subtitle: vm.tr("tg4_sub"), - rows: vm.content.tg4.map { l in - let id = l.int("id") - return LessonRow(id: "t4\(id)", title: vm.tr(l.str("titleKey")), done: vm.progress.tg4Done(id), destination: .tg4Lesson(id)) - } - ) - case .tg4Lesson(let id): - if let l = vm.content.tg4Lesson(id) { - SlidesScreen(vm: vm, title: vm.tr(l.str("titleKey")), subtitle: vm.tr(l.str("subKey")), slides: l.arr("slides"), next: .tg4Ex(id)) - } - case .tg4Ex(let id): - TgQuizScreen(vm: vm, year: 4, id: id) case .mluvnice: LessonListScreen( vm: vm, @@ -3473,446 +2836,3 @@ struct RouteDestination: View { } } } - -struct CodeLessonScreen: View { - @ObservedObject var vm: AppModel - let lesson: J - let onSuccess: () -> Void - @State private var code = "" - @State private var stdin = "" - @State private var output = "" - @State private var status = "" - - private var running: Bool { status == "running" } - private var needsInput: Bool { code.contains("ReadLine") } - - var body: some View { - GeometryReader { geo in - if geo.size.width >= 900 { - HStack(alignment: .top, spacing: 28) { - ScrollView { - explanation - .padding(.vertical, 4) - } - .frame(width: min(560, geo.size.width * 0.4)) - workspace(height: geo.size.height) - } - .padding(.horizontal, 28) - .padding(.vertical, 20) - .frame(maxWidth: 1640) - .frame(maxWidth: .infinity, maxHeight: .infinity) - } else { - ScrollView { - VStack(alignment: .leading, spacing: 20) { - explanation - editorCard.frame(height: 320) - if needsInput { inputField } - outputCard.frame(height: 220) - } - .padding(16) - } - } - } - .detailScreen(vm.tr(lesson.str("titleKey")), subtitle: vm.tr(lesson.str("subKey"))) - .onAppear { - if code.isEmpty { code = lesson.str("code") } - } - } - - private var explanation: some View { - VStack(alignment: .leading, spacing: 34) { - ForEach(Array(lesson.arr("slides").enumerated()), id: \.offset) { _, slide in - SlideBody(slide: slide) - } - } - } - - private func workspace(height: CGFloat) -> some View { - VStack(spacing: 16) { - editorCard - .frame(maxHeight: .infinity) - if needsInput { inputField } - outputCard - .frame(height: max(180, height * 0.32)) - } - .frame(maxWidth: .infinity, maxHeight: .infinity) - } - - private var editorCard: some View { - VStack(spacing: 0) { - HStack(spacing: 10) { - Image(systemName: "chevron.left.forwardslash.chevron.right") - .foregroundStyle(Color.accentColor) - Text("Program.cs") - .font(.headline.monospaced()) - Spacer(minLength: 8) - Button { - code = lesson.str("code") - output = "" - status = "" - } label: { - Label(vm.tr("cs_reset"), systemImage: "arrow.counterclockwise") - } - .buttonStyle(.bordered) - .disabled(running) - Button { run() } label: { - Label(vm.tr("cs_run"), systemImage: "play.fill") - .padding(.horizontal, 4) - } - .buttonStyle(.borderedProminent) - .keyboardShortcut(.return, modifiers: .command) - .help("⌘↩") - .disabled(running) - } - #if os(macOS) - .controlSize(.large) - #endif - .padding(.horizontal, 14) - .padding(.vertical, 10) - Divider().opacity(0.5) - editorField - .frame(maxWidth: .infinity, maxHeight: .infinity) - } - .background(codeFill, in: RoundedRectangle(cornerRadius: 16, style: .continuous)) - .overlay { - RoundedRectangle(cornerRadius: 16, style: .continuous) - .strokeBorder(.separator.opacity(0.6), lineWidth: 0.5) - } - } - - @ViewBuilder - private var editorField: some View { - #if os(macOS) - CodeEditor(text: $code) - #else - TextEditor(text: $code) - .font(.system(size: 15, design: .monospaced)) - .textInputAutocapitalization(.never) - .autocorrectionDisabled() - .scrollContentBackground(.hidden) - .padding(8) - #endif - } - - private var inputField: some View { - VStack(alignment: .leading, spacing: 6) { - Label(vm.tr("cs_stdin"), systemImage: "keyboard") - .font(.subheadline) - .foregroundStyle(.secondary) - TextField("", text: $stdin, axis: .vertical) - .font(.system(size: 15, design: .monospaced)) - .lineLimit(1...4) - .textFieldStyle(.roundedBorder) - } - } - - private var outputCard: some View { - VStack(spacing: 0) { - HStack(spacing: 10) { - Image(systemName: "terminal") - .foregroundStyle(.secondary) - Text(vm.tr("cs_output")) - .font(.headline) - Spacer(minLength: 8) - statusBadge - } - .padding(.horizontal, 14) - .frame(height: 44) - Divider().opacity(0.5) - ScrollView { - Text(output.isEmpty ? vm.tr("cs_empty") : output) - .font(.system(size: 15, design: .monospaced)) - .foregroundStyle(output.isEmpty || running ? .secondary : .primary) - .frame(maxWidth: .infinity, alignment: .topLeading) - .textSelection(.enabled) - .padding(14) - } - } - .background(codeFill, in: RoundedRectangle(cornerRadius: 16, style: .continuous)) - .overlay { - RoundedRectangle(cornerRadius: 16, style: .continuous) - .strokeBorder(.separator.opacity(0.6), lineWidth: 0.5) - } - } - - @ViewBuilder - private var statusBadge: some View { - switch status { - case "running": - ProgressView().controlSize(.small) - case "ok": - Label(vm.tr("cs_done"), systemImage: "checkmark.circle.fill") - .font(.subheadline.weight(.semibold)) - .foregroundStyle(vm.palette.success) - case "fail", "timeout": - Label(vm.tr("cs_failed"), systemImage: "xmark.octagon.fill") - .font(.subheadline.weight(.semibold)) - .foregroundStyle(vm.palette.error) - default: - EmptyView() - } - } - - private var codeFill: AnyShapeStyle { - #if os(macOS) - AnyShapeStyle(.background.secondary) - #else - AnyShapeStyle(Color(.secondarySystemBackground)) - #endif - } - - private func run() { - guard !running else { return } - status = "running" - output = vm.tr("cs_running") - CSharpRunner.run(code, stdin: needsInput ? stdin : "") { result, text in - status = result - switch result { - case "unavailable": - output = vm.tr("cs_unavailable") - case "timeout": - output = (text + "\n\n" + vm.tr("cs_timeout")).trimmingCharacters(in: .whitespacesAndNewlines) - default: - output = text.isEmpty ? vm.tr("cs_empty") : text - } - if result == "ok" { onSuccess() } - } - } -} - -#if os(macOS) -/// Plain-text editor for C#: monospaced, coloured, and without smart quotes or -/// autocorrect, which would turn "text" into “text” and break the program. -struct CodeEditor: NSViewRepresentable { - @Binding var text: String - - func makeCoordinator() -> Coordinator { Coordinator(text: $text) } - - func makeNSView(context: Context) -> NSScrollView { - let scroll = NSTextView.scrollableTextView() - scroll.drawsBackground = false - scroll.autohidesScrollers = true - guard let view = scroll.documentView as? NSTextView else { return scroll } - view.delegate = context.coordinator - view.isRichText = false - view.allowsUndo = true - view.isAutomaticQuoteSubstitutionEnabled = false - view.isAutomaticDashSubstitutionEnabled = false - view.isAutomaticTextReplacementEnabled = false - view.isAutomaticSpellingCorrectionEnabled = false - view.isContinuousSpellCheckingEnabled = false - view.isGrammarCheckingEnabled = false - view.isAutomaticLinkDetectionEnabled = false - view.smartInsertDeleteEnabled = false - view.drawsBackground = false - view.font = CSharpStyle.font - view.textContainerInset = NSSize(width: 10, height: 12) - view.typingAttributes = CSharpStyle.base - view.string = text - CSharpStyle.highlight(view.textStorage) - return scroll - } - - func updateNSView(_ scroll: NSScrollView, context: Context) { - context.coordinator.text = $text - guard let view = scroll.documentView as? NSTextView, view.string != text else { return } - view.string = text - CSharpStyle.highlight(view.textStorage) - } - - final class Coordinator: NSObject, NSTextViewDelegate { - var text: Binding - - init(text: Binding) { - self.text = text - } - - func textDidChange(_ notification: Notification) { - guard let view = notification.object as? NSTextView else { return } - text.wrappedValue = view.string - CSharpStyle.highlight(view.textStorage) - view.typingAttributes = CSharpStyle.base - } - } -} - -enum CSharpStyle { - static let font = NSFont.monospacedSystemFont(ofSize: 15, weight: .regular) - static var base: [NSAttributedString.Key: Any] { [.font: font, .foregroundColor: NSColor.labelColor] } - - private static func adaptive(_ light: Int, _ dark: Int) -> NSColor { - func color(_ hex: Int) -> NSColor { - NSColor( - srgbRed: CGFloat((hex >> 16) & 0xFF) / 255, - green: CGFloat((hex >> 8) & 0xFF) / 255, - blue: CGFloat(hex & 0xFF) / 255, - alpha: 1 - ) - } - return NSColor(name: nil) { appearance in - appearance.bestMatch(from: [.aqua, .darkAqua]) == .darkAqua ? color(dark) : color(light) - } - } - - private static let keywords = [ - "abstract", "as", "async", "await", "base", "bool", "break", "case", "catch", "char", "class", - "const", "continue", "decimal", "default", "do", "double", "else", "enum", "false", "finally", - "float", "for", "foreach", "get", "if", "in", "int", "interface", "internal", "is", "long", - "namespace", "new", "null", "object", "out", "override", "private", "protected", "public", - "readonly", "record", "ref", "return", "sealed", "set", "static", "string", "struct", "switch", - "this", "throw", "true", "try", "using", "var", "virtual", "void", "while", - ] - - private static let rules: [(NSRegularExpression, NSColor)] = { - func re(_ pattern: String) -> NSRegularExpression { - try! NSRegularExpression(pattern: pattern) - } - return [ - (re("\\b(?:" + keywords.joined(separator: "|") + ")\\b"), adaptive(0x9B2393, 0xFF7AB2)), - (re("\\b(?:Console|Math|List|Dictionary|File|Task|Exception|Func|Action|String|DateTime|Random)\\b"), adaptive(0x0B4F79, 0x5DD8FF)), - (re("\\b\\d+(?:\\.\\d+)?\\b"), adaptive(0x1C00CF, 0xD9C97C)), - (re("\\$?@?\"(?:\\\\.|[^\"\\\\\\n])*\"|'(?:\\\\.|[^'\\\\\\n])'"), adaptive(0xC41A16, 0xFC6A5D)), - (re("//[^\\n]*|/\\*[\\s\\S]*?\\*/"), adaptive(0x5D6C79, 0x7F8C98)), - ] - }() - - static func highlight(_ storage: NSTextStorage?) { - guard let storage else { return } - let text = storage.string - let full = NSRange(location: 0, length: (text as NSString).length) - storage.beginEditing() - storage.setAttributes(base, range: full) - for (pattern, color) in rules { - pattern.enumerateMatches(in: text, range: full) { match, _, _ in - if let range = match?.range { - storage.addAttribute(.foregroundColor, value: color, range: range) - } - } - } - storage.endEditing() - } -} -#endif - -enum CSharpRunner { - static func run(_ source: String, stdin: String, done: @escaping (String, String) -> Void) { - #if os(macOS) - DispatchQueue.global(qos: .userInitiated).async { - let result = runMac(source, stdin: stdin) - DispatchQueue.main.async { done(result.0, result.1) } - } - #else - done("unavailable", "") - #endif - } - - #if os(macOS) - private static func runMac(_ source: String, stdin: String) -> (String, String) { - guard source.count <= 100_000 else { return ("fail", "Program je příliš dlouhý.") } - guard let dotnet = findDotnet() else { return ("unavailable", "") } - let dir = URL(fileURLWithPath: NSHomeDirectory()).appendingPathComponent(".graduately/csharp-lab") - let csproj = dir.appendingPathComponent("Lab.csproj") - if !FileManager.default.fileExists(atPath: csproj.path) { - try? FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true) - let framework = targetFramework(dotnet) - let xml = """ - - - Exe - \(framework) - enable - disable - latest - - - """ - try? xml.write(to: csproj, atomically: true, encoding: .utf8) - let restored = command(dotnet, ["restore", dir.path], dir, "", 90) - if restored.0 != "ok" { return restored } - } - do { - try source.write(to: dir.appendingPathComponent("Program.cs"), atomically: true, encoding: .utf8) - } catch { - return ("fail", error.localizedDescription) - } - var args = ["run", "--project", dir.path, "--verbosity", "quiet"] - if FileManager.default.fileExists(atPath: dir.appendingPathComponent("obj").path) { - args.append("--no-restore") - } - return command(dotnet, args, dir, stdin, 20) - } - - private static func command(_ dotnet: String, _ args: [String], _ dir: URL, _ stdin: String, _ seconds: Double) -> (String, String) { - let proc = Process() - proc.executableURL = URL(fileURLWithPath: dotnet) - proc.arguments = args - proc.currentDirectoryURL = dir - var env = ProcessInfo.processInfo.environment - let root = (dotnet as NSString).deletingLastPathComponent - env["PATH"] = [root, "/opt/homebrew/bin", "/usr/local/bin", "/usr/bin", "/bin"].joined(separator: ":") - env["DOTNET_ROOT"] = root - env["DOTNET_CLI_TELEMETRY_OPTOUT"] = "1" - env["DOTNET_NOLOGO"] = "1" - env["DOTNET_SKIP_FIRST_TIME_EXPERIENCE"] = "1" - proc.environment = env - let out = Pipe() - let input = Pipe() - proc.standardOutput = out - proc.standardError = out - proc.standardInput = input - var collected = Data() - let lock = NSLock() - out.fileHandleForReading.readabilityHandler = { handle in - let chunk = handle.availableData - guard !chunk.isEmpty else { return } - lock.lock() - collected.append(chunk) - lock.unlock() - } - do { try proc.run() } catch { return ("fail", error.localizedDescription) } - if let data = stdin.data(using: .utf8) { input.fileHandleForWriting.write(data) } - try? input.fileHandleForWriting.close() - let group = DispatchGroup() - group.enter() - proc.terminationHandler = { _ in group.leave() } - if group.wait(timeout: .now() + seconds) == .timedOut { - proc.terminate() - kill(proc.processIdentifier, SIGKILL) - out.fileHandleForReading.readabilityHandler = nil - return ("timeout", clip(collected, lock)) - } - out.fileHandleForReading.readabilityHandler = nil - let rest = out.fileHandleForReading.readDataToEndOfFile() - lock.lock() - collected.append(rest) - lock.unlock() - let text = clip(collected, lock) - return proc.terminationStatus == 0 ? ("ok", text) : ("fail", text) - } - - private static func clip(_ data: Data, _ lock: NSLock) -> String { - lock.lock() - let copy = data - lock.unlock() - let text = String(data: copy, encoding: .utf8) ?? "" - let trimmed = text.trimmingCharacters(in: .whitespacesAndNewlines) - return trimmed.count <= 16_000 ? trimmed : String(trimmed.prefix(16_000)) + "\n…" - } - - private static func targetFramework(_ dotnet: String) -> String { - let version = command(dotnet, ["--version"], URL(fileURLWithPath: NSTemporaryDirectory()), "", 20) - let major = version.1.split(separator: ".").first.map(String.init) ?? "" - return major.allSatisfy(\.isNumber) && !major.isEmpty ? "net\(major).0" : "net8.0" - } - - private static func findDotnet() -> String? { - let names = [ - "/usr/local/share/dotnet/dotnet", - "/opt/homebrew/share/dotnet/dotnet", - "/usr/local/bin/dotnet", - NSHomeDirectory() + "/.dotnet/dotnet", - ] - return names.first { FileManager.default.isExecutableFile(atPath: $0) } - } - #endif -} diff --git a/macos/Graduately.xcodeproj/project.pbxproj b/macos/Graduately.xcodeproj/project.pbxproj index 42b58cc..6baafad 100644 --- a/macos/Graduately.xcodeproj/project.pbxproj +++ b/macos/Graduately.xcodeproj/project.pbxproj @@ -23,7 +23,6 @@ B101000000000000000014 /* Exercises.swift in Sources */ = {isa = PBXBuildFile; fileRef = B201000000000000000014 /* Exercises.swift */; }; B101000000000000000015 /* ExercisesMore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B201000000000000000015 /* ExercisesMore.swift */; }; B101000000000000000016 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B201000000000000000016 /* Assets.xcassets */; }; - B101000000000000000018 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = B201000000000000000020 /* Localizable.strings */; }; B101000000000000000017 /* PathMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = B201000000000000000019 /* PathMap.swift */; }; /* End PBXBuildFile section */ @@ -47,8 +46,6 @@ B201000000000000000017 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; B201000000000000000018 /* Graduately.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Graduately.entitlements; sourceTree = ""; }; B201000000000000000019 /* PathMap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = PathMap.swift; path = ../ios/Graduately/UI/PathMap.swift; sourceTree = SOURCE_ROOT; }; - B201000000000000000021 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; - B201000000000000000022 /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = ""; }; B301000000000000000001 /* Graduately.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Graduately.app; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -82,7 +79,6 @@ B501000000000000000004 /* Update */, B501000000000000000005 /* UI */, B201000000000000000016 /* Assets.xcassets */, - B201000000000000000020 /* Localizable.strings */, B201000000000000000017 /* Info.plist */, B201000000000000000018 /* Graduately.entitlements */, ); @@ -132,18 +128,6 @@ }; /* End PBXGroup section */ -/* Begin PBXVariantGroup section */ - B201000000000000000020 /* Localizable.strings */ = { - isa = PBXVariantGroup; - children = ( - B201000000000000000021 /* en */, - B201000000000000000022 /* cs */, - ); - name = Localizable.strings; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - /* Begin PBXNativeTarget section */ B601000000000000000001 /* Graduately */ = { isa = PBXNativeTarget; @@ -180,7 +164,7 @@ }; buildConfigurationList = B801000000000000000001 /* Build configuration list for PBXProject "Graduately" */; compatibilityVersion = "Xcode 14.0"; - developmentRegion = en; + developmentRegion = cs; hasScannedForEncodings = 0; knownRegions = ( en, @@ -203,7 +187,6 @@ buildActionMask = 2147483647; files = ( B101000000000000000016 /* Assets.xcassets in Resources */, - B101000000000000000018 /* Localizable.strings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/macos/Graduately/cs.lproj/Localizable.strings b/macos/Graduately/cs.lproj/Localizable.strings deleted file mode 100644 index a080c4c..0000000 --- a/macos/Graduately/cs.lproj/Localizable.strings +++ /dev/null @@ -1 +0,0 @@ -/* Označí češtinu jako podporovaný jazyk, aby nabídky macOS zůstaly česky na českém systému. */ diff --git a/macos/Graduately/en.lproj/Localizable.strings b/macos/Graduately/en.lproj/Localizable.strings deleted file mode 100644 index 3c0e8ca..0000000 --- a/macos/Graduately/en.lproj/Localizable.strings +++ /dev/null @@ -1 +0,0 @@ -/* Marks English as a supported language so macOS menus follow an English system. */ diff --git a/scripts/build-content.py b/scripts/build-content.py index ca44c03..fe5fbcf 100644 --- a/scripts/build-content.py +++ b/scripts/build-content.py @@ -116,20 +116,9 @@ def parse_doc(path: Path) -> Doc: para: Node | None = None table: Node | None = None in_comment = False - indexes = iter(range(i, len(lines))) - for n in indexes: + for n in range(i, len(lines)): ln = lines[n].rstrip() no = n + 1 - if ln.startswith("```"): - para = table = None - body: list[str] = [] - for n2 in indexes: - raw_line = lines[n2] - if raw_line.rstrip().startswith("```"): - break - body.append(raw_line) - nodes.append(Node("code", "\n".join(body).strip("\n"), no)) - continue if in_comment: if "-->" in ln: in_comment = False @@ -550,36 +539,6 @@ def lesson_files(directory: Path) -> list[Path]: return files -def code_of(p: Part | None) -> str: - if p is None: - return "" - for nd in p.nodes: - if nd.kind == "code": - return nd.text - return "" - - -def code_lessons(directory: Path, prefix: str) -> list[dict]: - """Lessons with an explanation and a C# program the student can edit and run.""" - out = [] - for i, path in enumerate(lesson_files(directory), start=1): - doc, en = parse_doc(path), en_doc(path) - load_translations(en) - lid = lesson_id(doc, f"{prefix}.{i}") - code = code_of(part(doc, "Kód", "Code")) - if not code.strip(): - fail(path, None, "lekce nemá ukázkový kód v sekci # Kód") - out.append({ - "id": i, - "key": lid, - "titleKey": keyed(f"{prefix}_unit{i}", doc, en, "nazev"), - "subKey": keyed(f"{prefix}_unit{i}_sub", doc, en, "popis"), - "slides": read_slides(doc, part(doc, "Výklad")), - "code": code, - }) - return out - - def std_lessons(directory: Path, prefix: str) -> list[dict]: """Lessons with slides and a choice quiz (IT, civics, literature, sciences, physics).""" out = [] @@ -1106,16 +1065,6 @@ STD = [ ("prirodni-vedy/chemie", "chem"), ("prirodni-vedy/biologie", "bio"), ("fyzika/1-rocnik", "fyz"), ("fyzika/2-rocnik", "fyz2"), ("fyzika/3-rocnik", "fyz3"), ("fyzika/4-rocnik", "fyz4"), - ("technicka-grafika/1-rocnik", "tg"), ("technicka-grafika/2-rocnik", "tg2"), - ("technicka-grafika/3-rocnik", "tg3"), ("technicka-grafika/4-rocnik", "tg4"), - ("prezentacni-grafika/1-rocnik", "pg"), ("prezentacni-grafika/2-rocnik", "pg2"), - ("prezentacni-grafika/3-rocnik", "pg3"), ("prezentacni-grafika/4-rocnik", "pg4"), - ("programove-vybaveni/1-rocnik", "sw"), ("programove-vybaveni/2-rocnik", "sw2"), - ("programove-vybaveni/3-rocnik", "sw3"), ("programove-vybaveni/4-rocnik", "sw4"), -] -CODE = [ - ("programovani/1-rocnik", "cs"), ("programovani/2-rocnik", "cs2"), - ("programovani/3-rocnik", "cs3"), ("programovani/4-rocnik", "cs4"), ] MATH = [ ("matematika/0-opakovani", "mat0"), ("matematika/1-rocnik", "mat"), @@ -1140,8 +1089,6 @@ def build(content: Path = CONTENT) -> dict: payload[key] = std_lessons(content / d, key) for d, key in MATH: payload[key] = math_lessons(content / d, key) - for d, key in CODE: - payload[key] = code_lessons(content / d, key) for d, tag in SKILLS: for year in range(1, 5): payload[tag if year == 1 else f"{tag}{year}"] = skill_lessons(