Add Czech literature lessons across four secondary-school years.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
pepaskopec-blip 2026-10-06 08:38:49 +02:00
commit 09312d8c93
31 changed files with 4395 additions and 35 deletions

View file

@ -66,8 +66,9 @@ Intel Mac, jiná architektura nebo úpravy kódu → [sestavení ze zdroje](#ses
- **Správa počítačových sítí** — 1. ročník, 27 lekcí (VLSM + teorie a kvízy);
ročníky 2–4 jsou zamčené
- **Technické vybavení** — 1. ročník, 29 lekcí (architektura, data, skříň a deska, karty, disky, vstupní zařízení); ročníky 2–4 jsou zamčené
- **Český jazyk a literatura** — mluvnice (20 cvičení) a maturitní četba
(82 knih: zápisky, kvíz, sestavení děje); literární teorie je zatím zamčená
- **Č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)
- **Občanská nauka** — 1. ročník, 17 lekcí (člověk v lidském společenství);
2. ročník, 16 lekcí (člověk jako občan); 3. ročník, 16 lekcí (člověk a právo);
4. ročník, 16 lekcí (hospodářství, svět a filozofie)
@ -262,8 +263,9 @@ Intel Mac, another architecture, or hacking on the code →
- **Computer networks** — year 1, 27 lessons (VLSM + theory/quizzes);
years 2–4 are locked
- **Computer hardware** — year 1, 29 lessons (architecture, data, case and board, cards, drives, input devices); years 2–4 are locked
- **Czech language** — grammar (20 exercises) and required reading
(82 books: notes, quiz, plot ordering); literature theory is still locked
- **Czech language** — literature (4 years, 32 lessons from the secondary-school
syllabus), grammar (20 exercises) and required reading
(82 books: notes, quiz, plot ordering)
- **Civics** — year 1, 17 lessons (the individual and society);
year 2, 16 lessons (the citizen in a democratic state);
year 3, 16 lessons (the individual and the law);

View file

@ -146,6 +146,26 @@ class AppViewModel(app: Application) : AndroidViewModel(app) {
refresh()
}
fun markLit(id: Int) {
progress.markLit(id)
refresh()
}
fun markLit2(id: Int) {
progress.markLit2(id)
refresh()
}
fun markLit3(id: Int) {
progress.markLit3(id)
refresh()
}
fun markLit4(id: Int) {
progress.markLit4(id)
refresh()
}
fun markMluv(n: Int) {
progress.markMluv(n)
refresh()

View file

@ -32,6 +32,7 @@ import org.maturita.maturita.ui.HomeScreen
import org.maturita.maturita.ui.HwQuizScreen
import org.maturita.maturita.ui.HwYearsScreen
import org.maturita.maturita.ui.LessonListScreen
import org.maturita.maturita.ui.LitYearsScreen
import org.maturita.maturita.ui.LessonRow
import org.maturita.maturita.ui.LitQuizScreen
import org.maturita.maturita.ui.MluvExercise
@ -288,6 +289,63 @@ private fun MaturitaAppBody(vm: AppViewModel) {
}
}
is Route.On4Ex -> On4QuizScreen(vm, r.id)
Route.LitYears -> LitYearsScreen(vm)
Route.LitMap -> LessonListScreen(
vm, vm.tr("lit_year1"), vm.tr("lit_sub"),
vm.content.lit.map { l ->
val id = l.int("id")
LessonRow(vm.tr(l.str("titleKey")), vm.progress.litDone(id), Route.LitLesson(id))
},
)
is Route.LitLesson -> {
val l = vm.content.litLesson(r.id)
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
vm.replace(Route.LitEx(r.id))
}
}
is Route.LitEx -> LitQuizScreen(vm, 1, r.id)
Route.Lit2Map -> LessonListScreen(
vm, vm.tr("lit_year2"), vm.tr("lit2_sub"),
vm.content.lit2.map { l ->
val id = l.int("id")
LessonRow(vm.tr(l.str("titleKey")), vm.progress.lit2Done(id), Route.Lit2Lesson(id))
},
)
is Route.Lit2Lesson -> {
val l = vm.content.lit2Lesson(r.id)
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
vm.replace(Route.Lit2Ex(r.id))
}
}
is Route.Lit2Ex -> LitQuizScreen(vm, 2, r.id)
Route.Lit3Map -> LessonListScreen(
vm, vm.tr("lit_year3"), vm.tr("lit3_sub"),
vm.content.lit3.map { l ->
val id = l.int("id")
LessonRow(vm.tr(l.str("titleKey")), vm.progress.lit3Done(id), Route.Lit3Lesson(id))
},
)
is Route.Lit3Lesson -> {
val l = vm.content.lit3Lesson(r.id)
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
vm.replace(Route.Lit3Ex(r.id))
}
}
is Route.Lit3Ex -> LitQuizScreen(vm, 3, r.id)
Route.Lit4Map -> LessonListScreen(
vm, vm.tr("lit_year4"), vm.tr("lit4_sub"),
vm.content.lit4.map { l ->
val id = l.int("id")
LessonRow(vm.tr(l.str("titleKey")), vm.progress.lit4Done(id), Route.Lit4Lesson(id))
},
)
is Route.Lit4Lesson -> {
val l = vm.content.lit4Lesson(r.id)
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
vm.replace(Route.Lit4Ex(r.id))
}
}
is Route.Lit4Ex -> LitQuizScreen(vm, 4, r.id)
Route.CzechMap -> CzechMapScreen(vm)
Route.Mluvnice -> LessonListScreen(
vm, vm.tr("Mluvnice"), vm.tr("mluv_sub"),

View file

@ -30,6 +30,19 @@ sealed class Route(val page: String) {
data object On4Map : Route("on4map")
data class On4Lesson(val id: Int) : Route("on4unit$id")
data class On4Ex(val id: Int) : Route("on4ex$id")
data object LitYears : Route("lityears")
data object LitMap : Route("litmap")
data class LitLesson(val id: Int) : Route("litunit$id")
data class LitEx(val id: Int) : Route("litex$id")
data object Lit2Map : Route("lit2map")
data class Lit2Lesson(val id: Int) : Route("lit2unit$id")
data class Lit2Ex(val id: Int) : Route("lit2ex$id")
data object Lit3Map : Route("lit3map")
data class Lit3Lesson(val id: Int) : Route("lit3unit$id")
data class Lit3Ex(val id: Int) : Route("lit3ex$id")
data object Lit4Map : Route("lit4map")
data class Lit4Lesson(val id: Int) : Route("lit4unit$id")
data class Lit4Ex(val id: Int) : Route("lit4ex$id")
data object CzechMap : Route("czechmap")
data object Mluvnice : Route("mluvnice")
data class MluvEx(val n: Int) : Route("mluve$n")
@ -45,7 +58,9 @@ sealed class Route(val page: String) {
val isExercise: Boolean
get() = this is GermanEx || this is Vocab || this is NetEx || this is HwEx ||
this is OnEx || this is On2Ex || this is On3Ex || this is On4Ex || this is MluvEx || this is BookQuiz || this is BookPlot ||
this is NetLesson || this is HwLesson || this is OnLesson || this is On2Lesson || this is On3Lesson || this is On4Lesson
this is NetLesson || this is HwLesson || this is OnLesson || this is On2Lesson || this is On3Lesson || this is On4Lesson ||
this is LitLesson || this is LitEx || this is Lit2Lesson || this is Lit2Ex ||
this is Lit3Lesson || this is Lit3Ex || this is Lit4Lesson || this is Lit4Ex
/** Full stack from the practice root to this screen, so back always goes up one level. */
fun stack(): List<Route> = when (this) {
@ -77,6 +92,19 @@ sealed class Route(val page: String) {
On4Map -> listOf(Subjects, OnYears, On4Map)
is On4Lesson -> listOf(Subjects, OnYears, On4Map, this)
is On4Ex -> listOf(Subjects, OnYears, On4Map, On4Lesson(id), this)
LitYears -> listOf(Subjects, CzechMap, LitYears)
LitMap -> listOf(Subjects, CzechMap, LitYears, LitMap)
is LitLesson -> listOf(Subjects, CzechMap, LitYears, LitMap, this)
is LitEx -> listOf(Subjects, CzechMap, LitYears, LitMap, LitLesson(id), this)
Lit2Map -> listOf(Subjects, CzechMap, LitYears, Lit2Map)
is Lit2Lesson -> listOf(Subjects, CzechMap, LitYears, Lit2Map, this)
is Lit2Ex -> listOf(Subjects, CzechMap, LitYears, Lit2Map, Lit2Lesson(id), this)
Lit3Map -> listOf(Subjects, CzechMap, LitYears, Lit3Map)
is Lit3Lesson -> listOf(Subjects, CzechMap, LitYears, Lit3Map, this)
is Lit3Ex -> listOf(Subjects, CzechMap, LitYears, Lit3Map, Lit3Lesson(id), this)
Lit4Map -> listOf(Subjects, CzechMap, LitYears, Lit4Map)
is Lit4Lesson -> listOf(Subjects, CzechMap, LitYears, Lit4Map, this)
is Lit4Ex -> listOf(Subjects, CzechMap, LitYears, Lit4Map, Lit4Lesson(id), this)
CzechMap -> listOf(Subjects, CzechMap)
Mluvnice -> listOf(Subjects, CzechMap, Mluvnice)
is MluvEx -> listOf(Subjects, CzechMap, Mluvnice, this)
@ -102,6 +130,11 @@ fun routeFromPage(page: String): Route? = when (page) {
"on2map" -> Route.On2Map
"on3map" -> Route.On3Map
"on4map" -> Route.On4Map
"lityears" -> Route.LitYears
"litmap" -> Route.LitMap
"lit2map" -> Route.Lit2Map
"lit3map" -> Route.Lit3Map
"lit4map" -> Route.Lit4Map
"czechmap" -> Route.CzechMap
"mluvnice" -> Route.Mluvnice
"readinglist" -> Route.ReadingList
@ -133,6 +166,30 @@ fun routeFromPage(page: String): Route? = when (page) {
Regex("""hwex(\d+)""").matchEntire(page)?.let {
return Route.HwEx(it.groupValues[1].toInt())
}
Regex("""lit4unit(\d+)""").matchEntire(page)?.let {
return Route.Lit4Lesson(it.groupValues[1].toInt())
}
Regex("""lit4ex(\d+)""").matchEntire(page)?.let {
return Route.Lit4Ex(it.groupValues[1].toInt())
}
Regex("""lit3unit(\d+)""").matchEntire(page)?.let {
return Route.Lit3Lesson(it.groupValues[1].toInt())
}
Regex("""lit3ex(\d+)""").matchEntire(page)?.let {
return Route.Lit3Ex(it.groupValues[1].toInt())
}
Regex("""lit2unit(\d+)""").matchEntire(page)?.let {
return Route.Lit2Lesson(it.groupValues[1].toInt())
}
Regex("""lit2ex(\d+)""").matchEntire(page)?.let {
return Route.Lit2Ex(it.groupValues[1].toInt())
}
Regex("""litunit(\d+)""").matchEntire(page)?.let {
return Route.LitLesson(it.groupValues[1].toInt())
}
Regex("""litex(\d+)""").matchEntire(page)?.let {
return Route.LitEx(it.groupValues[1].toInt())
}
Regex("""on4unit(\d+)""").matchEntire(page)?.let {
return Route.On4Lesson(it.groupValues[1].toInt())
}

View file

@ -33,6 +33,10 @@ class Content(root: JSONObject) {
val on2 = raw.arr("on2")
val on3 = raw.arr("on3")
val on4 = raw.arr("on4")
val lit = raw.arr("lit")
val lit2 = raw.arr("lit2")
val lit3 = raw.arr("lit3")
val lit4 = raw.arr("lit4")
val mluvnice = raw.arr("mluvnice")
val books = raw.arr("books")
val changelog = raw.arr("changelog")
@ -44,6 +48,10 @@ class Content(root: JSONObject) {
fun on2Lesson(id: Int) = on2.firstOrNull { it.int("id") == id }
fun on3Lesson(id: Int) = on3.firstOrNull { it.int("id") == id }
fun on4Lesson(id: Int) = on4.firstOrNull { it.int("id") == id }
fun litLesson(id: Int) = lit.firstOrNull { it.int("id") == id }
fun lit2Lesson(id: Int) = lit2.firstOrNull { it.int("id") == id }
fun lit3Lesson(id: Int) = lit3.firstOrNull { it.int("id") == id }
fun lit4Lesson(id: Int) = lit4.firstOrNull { it.int("id") == id }
fun mluv(n: Int) = mluvnice.firstOrNull { it.int("id") == n }
fun book(id: String) = books.firstOrNull { it.str("id") == id }

View file

@ -44,6 +44,15 @@ class ProgressStore(context: Context) {
fun on4Done(id: Int) = prefs.getBoolean("on4.$id", false)
fun markOn4(id: Int) { prefs.edit().putBoolean("on4.$id", true).apply() }
fun litDone(id: Int) = prefs.getBoolean("lit.$id", false)
fun markLit(id: Int) { prefs.edit().putBoolean("lit.$id", true).apply() }
fun lit2Done(id: Int) = prefs.getBoolean("lit2.$id", false)
fun markLit2(id: Int) { prefs.edit().putBoolean("lit2.$id", true).apply() }
fun lit3Done(id: Int) = prefs.getBoolean("lit3.$id", false)
fun markLit3(id: Int) { prefs.edit().putBoolean("lit3.$id", true).apply() }
fun lit4Done(id: Int) = prefs.getBoolean("lit4.$id", false)
fun markLit4(id: Int) { prefs.edit().putBoolean("lit4.$id", true).apply() }
fun mluvDone(n: Int) = prefs.getBoolean("mluv.$n", false)
fun markMluv(n: Int) { prefs.edit().putBoolean("mluv.$n", true).apply() }
@ -114,6 +123,38 @@ fun summarize(content: Content, p: ProgressStore): ProgressSum {
sum.doneUnits += 1
}
}
content.lit.forEach { l ->
sum.totalEx += 1
sum.openUnits += 1
if (p.litDone(l.int("id"))) {
sum.doneEx += 1
sum.doneUnits += 1
}
}
content.lit2.forEach { l ->
sum.totalEx += 1
sum.openUnits += 1
if (p.lit2Done(l.int("id"))) {
sum.doneEx += 1
sum.doneUnits += 1
}
}
content.lit3.forEach { l ->
sum.totalEx += 1
sum.openUnits += 1
if (p.lit3Done(l.int("id"))) {
sum.doneEx += 1
sum.doneUnits += 1
}
}
content.lit4.forEach { l ->
sum.totalEx += 1
sum.openUnits += 1
if (p.lit4Done(l.int("id"))) {
sum.doneEx += 1
sum.doneUnits += 1
}
}
sum.totalEx += content.mluvnice.size
sum.openUnits += 1
val md = content.mluvnice.count { p.mluvDone(it.int("id")) }

View file

@ -146,6 +146,7 @@ private fun ChoiceEx(vm: AppViewModel, title: String, sub: String?, spec: J, onD
if (revealed) {
meanings.getOrNull(i)?.let { Meaning(vm.tr(it), true) }
expls.getOrNull(i)?.let { Meaning(it, true) }
q.strOrNull("expl")?.let { Meaning(it, true) }
}
Spacer(Modifier.height(12.dp))
}
@ -848,6 +849,30 @@ fun NetQuizScreen(vm: AppViewModel, id: Int) {
DispatchExercise(vm, spec, vm.tr(lesson.str("exTitleKey"))) { vm.markNet(id) }
}
@Composable
fun LitQuizScreen(vm: AppViewModel, year: Int, id: Int) {
val lesson = when (year) {
2 -> vm.content.lit2Lesson(id)
3 -> vm.content.lit3Lesson(id)
4 -> vm.content.lit4Lesson(id)
else -> vm.content.litLesson(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.markLit2(id)
3 -> vm.markLit3(id)
4 -> vm.markLit4(id)
else -> vm.markLit(id)
}
}
}
@Composable
fun OnQuizScreen(vm: AppViewModel, id: Int) {
val lesson = vm.content.onLesson(id) ?: return

View file

@ -308,8 +308,13 @@ private fun subjectSum(vm: AppViewModel, s: J): ProgressSum {
vm.content.on4.count { vm.progress.on4Done(it.int("id")) }
}
"czechmap" -> {
sum.totalEx = vm.content.mluvnice.size
sum.doneEx = vm.content.mluvnice.count { vm.progress.mluvDone(it.int("id")) }
val litDone = vm.content.lit.count { vm.progress.litDone(it.int("id")) } +
vm.content.lit2.count { vm.progress.lit2Done(it.int("id")) } +
vm.content.lit3.count { vm.progress.lit3Done(it.int("id")) } +
vm.content.lit4.count { vm.progress.lit4Done(it.int("id")) }
sum.totalEx = vm.content.mluvnice.size + vm.content.lit.size + vm.content.lit2.size +
vm.content.lit3.size + vm.content.lit4.size
sum.doneEx = vm.content.mluvnice.count { vm.progress.mluvDone(it.int("id")) } + litDone
}
}
return sum
@ -514,6 +519,27 @@ private fun buildSearch(vm: AppViewModel): List<Hit> {
add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "on4unit${l.int("id")}", extra = "obcanka")
add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "on4ex${l.int("id")}")
}
add(vm.tr("Literatura"), vm.tr("search_lesson"), "lityears", extra = "literatura")
add(vm.tr("lit_year1"), vm.tr("search_lesson"), "litmap", extra = "rocnik")
add(vm.tr("lit_year2"), vm.tr("search_lesson"), "lit2map", extra = "rocnik")
add(vm.tr("lit_year3"), vm.tr("search_lesson"), "lit3map", extra = "rocnik")
add(vm.tr("lit_year4"), vm.tr("search_lesson"), "lit4map", extra = "rocnik")
vm.content.lit.forEach { l ->
add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "litunit${l.int("id")}", extra = "literatura")
add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "litex${l.int("id")}")
}
vm.content.lit2.forEach { l ->
add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "lit2unit${l.int("id")}", extra = "literatura")
add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "lit2ex${l.int("id")}")
}
vm.content.lit3.forEach { l ->
add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "lit3unit${l.int("id")}", extra = "literatura")
add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "lit3ex${l.int("id")}")
}
vm.content.lit4.forEach { l ->
add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "lit4unit${l.int("id")}", extra = "literatura")
add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "lit4ex${l.int("id")}")
}
add(vm.tr("Mluvnice"), vm.tr("search_lesson"), "mluvnice")
vm.content.mluvnice.forEach { m -> add(m.str("name"), vm.tr("Mluvnice"), "mluve${m.int("id")}") }
add(vm.tr("Maturitní četba"), vm.tr("search_book"), "readinglist")
@ -626,11 +652,27 @@ fun OnYearsScreen(vm: AppViewModel) {
}
}
@Composable
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 = { 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) }
}
}
}
}
@Composable
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"), locked = true, onClick = null) }
item {
NavRow(title = vm.tr("Literatura"), subtitle = vm.tr("lit_years_sub")) { vm.go(Route.LitYears) }
}
item {
NavRow(
title = vm.tr("Mluvnice"),

View file

@ -6,6 +6,12 @@
# cs: bullet
# en: bullet
--- 2026-10-06
cs: Český jazyk: literatura ve čtyřech ročnících podle osnov středních škol
cs: 32 lekcí od starověku po současnost, každá s výkladem a kvízem
en: Czech: literature across four years, following the secondary-school syllabus
en: 32 lessons from antiquity to the present, each with an overview and a quiz
--- 2026-10-03
cs: Občanská nauka: 4. ročník, 16 lekcí (hospodářství, svět a filozofie)
en: Civics: year 4, 16 lessons (the economy, the world and philosophy)

View file

@ -148,6 +148,26 @@ final class AppModel: ObservableObject {
refresh()
}
func markLit(_ id: Int) {
progress.markLit(id)
refresh()
}
func markLit2(_ id: Int) {
progress.markLit2(id)
refresh()
}
func markLit3(_ id: Int) {
progress.markLit3(id)
refresh()
}
func markLit4(_ id: Int) {
progress.markLit4(id)
refresh()
}
func markMluv(_ n: Int) {
progress.markMluv(n)
refresh()

View file

@ -35,6 +35,10 @@ final class Content {
let on2: [J]
let on3: [J]
let on4: [J]
let lit: [J]
let lit2: [J]
let lit3: [J]
let lit4: [J]
let mluvnice: [J]
let books: [J]
let changelog: [J]
@ -70,6 +74,10 @@ final class Content {
on2 = raw.arr("on2")
on3 = raw.arr("on3")
on4 = raw.arr("on4")
lit = raw.arr("lit")
lit2 = raw.arr("lit2")
lit3 = raw.arr("lit3")
lit4 = raw.arr("lit4")
mluvnice = raw.arr("mluvnice")
books = raw.arr("books")
changelog = raw.arr("changelog")
@ -82,6 +90,10 @@ final class Content {
func on2Lesson(_ id: Int) -> J? { on2.first { $0.int("id") == id } }
func on3Lesson(_ id: Int) -> J? { on3.first { $0.int("id") == id } }
func on4Lesson(_ id: Int) -> J? { on4.first { $0.int("id") == id } }
func litLesson(_ id: Int) -> J? { lit.first { $0.int("id") == id } }
func lit2Lesson(_ id: Int) -> J? { lit2.first { $0.int("id") == id } }
func lit3Lesson(_ id: Int) -> J? { lit3.first { $0.int("id") == id } }
func lit4Lesson(_ id: Int) -> J? { lit4.first { $0.int("id") == id } }
func mluv(_ n: Int) -> J? { mluvnice.first { $0.int("id") == n } }
func book(_ id: String) -> J? { books.first { $0.str("id") == id } }

View file

@ -46,6 +46,15 @@ final class ProgressStore {
func on4Done(_ id: Int) -> Bool { defaults.bool(forKey: "on4.\(id)") }
func markOn4(_ id: Int) { defaults.set(true, forKey: "on4.\(id)") }
func litDone(_ id: Int) -> Bool { defaults.bool(forKey: "lit.\(id)") }
func markLit(_ id: Int) { defaults.set(true, forKey: "lit.\(id)") }
func lit2Done(_ id: Int) -> Bool { defaults.bool(forKey: "lit2.\(id)") }
func markLit2(_ id: Int) { defaults.set(true, forKey: "lit2.\(id)") }
func lit3Done(_ id: Int) -> Bool { defaults.bool(forKey: "lit3.\(id)") }
func markLit3(_ id: Int) { defaults.set(true, forKey: "lit3.\(id)") }
func lit4Done(_ id: Int) -> Bool { defaults.bool(forKey: "lit4.\(id)") }
func markLit4(_ id: Int) { defaults.set(true, forKey: "lit4.\(id)") }
func mluvDone(_ n: Int) -> Bool { defaults.bool(forKey: "mluv.\(n)") }
func markMluv(_ n: Int) { defaults.set(true, forKey: "mluv.\(n)") }
@ -121,6 +130,38 @@ func summarize(_ content: Content, _ p: ProgressStore) -> ProgressSum {
sum.doneUnits += 1
}
}
for l in content.lit {
sum.totalEx += 1
sum.openUnits += 1
if p.litDone(l.int("id")) {
sum.doneEx += 1
sum.doneUnits += 1
}
}
for l in content.lit2 {
sum.totalEx += 1
sum.openUnits += 1
if p.lit2Done(l.int("id")) {
sum.doneEx += 1
sum.doneUnits += 1
}
}
for l in content.lit3 {
sum.totalEx += 1
sum.openUnits += 1
if p.lit3Done(l.int("id")) {
sum.doneEx += 1
sum.doneUnits += 1
}
}
for l in content.lit4 {
sum.totalEx += 1
sum.openUnits += 1
if p.lit4Done(l.int("id")) {
sum.doneEx += 1
sum.doneUnits += 1
}
}
sum.totalEx += content.mluvnice.count
sum.openUnits += 1
let md = content.mluvnice.filter { p.mluvDone($0.int("id")) }.count

View file

@ -36,6 +36,19 @@ enum Route: Hashable {
case on4Map
case on4Lesson(Int)
case on4Ex(Int)
case litYears
case litMap
case litLesson(Int)
case litEx(Int)
case lit2Map
case lit2Lesson(Int)
case lit2Ex(Int)
case lit3Map
case lit3Lesson(Int)
case lit3Ex(Int)
case lit4Map
case lit4Lesson(Int)
case lit4Ex(Int)
case czechMap
case mluvnice
case mluvEx(Int)
@ -74,6 +87,19 @@ enum Route: Hashable {
case .on4Map: return "on4map"
case .on4Lesson(let id): return "on4unit\(id)"
case .on4Ex(let id): return "on4ex\(id)"
case .litYears: return "lityears"
case .litMap: return "litmap"
case .litLesson(let id): return "litunit\(id)"
case .litEx(let id): return "litex\(id)"
case .lit2Map: return "lit2map"
case .lit2Lesson(let id): return "lit2unit\(id)"
case .lit2Ex(let id): return "lit2ex\(id)"
case .lit3Map: return "lit3map"
case .lit3Lesson(let id): return "lit3unit\(id)"
case .lit3Ex(let id): return "lit3ex\(id)"
case .lit4Map: return "lit4map"
case .lit4Lesson(let id): return "lit4unit\(id)"
case .lit4Ex(let id): return "lit4ex\(id)"
case .czechMap: return "czechmap"
case .mluvnice: return "mluvnice"
case .mluvEx(let n): return "mluve\(n)"
@ -148,6 +174,32 @@ enum Route: Hashable {
return [.onYears, .on4Map, .on4Lesson(id)]
case .on4Ex(let id):
return [.onYears, .on4Map, .on4Lesson(id), .on4Ex(id)]
case .litYears:
return [.czechMap, .litYears]
case .litMap:
return [.czechMap, .litYears, .litMap]
case .litLesson(let id):
return [.czechMap, .litYears, .litMap, .litLesson(id)]
case .litEx(let id):
return [.czechMap, .litYears, .litMap, .litLesson(id), .litEx(id)]
case .lit2Map:
return [.czechMap, .litYears, .lit2Map]
case .lit2Lesson(let id):
return [.czechMap, .litYears, .lit2Map, .lit2Lesson(id)]
case .lit2Ex(let id):
return [.czechMap, .litYears, .lit2Map, .lit2Lesson(id), .lit2Ex(id)]
case .lit3Map:
return [.czechMap, .litYears, .lit3Map]
case .lit3Lesson(let id):
return [.czechMap, .litYears, .lit3Map, .lit3Lesson(id)]
case .lit3Ex(let id):
return [.czechMap, .litYears, .lit3Map, .lit3Lesson(id), .lit3Ex(id)]
case .lit4Map:
return [.czechMap, .litYears, .lit4Map]
case .lit4Lesson(let id):
return [.czechMap, .litYears, .lit4Map, .lit4Lesson(id)]
case .lit4Ex(let id):
return [.czechMap, .litYears, .lit4Map, .lit4Lesson(id), .lit4Ex(id)]
case .czechMap:
return [.czechMap]
case .mluvnice:
@ -181,6 +233,11 @@ func routeFromPage(_ page: String) -> Route? {
case "on2map": return .on2Map
case "on3map": return .on3Map
case "on4map": return .on4Map
case "lityears": return .litYears
case "litmap": return .litMap
case "lit2map": return .lit2Map
case "lit3map": return .lit3Map
case "lit4map": return .lit4Map
case "czechmap": return .czechMap
case "mluvnice": return .mluvnice
case "readinglist": return .readingList
@ -224,6 +281,30 @@ func routeFromPage(_ page: String) -> Route? {
if let m = page.wholeMatch(of: /hwex(\d+)/), let n = Int(m.1) {
return .hwEx(n)
}
if let m = page.wholeMatch(of: /lit4unit(\d+)/), let n = Int(m.1) {
return .lit4Lesson(n)
}
if let m = page.wholeMatch(of: /lit4ex(\d+)/), let n = Int(m.1) {
return .lit4Ex(n)
}
if let m = page.wholeMatch(of: /lit3unit(\d+)/), let n = Int(m.1) {
return .lit3Lesson(n)
}
if let m = page.wholeMatch(of: /lit3ex(\d+)/), let n = Int(m.1) {
return .lit3Ex(n)
}
if let m = page.wholeMatch(of: /lit2unit(\d+)/), let n = Int(m.1) {
return .lit2Lesson(n)
}
if let m = page.wholeMatch(of: /lit2ex(\d+)/), let n = Int(m.1) {
return .lit2Ex(n)
}
if let m = page.wholeMatch(of: /litunit(\d+)/), let n = Int(m.1) {
return .litLesson(n)
}
if let m = page.wholeMatch(of: /litex(\d+)/), let n = Int(m.1) {
return .litEx(n)
}
if let m = page.wholeMatch(of: /on4unit(\d+)/), let n = Int(m.1) {
return .on4Lesson(n)
}

View file

@ -149,6 +149,9 @@ private struct ChoiceEx: View {
if revealed {
if i < meanings.count { Meaning(text: vm.tr(meanings[i]), palette: p, visible: true) }
if i < expls.count { Meaning(text: expls[i], palette: p, visible: true) }
if let expl = qs[i].strOrNull("expl") {
Meaning(text: expl, palette: p, visible: true)
}
}
Spacer().frame(height: 10)
}

View file

@ -625,6 +625,39 @@ struct NetQuizScreen: View {
}
}
struct LitYearQuizScreen: 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.lit2Lesson(id)
case 3: return vm.content.lit3Lesson(id)
case 4: return vm.content.lit4Lesson(id)
default: return vm.content.litLesson(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.markLit2(id)
case 3: vm.markLit3(id)
case 4: vm.markLit4(id)
default: vm.markLit(id)
}
}
}
}
}
struct OnQuizScreen: View {
@ObservedObject var vm: AppModel
let id: Int

View file

@ -696,8 +696,13 @@ private func subjectSum(_ vm: AppModel, _ s: J) -> ProgressSum {
+ vm.content.on3.filter { vm.progress.on3Done($0.int("id")) }.count
+ vm.content.on4.filter { vm.progress.on4Done($0.int("id")) }.count
case "czechmap":
sum.totalEx = vm.content.mluvnice.count
sum.doneEx = vm.content.mluvnice.filter { vm.progress.mluvDone($0.int("id")) }.count
let litCount = vm.content.lit.count + vm.content.lit2.count + vm.content.lit3.count + vm.content.lit4.count
let litDone = vm.content.lit.filter { vm.progress.litDone($0.int("id")) }.count
+ vm.content.lit2.filter { vm.progress.lit2Done($0.int("id")) }.count
+ vm.content.lit3.filter { vm.progress.lit3Done($0.int("id")) }.count
+ vm.content.lit4.filter { vm.progress.lit4Done($0.int("id")) }.count
sum.totalEx = vm.content.mluvnice.count + litCount
sum.doneEx = vm.content.mluvnice.filter { vm.progress.mluvDone($0.int("id")) }.count + litDone
default:
break
}
@ -899,6 +904,27 @@ private func buildSearch(_ vm: AppModel) -> [Hit] {
add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "on4unit\(l.int("id"))", extra: "obcanka")
add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "on4ex\(l.int("id"))")
}
add(vm.tr("Literatura"), vm.tr("search_lesson"), "lityears", extra: "literatura")
add(vm.tr("lit_year1"), vm.tr("search_lesson"), "litmap", extra: "rocnik")
add(vm.tr("lit_year2"), vm.tr("search_lesson"), "lit2map", extra: "rocnik")
add(vm.tr("lit_year3"), vm.tr("search_lesson"), "lit3map", extra: "rocnik")
add(vm.tr("lit_year4"), vm.tr("search_lesson"), "lit4map", extra: "rocnik")
for l in vm.content.lit {
add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "litunit\(l.int("id"))", extra: "literatura")
add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "litex\(l.int("id"))")
}
for l in vm.content.lit2 {
add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "lit2unit\(l.int("id"))", extra: "literatura")
add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "lit2ex\(l.int("id"))")
}
for l in vm.content.lit3 {
add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "lit3unit\(l.int("id"))", extra: "literatura")
add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "lit3ex\(l.int("id"))")
}
for l in vm.content.lit4 {
add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "lit4unit\(l.int("id"))", extra: "literatura")
add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "lit4ex\(l.int("id"))")
}
add(vm.tr("Mluvnice"), vm.tr("search_lesson"), "mluvnice")
add(vm.tr("Maturitní četba"), vm.tr("search_book"), "readinglist")
for b in vm.content.books {
@ -1404,6 +1430,47 @@ struct SlidesScreen: View {
}
}
struct LitYearsScreen: View {
@ObservedObject var vm: AppModel
var body: some View {
#if os(macOS)
let years: [(String, String, Route)] = [
("lit_year1", "lit_sub", .litMap),
("lit_year2", "lit2_sub", .lit2Map),
("lit_year3", "lit3_sub", .lit3Map),
("lit_year4", "lit4_sub", .lit4Map),
]
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).")
}
.buttonStyle(.plain)
}
.navigationTitle(vm.tr("Literatura"))
.navigationSubtitle(vm.tr("lit_years_sub"))
#else
List {
NavigationLink(value: 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"))
}
NavigationLink(value: 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"))
}
}
.navigationTitle(vm.tr("Literatura"))
.navigationSubtitle(vm.tr("lit_years_sub"))
.appListStyle()
#endif
}
}
struct CzechMapScreen: View {
@ObservedObject var vm: AppModel
@ -1422,19 +1489,23 @@ struct CzechMapScreen: View {
}
.buttonStyle(.plain)
default:
MacLinkCard(title: vm.tr("Literatura"), systemImage: "book.closed", locked: true)
NavigationLink(value: Route.litYears) {
MacLinkCard(title: vm.tr("Literatura"), systemImage: "book.closed")
}
.buttonStyle(.plain)
}
}
.navigationTitle(vm.tr("Český jazyk a literatura"))
.navigationSubtitle(vm.tr("czech_sub"))
#else
List {
NavigationLink(value: Route.litYears) {
Label {
Text(vm.tr("Literatura"))
} icon: {
Image(systemName: "lock.fill")
Image(systemName: "book.closed")
}
}
.foregroundStyle(.secondary)
NavigationLink(value: Route.mluvnice) {
Label {
Text(vm.tr("Mluvnice"))
@ -1994,6 +2065,92 @@ struct RouteDestination: View {
On4QuizScreen(vm: vm, id: id)
case .czechMap:
CzechMapScreen(vm: vm)
case .litYears:
LitYearsScreen(vm: vm)
case .litMap:
LessonListScreen(
vm: vm,
title: vm.tr("lit_year1"),
subtitle: vm.tr("lit_sub"),
rows: vm.content.lit.map { l in
let id = l.int("id")
return LessonRow(
id: "l\(id)",
title: vm.tr(l.str("titleKey")),
done: vm.progress.litDone(id),
destination: .litLesson(id)
)
}
)
case .litLesson(let id):
if let l = vm.content.litLesson(id) {
SlidesScreen(vm: vm, title: vm.tr(l.str("titleKey")), subtitle: vm.tr(l.str("subKey")), slides: l.arr("slides"), next: .litEx(id))
}
case .litEx(let id):
LitYearQuizScreen(vm: vm, year: 1, id: id)
case .lit2Map:
LessonListScreen(
vm: vm,
title: vm.tr("lit_year2"),
subtitle: vm.tr("lit2_sub"),
rows: vm.content.lit2.map { l in
let id = l.int("id")
return LessonRow(
id: "l2\(id)",
title: vm.tr(l.str("titleKey")),
done: vm.progress.lit2Done(id),
destination: .lit2Lesson(id)
)
}
)
case .lit2Lesson(let id):
if let l = vm.content.lit2Lesson(id) {
SlidesScreen(vm: vm, title: vm.tr(l.str("titleKey")), subtitle: vm.tr(l.str("subKey")), slides: l.arr("slides"), next: .lit2Ex(id))
}
case .lit2Ex(let id):
LitYearQuizScreen(vm: vm, year: 2, id: id)
case .lit3Map:
LessonListScreen(
vm: vm,
title: vm.tr("lit_year3"),
subtitle: vm.tr("lit3_sub"),
rows: vm.content.lit3.map { l in
let id = l.int("id")
return LessonRow(
id: "l3\(id)",
title: vm.tr(l.str("titleKey")),
done: vm.progress.lit3Done(id),
destination: .lit3Lesson(id)
)
}
)
case .lit3Lesson(let id):
if let l = vm.content.lit3Lesson(id) {
SlidesScreen(vm: vm, title: vm.tr(l.str("titleKey")), subtitle: vm.tr(l.str("subKey")), slides: l.arr("slides"), next: .lit3Ex(id))
}
case .lit3Ex(let id):
LitYearQuizScreen(vm: vm, year: 3, id: id)
case .lit4Map:
LessonListScreen(
vm: vm,
title: vm.tr("lit_year4"),
subtitle: vm.tr("lit4_sub"),
rows: vm.content.lit4.map { l in
let id = l.int("id")
return LessonRow(
id: "l4\(id)",
title: vm.tr(l.str("titleKey")),
done: vm.progress.lit4Done(id),
destination: .lit4Lesson(id)
)
}
)
case .lit4Lesson(let id):
if let l = vm.content.lit4Lesson(id) {
SlidesScreen(vm: vm, title: vm.tr(l.str("titleKey")), subtitle: vm.tr(l.str("subKey")), slides: l.arr("slides"), next: .lit4Ex(id))
}
case .lit4Ex(let id):
LitYearQuizScreen(vm: vm, year: 4, id: id)
case .mluvnice:
LessonListScreen(
vm: vm,

View file

@ -291,8 +291,8 @@ def find_arrays(src: str) -> dict[str, tuple[str, list]]:
val, _ = parse_list(toks, 0)
fn = func_at(pos_brace)
key = f"{fn}.{name}" if fn and name in {
"slides", "qs", "about", "world", "people", "terms", "persons",
"nouns", "ans",
"slides", "qs", "hints", "about", "world", "people", "terms",
"persons", "nouns", "ans",
} else name
# Prefer the first global, overwrite locals with prefixed names.
if key in found and not key.startswith(fn or "\0"):
@ -1084,6 +1084,32 @@ def main() -> int:
"quiz": qs,
})
def lit_pack(prefix):
lessons = []
for i in range(1, 9):
fn_u = f"build_{prefix}_unit{i}_page"
fn_e = f"build_{prefix}_unit{i}_exercise_page"
quiz = choice_items(A(f"{fn_e}.qs"))
hints = str_list(A(f"{fn_e}.hints")) if f"{fn_e}.hints" in arrays else []
for qi, q in enumerate(quiz):
if qi < len(hints) and hints[qi]:
q["expl"] = hints[qi]
lessons.append({
"id": i,
"titleKey": f"{prefix}_unit{i}",
"subKey": f"{prefix}_unit{i}_sub",
"exTitleKey": f"{prefix}_ex{i}_title",
"quizHeadKey": f"{prefix}_quiz{i}_head",
"slides": slides_items(A(f"{fn_u}.slides")),
"quiz": quiz,
})
return lessons
lit_lessons = lit_pack("lit")
lit2_lessons = lit_pack("lit2")
lit3_lessons = lit_pack("lit3")
lit4_lessons = lit_pack("lit4")
on_lessons = []
for i in range(1, 18):
on_lessons.append({
@ -1551,6 +1577,10 @@ def main() -> int:
},
"hw": hw_lessons,
"on": on_lessons,
"lit": lit_lessons,
"lit2": lit2_lessons,
"lit3": lit3_lessons,
"lit4": lit4_lessons,
"on2": on2_lessons,
"on3": on3_lessons,
"on4": on4_lessons,
@ -1589,6 +1619,7 @@ def main() -> int:
print(f" net quizzes: {sum(1 for L in net_lessons if L['quiz'])}")
print(f" hw lessons: {sum(1 for L in hw_lessons if L['slides'])}")
print(f" on lessons: {sum(1 for L in on_lessons if L['slides'])}")
print(f" lit lessons: {sum(1 for L in lit_lessons + lit2_lessons + lit3_lessons + lit4_lessons if L['slides'])}")
print(f" on2 lessons: {sum(1 for L in on2_lessons if L['slides'])}")
print(f" on3 lessons: {sum(1 for L in on3_lessons if L['slides'])}")
print(f" on4 lessons: {sum(1 for L in on4_lessons if L['slides'])}")
@ -1645,6 +1676,17 @@ def main() -> int:
missing.append(f"on4{L['id']} slides")
if not L["quiz"]:
missing.append(f"on4{L['id']} quiz")
for label, block in (
("lit", lit_lessons), ("lit2", lit2_lessons),
("lit3", lit3_lessons), ("lit4", lit4_lessons),
):
for L in block:
if not L["slides"]:
missing.append(f"{label}{L['id']} slides")
if len(L["quiz"]) < 4:
missing.append(f"{label}{L['id']} quiz")
if not all(q.get("expl") for q in L["quiz"]):
missing.append(f"{label}{L['id']} expl")
for m in mluvnice:
if m["type"] in ("typed", "reveal") and not m.get("items"):
missing.append(f"mluv{m['id']}")

View file

@ -134,20 +134,15 @@ GtkWidget *build_czechmap_page(void) {
cz_rail = rail;
for (int i = 0; i < CZ_NODES; i++) {
/* Literatura has no lessons yet; keep the node visible but locked. */
gboolean locked = (i == 0);
GtkWidget *btn = cz_make_node(i, locked);
GtkWidget *btn = cz_make_node(i, FALSE);
GtkWidget *name = gtk_label_new(NULL);
const char *target = (i == 0) ? "lityears"
: (i == 1) ? "mluvnice"
: "readinglist";
if (i == 2) {
g_object_set_data_full(G_OBJECT(btn), "target",
g_strdup("readinglist"), g_free);
g_strdup(target), g_free);
g_signal_connect(btn, "clicked", G_CALLBACK(on_nav_clicked), NULL);
} else if (i == 1) {
g_object_set_data_full(G_OBJECT(btn), "target",
g_strdup("mluvnice"), g_free);
g_signal_connect(btn, "clicked", G_CALLBACK(on_nav_clicked), NULL);
}
i18n_bind(name, cz_keys[i], 0);
gtk_widget_set_size_request(name, (int)CZ_LABEL_W, -1);
@ -156,8 +151,6 @@ GtkWidget *build_czechmap_page(void) {
gtk_label_set_wrap(GTK_LABEL(name), TRUE);
gtk_widget_add_css_class(name, "unit-name");
gtk_widget_add_css_class(name, "cz-label");
if (locked)
gtk_widget_add_css_class(name, "unit-name-locked");
gtk_fixed_put(GTK_FIXED(fixed), btn, 0, 0);
gtk_fixed_put(GTK_FIXED(fixed), name, 0, 0);

View file

@ -55,6 +55,10 @@ extern char *app_progress_on3;
extern char *app_progress_on4;
extern char *app_progress_mluvnice;
extern char *app_progress_cetba;
extern char *app_progress_lit;
extern char *app_progress_lit2;
extern char *app_progress_lit3;
extern char *app_progress_lit4;
#define PROGRESS_DIR app_progress_dir
#define PROGRESS_U1 app_progress_u1
#define PROGRESS_U2 app_progress_u2
@ -131,6 +135,7 @@ extern char *app_progress_cetba;
#define ON3_LESSONS 16
#define ON4_UNITS 16
#define ON4_LESSONS 16
#define LIT_N 8
#define HW_SLIDES 3
#define HW2_SLIDES 6
#define HW3_SLIDES 2
@ -901,6 +906,29 @@ void on4_lessons_apply_lang(void);
GtkWidget *build_on4map_page(void);
void add_on4_pages(GtkStack *stack);
void czech_rail_theme_reset(void);
void lit_load_progress(void);
void lit_rail_theme_reset(void);
void lit_lessons_apply_lang(void);
void progress_for_lit(ProgressSum *out);
GtkWidget *lit_unit_page(int year, NetLesson *L, const char *title_key,
const char *sub_key, const NetSlide *slides,
guint n_slides);
GtkWidget *lit_mcq_page(int year, int lesson_id, const char *back_page,
const char *title_key, const char *heading_key,
const ChoiceQ *qs, const char **hints, int n);
GtkWidget *build_lityears_page(void);
GtkWidget *build_litmap_page(void);
GtkWidget *build_lit2map_page(void);
GtkWidget *build_lit3map_page(void);
GtkWidget *build_lit4map_page(void);
void add_lit_pages(GtkStack *stack);
void add_lit2_pages(GtkStack *stack);
void add_lit3_pages(GtkStack *stack);
void add_lit4_pages(GtkStack *stack);
extern NetLesson lit_lessons[LIT_N];
extern NetLesson lit2_lessons[LIT_N];
extern NetLesson lit3_lessons[LIT_N];
extern NetLesson lit4_lessons[LIT_N];
void hw_lessons_apply_lang(void);
GtkWidget *build_hwyears_page(void);
GtkWidget *build_hwmap_page(void);

View file

@ -1098,6 +1098,212 @@ const TrEntry tr_ui[] = {
{"on4_ex16_title", "Kvíz: hodnoty", "Quiz: values"},
{"on4_quiz16_head", "Kvíz k hodnotám",
"Quiz on values"},
{"lit_years_sub", "Literatura podle osnov středních škol. Vyberte ročník.",
"Literature from the secondary-school syllabus. Pick a year."},
{"lit_year1", "1. ročník", "Year 1"},
{"lit_year2", "2. ročník", "Year 2"},
{"lit_year3", "3. ročník", "Year 3"},
{"lit_year4", "4. ročník", "Year 4"},
{"lit_sub", "Od literární teorie po osvícenství.",
"From literary theory to the Enlightenment."},
{"lit2_sub", "Od národního obrození k moderně.",
"From the National Revival to the modern movement."},
{"lit3_sub", "První polovina 20. století.",
"The first half of the 20th century."},
{"lit4_sub", "Od roku 1945 k interpretaci textu.",
"From 1945 to reading a text."},
{"lit_unit1", "Základy literární teorie", "Basics of literary theory"},
{"lit_unit1_sub", "Druhy, žánry, verš a obrazná pojmenování.",
"Genres, verse and figurative language."},
{"lit_ex1_title", "Kvíz: literární teorie", "Quiz: literary theory"},
{"lit_quiz1_head", "Ověřte si základy literární teorie",
"Check the basics of literary theory"},
{"lit_unit2", "Starověké literatury", "Ancient literatures"},
{"lit_unit2_sub", "Orient a Bible jako pramen evropské kultury.",
"The ancient East and the Bible."},
{"lit_ex2_title", "Kvíz: starověk", "Quiz: antiquity"},
{"lit_quiz2_head", "Ověřte si starověké literatury",
"Check the ancient literatures"},
{"lit_unit3", "Antická literatura", "Classical literature"},
{"lit_unit3_sub", "Řecký epos a drama, římská klasika.",
"Greek epic and drama, Roman classics."},
{"lit_ex3_title", "Kvíz: antika", "Quiz: classical antiquity"},
{"lit_quiz3_head", "Ověřte si antickou literaturu",
"Check classical literature"},
{"lit_unit4", "Středověká literatura", "Medieval literature"},
{"lit_unit4_sub", "Hrdinská epika, rytířská tvorba a Dante.",
"Heroic epic, courtly literature and Dante."},
{"lit_ex4_title", "Kvíz: středověk", "Quiz: the Middle Ages"},
{"lit_quiz4_head", "Ověřte si středověkou literaturu",
"Check medieval literature"},
{"lit_unit5", "Česká literatura do husitství", "Early Czech literature"},
{"lit_unit5_sub", "Staroslověnština, latina, čeština a husitství.",
"Old Church Slavonic, Latin, Czech and the Hussites."},
{"lit_ex5_title", "Kvíz: počátky české literatury",
"Quiz: early Czech literature"},
{"lit_quiz5_head", "Ověřte si literaturu do husitství",
"Check early Czech literature"},
{"lit_unit6", "Humanismus a renesance", "Humanism and the Renaissance"},
{"lit_unit6_sub", "Od Petrarky a Shakespeara k Bibli kralické.",
"From Petrarch and Shakespeare to the Kralice Bible."},
{"lit_ex6_title", "Kvíz: renesance", "Quiz: the Renaissance"},
{"lit_quiz6_head", "Ověřte si humanismus a renesanci",
"Check humanism and the Renaissance"},
{"lit_unit7", "Baroko", "The Baroque"},
{"lit_unit7_sub", "Kontrast, Bridel a Komenský.",
"Contrast, Bridel and Comenius."},
{"lit_ex7_title", "Kvíz: baroko", "Quiz: the Baroque"},
{"lit_quiz7_head", "Ověřte si barokní literaturu",
"Check Baroque literature"},
{"lit_unit8", "Klasicismus a osvícenství", "Classicism and the Enlightenment"},
{"lit_unit8_sub", "Pravidlo, rozum a preromantický cit.",
"Rules, reason and pre-Romantic feeling."},
{"lit_ex8_title", "Kvíz: klasicismus", "Quiz: Classicism"},
{"lit_quiz8_head", "Ověřte si klasicismus a osvícenství",
"Check Classicism and the Enlightenment"},
{"lit2_unit1", "Národní obrození", "The Czech National Revival"},
{"lit2_unit1_sub", "Obrana češtiny a Jungmannova generace.",
"Defending Czech and Jungmann's generation."},
{"lit2_ex1_title", "Kvíz: národní obrození", "Quiz: the National Revival"},
{"lit2_quiz1_head", "Ověřte si národní obrození",
"Check the National Revival"},
{"lit2_unit2", "Světový romantismus", "Romanticism abroad"},
{"lit2_unit2_sub", "Byron, Hugo, Puškin a Poe.",
"Byron, Hugo, Pushkin and Poe."},
{"lit2_ex2_title", "Kvíz: světový romantismus", "Quiz: Romanticism abroad"},
{"lit2_quiz2_head", "Ověřte si světový romantismus",
"Check Romanticism abroad"},
{"lit2_unit3", "Český romantismus", "Czech Romanticism"},
{"lit2_unit3_sub", "Mácha, Erben, Tyl, Němcová a Havlíček.",
"Mácha, Erben, Tyl, Němcová and Havlíček."},
{"lit2_ex3_title", "Kvíz: český romantismus", "Quiz: Czech Romanticism"},
{"lit2_quiz3_head", "Ověřte si český romantismus",
"Check Czech Romanticism"},
{"lit2_unit4", "Realismus a naturalismus", "Realism and naturalism"},
{"lit2_unit4_sub", "Balzac, Flaubert, Dickens, Tolstoj a Dostojevskij.",
"Balzac, Flaubert, Dickens, Tolstoy and Dostoevsky."},
{"lit2_ex4_title", "Kvíz: realismus", "Quiz: realism"},
{"lit2_quiz4_head", "Ověřte si realismus a naturalismus",
"Check realism and naturalism"},
{"lit2_unit5", "Májovci", "The Máj generation"},
{"lit2_unit5_sub", "Almanach Máj, Neruda, Hálek a Světlá.",
"The Máj almanac, Neruda, Hálek and Světlá."},
{"lit2_ex5_title", "Kvíz: májovci", "Quiz: the Máj generation"},
{"lit2_quiz5_head", "Ověřte si májovce", "Check the Máj generation"},
{"lit2_unit6", "Ruchovci a lumírovci", "Ruchovci and lumírovci"},
{"lit2_unit6_sub", "Čech, Vrchlický, Sládek a Zeyer.",
"Čech, Vrchlický, Sládek and Zeyer."},
{"lit2_ex6_title", "Kvíz: ruchovci a lumírovci", "Quiz: ruchovci and lumírovci"},
{"lit2_quiz6_head", "Ověřte si ruchovce a lumírovce",
"Check ruchovci and lumírovci"},
{"lit2_unit7", "Česká próza 19. století", "Czech prose of the 19th century"},
{"lit2_unit7_sub", "Rais, Jirásek a Maryša.",
"Rais, Jirásek and Maryša."},
{"lit2_ex7_title", "Kvíz: český realismus", "Quiz: Czech realism"},
{"lit2_quiz7_head", "Ověřte si českou prózu 19. století",
"Check Czech prose of the 19th century"},
{"lit2_unit8", "Moderna a buřiči", "The modern movement and the rebels"},
{"lit2_unit8_sub", "Baudelaire, česká moderna, Šrámek a Bezruč.",
"Baudelaire, the Czech modern movement, Šrámek and Bezruč."},
{"lit2_ex8_title", "Kvíz: moderna", "Quiz: the modern movement"},
{"lit2_quiz8_head", "Ověřte si modernu a buřiče",
"Check the modern movement and the rebels"},
{"lit3_unit1", "Světová avantgarda", "The world avant-garde"},
{"lit3_unit1_sub", "Futurismus, surrealismus a Apollinaire.",
"Futurism, surrealism and Apollinaire."},
{"lit3_ex1_title", "Kvíz: avantgarda", "Quiz: the avant-garde"},
{"lit3_quiz1_head", "Ověřte si světovou avantgardu",
"Check the world avant-garde"},
{"lit3_unit2", "Světová próza mezi válkami", "World prose between the wars"},
{"lit3_unit2_sub", "Ztracená generace, Kafka a experiment.",
"The Lost Generation, Kafka and experiment."},
{"lit3_ex2_title", "Kvíz: meziválečná próza", "Quiz: interwar prose"},
{"lit3_quiz2_head", "Ověřte si světovou prózu mezi válkami",
"Check world prose between the wars"},
{"lit3_unit3", "Světové drama do roku 1945", "World drama to 1945"},
{"lit3_unit3_sub", "Shaw, Pirandello a Brecht.",
"Shaw, Pirandello and Brecht."},
{"lit3_ex3_title", "Kvíz: světové drama", "Quiz: world drama"},
{"lit3_quiz3_head", "Ověřte si drama první poloviny století",
"Check drama of the early 20th century"},
{"lit3_unit4", "První válka v české literatuře", "The First World War in Czech literature"},
{"lit3_unit4_sub", "Hašek, legie a Wolker.",
"Hašek, the legions and Wolker."},
{"lit3_ex4_title", "Kvíz: první válka", "Quiz: the First World War"},
{"lit3_quiz4_head", "Ověřte si literaturu první války",
"Check literature of the First World War"},
{"lit3_unit5", "Česká poezie mezi válkami", "Czech poetry between the wars"},
{"lit3_unit5_sub", "Poetismus, surrealismus, Halas a Holan.",
"Poetism, surrealism, Halas and Holan."},
{"lit3_ex5_title", "Kvíz: meziválečná poezie", "Quiz: interwar poetry"},
{"lit3_quiz5_head", "Ověřte si českou poezii 1918–1938",
"Check Czech poetry of 1918–1938"},
{"lit3_unit6", "Demokratický proud", "The democratic current"},
{"lit3_unit6_sub", "Čapek, Vančura, Poláček a Olbracht.",
"Čapek, Vančura, Poláček and Olbracht."},
{"lit3_ex6_title", "Kvíz: demokratický proud", "Quiz: the democratic current"},
{"lit3_quiz6_head", "Ověřte si meziválečnou demokratickou prózu",
"Check interwar democratic prose"},
{"lit3_unit7", "Psychologická a katolická próza", "Psychological and Catholic prose"},
{"lit3_unit7_sub", "Havlíček, Durych a ruralismus.",
"Havlíček, Durych and ruralism."},
{"lit3_ex7_title", "Kvíz: další próza", "Quiz: other prose"},
{"lit3_quiz7_head", "Ověřte si psychologickou a katolickou prózu",
"Check psychological and Catholic prose"},
{"lit3_unit8", "Literatura za okupace", "Literature under the occupation"},
{"lit3_unit8_sub", "Orten a Skupina 42.",
"Orten and Group 42."},
{"lit3_ex8_title", "Kvíz: okupace", "Quiz: the occupation"},
{"lit3_quiz8_head", "Ověřte si literaturu za okupace",
"Check literature under the occupation"},
{"lit4_unit1", "Světová próza po roce 1945", "World prose after 1945"},
{"lit4_unit1_sub", "Orwell, Camus, Márquez a Solženicyn.",
"Orwell, Camus, Márquez and Solzhenitsyn."},
{"lit4_ex1_title", "Kvíz: poválečná próza", "Quiz: postwar prose"},
{"lit4_quiz1_head", "Ověřte si světovou prózu po roce 1945",
"Check world prose after 1945"},
{"lit4_unit2", "Drama a postmoderna", "Drama and postmodernism"},
{"lit4_unit2_sub", "Beckett, Dürrenmatt a Eco.",
"Beckett, Dürrenmatt and Eco."},
{"lit4_ex2_title", "Kvíz: drama a postmoderna", "Quiz: drama and postmodernism"},
{"lit4_quiz2_head", "Ověřte si absurdní drama a postmodernu",
"Check absurdist drama and postmodernism"},
{"lit4_unit3", "Česká literatura 1945–1956", "Czech literature 1945–1956"},
{"lit4_unit3_sub", "Krátká svoboda a budovatelský román.",
"A brief freedom and the construction novel."},
{"lit4_ex3_title", "Kvíz: léta 1945–1956", "Quiz: 1945–1956"},
{"lit4_quiz3_head", "Ověřte si literaturu let 1945–1956",
"Check literature of 1945–1956"},
{"lit4_unit4", "Česká literatura 60. let", "Czech literature of the 1960s"},
{"lit4_unit4_sub", "Hrabal, Kundera, Škvorecký a Fuks.",
"Hrabal, Kundera, Škvorecký and Fuks."},
{"lit4_ex4_title", "Kvíz: 60. léta", "Quiz: the 1960s"},
{"lit4_quiz4_head", "Ověřte si literaturu 60. let",
"Check the literature of the 1960s"},
{"lit4_unit5", "Normalizace", "Normalization"},
{"lit4_unit5_sub", "Oficiální tvorba, samizdat a exil.",
"Official writing, samizdat and exile."},
{"lit4_ex5_title", "Kvíz: normalizace", "Quiz: Normalization"},
{"lit4_quiz5_head", "Ověřte si tři proudy normalizace",
"Check the three currents of Normalization"},
{"lit4_unit6", "Poezie a drama po roce 1945", "Poetry and drama after 1945"},
{"lit4_unit6_sub", "Seifert, Havel a autorské divadlo.",
"Seifert, Havel and authorial theatre."},
{"lit4_ex6_title", "Kvíz: poezie a drama", "Quiz: poetry and drama"},
{"lit4_quiz6_head", "Ověřte si poválečnou poezii a drama",
"Check postwar poetry and drama"},
{"lit4_unit7", "Literatura po roce 1989", "Literature after 1989"},
{"lit4_unit7_sub", "Konec cenzury, Viewegh a Topol.",
"The end of censorship, Viewegh and Topol."},
{"lit4_ex7_title", "Kvíz: literatura po roce 1989", "Quiz: literature after 1989"},
{"lit4_quiz7_head", "Ověřte si literaturu po roce 1989",
"Check literature after 1989"},
{"lit4_unit8", "Interpretace textu", "Interpreting a text"},
{"lit4_unit8_sub", "Druh, jazyk, kontext a vlastní soud.",
"Genre, language, context and your own judgement."},
{"lit4_ex8_title", "Kvíz: interpretace", "Quiz: interpretation"},
{"lit4_quiz8_head", "Ověřte si postup rozboru textu",
"Check how to read a text"},
{"czech_sub", "Vyberte oblast a začněte procvičovat.",
"Pick an area and start practicing."},
{"Literatura", "Literatura", "Literature"},
@ -2125,6 +2331,7 @@ void on_lessons_apply_lang(void);
void on2_lessons_apply_lang(void);
void on3_lessons_apply_lang(void);
void on4_lessons_apply_lang(void);
void lit_lessons_apply_lang(void);
void net_rail_theme_reset(void);
void apply_language(void) {
@ -2143,5 +2350,6 @@ void apply_language(void) {
on2_lessons_apply_lang();
on3_lessons_apply_lang();
on4_lessons_apply_lang();
lit_lessons_apply_lang();
search_apply_lang();
}

614
src/lit_year1.c Normal file
View file

@ -0,0 +1,614 @@
#include "graduately.h"
/* Year 1: literary theory, antiquity, the Middle Ages, Renaissance,
* Baroque, Classicism and the Enlightenment. */
NetLesson lit_lessons[LIT_N] = {
{ .n_slides = 3, .unit_page = "litunit1", .ex_page = "litex1" },
{ .n_slides = 3, .unit_page = "litunit2", .ex_page = "litex2" },
{ .n_slides = 3, .unit_page = "litunit3", .ex_page = "litex3" },
{ .n_slides = 3, .unit_page = "litunit4", .ex_page = "litex4" },
{ .n_slides = 3, .unit_page = "litunit5", .ex_page = "litex5" },
{ .n_slides = 3, .unit_page = "litunit6", .ex_page = "litex6" },
{ .n_slides = 3, .unit_page = "litunit7", .ex_page = "litex7" },
{ .n_slides = 3, .unit_page = "litunit8", .ex_page = "litex8" },
};
static GtkWidget *build_lit_unit1_page(void) {
static const NetSlide slides[] = {
{
"1 / 3 • Úvod", "Literatura jako umění slova",
"Tip: nejdřív druh a žánr, potom jazyk a dobový kontext.",
{
"Literatura sděluje zážitek uměleckým jazykem, nejen holou informaci.",
"Od publicistiky ji odlišuje estetická funkce a práce s obrazností.",
"Má i funkci poznávací, výchovnou a zábavnou.",
"Ve škole se sleduje vývoj v kulturních a historických souvislostech.",
NULL,
},
},
{
"2 / 3 • Druhy", "Lyrika, epika a drama",
"Tip: žánr je užší typ uvnitř literárního druhu.",
{
"Lyrika vyjadřuje niterný zážitek, epika vypráví příběh.",
"Drama je určeno k jevištnímu provedení a stojí na dialogu.",
"Epika: epos, román, povídka, novela, bajka. Lyrika: píseň, óda, elegie, sonet, balada.",
"Drama: tragédie, komedie, činohra. Vypravěč bývá v ich-formě, nebo er-formě.",
NULL,
},
},
{
"3 / 3 • Jazyk", "Verš, tropy a figury",
"Tip: metafora pojmenuje podobnost přímo, přirovnání použije jako.",
{
"Rým je sdružený (AABB), střídavý (ABAB), obkročný (ABBA) nebo přerývaný.",
"Volný verš se neváže pravidelným rýmem ani stopou.",
"Stopy: trochej, jamb a daktyl. Tropy: metafora, metonymie, personifikace, symbol, alegorie.",
"Figury: anafora, epifora, gradace, inverze, oxymóron a apostrofa.",
NULL,
},
},
};
return lit_unit_page(0, &lit_lessons[0], "lit_unit1", "lit_unit1_sub",
slides, G_N_ELEMENTS(slides));
}
static GtkWidget *build_lit_unit1_exercise_page(void) {
static const ChoiceQ qs[] = {
{"Které jsou tři literární druhy?",
{"Lyrika, epika a drama", "Román, povídka a novela",
"Metafora, metonymie a symbol", "Baroko, romantismus a realismus"},
4, 0},
{"Co je metafora?",
{"Přímé přirovnání se slovem jako",
"Pojmenování na základě podobnosti",
"Opakování slov na začátku veršů", "Báseň bez rýmu"},
4, 1},
{"Který rým má schéma ABAB?",
{"Sdružený", "Obkročný", "Střídavý", "Přerývaný"},
4, 2},
{"Co znamená ich-forma?",
{"Vyprávění v první osobě", "Vyprávění v třetí osobě",
"Drama beze slov", "Volný verš"},
4, 0},
};
static const char *hints[] = {
"Druh je základní členění, žánr je užší typ uvnitř druhu.",
"Přirovnání používá jako, metafora podobnost pojmenuje přímo.",
"Sdružený je AABB, obkročný ABBA, střídavý ABAB.",
"Ich-forma je já, er-forma je on nebo ona.",
};
return lit_mcq_page(0, 0, "litunit1", "lit_ex1_title", "lit_quiz1_head",
qs, hints, 4);
}
static GtkWidget *build_lit_unit2_page(void) {
static const NetSlide slides[] = {
{
"1 / 3 • Orient", "Nejstarší písemnictví",
"Tip: Epos o Gilgamešovi je nejstarší dochovaný epos.",
{
"Mezopotámie zanechala Epos o Gilgamešovi, příběh o přátelství a hledání nesmrtelnosti.",
"Egypt známe z Knihy mrtvých, hymnů a milostné lyriky.",
"Indie má Védy, eposy Mahábhárata a Rámájana a divadelní hry Kálidásovy.",
"Čínská Kniha písní sbírá lidovou i obřadní lyriku.",
NULL,
},
},
{
"2 / 3 • Bible", "Hebrejská a křesťanská tradice",
"Tip: Bible je pramen motivů celé evropské kultury.",
{
"Starý zákon tvoří Tóra, historické a prorocké knihy, žalmy a mudrosloví.",
"Kazatel, Job a Píseň písní patří k nejčtenějším starozákonním knihám.",
"Nový zákon přináší evangelia, Skutky, epištoly a Zjevení.",
"Biblické postavy a obrazy se vracejí v literatuře všech pozdějších epoch.",
NULL,
},
},
{
"3 / 3 • Paměť", "Co si z orientu odnést",
"Tip: u eposu sledujte hrdinu, cestu a střet s osudem.",
{
"Společná témata jsou stvoření, potopa, zákon, láska a smrt.",
"Texty často vznikaly ústně a teprve později byly zapsány.",
"Anonymita a náboženský výklad světa převažují nad autorským já.",
"Na maturitě stačí zařadit dílo do kultury a říct, čím ovlivnilo Evropu.",
NULL,
},
},
};
return lit_unit_page(0, &lit_lessons[1], "lit_unit2", "lit_unit2_sub",
slides, G_N_ELEMENTS(slides));
}
static GtkWidget *build_lit_unit2_exercise_page(void) {
static const ChoiceQ qs[] = {
{"Odkud pochází Epos o Gilgamešovi?",
{"Ze starého Egypta", "Z Mezopotámie", "Z antického Říma", "Ze středověké Francie"},
4, 1},
{"Které knihy patří k indické epice?",
{"Ilias a Odyssea", "Mahábhárata a Rámájana",
"Aeneis a Proměny", "Božská komedie a Dekameron"},
4, 1},
{"Co tvoří jádro Starého zákona?",
{"Čtyři evangelia", "Tóra a další knihy hebrejské bible",
"Korán", "Védy"},
4, 1},
{"Proč se Bible probírá v literatuře?",
{"Je to učebnice zeměpisu",
"Je pramenem motivů evropské kultury",
"Vznikla v národním obrození",
"Patří k absurdnímu dramatu"},
4, 1},
};
static const char *hints[] = {
"Gilgameš je nejstarší dochovaný epos, zapsaný klínovým písmem.",
"Mahábhárata a Rámájana jsou velké indické eposy.",
"Starý zákon je hebrejská bible, Nový zákon evangelia a epištoly.",
"Biblické obrazy se vracejí od středověku po současnost.",
};
return lit_mcq_page(0, 1, "litunit2", "lit_ex2_title", "lit_quiz2_head",
qs, hints, 4);
}
static GtkWidget *build_lit_unit3_page(void) {
static const NetSlide slides[] = {
{
"1 / 3 • Řecko", "Homér a attické drama",
"Tip: katarze je očištění diváka soucitem a bázní.",
{
"Homérova Ilias a Odyssea jsou vrchol řeckého eposu, veršovaný hexametrem.",
"Lyriku představují Sapfó, Anakreón a Pindaros.",
"Tragédie: Aischylos, Sofoklés (Král Oidipus, Antigona) a Eurípidés (Médeia).",
"Aristofanés psal komedie. Ideál kalokagathia spojoval krásu a dobro.",
NULL,
},
},
{
"2 / 3 • Řím", "Vergilius, Ovidius, Horatius",
"Tip: Aeneis vědomě navazuje na Homéra a zakládá římský mýtus.",
{
"Vergiliova Aeneis vypráví o útěku z Tróje a založení římského rodu.",
"Ovidiovy Proměny shrnují antické mýty, Umění milovat je milostný návod.",
"Horatius proslul ódami a myšlenkou zlaté střední cesty.",
"Římská literatura přejímá řecké vzory a předává je středověké Evropě.",
NULL,
},
},
{
"3 / 3 • Pojmy", "Co si z antiky pamatovat",
"Tip: u tragédie hledejte vinu, osud a poznání.",
{
"Epos začíná často in medias res a vzývá Múzu.",
"Tragický hrdina naráží na osud; divák prožívá katarzi.",
"Mýtus vysvětluje svět příběhem bohů a hrdinů.",
"Antika je stálý zdroj námětů pro renesanci, klasicismus i pozdější doby.",
NULL,
},
},
};
return lit_unit_page(0, &lit_lessons[2], "lit_unit3", "lit_unit3_sub",
slides, G_N_ELEMENTS(slides));
}
static GtkWidget *build_lit_unit3_exercise_page(void) {
static const ChoiceQ qs[] = {
{"Kdo napsal Iliadu a Odysseu?",
{"Sofoklés", "Homér", "Vergilius", "Ovidius"},
4, 1},
{"Které dílo napsal Sofoklés?",
{"Médeia", "Král Oidipus", "Aeneis", "Proměny"},
4, 1},
{"Co je katarze?",
{"Začátek eposu uprostřed děje",
"Očištění diváka soucitem a bázní",
"Římský název pro komedii",
"Volný verš bez stopy"},
4, 1},
{"Kdo složil Aeneis?",
{"Horatius", "Homér", "Vergilius", "Aristofanés"},
4, 2},
};
static const char *hints[] = {
"Ilias a Odyssea jsou homérské eposy.",
"Sofoklés: Král Oidipus a Antigona. Médeia je Eurípidés.",
"Pojem katarze vychází z Aristotelovy Poetiky.",
"Aeneis je římský epos Vergiliův, Proměny napsal Ovidius.",
};
return lit_mcq_page(0, 2, "litunit3", "lit_ex3_title", "lit_quiz3_head",
qs, hints, 4);
}
static GtkWidget *build_lit_unit4_page(void) {
static const NetSlide slides[] = {
{
"1 / 3 • Doba", "Středověký pohled na svět",
"Tip: texty bývají anonymní a často nábožensky alegorické.",
{
"Středověk vykládá svět křesťansky: pozemský život je cestou ke spáse.",
"Převažuje latina, postupně se prosazují národní jazyky.",
"Autor často ustupuje, dílo má sloužit víře, poučení nebo oslavě hrdiny.",
"Vedle učené tvorby žije ústní lidová slovesnost.",
NULL,
},
},
{
"2 / 3 • Žánry", "Hrdinská, rytířská a městská literatura",
"Tip: Dante uzavírá středověk a otevírá cestu k renesanci.",
{
"Hrdinská epika: Píseň o Rolandovi, Píseň o Nibelunzích, Beowulf.",
"Rytířská epika a dvorská lyrika: artušovské romány, Tristan a Isolda, trubadúři.",
"Náboženská literatura: legendy, hymny, exempla a duchovní drama.",
"Městská satira a Danteho Božská komedie, psaná tercínou.",
NULL,
},
},
{
"3 / 3 • Paměť", "Jak středověk číst",
"Tip: alegorie říká jednu věc a míní jinou, hlubší.",
{
"Hrdina ztělesňuje čest, věrnost, víru nebo rytířskou lásku.",
"Symbol a alegorie jsou důležitější než psychologická kresba.",
"Božská komedie provádí poutníka Peklem, Očistcem a Rájem.",
"Středověké látky se vracejí v romantismu i v moderní kultuře.",
NULL,
},
},
};
return lit_unit_page(0, &lit_lessons[3], "lit_unit4", "lit_unit4_sub",
slides, G_N_ELEMENTS(slides));
}
static GtkWidget *build_lit_unit4_exercise_page(void) {
static const ChoiceQ qs[] = {
{"Které dílo patří k hrdinské epice?",
{"Dekameron", "Píseň o Rolandovi", "Hamlet", "Lakomec"},
4, 1},
{"Čím je typický středověký text?",
{"Důrazem na individuální autorské já",
"Náboženským výkladem a častou anonymitou",
"Volným veršem avantgardy",
"Naturalistickým popisem dědičnosti"},
4, 1},
{"Kdo napsal Božskou komedii?",
{"Francesco Petrarca", "Dante Alighieri",
"Giovanni Boccaccio", "William Shakespeare"},
4, 1},
{"Jakou strofou je psána Božská komedie?",
{"Sonetem", "Tercínou", "Blankversem", "Hexametrem"},
4, 1},
};
static const char *hints[] = {
"Píseň o Rolandovi je francouzská chanson de geste.",
"Středověk klade víru a poučení nad autorskou originalitu.",
"Dante, Petrarca a Boccaccio jsou tři velcí Italové, Božská komedie je Dantova.",
"Tercína je trojverší, které Dante v komedii používá.",
};
return lit_mcq_page(0, 3, "litunit4", "lit_ex4_title", "lit_quiz4_head",
qs, hints, 4);
}
static GtkWidget *build_lit_unit5_page(void) {
static const NetSlide slides[] = {
{
"1 / 3 • Počátky", "Staroslověnština a latina",
"Tip: rok 863 je příchod Konstantina a Metoděje na Velkou Moravu.",
{
"Konstantin a Metoděj přinesli staroslověnské písmo a překlady bohoslužebných textů.",
"K památkám patří Proglas, Život Konstantinův a Metodějův a Kyjevské listy.",
"Po vyhnání slovanské liturgie přebírá vzdělanost latina.",
"Kosmova kronika je nejstarší česká kronika, psaná latinsky.",
NULL,
},
},
{
"2 / 3 • Čeština", "Literatura 14. století",
"Tip: Dalimil píše česky a z hlediska české šlechty.",
{
"Dalimilova kronika je první veršovaná kronika v češtině.",
"Alexandreida přenáší antický příběh o Alexandrovi do rytířského světa.",
"Mastičkář je nejstarší české drama, Hradecký rukopis sbírá legendy a satiru.",
"Doba Karla IV. posiluje češtinu vedle latiny a němčiny.",
NULL,
},
},
{
"3 / 3 • Husitství", "Hus, píseň a Chelčický",
"Tip: husitství je vrchol starší české literatury v národním jazyce.",
{
"Jan Hus kritizuje církev v českých kázáních a latinském spise O církvi.",
"Jistebnický kancionál uchoval píseň Ktož jsú boží bojovníci.",
"Petr Chelčický v Sieti viery odmítá násilí a spojení víry s mocí.",
"Husitská čeština zjednodušuje pravopis a posiluje srozumitelnost.",
NULL,
},
},
};
return lit_unit_page(0, &lit_lessons[4], "lit_unit5", "lit_unit5_sub",
slides, G_N_ELEMENTS(slides));
}
static GtkWidget *build_lit_unit5_exercise_page(void) {
static const ChoiceQ qs[] = {
{"Kdy přišli Konstantin a Metoděj na Velkou Moravu?",
{"Roku 863", "Roku 1415", "Roku 1348", "Roku 1620"},
4, 0},
{"Která kronika je první v češtině?",
{"Kosmova kronika", "Dalimilova kronika",
"Hájkova kronika", "Vita Caroli"},
4, 1},
{"Kterou píseň uchoval Jistebnický kancionál?",
{"Kde domov můj", "Ktož jsú boží bojovníci",
"Ach synku, synku", "Hej, Slované"},
4, 1},
{"Čím je Petr Chelčický?",
{"Autorem renesančních sonetů",
"Myslitelem, který odmítá násilí a spojení víry s mocí",
"Barokním kazatelem protireformace",
"Obrozenským jazykovědcem"},
4, 1},
};
static const char *hints[] = {
"863 je cyrilometodějská misie, 1415 upálení Husa.",
"Kosmas psal latinsky, Dalimil česky.",
"Ktož jsú boží bojovníci je husitská bojová píseň.",
"Sieť viery pravé je Chelčického hlavní spis.",
};
return lit_mcq_page(0, 4, "litunit5", "lit_ex5_title", "lit_quiz5_head",
qs, hints, 4);
}
static GtkWidget *build_lit_unit6_page(void) {
static const NetSlide slides[] = {
{
"1 / 3 • Doba", "Člověk se vrací do středu",
"Tip: humanismus staví na antice, renesance na smyslovém světě.",
{
"Humanismus obnovuje zájem o antiku, jazyk a vzdělání člověka.",
"Renesance oslavuje pozemský život, individualitu a smyslovou krásu.",
"Itálie udává tón: Petrarcův sonet a Boccacciův Dekameron.",
"Proti středověkému teocentrismu stojí zájem o člověka a přírodu.",
NULL,
},
},
{
"2 / 3 • Evropa", "Od Cervantese k Shakespearovi",
"Tip: Hamlet je renesanční hrdina, který pochybuje a zkoumá.",
{
"Francie: Rabelais (Gargantua a Pantagruel) a Montaignovy Eseje.",
"Španělsko: Cervantesův Důmyslný rytíř don Quijote de la Mancha.",
"Anglie: Shakespeare, tragédie Hamlet, Romeo a Julie, Macbeth, Othello a komedie.",
"Sonet má 14 veršů a pevné schéma; Shakespeare ho užívá i v milostné lyrice.",
NULL,
},
},
{
"3 / 3 • Čechy", "Veleslavín a Bible kralická",
"Tip: Bible kralická je vrchol humanistické češtiny.",
{
"Jednota bratrská vydává Bibli kralickou, vzor spisovného jazyka.",
"Daniel Adam z Veleslavína podporuje tisk, překlady a vzdělanost.",
"Jan Blahoslav pečuje o jazyk a bratrský zpěvník.",
"Český humanismus končí porážkou stavovského povstání a pobělohorskou změnou.",
NULL,
},
},
};
return lit_unit_page(0, &lit_lessons[5], "lit_unit6", "lit_unit6_sub",
slides, G_N_ELEMENTS(slides));
}
static GtkWidget *build_lit_unit6_exercise_page(void) {
static const ChoiceQ qs[] = {
{"Kdo je autorem Dekameronu?",
{"Dante Alighieri", "Giovanni Boccaccio",
"Francesco Petrarca", "Miguel de Cervantes"},
4, 1},
{"Které dílo napsal Shakespeare?",
{"Don Quijote", "Hamlet", "Gargantua a Pantagruel", "Božská komedie"},
4, 1},
{"Co je sonet?",
{"Báseň o 14 verších s pevnou stavbou",
"Středověká hrdinská píseň",
"Dramatická jednota času",
"Barokní kázání"},
4, 0},
{"Která kniha je vrcholem humanistické češtiny?",
{"Kosmova kronika", "Bible kralická", "Labyrint světa", "Máj"},
4, 1},
};
static const char *hints[] = {
"Petrarca je sonet, Boccaccio Dekameron, Dante Božská komedie.",
"Hamlet, Romeo a Julie, Macbeth a Othello jsou Shakespearovy tragédie.",
"Sonet má 14 veršů, obvykle dvě čtyřverší a dvě trojverší.",
"Bibli kralickou vydala Jednota bratrská na přelomu 16. a 17. století.",
};
return lit_mcq_page(0, 5, "litunit6", "lit_ex6_title", "lit_quiz6_head",
qs, hints, 4);
}
static GtkWidget *build_lit_unit7_page(void) {
static const NetSlide slides[] = {
{
"1 / 3 • Styl", "Kontrast a napětí",
"Tip: baroko miluje protiklad těla a duše, světa a věčnosti.",
{
"Baroko vzniká v napětí reformace a protireformace.",
"Vyhledává kontrast, nadsázku, emblém a smyslovou okázalost.",
"Častý je motiv marnosti, smrti a touhy po Bohu.",
"Ve světě sem patří Calderónův Život je sen a Miltonův Ztracený ráj.",
NULL,
},
},
{
"2 / 3 • Čechy", "Pobělohorská tvorba",
"Tip: po roce 1620 se dělí domácí katolická tvorba a exil.",
{
"Bedřich Bridel v básni Co Bůh? Člověk? staví nicotu člověka proti Bohu.",
"Bohuslav Balbín brání v latině český jazyk a dějiny.",
"Lidová a pololidová tvorba, kramářské písně a legendy udržují češtinu.",
"Oficiální kultura je katolická, mnoho vzdělanců odchází do exilu.",
NULL,
},
},
{
"3 / 3 • Komenský", "Labyrint světa a ráj srdce",
"Tip: Komenský je vrchol českého baroka i evropského pedagogického myšlení.",
{
"Jan Amos Komenský, poslední biskup Jednoty bratrské, píše v exilu.",
"Labyrint světa a ráj srdce je alegorické putování za smyslem života.",
"Informatorium školy mateřské a Orbis pictus zakládají moderní pedagogiku.",
"Kšaft umírající matky Jednoty bratrské je odkaz národu a jazyku.",
NULL,
},
},
};
return lit_unit_page(0, &lit_lessons[6], "lit_unit7", "lit_unit7_sub",
slides, G_N_ELEMENTS(slides));
}
static GtkWidget *build_lit_unit7_exercise_page(void) {
static const ChoiceQ qs[] = {
{"Který rys vystihuje baroko?",
{"Klidná vyváženost a tři jednoty",
"Kontrast, nadsázka a napětí těla a duše",
"Popis všedního dne bez obraznosti",
"Odmítání náboženství"},
4, 1},
{"Kdo napsal Co Bůh? Člověk?",
{"Jan Amos Komenský", "Bedřich Bridel",
"Bohuslav Balbín", "Daniel Adam z Veleslavína"},
4, 1},
{"O čem je Labyrint světa a ráj srdce?",
{"O alegorickém putování za smyslem života",
"O válce s mloky",
"O národním obrození",
"O životě Švejka"},
4, 0},
{"Kam patří Komenského pedagogické spisy?",
{"K poetismu", "K baroku a počátkům moderní pedagogiky",
"K májovcům", "K existencialismu"},
4, 1},
};
static const char *hints[] = {
"Baroko pracuje s protikladem, světlem a stínem, tělem a věčností.",
"Bridel je autor básně Co Bůh? Člověk?, Komenský napsal Labyrint.",
"Poutník prochází marným světem a nalézá klid v srdci u Boha.",
"Informatorium a Orbis pictus jsou Komenského učební spisy.",
};
return lit_mcq_page(0, 6, "litunit7", "lit_ex7_title", "lit_quiz7_head",
qs, hints, 4);
}
static GtkWidget *build_lit_unit8_page(void) {
static const NetSlide slides[] = {
{
"1 / 3 • Klasicismus", "Rozum a pravidlo",
"Tip: tři jednoty jsou jednota času, místa a děje.",
{
"Klasicismus 17. století navazuje na antiku a žádá kázeň, harmonii a pravidla.",
"Vyvrcholil ve Francii: Corneille, Racine a Molièrovy komedie.",
"Molièrův Lakomec a Tartuffe zesměšňují lidskou vadu jako typ.",
"La Fontaine převyprávěl bajky, Boileau sepsal pravidla básnictví.",
NULL,
},
},
{
"2 / 3 • Osvícenství", "Rozum má měnit společnost",
"Tip: Candide se vysmívá lehké víře, že žijeme v nejlepším z světů.",
{
"Osvícenství věří rozumu, vzdělání, toleranci a kritice předsudků.",
"Voltairův Candide a Swiftovy Gulliverovy cesty jsou satirické prózy.",
"Defoeův Robinson Crusoe oslavuje práci a praktický rozum.",
"Encyklopedisté včetně Diderota chtějí zpřístupnit vědění.",
NULL,
},
},
{
"3 / 3 • Cit", "Preromantismus a cesta k obrození",
"Tip: Werther otevírá literaturu citovému jednotlivci.",
{
"Preromantismus staví cit, přírodu a středověk proti chladnému rozumu.",
"Goethovo Utrpení mladého Werthera a Faust spojují cit i filozofii.",
"Schillerovy Loupežníci hájí svobodu proti útisku.",
"V Čechách na osvícenskou učenost naváže národní obrození.",
NULL,
},
},
};
return lit_unit_page(0, &lit_lessons[7], "lit_unit8", "lit_unit8_sub",
slides, G_N_ELEMENTS(slides));
}
static GtkWidget *build_lit_unit8_exercise_page(void) {
static const ChoiceQ qs[] = {
{"Co jsou tři jednoty klasicistního dramatu?",
{"Jednota času, místa a děje",
"Jednota autora, hrdiny a čtenáře",
"Jednota rýmu, stopy a sloky",
"Jednota lyriky, epiky a dramatu"},
4, 0},
{"Kdo napsal Lakomce?",
{"William Shakespeare", "Molière", "Johann Wolfgang Goethe", "Voltaire"},
4, 1},
{"Které dílo je osvícenská satira?",
{"Kytice", "Candide", "Máj", "Babička"},
4, 1},
{"Čím preromantismus překonává klasicismus?",
{"Důrazem na cit, přírodu a individuální prožitek",
"Přísnějšími pravidly rýmu",
"Návratem výhradně k latině",
"Odmítnutím divadla"},
4, 0},
};
static const char *hints[] = {
"Klasicistní tragédie se má odehrát v jednom dni, na jednom místě a v jedné linii.",
"Molière je autorem Lakomce a Tartuffa.",
"Candide napsal Voltaire, Gulliverovy cesty Swift.",
"Werther a Schillerovi Loupežníci už staví cit proti pravidlu.",
};
return lit_mcq_page(0, 7, "litunit8", "lit_ex8_title", "lit_quiz8_head",
qs, hints, 4);
}
void add_lit_pages(GtkStack *stack) {
typedef GtkWidget *(*LitBuilder)(void);
static const struct {
const char *unit_name;
const char *ex_name;
LitBuilder build_unit;
LitBuilder build_ex;
} pages[] = {
{"litunit1", "litex1", build_lit_unit1_page, build_lit_unit1_exercise_page},
{"litunit2", "litex2", build_lit_unit2_page, build_lit_unit2_exercise_page},
{"litunit3", "litex3", build_lit_unit3_page, build_lit_unit3_exercise_page},
{"litunit4", "litex4", build_lit_unit4_page, build_lit_unit4_exercise_page},
{"litunit5", "litex5", build_lit_unit5_page, build_lit_unit5_exercise_page},
{"litunit6", "litex6", build_lit_unit6_page, build_lit_unit6_exercise_page},
{"litunit7", "litex7", build_lit_unit7_page, build_lit_unit7_exercise_page},
{"litunit8", "litex8", build_lit_unit8_page, build_lit_unit8_exercise_page},
};
for (guint i = 0; i < G_N_ELEMENTS(pages); i++) {
gtk_stack_add_named(stack, pages[i].build_unit(), pages[i].unit_name);
gtk_stack_add_named(stack, pages[i].build_ex(), pages[i].ex_name);
}
}

611
src/lit_year2.c Normal file
View file

@ -0,0 +1,611 @@
#include "graduately.h"
/* Year 2: National Revival, Romanticism, Realism, the Máj generation,
* ruchovci and lumírovci, Czech realism, the modern movement. */
NetLesson lit2_lessons[LIT_N] = {
{ .n_slides = 3, .unit_page = "lit2unit1", .ex_page = "lit2ex1" },
{ .n_slides = 3, .unit_page = "lit2unit2", .ex_page = "lit2ex2" },
{ .n_slides = 3, .unit_page = "lit2unit3", .ex_page = "lit2ex3" },
{ .n_slides = 3, .unit_page = "lit2unit4", .ex_page = "lit2ex4" },
{ .n_slides = 3, .unit_page = "lit2unit5", .ex_page = "lit2ex5" },
{ .n_slides = 3, .unit_page = "lit2unit6", .ex_page = "lit2ex6" },
{ .n_slides = 3, .unit_page = "lit2unit7", .ex_page = "lit2ex7" },
{ .n_slides = 3, .unit_page = "lit2unit8", .ex_page = "lit2ex8" },
};
static GtkWidget *build_lit2_unit1_page(void) {
static const NetSlide slides[] = {
{
"1 / 3 • Smysl", "Proč obrození vzniklo",
"Tip: obrození zachraňuje češtinu jako jazyk vzdělanosti a národa.",
{
"Na konci 18. století je čeština hlavně jazykem venkova a kuchyně.",
"Osvícenství a herderovská myšlenka národa dávají podnět k obraně jazyka.",
"Cíl je vrátit češtinu do vědy, školy, divadla a krásné literatury.",
"Obrození se obvykle dělí na fázi obrannou a ofenzivní.",
NULL,
},
},
{
"2 / 3 • Obrana", "Dobrovský a první generace",
"Tip: Dobrovský češtinu vědecky popisuje, ale o její budoucnosti pochybuje.",
{
"Josef Dobrovský píše Zevrubnou mluvnici a zkoumá staroslověnštinu.",
"Václav Thám a Kramerius vydávají české knihy a noviny pro lid.",
"Vzniká české divadlo, Bouda a snaha hrát v národním jazyce.",
"První fáze jazyk brání a popisuje, ještě ho plně nerozvíjí v umění.",
NULL,
},
},
{
"3 / 3 • Útok", "Jungmann, Kollár, Čelakovský",
"Tip: Rukopisy královédvorský a zelenohorský měly dodat národu starou epiku.",
{
"Josef Jungmann vytváří česko-německý slovník a překládá z evropských literatur.",
"František Palacký píše dějiny jako příběh národa.",
"Kollárova Slávy dcera a Čelakovského Ohlasy spojují slovanskou myšlenku s lidovou písní.",
"Rukopisy z let 1817 a 1818 literaturu na čas ovlivnily, později byly odhaleny jako padělky.",
NULL,
},
},
};
return lit_unit_page(1, &lit2_lessons[0], "lit2_unit1", "lit2_unit1_sub",
slides, G_N_ELEMENTS(slides));
}
static GtkWidget *build_lit2_unit1_exercise_page(void) {
static const ChoiceQ qs[] = {
{"Jaký byl hlavní cíl národního obrození?",
{"Nahradit češtinu latinou",
"Obnovit češtinu jako jazyk kultury a národa",
"Zavést romantický román podle Francie",
"Zrušit divadlo"},
4, 1},
{"Čím je Josef Dobrovský?",
{"Autorem Máje", "Jazykovědcem obranné fáze",
"Lumírovcem", "Autorem Bible kralické"},
4, 1},
{"Kdo sestavil velký česko-německý slovník?",
{"Josef Jungmann", "Karel Hynek Mácha",
"Jan Neruda", "Jaroslav Vrchlický"},
4, 0},
{"Co jsou Rukopisy královédvorský a zelenohorský?",
{"Díla Kosmy", "Padělky, které měly dokázat starobylost české epiky",
"Husitské kroniky", "Barokní kancionály"},
4, 1},
};
static const char *hints[] = {
"Obrození brání a potom rozvíjí národní jazyk.",
"Dobrovský patří k obranné fázi, Jungmann k ofenzivní.",
"Jungmannův slovník a překlady otevírají češtinu vysoké literatuře.",
"RKZ vznikly 1817 a 1818 a později byly rozpoznány jako podvrhy.",
};
return lit_mcq_page(1, 0, "lit2unit1", "lit2_ex1_title", "lit2_quiz1_head",
qs, hints, 4);
}
static GtkWidget *build_lit2_unit2_page(void) {
static const NetSlide slides[] = {
{
"1 / 3 • Postoj", "Jedinec proti světu",
"Tip: romantik hledá v minulosti, přírodě a výjimečném hrdinovi to, co současnost nedává.",
{
"Romantismus staví cit, obraznost a svobodu jednotlivce proti pravidlům klasicismu.",
"Hrdina je výjimečný, často vyvržený, a střetává se se společností.",
"Oblíbené je středověk, lidová slovesnost, exotika a tajemno.",
"Rozpor mezi snem a skutečností je základní romantické napětí.",
NULL,
},
},
{
"2 / 3 • Evropa", "Byron, Hugo, Puškin",
"Tip: Byronův hrdina je unavený, hrdý a v rozporu se světem.",
{
"Anglie: Byron, Shelley, Scottovy historické romány a jezerní básníci.",
"Francie: Victor Hugo, Chrám Matky Boží v Paříži a Bídníci, předmluva ke Cromwellovi.",
"Německo: bratři Grimmové, Novalis a Heinrich Heine.",
"Rusko: Puškinův Evžen Oněgin a Lermontov. Polsko: Mickiewicz.",
NULL,
},
},
{
"3 / 3 • Amerika", "Poe a romantické tajemno",
"Tip: Poe stojí u hororu, detektivky i teorie básně.",
{
"Edgar Allan Poe píše Havrana, hrůzostrašné povídky a detektivní záhady.",
"Romantismus otevírá i gotický román a téma dvojnictví.",
"Historický román učí číst dějiny jako osud národa.",
"Tyto vzory silně působí na český romantismus v čele s Máchou.",
NULL,
},
},
};
return lit_unit_page(1, &lit2_lessons[1], "lit2_unit2", "lit2_unit2_sub",
slides, G_N_ELEMENTS(slides));
}
static GtkWidget *build_lit2_unit2_exercise_page(void) {
static const ChoiceQ qs[] = {
{"Co je pro romantismus typické?",
{"Tři jednoty a rozumová kázeň",
"Cit, rozpor jedince se společností a zájem o minulost",
"Přesný popis všední práce",
"Odmítnutí obraznosti"},
4, 1},
{"Kdo napsal Evžena Oněgina?",
{"Victor Hugo", "Alexandr Sergejevič Puškin",
"George Gordon Byron", "Edgar Allan Poe"},
4, 1},
{"Které dílo patří Victoru Hugovi?",
{"Bídníci", "Lakomec", "Candide", "Král Oidipus"},
4, 0},
{"Čím je Edgar Allan Poe?",
{"Autorem realistického románu o venkově",
"Romantikem hororu, tajemna a detektivní povídky",
"Klasicistním dramatikem",
"Autorem husitské kroniky"},
4, 1},
};
static const char *hints[] = {
"Romantický hrdina stojí proti obyčejnému světu.",
"Evžen Oněgin je veršovaný román Puškinův.",
"Hugo napsal Bídníky a Chrám Matky Boží v Paříži.",
"Havran a povídky tajemna jsou Poeova romantická tvorba.",
};
return lit_mcq_page(1, 1, "lit2unit2", "lit2_ex2_title", "lit2_quiz2_head",
qs, hints, 4);
}
static GtkWidget *build_lit2_unit3_page(void) {
static const NetSlide slides[] = {
{
"1 / 3 • Máj", "Karel Hynek Mácha",
"Tip: Máj vyšel 1836 a doba mu vytýkala, že není dost vlastenecký.",
{
"Máj je lyrickoepická skladba o vině, času a rozporu snu se skutečností.",
"Vilém zabije svůdce milenky a neví, že zabil vlastního otce.",
"Příroda je krásná a lhostejná k lidskému utrpení.",
"Báseň je psána jambem a patří k vrcholům české poezie.",
NULL,
},
},
{
"2 / 3 • Balada", "Erben, Tyl a Němcová",
"Tip: v Kytici trestá osud vinu, často vinu rodičů na dětech.",
{
"Karel Jaromír Erben vydal 1853 Kytici, soubor balad z lidové víry.",
"Josef Kajetán Tyl píše Strakonického dudáka a hru Fidlovačka s písní Kde domov můj.",
"Božena Němcová v Babičce staví ideál lidskosti a venkovského řádu.",
"Její povídky, třeba Divá Bára, hájí právo ženy na vlastní cestu.",
NULL,
},
},
{
"3 / 3 • Satira", "Havlíček a vyvrcholení obrození",
"Tip: Havlíček už romantický patos ironizuje a měří ho politikou.",
{
"Karel Havlíček Borovský píše epigramy, Tyrolské elegie a Křest svatého Vladimíra.",
"Satira míří na absolutismus, církevní moc a národní pózu.",
"Třetí fáze obrození splývá s romantismem a politickým ruchem roku 1848.",
"Mácha, Erben, Tyl, Němcová a Havlíček jsou jádro českého romantismu.",
NULL,
},
},
};
return lit_unit_page(1, &lit2_lessons[2], "lit2_unit3", "lit2_unit3_sub",
slides, G_N_ELEMENTS(slides));
}
static GtkWidget *build_lit2_unit3_exercise_page(void) {
static const ChoiceQ qs[] = {
{"Kdy vyšel Máchův Máj?",
{"Roku 1836", "Roku 1853", "Roku 1858", "Roku 1895"},
4, 0},
{"O čem jsou Erbenovy balady v Kytici?",
{"O budování továren", "O vině a trestu podle lidové víry",
"O legionářích", "O absurdním čekání"},
4, 1},
{"Kde zazní píseň Kde domov můj?",
{"V Máji", "Ve Fidlovačce Josefa Kajetána Tyla",
"V Babičce", "V Labyrintu světa"},
4, 1},
{"Které dílo napsal Karel Havlíček Borovský?",
{"Tyrolské elegie", "Povídky malostranské",
"Psohlavci", "R.U.R."},
4, 0},
};
static const char *hints[] = {
"Máj 1836, Kytice 1853, almanach Máj 1858.",
"Erbenova balada spojuje lidový příběh s mravním řádem.",
"Tylova Fidlovačka obsahuje píseň, z níž vznikla hymna.",
"Havlíček: epigramy, Tyrolské elegie, Křest svatého Vladimíra.",
};
return lit_mcq_page(1, 2, "lit2unit3", "lit2_ex3_title", "lit2_quiz3_head",
qs, hints, 4);
}
static GtkWidget *build_lit2_unit4_page(void) {
static const NetSlide slides[] = {
{
"1 / 3 • Metoda", "Vidět společnost takovou, jaká je",
"Tip: realismus typizuje, naturalismus přidává dědičnost a prostředí.",
{
"Realismus popisuje současnost, společenské vrstvy a všední konflikty.",
"Postava je typ: nese rysy své doby, třídy a prostředí.",
"Vypravěč bývá střízlivý a dává prostor detailu.",
"Naturalismus jde dál: člověka určuje dědičnost, pudy a hmotné podmínky.",
NULL,
},
},
{
"2 / 3 • Francie a Anglie", "Od Balzaca k Zolovi",
"Tip: Paní Bovaryová ukazuje střet romantického snu s provincií.",
{
"Honoré de Balzac v Lidské komedii mapuje francouzskou společnost.",
"Stendhalův Červený a černý sleduje ctižádost v porevoluční Francii.",
"Flaubertova Paní Bovaryová je vrchol psychologického realismu.",
"Zola (Zabiják) je naturalista. Dickens (Oliver Twist) kritizuje bídu průmyslové Anglie.",
NULL,
},
},
{
"3 / 3 • Rusko", "Tolstoj, Dostojevskij, Čechov",
"Tip: Dostojevskij zkoumá vinu svědomí, Tolstoj široký obraz doby.",
{
"Nikolaj Gogol spojuje satiru a grotesku, Revizor je komedie o strachu z moci.",
"Lev Tolstoj píše Vojnu a mír a Annu Kareninu.",
"Fjodor Michajlovič Dostojevskij ve Zločinu a trestu řeší vinu a trest svědomí.",
"Anton Pavlovič Čechov zklidňuje drama i povídku do zdánlivě obyčejného života.",
NULL,
},
},
};
return lit_unit_page(1, &lit2_lessons[3], "lit2_unit4", "lit2_unit4_sub",
slides, G_N_ELEMENTS(slides));
}
static GtkWidget *build_lit2_unit4_exercise_page(void) {
static const ChoiceQ qs[] = {
{"Čím se realismus liší od romantismu?",
{"Hledá výjimečného hrdinu mimo společnost",
"Zobrazuje současnou společnost a typické postavy",
"Drží se tří jednot klasicismu",
"Píše jen duchovní legendy"},
4, 1},
{"Kdo je autorem Paní Bovaryové?",
{"Émile Zola", "Gustave Flaubert", "Charles Dickens", "Lev Tolstoj"},
4, 1},
{"Které dílo napsal Dostojevskij?",
{"Zločin a trest", "Oliver Twist", "Evžen Oněgin", "Bídníci"},
4, 0},
{"Co zdůrazňuje naturalismus?",
{"Jen šťastný konec pohádky",
"Vliv dědičnosti, pudů a prostředí",
"Pravidla antické tragédie",
"Slovanskou vzájemnost"},
4, 1},
};
static const char *hints[] = {
"Realistický hrdina je typ své vrstvy a doby.",
"Flaubert napsal Paní Bovaryovou, Zola je naturalista.",
"Zločin a trest je román o vině Raskolnikova.",
"Zola chápe člověka jako určeného tělem a prostředím.",
};
return lit_mcq_page(1, 3, "lit2unit4", "lit2_ex4_title", "lit2_quiz4_head",
qs, hints, 4);
}
static GtkWidget *build_lit2_unit5_page(void) {
static const NetSlide slides[] = {
{
"1 / 3 • Program", "Almanach Máj 1858",
"Tip: májovci chtějí literaturu světovou, pravdivou a současnou.",
{
"Mladá generace se hlásí k Máchovi a odmítá vlasteneckou frázi.",
"Almanach Máj žádá umění otevřené Evropě a skutečnému životu.",
"K okruhu patří Neruda, Hálek, Světlá a Pfleger.",
"Generace reaguje na Bachův absolutismus a politické zklamání.",
NULL,
},
},
{
"2 / 3 • Neruda", "Poezie, fejeton a Malá Strana",
"Tip: Povídky malostranské jsou galerie typů, ne idyla.",
{
"Jan Neruda píše Hřbitovní kvítí, Knihy veršů, Písně kosmické a Balady a romance.",
"Povídky malostranské zachycují pražskou čtvrť s ironií i soucitem.",
"Fejeton v Národních listech je Nerudova škola pohledu na den.",
"Balady a romance spojují legendu, lidový tón a moderní skepsi.",
NULL,
},
},
{
"3 / 3 • Vedle něj", "Hálek, Světlá, Arbes",
"Tip: Arbesovo romaneto je napínavý příběh s racionálním vysvětlením.",
{
"Vítězslav Hálek je lyrik májovců, autor Večerních písní.",
"Karolina Světlá píše Vesnický román a prosazuje ženskou vzdělanost.",
"Jakub Arbes vytváří romaneto, třeba Newtonův mozek.",
"Májovci otevírají cestu pozdějšímu realismu.",
NULL,
},
},
};
return lit_unit_page(1, &lit2_lessons[4], "lit2_unit5", "lit2_unit5_sub",
slides, G_N_ELEMENTS(slides));
}
static GtkWidget *build_lit2_unit5_exercise_page(void) {
static const ChoiceQ qs[] = {
{"Kdy vyšel almanach Máj?",
{"Roku 1836", "Roku 1858", "Roku 1868", "Roku 1895"},
4, 1},
{"Kdo napsal Povídky malostranské?",
{"Jan Neruda", "Božena Němcová", "Alois Jirásek", "Karel Čapek"},
4, 0},
{"Co je romaneto?",
{"Lidová balada", "Napínavý příběh s racionálním jádrem",
"Klasicistní tragédie", "Husitská píseň"},
4, 1},
{"Jaký program měli májovci?",
{"Návrat výhradně k latině",
"Literatura světová, pravdivá a současná",
"Jen oslavné ódy na panovníka",
"Odmítnutí Máje"},
4, 1},
};
static const char *hints[] = {
"Almanach Máj je 1858, Máchův Máj je 1836, Ruch 1868.",
"Neruda v nich kreslí typy z Malé Strany.",
"Romaneto je žánr Jakuba Arbesa.",
"Májovci navazují na Máchu a chtějí umění bez fráze.",
};
return lit_mcq_page(1, 4, "lit2unit5", "lit2_ex5_title", "lit2_quiz5_head",
qs, hints, 4);
}
static GtkWidget *build_lit2_unit6_page(void) {
static const NetSlide slides[] = {
{
"1 / 3 • Spor", "Dvě odpovědi na smysl literatury",
"Tip: ruchovci brání národní tradici, lumírovci otevírají okno do Evropy.",
{
"Po májovcích se generace rozchází v tom, čemu má literatura sloužit.",
"Ruchovci kolem almanachu Ruch 1868 zdůrazňují národ a domácí látky.",
"Lumírovci kolem časopisu Lumír chtějí světovost a dokonalou formu.",
"Spor není osobní hádka, ale dvě představy o úkolu českého umění.",
NULL,
},
},
{
"2 / 3 • Ruch", "Svatopluk Čech",
"Tip: Písně otroka jsou politická alegorie nesvobody.",
{
"Svatopluk Čech píše Písně otroka, Evropy a satiru o panu Broučkovi.",
"Eliška Krásnohorská hájí srozumitelnost a národní úkol poezie.",
"Ruchovci navazují na obrozenskou představu básníka jako mluvčího národa.",
"Forma bývá rétorická, téma často vlastenecké a slovanské.",
NULL,
},
},
{
"3 / 3 • Lumír", "Vrchlický, Sládek, Zeyer",
"Tip: Vrchlický přináší do češtiny formy i látky z celé Evropy.",
{
"Jaroslav Vrchlický je mimořádně plodný lyrik, epik i dramatik, autor Noci na Karlštejně.",
"Josef Václav Sládek píše intimní a venkovskou lyriku a překládá.",
"Julius Zeyer čerpá z mýtů a legend, Radúz a Mahulena je pohádkové drama.",
"Lumírovci připravují půdu pro českou modernu.",
NULL,
},
},
};
return lit_unit_page(1, &lit2_lessons[5], "lit2_unit6", "lit2_unit6_sub",
slides, G_N_ELEMENTS(slides));
}
static GtkWidget *build_lit2_unit6_exercise_page(void) {
static const ChoiceQ qs[] = {
{"Čím se lumírovci liší od ruchovců?",
{"Odmítají veškerou poezii",
"Kladou důraz na světovost a uměleckou formu",
"Píšou jen latinsky",
"Patří k baroku"},
4, 1},
{"Kdo napsal Písně otroka?",
{"Svatopluk Čech", "Jaroslav Vrchlický", "Jan Neruda", "Karel Hynek Mácha"},
4, 0},
{"Které drama napsal Vrchlický?",
{"Maryša", "Noc na Karlštejně", "Lakomec", "Audience"},
4, 1},
{"Kam patří Julius Zeyer?",
{"K májovcům", "K lumírovcům", "K proletářské poezii", "K samizdatu"},
4, 1},
};
static const char *hints[] = {
"Lumír znamená otevření české literatury Evropě.",
"Svatopluk Čech je hlavní básník ruchovců.",
"Noc na Karlštejně je veršovaná komedie Vrchlického.",
"Zeyer, Vrchlický a Sládek tvoří jádro lumírovců.",
};
return lit_mcq_page(1, 5, "lit2unit6", "lit2_ex6_title", "lit2_quiz6_head",
qs, hints, 4);
}
static GtkWidget *build_lit2_unit7_page(void) {
static const NetSlide slides[] = {
{
"1 / 3 • Venkov", "Realistická próza",
"Tip: venkovský realismus neidealizuje, ukazuje bídu, víru i krutost zvyku.",
{
"Český realismus se obrací k venkovu, městu i historii.",
"Karel Václav Rais v Kalibově zločinu sleduje chudobu a vinu.",
"Teréza Nováková a Ignát Herrmann přidávají region a město.",
"Postava je určena prostředím, majetkem a mravem obce.",
NULL,
},
},
{
"2 / 3 • Historie", "Jirásek a historická próza",
"Tip: Jirásek vykládá dějiny jako posilu národního vědomí.",
{
"Alois Jirásek píše Psohlavce, Temno, F. L. Věka a Staré pověsti české.",
"Zikmund Winter přidává kulturněhistorický detail městského života.",
"Historická próza navazuje na Palackého pojetí českých dějin.",
"Na jevišti ji doplňuje drama z venkova a z dějin.",
NULL,
},
},
{
"3 / 3 • Drama", "Maryša a naturalismus",
"Tip: Maryša je tragédie nevolené svatby a bezmoci ženy.",
{
"Alois a Vilém Mrštíkové napsali Maryšu, hru o vynuceném sňatku.",
"Gabriela Preissová v Gazdině robě otevírá ženský osud na vesnici.",
"Naturalismus u nás zastupuje Karel Matěj Čapek-Chod.",
"Konec století už připravuje modernu, symbol a individuální senzibilitu.",
NULL,
},
},
};
return lit_unit_page(1, &lit2_lessons[6], "lit2_unit7", "lit2_unit7_sub",
slides, G_N_ELEMENTS(slides));
}
static GtkWidget *build_lit2_unit7_exercise_page(void) {
static const ChoiceQ qs[] = {
{"Kdo napsal Kalibův zločin?",
{"Karel Václav Rais", "Alois Jirásek", "Jan Neruda", "Julius Zeyer"},
4, 0},
{"Které dílo patří Aloisi Jiráskovi?",
{"Temno", "Máj", "Babička", "R.U.R."},
4, 0},
{"O čem je Maryša?",
{"O kosmických písních",
"O vynuceném sňatku a tragédii venkovské ženy",
"O cestě do Itálie",
"O robotovi"},
4, 1},
{"Kam patří historická próza Jiráska a Wintra?",
{"K českému realismu druhé poloviny 19. století",
"K antice", "K poetismu", "K literatuře po roce 1989"},
4, 0},
};
static const char *hints[] = {
"Rais je představitel venkovského realismu.",
"Temno, Psohlavci a Staré pověsti české jsou Jiráskovy.",
"Maryšu napsali bratři Mrštíkové.",
"Historický román tu slouží i národní paměti.",
};
return lit_mcq_page(1, 6, "lit2unit7", "lit2_ex7_title", "lit2_quiz7_head",
qs, hints, 4);
}
static GtkWidget *build_lit2_unit8_page(void) {
static const NetSlide slides[] = {
{
"1 / 3 • Evropa", "Prokletí básníci a dekadence",
"Tip: Baudelairovy Květy zla otevírají moderní městskou obraznost.",
{
"Konec století hledá nový jazyk: symbol, náladu, smyslovost a skepsi.",
"Charles Baudelaire, Paul Verlaine a Arthur Rimbaud jsou prokletí básníci.",
"Oscar Wilde v Obrazu Doriana Graye spojuje krásu, morálku a rozklad.",
"Symbol nesděluje věc přímo, nýbrž ji naznačuje.",
NULL,
},
},
{
"2 / 3 • Čechy", "Česká moderna",
"Tip: Manifest české moderny vyšel roku 1895.",
{
"Manifest žádá individualitu, kritičnost a konec vlastenecké rutiny.",
"K modernistům patří Antonín Sova, Otokar Březina a Karel Hlaváček.",
"Jiří Karásek ze Lvovic reprezentuje dekadenci, Josef Svatopluk Machar skepsi a satiru.",
"Impresionismus v básni zachycuje prchavý dojem, symbolismus skrytý smysl.",
NULL,
},
},
{
"3 / 3 • Buřiči", "Generace anarchistů",
"Tip: buřiči spojují vzdor, erotiku a soucit se sociálním dnem.",
{
"Fráňa Šrámek píše Stříbrný vítr a drama Měsíc nad řekou.",
"Viktor Dyk je autorem Krysaře a vzdorné politické lyriky.",
"Petr Bezruč ve Slezských písních mluví hlasem utiskovaného regionu.",
"S modernou končí 19. století a otevírá se literatura století dvacátého.",
NULL,
},
},
};
return lit_unit_page(1, &lit2_lessons[7], "lit2_unit8", "lit2_unit8_sub",
slides, G_N_ELEMENTS(slides));
}
static GtkWidget *build_lit2_unit8_exercise_page(void) {
static const ChoiceQ qs[] = {
{"Kdy vyšel Manifest české moderny?",
{"Roku 1858", "Roku 1895", "Roku 1918", "Roku 1948"},
4, 1},
{"Kdo napsal Květy zla?",
{"Charles Baudelaire", "Oscar Wilde", "Antonín Sova", "Jan Neruda"},
4, 0},
{"Které dílo napsal Viktor Dyk?",
{"Krysař", "Babička", "Maryša", "Edison"},
4, 0},
{"Čím jsou Slezské písně Petra Bezruče?",
{"Oslavou pražského salonu",
"Hlasem sociálního a národního útisku ve Slezsku",
"Barokní legendou",
"Antickým eposem"},
4, 1},
};
static const char *hints[] = {
"1895 je programový rok české moderny.",
"Baudelaire je ústřední prokletý básník.",
"Krysař je Dykova novela o moci a pomstě.",
"Bezruč mluví za chudý a utlačovaný kraj.",
};
return lit_mcq_page(1, 7, "lit2unit8", "lit2_ex8_title", "lit2_quiz8_head",
qs, hints, 4);
}
void add_lit2_pages(GtkStack *stack) {
typedef GtkWidget *(*LitBuilder)(void);
static const struct {
const char *unit_name;
const char *ex_name;
LitBuilder build_unit;
LitBuilder build_ex;
} pages[] = {
{"lit2unit1", "lit2ex1", build_lit2_unit1_page, build_lit2_unit1_exercise_page},
{"lit2unit2", "lit2ex2", build_lit2_unit2_page, build_lit2_unit2_exercise_page},
{"lit2unit3", "lit2ex3", build_lit2_unit3_page, build_lit2_unit3_exercise_page},
{"lit2unit4", "lit2ex4", build_lit2_unit4_page, build_lit2_unit4_exercise_page},
{"lit2unit5", "lit2ex5", build_lit2_unit5_page, build_lit2_unit5_exercise_page},
{"lit2unit6", "lit2ex6", build_lit2_unit6_page, build_lit2_unit6_exercise_page},
{"lit2unit7", "lit2ex7", build_lit2_unit7_page, build_lit2_unit7_exercise_page},
{"lit2unit8", "lit2ex8", build_lit2_unit8_page, build_lit2_unit8_exercise_page},
};
for (guint i = 0; i < G_N_ELEMENTS(pages); i++) {
gtk_stack_add_named(stack, pages[i].build_unit(), pages[i].unit_name);
gtk_stack_add_named(stack, pages[i].build_ex(), pages[i].ex_name);
}
}

616
src/lit_year3.c Normal file
View file

@ -0,0 +1,616 @@
#include "graduately.h"
/* Year 3: the first half of the 20th century, world and Czech. */
NetLesson lit3_lessons[LIT_N] = {
{ .n_slides = 3, .unit_page = "lit3unit1", .ex_page = "lit3ex1" },
{ .n_slides = 3, .unit_page = "lit3unit2", .ex_page = "lit3ex2" },
{ .n_slides = 3, .unit_page = "lit3unit3", .ex_page = "lit3ex3" },
{ .n_slides = 3, .unit_page = "lit3unit4", .ex_page = "lit3ex4" },
{ .n_slides = 3, .unit_page = "lit3unit5", .ex_page = "lit3ex5" },
{ .n_slides = 3, .unit_page = "lit3unit6", .ex_page = "lit3ex6" },
{ .n_slides = 3, .unit_page = "lit3unit7", .ex_page = "lit3ex7" },
{ .n_slides = 3, .unit_page = "lit3unit8", .ex_page = "lit3ex8" },
};
static GtkWidget *build_lit3_unit1_page(void) {
static const NetSlide slides[] = {
{
"1 / 3 • Zlom", "Umění po roce 1900",
"Tip: avantgarda chce tvořit budoucnost, ne jen zdobit přítomnost.",
{
"Nové směry odmítají popisnou iluzi 19. století.",
"Futurismus oslavuje rychlost, stroj a rozchod s muzeem.",
"Expresionismus křičí vnitřní úzkost, dadaismus se vysmívá smyslu války.",
"Surrealismus, vedený Bretonem, čerpá ze snu a nevědomí.",
NULL,
},
},
{
"2 / 3 • Báseň", "Apollinaire a pásmo",
"Tip: Pásmo ruší pravidelnou sloku a skládá báseň z volných obrazů.",
{
"Guillaume Apollinaire píše Pásmo a dává jméno kubismu i novému lyrismu.",
"Báseň může být bez interpunkce, jako proud vjemů velkoměsta.",
"Vladimir Majakovskij spojuje futurismus s politickým gestem.",
"Volný verš a asociace se stávají běžným nástrojem moderny.",
NULL,
},
},
{
"3 / 3 • Smysl", "Proč avantgardu znát",
"Tip: český poetismus a surrealismus z těchto podnětů přímo vyrůstají.",
{
"Avantgarda je mezinárodní a časopisy i manifesty putují přes hranice.",
"Umění se chápe jako experiment, ne jako hotový vzor.",
"Válka 1914–1918 tyto směry radikalizuje.",
"Bez avantgardy nelze číst Nezvala, Seiferta ani evropskou poezii 20. století.",
NULL,
},
},
};
return lit_unit_page(2, &lit3_lessons[0], "lit3_unit1", "lit3_unit1_sub",
slides, G_N_ELEMENTS(slides));
}
static GtkWidget *build_lit3_unit1_exercise_page(void) {
static const ChoiceQ qs[] = {
{"Co chce avantgarda?",
{"Vrátit se k třem jednotám",
"Experimentovat a tvořit nové umění",
"Psát jen historické romány",
"Obnovit latinskou kroniku"},
4, 1},
{"Kdo napsal Pásmo?",
{"Guillaume Apollinaire", "Franz Kafka",
"Ernest Hemingway", "Karel Čapek"},
4, 0},
{"Odkud čerpá surrealismus?",
{"Z úředního jazyka", "Ze snu a nevědomí",
"Z antické jednoty času", "Z kramářské písně"},
4, 1},
{"Který směr oslavuje rychlost a stroj?",
{"Klasicismus", "Futurismus", "Venkovský realismus", "Baroko"},
4, 1},
};
static const char *hints[] = {
"Avantgarda je programová moderna počátku 20. století.",
"Apollinairovo Pásmo je vzor moderní volné básně.",
"Bretonův surrealismus navazuje na Freudovo nevědomí.",
"Futurismus vyhlašuje Marinetti, v Rusku Majakovskij.",
};
return lit_mcq_page(2, 0, "lit3unit1", "lit3_ex1_title", "lit3_quiz1_head",
qs, hints, 4);
}
static GtkWidget *build_lit3_unit2_page(void) {
static const NetSlide slides[] = {
{
"1 / 3 • Válka", "Ztracená generace a Remarque",
"Tip: ztracená generace jsou autoři, které první válka připravila o iluze.",
{
"Ernest Hemingway píše Sbohem, armádo a později Stařec a moře.",
"Francis Scott Fitzgerald zachycuje Velkého Gatsbyho a lesk i prázdnotu úspěchu.",
"Erich Maria Remarque v románu Na západní frontě klid ukazuje zákop očima vojáka.",
"John Steinbeck přidává sociální prózu, třeba O myších a lidech.",
NULL,
},
},
{
"2 / 3 • Experiment", "Kafka, Joyce, Proust",
"Tip: Proměna začíná tím, že se člověk probudí jako hmyz, a nikdo se nad tím nepozastaví dost.",
{
"Franz Kafka v Proměně a Procesu zobrazuje úzkost a nepřehlednou moc.",
"James Joyce v Odysseovi rozbíjí tradiční vyprávění proudem vědomí.",
"Marcel Proust staví román na paměti a čase.",
"Moderní próza už nespoléhá na vševědoucího vypravěče a lineární děj.",
NULL,
},
},
{
"3 / 3 • Varování", "Antiutopie a svědomí",
"Tip: antiutopie ukazuje společnost, která štěstí vynucuje a svobodu ruší.",
{
"Aldous Huxley v Konci civilizace líčí svět řízený technikou a konzumem.",
"Thomas Mann v Kouzelném vrchu spojuje nemoc, čas a evropskou krizi.",
"Michail Bulgakov v Mistrovi a Markétce hájí umění proti násilné moci.",
"Tyto prózy připravují poválečné antiutopie Orwella a Bradburyho.",
NULL,
},
},
};
return lit_unit_page(2, &lit3_lessons[1], "lit3_unit2", "lit3_unit2_sub",
slides, G_N_ELEMENTS(slides));
}
static GtkWidget *build_lit3_unit2_exercise_page(void) {
static const ChoiceQ qs[] = {
{"Kdo patří ke ztracené generaci?",
{"Homér", "Ernest Hemingway", "Dante Alighieri", "Molière"},
4, 1},
{"Které dílo napsal Franz Kafka?",
{"Proměna", "Babička", "Evžen Oněgin", "Maryša"},
4, 0},
{"O čem je Remarquův román Na západní frontě klid?",
{"O salonu 18. století",
"O zážitku vojáka v první světové válce",
"O husitském zpěvu",
"O národním obrození"},
4, 1},
{"Co je proud vědomí?",
{"Lidová balada",
"Záznam vnitřní řeči a vjemů bez tradičního děje",
"Klasicistní prolog",
"Barokní kázání"},
4, 1},
};
static const char *hints[] = {
"Hemingway, Fitzgerald a další píšou po první válce o ztrátě jistot.",
"Proměna a Proces jsou Kafkovy klíčové prózy.",
"Remarque bourá představu války jako hrdinského dobrodružství.",
"Proud vědomí užívá Joyce a další modernisté.",
};
return lit_mcq_page(2, 1, "lit3unit2", "lit3_ex2_title", "lit3_quiz2_head",
qs, hints, 4);
}
static GtkWidget *build_lit3_unit3_page(void) {
static const NetSlide slides[] = {
{
"1 / 3 • Jeviště", "Drama se rozchází s iluzí",
"Tip: epické divadlo Brechtovo chce, aby divák přemýšlel, ne jen prožíval.",
{
"Moderní drama opouští měšťanskou konverzaci jako jediný vzor.",
"George Bernard Shaw spojuje komedii s myšlenkou a kritikou.",
"Luigi Pirandello tematizuje, že člověk hraje role a pravda se tříští.",
"Expresionistické drama křičí úzkost rozbitého světa.",
NULL,
},
},
{
"2 / 3 • Brecht", "Epické divadlo",
"Tip: zcizovací efekt brání divákovi, aby se v postavě jen rozplynul.",
{
"Bertolt Brecht píše Matku Kuráž a Kavkazský křídový kruh.",
"Písně, komentář a přerušení děje nutí zaujmout postoj.",
"Divadlo má být politické a rozumové, ne jen dojemné.",
"Brecht silně ovlivnil české divadlo druhé poloviny století.",
NULL,
},
},
{
"3 / 3 • Amerika", "O'Neill a počátek absurdity",
"Tip: absurdní drama v plné podobě přijde až po druhé válce.",
{
"Eugene O'Neill přináší do Ameriky psychologické a tragické drama.",
"Meziválečné jeviště zkouší masku, sbor i sen.",
"Po roce 1945 na to naváže Beckett a Ionesco.",
"Na maturitu patří Shaw, Pirandello a Brecht jako tři různé moderní cesty.",
NULL,
},
},
};
return lit_unit_page(2, &lit3_lessons[2], "lit3_unit3", "lit3_unit3_sub",
slides, G_N_ELEMENTS(slides));
}
static GtkWidget *build_lit3_unit3_exercise_page(void) {
static const ChoiceQ qs[] = {
{"Co je epické divadlo?",
{"Divadlo, které chce diváka dojmout až k slzám a nic víc",
"Brechtovo divadlo, které nutí přemýšlet a zaujímat postoj",
"Středověký mysterijní cyklus",
"Opera bez textu"},
4, 1},
{"Kdo napsal Matku Kuráž?",
{"Bertolt Brecht", "William Shakespeare",
"Molière", "Václav Havel"},
4, 0},
{"Čím se Pirandello zabývá?",
{"Husitskou písní", "Tím, že člověk hraje role a skutečnost se tříští",
"Venkovským realismem", "Eposem o Gilgamešovi"},
4, 1},
{"Kdy se plně rozvine absurdní drama?",
{"V antice", "Až po druhé světové válce",
"V národním obrození", "Ve 14. století"},
4, 1},
};
static const char *hints[] = {
"Zcizovací efekt je hlavní nástroj Brechtova epického divadla.",
"Matka Kuráž je brechtovská hra o válce a obchodu.",
"Pirandello patří k moderně, která pochybuje o jedné pravdě postavy.",
"Beckettovo Čekání na Godota je 1952, tedy po válce.",
};
return lit_mcq_page(2, 2, "lit3unit3", "lit3_ex3_title", "lit3_quiz3_head",
qs, hints, 4);
}
static GtkWidget *build_lit3_unit4_page(void) {
static const NetSlide slides[] = {
{
"1 / 3 • Švejk", "Jaroslav Hašek",
"Tip: Švejk není jen vtip, je to obrana malého člověka proti mašinerii.",
{
"Osudy dobrého vojáka Švejka za světové války vyšly 1921–1923.",
"Hašek zesměšňuje rakouskou armádu, úřad a velkou frázi.",
"Švejk poslouchá tak doslova, až rozkaz ztrácí smysl.",
"Román zůstal nedokončený a přesto se stal světovým.",
NULL,
},
},
{
"2 / 3 • Legie", "Válka a legionářská próza",
"Tip: legionářská literatura vypráví anabázi československých legií.",
{
"Rudolf Medek a Josef Kopta píšou o legiích v Rusku.",
"Válka vstupuje i do Vančurova Pole orná a válečná.",
"Proti hrdinské legendě stojí Haškova groteska.",
"Oba póly, patos i výsměch, patří k české paměti první války.",
NULL,
},
},
{
"3 / 3 • Poezie", "Wolker a proletářská poezie",
"Tip: Wolker chce, aby báseň sloužila chudým a byla srozumitelná.",
{
"Jiří Wolker vydává Host do domu a Těžkou hodinu.",
"Balady, třeba Balada o nenarozeném dítěti, spojují sociální téma s lidovým tónem.",
"Proletářská poezie věří kolektivu a změně světa.",
"Devětsil, založený 1920, z ní brzy přejde k poetismu.",
NULL,
},
},
};
return lit_unit_page(2, &lit3_lessons[3], "lit3_unit4", "lit3_unit4_sub",
slides, G_N_ELEMENTS(slides));
}
static GtkWidget *build_lit3_unit4_exercise_page(void) {
static const ChoiceQ qs[] = {
{"Kdo napsal Osudy dobrého vojáka Švejka?",
{"Jaroslav Hašek", "Karel Čapek", "Jiří Wolker", "Viktor Dyk"},
4, 0},
{"Jak Švejk vzdoruje armádě?",
{"Hrdinským útokem v čele legií",
"Doslovnou poslušností, která rozkaz zesměšní",
"Útěkem do exilu po roce 1968",
"Psaním manifestu moderny"},
4, 1},
{"Které sbírky napsal Jiří Wolker?",
{"Host do domu a Těžká hodina", "Kytice a Máj",
"Květy zla a Havran", "Edison a Pásmo"},
4, 0},
{"Co je Devětsil?",
{"Barokní řád", "Umělecký svaz založený roku 1920",
"Husitská píseň", "Nakladatelství exilu v Torontu"},
4, 1},
};
static const char *hints[] = {
"Švejk je Haškův nedokončený román z první války.",
"Groteskní poslušnost je Švejkova zbraň.",
"Wolker je hlavní básník proletářské poezie.",
"Z Devětsilu vyroste poetismus.",
};
return lit_mcq_page(2, 3, "lit3unit4", "lit3_ex4_title", "lit3_quiz4_head",
qs, hints, 4);
}
static GtkWidget *build_lit3_unit5_page(void) {
static const NetSlide slides[] = {
{
"1 / 3 • Poetismus", "Radost, město a asociace",
"Tip: poetismus je český směr, teoretikem je Karel Teige.",
{
"Poetismus chce báseň jako hru obrazů, cestu a oslavu moderního života.",
"Vítězslav Nezval píše Podivuhodného kouzelníka a Edison.",
"Jaroslav Seifert debutuje Na vlnách TSF a zůstane u konkrétního, smyslového verše.",
"Konstantin Biebl přidává exotiku a později smutek.",
NULL,
},
},
{
"2 / 3 • Surrealismus", "Sen a úzkost",
"Tip: Nezvalův Absolutní hrobař už není radostný poetismus.",
{
"Ve 30. letech část poetistů přechází k surrealismu.",
"Skupina surrealistů v ČSR vzniká 1934 kolem Nezvala.",
"Obraz se stává snovějším a úzkostnějším.",
"Vedle toho roste meditativní poezie, která avantgardu přijímá jen zčásti.",
NULL,
},
},
{
"3 / 3 • Jiný hlas", "Halas, Holan, Zahradníček",
"Tip: Halasova Torzo naděje je odpověď na Mnichov, ne na karneval města.",
{
"František Halas píše temnou, zhuštěnou lyriku a Torzo naděje.",
"Vladimír Holan je básník meditace a později svědectví.",
"Jan Zahradníček představuje spirituální a katolickou poezii.",
"Meziválečná poezie tedy není jen Devětsil: má i pól víry a úzkosti.",
NULL,
},
},
};
return lit_unit_page(2, &lit3_lessons[4], "lit3_unit5", "lit3_unit5_sub",
slides, G_N_ELEMENTS(slides));
}
static GtkWidget *build_lit3_unit5_exercise_page(void) {
static const ChoiceQ qs[] = {
{"Kdo je teoretikem poetismu?",
{"Karel Teige", "Josef Dobrovský", "Jan Hus", "Bertolt Brecht"},
4, 0},
{"Kterou skladbu napsal Vítězslav Nezval?",
{"Edison", "Máj", "Kytice", "Babička"},
4, 0},
{"Kdy vznikla Skupina surrealistů v ČSR?",
{"Roku 1858", "Roku 1934", "Roku 863", "Roku 1989"},
4, 1},
{"Čím je Halasovo Torzo naděje?",
{"Poetistickou oslavou velkoměsta",
"Básnickou odpovědí na ohrožení republiky",
"Legionářským románem",
"Klasicistní komedií"},
4, 1},
};
static const char *hints[] = {
"Teige formuluje poetismus jako umění života.",
"Edison je Nezvalova pásmová báseň o vynálezci a noci.",
"1934 je rok českého surrealistického seskupení.",
"Torzo naděje reaguje na krizi konce 30. let.",
};
return lit_mcq_page(2, 4, "lit3unit5", "lit3_ex5_title", "lit3_quiz5_head",
qs, hints, 4);
}
static GtkWidget *build_lit3_unit6_page(void) {
static const NetSlide slides[] = {
{
"1 / 3 • Čapek", "Demokratický proud",
"Tip: Čapek brání obyčejného člověka a varuje před mocí, která se vymkne.",
{
"Karel Čapek píše R.U.R., kde zazní slovo robot, Krakatit a Válku s mloky.",
"Bílá nemoc a Matka jsou dramata o válce a odpovědnosti.",
"Hordubal, Povětroň a Obyčejný život jsou noetická trilogie: pravda není jedna.",
"Povídky z jedné a druhé kapsy a fejetony drží lidský rozměr.",
NULL,
},
},
{
"2 / 3 • Vančura", "Jazyk jako událost",
"Tip: Vančura píše obrazně a vědomě proti všednímu novinovému stylu.",
{
"Vladislav Vančura je autorem Rozmarného léta a Markéty Lazarové.",
"Jeho věta je rytmická, metaforická a často archaicky zbarvená.",
"Patří k levicové avantgardě, ale není schematický.",
"Vedle něj stojí reportážní a novinářská próza meziválečné demokracie.",
NULL,
},
},
{
"3 / 3 • Smích", "Poláček, Olbracht a další",
"Tip: Bylo nás pět je dětská perspektiva, která odhaluje svět dospělých.",
{
"Karel Poláček píše Bylo nás pět a Muže v offsidu.",
"Ivan Olbracht: Nikola Šuhaj loupežník a Golet v údolí.",
"Eduard Bass a Karel Poláček představují humoristickou a novinářskou linii.",
"Demokratický proud věří republice, rozumu a občanské slušnosti.",
NULL,
},
},
};
return lit_unit_page(2, &lit3_lessons[5], "lit3_unit6", "lit3_unit6_sub",
slides, G_N_ELEMENTS(slides));
}
static GtkWidget *build_lit3_unit6_exercise_page(void) {
static const ChoiceQ qs[] = {
{"Ve kterém díle zazní slovo robot?",
{"V R.U.R. Karla Čapka", "V Máji", "V Kytici", "V Švejkovi"},
4, 0},
{"Kdo napsal Rozmarné léto?",
{"Vladislav Vančura", "Jaroslav Hašek", "Božena Němcová", "Alois Jirásek"},
4, 0},
{"Kterou knihu napsal Karel Poláček?",
{"Bylo nás pět", "Temno", "Labyrint světa", "Krysař"},
4, 0},
{"O čem varuje Válka s mloky?",
{"O nebezpečí moci, která využije lidskou chtivost",
"O pravidlech sonetu",
"O příchodu věrozvěstů",
"O barokním emblému"},
4, 0},
};
static const char *hints[] = {
"Slovo robot vymyslel Josef Čapek, svět je zná z dramatu R.U.R.",
"Rozmarné léto a Markéta Lazarová jsou Vančurovy prózy.",
"Poláček je autor Bylo nás pět a Mužů v offsidu.",
"Mloci jsou podobenství o civilizaci, která si vypěstuje zhoubu.",
};
return lit_mcq_page(2, 5, "lit3unit6", "lit3_ex6_title", "lit3_quiz6_head",
qs, hints, 4);
}
static GtkWidget *build_lit3_unit7_page(void) {
static const NetSlide slides[] = {
{
"1 / 3 • Duše", "Psychologická próza",
"Tip: psychologická próza sleduje vnitřní motiv, ne jen vnější děj.",
{
"Jaroslav Havlíček píše Petrolejové lampy a Neviditelného.",
"Jarmila Glazarová v Adventu zobrazuje krutost a závislost na vesnici.",
"Egon Hostovský a Václav Řezáč přidávají úzkost a mravní selhání.",
"Člověk tu není typ vrstvy, ale spleť nutkání a vin.",
NULL,
},
},
{
"2 / 3 • Víra", "Katolický proud",
"Tip: katolická literatura není jen pobožnost, je to svébytný umělecký názor.",
{
"Jaroslav Durych píše historický román Bloudění.",
"Jakub Deml tvoří deníkovou a spirituální prózu.",
"Jan Čep a Jan Zahradníček drží venkov a víru jako řád.",
"Proud stojí vedle avantgardy a často s ní polemizuje.",
NULL,
},
},
{
"3 / 3 • Venkov", "Ruralismus",
"Tip: ruralismus idealizuje venkov jako zdroj řádu proti městu.",
{
"Ruralisté, třeba Josef Knap a František Křelina, brání selskou tradici.",
"Liší se od kritického realismu, který vesnici nešetřil.",
"Ve 30. letech je to vlivný, dnes diskutovaný proud.",
"Maturita má umět tyto proudy rozlišit, ne je slepit v jednu meziválečnou prózu.",
NULL,
},
},
};
return lit_unit_page(2, &lit3_lessons[6], "lit3_unit7", "lit3_unit7_sub",
slides, G_N_ELEMENTS(slides));
}
static GtkWidget *build_lit3_unit7_exercise_page(void) {
static const ChoiceQ qs[] = {
{"Kdo napsal Petrolejové lampy?",
{"Jaroslav Havlíček", "Karel Čapek", "Ivan Olbracht", "Jiří Wolker"},
4, 0},
{"Kam patří Jaroslav Durych?",
{"Ke katolickému proudu", "K poetismu",
"Ke ztracené generaci", "K ruchovcům"},
4, 0},
{"Co zdůrazňuje ruralismus?",
{"Velkoměstský kaleidoskop",
"Venkov a selský řád",
"Antickou tragédii",
"Absenci děje"},
4, 1},
{"Čím se psychologická próza zabývá především?",
{"Vnitřním motivem a vinou postavy",
"Překladem antických eposů",
"Pravidly klasicistního verše",
"Kronikou Velké Moravy"},
4, 0},
};
static const char *hints[] = {
"Havlíček je autor Petrolejových lamp a Neviditelného.",
"Durychovo Bloudění je historický román katolického proudu.",
"Ruralismus staví vesnici proti rozkladnému městu.",
"Děj je tu hlavně cesta do nitra.",
};
return lit_mcq_page(2, 6, "lit3unit7", "lit3_ex7_title", "lit3_quiz7_head",
qs, hints, 4);
}
static GtkWidget *build_lit3_unit8_page(void) {
static const NetSlide slides[] = {
{
"1 / 3 • Okupace", "Literatura za protektorátu",
"Tip: po roce 1939 mizí svobodný tisk a řada autorů píše do šuplíku nebo umírá.",
{
"Německá okupace zavírá českou kulturu do cenzury a perzekuce.",
"Mladí básníci kolem Jiřího Ortena píšou elegii a deník ohroženého života.",
"Ortenovy sbírky, třeba Ohnice, vycházejí pod cizím jménem.",
"Halas, Holan a Seifert reagují na válku zhuštěným veršem.",
NULL,
},
},
{
"2 / 3 • Skupina", "Skupina 42",
"Tip: Skupina 42 bere město, periferii a civilní řeč, ne snový symbol.",
{
"Skupina 42 vzniká za války a programově se dívá na civilizaci města.",
"Patří k ní Josef Kainar, Jiří Kolář, Ivan Blatný a teoretik Jindřich Chalupecký.",
"Báseň i próza zaznamenávají banalitu, která je pod tlakem dějin přízračná.",
"Skupina působí i po válce, než ji politický režim umlčí.",
NULL,
},
},
{
"3 / 3 • Svědectví", "Co se o válce píše hned a co později",
"Tip: velké prózy o šoa často vzniknou až po roce 1945.",
{
"Za války vzniká poezie, deník a ilegální text, ne velký románový odstup.",
"Julius Fučík píše Reportáž psanou na oprátce ve vězení.",
"Lustig, Fuks, Hrabal nebo Otčenášek válku zpracují až v dalších desetiletích.",
"Na maturitu oddělte dobu vzniku od doby, o které dílo vypráví.",
NULL,
},
},
};
return lit_unit_page(2, &lit3_lessons[7], "lit3_unit8", "lit3_unit8_sub",
slides, G_N_ELEMENTS(slides));
}
static GtkWidget *build_lit3_unit8_exercise_page(void) {
static const ChoiceQ qs[] = {
{"Kdo je básník Ohnice?",
{"Jiří Orten", "Jaroslav Seifert", "Vítězslav Nezval", "Petr Bezruč"},
4, 0},
{"Čím se vyznačuje Skupina 42?",
{"Návratem ke klasicistní tragédii",
"Civilním pohledem na město a periferii",
"Venkovským ruralismem",
"Psaním jen v latině"},
4, 1},
{"Kdo patří ke Skupině 42?",
{"Josef Kainar a Jiří Kolář", "Karel Hynek Mácha a Karel Jaromír Erben",
"Homér a Vergilius", "Jungmann a Dobrovský"},
4, 0},
{"Proč velké romány o válce často nejsou z let okupace?",
{"Protože za cenzury a bez odstupu vznikala spíš poezie, deník a svědectví",
"Protože se o válce nesmělo psát ani po roce 1945",
"Protože próza vznikla až ve středověku",
"Protože autoři neznali téma města"},
4, 0},
};
static const char *hints[] = {
"Orten publikoval za okupace pod pseudonymem a zahynul roku 1941.",
"Program Skupiny 42 formuluje civilizační a městský pohled.",
"Kainar, Kolář a Blatný jsou její básníci.",
"Lustig, Fuks a další válečné prózy jsou poválečné.",
};
return lit_mcq_page(2, 7, "lit3unit8", "lit3_ex8_title", "lit3_quiz8_head",
qs, hints, 4);
}
void add_lit3_pages(GtkStack *stack) {
typedef GtkWidget *(*LitBuilder)(void);
static const struct {
const char *unit_name;
const char *ex_name;
LitBuilder build_unit;
LitBuilder build_ex;
} pages[] = {
{"lit3unit1", "lit3ex1", build_lit3_unit1_page, build_lit3_unit1_exercise_page},
{"lit3unit2", "lit3ex2", build_lit3_unit2_page, build_lit3_unit2_exercise_page},
{"lit3unit3", "lit3ex3", build_lit3_unit3_page, build_lit3_unit3_exercise_page},
{"lit3unit4", "lit3ex4", build_lit3_unit4_page, build_lit3_unit4_exercise_page},
{"lit3unit5", "lit3ex5", build_lit3_unit5_page, build_lit3_unit5_exercise_page},
{"lit3unit6", "lit3ex6", build_lit3_unit6_page, build_lit3_unit6_exercise_page},
{"lit3unit7", "lit3ex7", build_lit3_unit7_page, build_lit3_unit7_exercise_page},
{"lit3unit8", "lit3ex8", build_lit3_unit8_page, build_lit3_unit8_exercise_page},
};
for (guint i = 0; i < G_N_ELEMENTS(pages); i++) {
gtk_stack_add_named(stack, pages[i].build_unit(), pages[i].unit_name);
gtk_stack_add_named(stack, pages[i].build_ex(), pages[i].ex_name);
}
}

631
src/lit_year4.c Normal file
View file

@ -0,0 +1,631 @@
#include "graduately.h"
/* Year 4: literature after 1945, Czech writing under censorship and after
* 1989, and how to interpret a text at the school-leaving exam. */
NetLesson lit4_lessons[LIT_N] = {
{ .n_slides = 3, .unit_page = "lit4unit1", .ex_page = "lit4ex1" },
{ .n_slides = 3, .unit_page = "lit4unit2", .ex_page = "lit4ex2" },
{ .n_slides = 3, .unit_page = "lit4unit3", .ex_page = "lit4ex3" },
{ .n_slides = 3, .unit_page = "lit4unit4", .ex_page = "lit4ex4" },
{ .n_slides = 3, .unit_page = "lit4unit5", .ex_page = "lit4ex5" },
{ .n_slides = 3, .unit_page = "lit4unit6", .ex_page = "lit4ex6" },
{ .n_slides = 3, .unit_page = "lit4unit7", .ex_page = "lit4ex7" },
{ .n_slides = 3, .unit_page = "lit4unit8", .ex_page = "lit4ex8" },
};
static GtkWidget *build_lit4_unit1_page(void) {
static const NetSlide slides[] = {
{
"1 / 3 • Po válce", "Svět, který už nevěří velkým frázím",
"Tip: antiutopie varuje před státem, který ovládne pravdu i soukromí.",
{
"Druhá světová válka a totalitní režimy mění téma viny, moci a paměti.",
"George Orwell píše Farmu zvířat a román 1984.",
"Ray Bradbury v 451 stupních Fahrenheita brání knihu proti cenzuře.",
"William Golding v Pánu much ukazuje, jak rychle se zboří civilizovaný řád.",
NULL,
},
},
{
"2 / 3 • Hlasy", "Existencialismus, beatnici a magický realismus",
"Tip: existencialismus říká, že člověk je svoboda a musí volit bez hotové opory.",
{
"Albert Camus píše Cizince a Mor, Jean-Paul Sartre Nevolnost.",
"Jack Kerouac v románu Na cestě dává hlas beat generation.",
"Gabriel García Márquez ve Sto rocích samoty mísí skutečnost a zázrak.",
"Jorge Luis Borges staví povídku jako filozofickou hru s nekonečnem.",
NULL,
},
},
{
"3 / 3 • Východ", "Svědectví o nesvobodě",
"Tip: Solženicyn a Bulgakov se čtou jako literatura i jako svědectví.",
{
"Alexandr Solženicyn v Jednom dni Ivana Děnisoviče otevírá téma lágru.",
"Michail Bulgakov hájí v Mistrovi a Markétce umění proti strachu.",
"Joseph Heller v Hlavě XXII zesměšňuje válečnou byrokracii.",
"Poválečná próza tedy není jeden styl, ale několik odpovědí na stejné století.",
NULL,
},
},
};
return lit_unit_page(3, &lit4_lessons[0], "lit4_unit1", "lit4_unit1_sub",
slides, G_N_ELEMENTS(slides));
}
static GtkWidget *build_lit4_unit1_exercise_page(void) {
static const ChoiceQ qs[] = {
{"Kdo napsal román 1984?",
{"George Orwell", "Ray Bradbury", "Albert Camus", "Umberto Eco"},
4, 0},
{"O čem je 451 stupňů Fahrenheita?",
{"O cenzuře a pálení knih", "O národním obrození",
"O antickém osudu", "O husitské písni"},
4, 0},
{"Který román patří Gabrielu Garcíovi Márquezovi?",
{"Sto roků samoty", "Babička", "Evžen Oněgin", "R.U.R."},
4, 0},
{"Co je existencialismus v próze Camuse a Sartra?",
{"Víra, že osud je předem dán bohy",
"Důraz na svobodu volby, absurditu a odpovědnost",
"Návrat ke třem jednotám",
"Popis venkova bez psychologie"},
4, 1},
};
static const char *hints[] = {
"Orwell: Farma zvířat a 1984. Bradbury: 451 stupňů Fahrenheita.",
"Hasiči u Bradburyho knihy pálí, lidé je zachraňují tím, že je umějí zpaměti.",
"Sto roků samoty je základní román magického realismu.",
"Cizinec a Mor jsou Camusovy, Nevolnost Sartrova.",
};
return lit_mcq_page(3, 0, "lit4unit1", "lit4_ex1_title", "lit4_quiz1_head",
qs, hints, 4);
}
static GtkWidget *build_lit4_unit2_page(void) {
static const NetSlide slides[] = {
{
"1 / 3 • Absurdita", "Čekání, které nekončí",
"Tip: v absurdním dramatu se děj neuzavře, protože svět sám nedává smysl.",
{
"Samuel Beckett v Čekání na Godota nechává dva tuláky čekat na někoho, kdo nepřijde.",
"Eugene Ionesco v Plešaté zpěvačce rozkládá obyčejnou řeč.",
"Postavy jednají, ale jejich jednání cíl nenaplní.",
"Smích a hrůza tu nejsou oddělené.",
NULL,
},
},
{
"2 / 3 • Myšlenka", "Sartre, Dürrenmatt a podobenství",
"Tip: Návštěva staré dámy je podobenství o tom, zač je město ochotné prodat spravedlnost.",
{
"Sartrovy Mouchy a S vyloučením veřejnosti jsou existencialistická dramata.",
"Friedrich Dürrenmatt píše Návštěvu staré dámy a Fyziky.",
"Podobenství dovoluje mluvit o vině, aniž hra kopíruje noviny.",
"Divadlo po roce 1945 často soudí diváka spolu s postavou.",
NULL,
},
},
{
"3 / 3 • Postmoderna", "Hra s tím, co už bylo napsáno",
"Tip: postmoderna cituje starší texty a nedůvěřuje jedinému velkému výkladu.",
{
"Umberto Eco v Jménu růže spojuje detektivku, středověk a učenou hru.",
"Intertextualita znamená, že dílo vědomě navazuje na jiná díla.",
"Vypravěč může být nespolehlivý a závěr otevřený.",
"Na maturitě postmoderu poznáte podle ironie, citace a pochybnosti o jedné pravdě.",
NULL,
},
},
};
return lit_unit_page(3, &lit4_lessons[1], "lit4_unit2", "lit4_unit2_sub",
slides, G_N_ELEMENTS(slides));
}
static GtkWidget *build_lit4_unit2_exercise_page(void) {
static const ChoiceQ qs[] = {
{"Kdo napsal Čekání na Godota?",
{"Samuel Beckett", "Molière", "William Shakespeare", "Karel Čapek"},
4, 0},
{"Co je typické pro absurdní drama?",
{"Jasný hrdinský konec",
"Jednání, které nevede k smysluplnému završení",
"Dodržení tří jednot",
"Jen historický námět z antiky"},
4, 1},
{"Kdo napsal Návštěvu staré dámy?",
{"Friedrich Dürrenmatt", "Bertolt Brecht",
"Václav Havel", "Victor Hugo"},
4, 0},
{"Čím se vyznačuje Jméno růže?",
{"Je to barokní kázání",
"Postmoderní román, který spojuje detektivku a středověk",
"Proletářská balada",
"Klasicistní tragédie"},
4, 1},
};
static const char *hints[] = {
"Beckettovo Čekání na Godota je základní absurdní drama.",
"Godot nepřijde a čekání se opakuje.",
"Dürrenmattova hra zkoumá, za co obec prodá svědomí.",
"Eco pracuje s citací, ironií a učenou hrou.",
};
return lit_mcq_page(3, 1, "lit4unit2", "lit4_ex2_title", "lit4_quiz2_head",
qs, hints, 4);
}
static GtkWidget *build_lit4_unit3_page(void) {
static const NetSlide slides[] = {
{
"1 / 3 • 1945–1948", "Krátká svoboda",
"Tip: mezi květnem 1945 a únorem 1948 ještě vedle sebe žijí různé směry.",
{
"Po válce se vracejí zakázaní autoři a vycházejí odložené rukopisy.",
"Skupina 42 ještě působí, katolická literatura má poslední veřejný prostor.",
"Zároveň sílí požadavek, aby umění sloužilo nové moci.",
"Únor 1948 tento spor rozhodne politicky.",
NULL,
},
},
{
"2 / 3 • Schematismus", "Budovatelský román",
"Tip: schematická postava nemá pochybnost, protože dějiny už mají vyhráno.",
{
"Na počátku 50. let vládne socialistický realismus a budovatelský román.",
"Hrdina je dělník nebo funkcionář, konflikt je mezi pokrokem a zpátečníkem.",
"Jazyk je průhledný, závěr optimistický, kritika režimu nemožná.",
"Mnoho autorů starších generací mlčí, překládá, nebo píše do zásuvky.",
NULL,
},
},
{
"3 / 3 • 1956", "První trhlina",
"Tip: rok 1956 je kritika kultu osobnosti a počátek opatrného uvolnění.",
{
"II. sjezd spisovatelů a světové události narušují jistotu schématu.",
"Časopis Květen a poezie všedního dne vracejí do verše obyčejný život.",
"Ještě to není svoboda 60. let, ale konec nejtvrdšího schématu.",
"Na maturitu odlište budovatelský román od literatury, která přišla po něm.",
NULL,
},
},
};
return lit_unit_page(3, &lit4_lessons[2], "lit4_unit3", "lit4_unit3_sub",
slides, G_N_ELEMENTS(slides));
}
static GtkWidget *build_lit4_unit3_exercise_page(void) {
static const ChoiceQ qs[] = {
{"Co se v české literatuře děje po únoru 1948?",
{"Návrat ke klasicismu",
"Nástup socialistického realismu a budovatelského románu",
"Vznik poetismu",
"Konec cenzury"},
4, 1},
{"Čím je schematická postava?",
{"Má jednoznačnou politickou roli a nepochybuje",
"Je romantický vyvrženec",
"Je vypravěč v ich-formě antického eposu",
"Je autor Bible kralické"},
4, 0},
{"Co znamená rok 1956 pro českou literaturu?",
{"Založení Devětsilu",
"Kritiku kultu osobnosti a první uvolnění schématu",
"Příchod Konstantina a Metoděje",
"Vydání Máje"},
4, 1},
{"Kdy končí krátké poválečné období otevřenější kultury?",
{"Únorem 1948", "Manifestem české moderny",
"Almanachem Máj", "Rokem 863"},
4, 0},
};
static const char *hints[] = {
"Budovatelský román je oficiální žánr počátku 50. let.",
"Schéma dělí postavy na kladné a záporné podle vztahu k režimu.",
"1956 oslabuje kult osobnosti, svoboda 60. let přijde později.",
"Únor 1948 je politický zlom, po němž mizí nezávislé proudy z veřejné scény.",
};
return lit_mcq_page(3, 2, "lit4unit3", "lit4_ex3_title", "lit4_quiz3_head",
qs, hints, 4);
}
static GtkWidget *build_lit4_unit4_page(void) {
static const NetSlide slides[] = {
{
"1 / 3 • Uvolnění", "Léta, kdy se smělo víc",
"Tip: 60. léta nejsou bez cenzury, ale cenzura polevila a experiment se vrátil.",
{
"Literatura znovu zkouší formu, ironii a tabuizovaná témata.",
"Válka, stalinismus i soukromí se dají pojmenovat otevřeněji.",
"Vrcholí to Pražským jarem 1968 a končí srpnovou okupací.",
"Mnoho knih, které tehdy vznikly, později vyjde jen v samizdatu nebo v exilu.",
NULL,
},
},
{
"2 / 3 • Próza", "Hrabal, Kundera, Škvorecký",
"Tip: pábitel je Hrabalův vypravěč, který skutečnost přetaví v proud řeči.",
{
"Bohumil Hrabal píše Pábitelé, Ostře sledované vlaky a Taneční hodiny.",
"Milan Kundera vydává Směšné lásky a Žert.",
"Josef Škvorecký v Zbabělcích vypráví konec války očima mladíka.",
"Arnošt Lustig a Ladislav Fuks vracejí téma šoa: Modlitba pro Kateřinu Horovitzovou, Spalovač mrtvol.",
NULL,
},
},
{
"3 / 3 • Kritika", "Vaculík, Páral a meze svobody",
"Tip: Žert ukazuje, jak jedna věta a jeden režim zničí život.",
{
"Ludvík Vaculík píše Sekyru a později Dva tisíce slov.",
"Vladimír Páral zachycuje konzumní stereotyp.",
"Divadlo a film 60. let jdou s literaturou ruku v ruce.",
"Okupace 1968 tuto vlnu utne a rozdělí autory na oficiální, samizdat a exil.",
NULL,
},
},
};
return lit_unit_page(3, &lit4_lessons[3], "lit4_unit4", "lit4_unit4_sub",
slides, G_N_ELEMENTS(slides));
}
static GtkWidget *build_lit4_unit4_exercise_page(void) {
static const ChoiceQ qs[] = {
{"Kdo napsal Ostře sledované vlaky?",
{"Bohumil Hrabal", "Milan Kundera", "Josef Škvorecký", "Ladislav Fuks"},
4, 0},
{"Který román napsal Milan Kundera v 60. letech?",
{"Žert", "Babička", "Temno", "1984"},
4, 0},
{"O čem jsou Zbabělci Josefa Škvoreckého?",
{"O konci války v českém městě očima mladíka",
"O barokním exilu Komenského",
"O antickém osudu",
"O národním obrození"},
4, 0},
{"Kdo napsal Spalovače mrtvol?",
{"Ladislav Fuks", "Jiří Wolker", "Karel Jaromír Erben", "Victor Hugo"},
4, 0},
};
static const char *hints[] = {
"Hrabal: Ostře sledované vlaky, Pábitelé, později Obsluhoval jsem anglického krále.",
"Žert je Kunderův román o trestu za vtip.",
"Zbabělci vyšli na konci 50. let a patří k uvolnění.",
"Fuksův Spalovač mrtvol ukazuje, jak se obyčejný člověk stane nástrojem zla.",
};
return lit_mcq_page(3, 3, "lit4unit4", "lit4_ex4_title", "lit4_quiz4_head",
qs, hints, 4);
}
static GtkWidget *build_lit4_unit5_page(void) {
static const NetSlide slides[] = {
{
"1 / 3 • Tři proudy", "Normalizace",
"Tip: po roce 1968 se česká literatura dělí na oficiální, samizdatovou a exilovou.",
{
"Normalizace vyřazuje nepohodlné autory z nakladatelství, novin i zaměstnání.",
"Oficiální scéna tiskne jen to, co projde cenzurou.",
"Samizdat opisuje rukopisy, známá je Vaculíkova Edice Petlice.",
"Exil vydává v cizině, Škvoreckého nakladatelství 68 Publishers vzniká v Torontu.",
NULL,
},
},
{
"2 / 3 • Autoři", "Kdo kam patří",
"Tip: jeden autor může v různých letech stát na různých stranách této hranice.",
{
"V exilu publikují Kundera, Škvorecký, Pavel Kohout a další.",
"V samizdatu píšou Václav Havel, Ludvík Vaculík, Ivan Klíma a Jiří Gruša.",
"Hrabal po nucených úpravách zčásti vychází oficiálně a zároveň koluje v opisech.",
"Underground, Egon Bondy a Ivan Jirous, stojí mimo oficiální kulturu zcela.",
NULL,
},
},
{
"3 / 3 • Charta", "Literatura a občanský postoj",
"Tip: Charta 77 není román, ale bez ní nelze normalizaci vysvětlit.",
{
"Charta 77 žádá dodržování práv, která stát sám podepsal.",
"Mnoho signatářů jsou spisovatelé a zakázaní autoři.",
"Čtení samizdatu je v té době čin, ne jen záliba.",
"Na maturitu vždy řekněte, v kterém z tří proudů dílo vyšlo.",
NULL,
},
},
};
return lit_unit_page(3, &lit4_lessons[4], "lit4_unit5", "lit4_unit5_sub",
slides, G_N_ELEMENTS(slides));
}
static GtkWidget *build_lit4_unit5_exercise_page(void) {
static const ChoiceQ qs[] = {
{"Jak se dělí česká literatura v normalizaci?",
{"Na lyriku, epiku a drama",
"Na oficiální tvorbu, samizdat a exil",
"Na ruchovce a lumírovce",
"Na antiku a středověk"},
4, 1},
{"Co je Edice Petlice?",
{"Samizdatová edice Ludvíka Vaculíka",
"Oficiální nakladatelství 50. let",
"Barokní tiskárna",
"Almanach májovců"},
4, 0},
{"Kde působilo nakladatelství 68 Publishers?",
{"V Torontu", "V Praze jako oficiální dům",
"Na Velké Moravě", "V Národním divadle"},
4, 0},
{"Kdo patří k undergroundu normalizace?",
{"Egon Bondy a Ivan Jirous", "Josef Dobrovský a Josef Jungmann",
"Homér a Sofoklés", "Božena Němcová a Karel Jaromír Erben"},
4, 0},
};
static const char *hints[] = {
"Tři okruhy publikování jsou základní schéma učebnic.",
"Petlici řídil Vaculík, opisy šly z ruky do ruky.",
"68 Publishers založili Škvorecký a Zdena Salivarová.",
"Underground odmítá oficiální kulturu i její kompromisy.",
};
return lit_mcq_page(3, 4, "lit4unit5", "lit4_ex5_title", "lit4_quiz5_head",
qs, hints, 4);
}
static GtkWidget *build_lit4_unit6_page(void) {
static const NetSlide slides[] = {
{
"1 / 3 • Verš", "Poezie po roce 1945",
"Tip: Seifert dostal Nobelovu cenu roku 1984, v době, kdy doma nebyl režimní básník.",
{
"Jaroslav Seifert píše po válce intimní a paměťovou lyriku, Morový sloup vychází v samizdatu.",
"Jan Skácel a Miroslav Holub představují dvě polohy: něhu a věcnou metaforu.",
"Oficiální poezie 50. let je agitační, později se vrací civilní tón.",
"Písničkáři Karel Kryl, Jaromír Nohavica a Vladimír Merta nesou verš mimo knižní cenzuru.",
NULL,
},
},
{
"2 / 3 • Havel", "Drama, které mluví o moci řeči",
"Tip: Zahradní slavnost ukazuje, jak fráze pohltí člověka.",
{
"Václav Havel debutuje Zahradní slavností a Vyrozuměním.",
"Audience, Vernisáž a Protest jsou jednoaktovky o přizpůsobení.",
"Havel navazuje na absurdní drama, ale dá mu konkrétní českou situaci.",
"Hry kolují v samizdatu a hrají se v cizině, doma dlouho ne.",
NULL,
},
},
{
"3 / 3 • Jeviště", "Semafor, Cimrman a autorské divadlo",
"Tip: Divadlo Járy Cimrmana si vymyslelo génia, aby se smělo smát dějinám.",
{
"Malá divadla 60. let, Semafor a další, vracela jevišti písničku a improvizaci.",
"Zdeněk Svěrák a Ladislav Smoljak vytvářejí hry o Járovi Cimrmanovi.",
"České nebe později shrne národní mýty s nadsázkou.",
"Poezie a drama této doby často říkají víc mezi řádky než v hesle.",
NULL,
},
},
};
return lit_unit_page(3, &lit4_lessons[5], "lit4_unit6", "lit4_unit6_sub",
slides, G_N_ELEMENTS(slides));
}
static GtkWidget *build_lit4_unit6_exercise_page(void) {
static const ChoiceQ qs[] = {
{"Kdy dostal Jaroslav Seifert Nobelovu cenu?",
{"Roku 1895", "Roku 1984", "Roku 1836", "Roku 1415"},
4, 1},
{"Kterou hru napsal Václav Havel?",
{"Zahradní slavnost", "Maryša", "Lakomec", "Noc na Karlštejně"},
4, 0},
{"Co jsou Audience a Vernisáž?",
{"Havlovy jednoaktovky o přizpůsobení",
"Erbenovy balady",
"Legionářské romány",
"Klasicistní tragédie"},
4, 0},
{"Kdo vytvořil Divadlo Járy Cimrmana?",
{"Zdeněk Svěrák a Ladislav Smoljak",
"Karel a Josef Čapkovi",
"Alois a Vilém Mrštíkové",
"Vítězslav Nezval a Karel Teige"},
4, 0},
};
static const char *hints[] = {
"Nobelova cena za literaturu 1984 patří Seifertovi.",
"Zahradní slavnost je Havlova první velká hra.",
"Audience se odehrává v pivovaře a ukazuje tlak na zakázaného spisovatele.",
"Cimrman je mystifikace, která paroduje národní dějiny.",
};
return lit_mcq_page(3, 5, "lit4unit6", "lit4_ex6_title", "lit4_quiz6_head",
qs, hints, 4);
}
static GtkWidget *build_lit4_unit7_page(void) {
static const NetSlide slides[] = {
{
"1 / 3 • 1989", "Konec cenzury",
"Tip: po listopadu se najednou tiskne to, co čtyřicet let chodilo v opisech.",
{
"Samizdat a exil se vracejí do knihkupectví.",
"Čtenář dohání Kundera, Škvoreckého, Havla i zapadlé básníky.",
"Zároveň vzniká trh: kniha se musí i prodat.",
"Literatura ztrácí roli jediného místa, kde se říkala pravda.",
NULL,
},
},
{
"2 / 3 • Próza", "Viewegh, Topol a další",
"Tip: Báječná léta pod psa jsou generační vzpomínka na normalizaci, napsaná už svobodně.",
{
"Michal Viewegh v Báječných letech pod psa spojuje rodinnou kroniku a humor.",
"Jáchym Topol v Sestře píše syrovým, téměř mluveným jazykem o podzemí a svobodě.",
"Michal Ajvaz, Miloš Urban a Petra Hůlová ukazují, jak se próza rozběhla do různých směrů.",
"Autobiografie, groteska i náročný experiment stojí vedle sebe.",
NULL,
},
},
{
"3 / 3 • Dnešek", "Co z toho plyne pro školu",
"Tip: současný text se čte stejně poctivě jako klasika: druh, jazyk, kontext.",
{
"Po roce 1989 už nelze mluvit o jednom oficiálním stylu.",
"Poezie žije i mimo velká nakladatelství, na čteních a na webu.",
"Drama se vrací na scény, které čtyřicet let nesměly hrát zakázané hry.",
"Maturita žádá, abyste současnost uměli zařadit, ne jen převyprávět.",
NULL,
},
},
};
return lit_unit_page(3, &lit4_lessons[6], "lit4_unit7", "lit4_unit7_sub",
slides, G_N_ELEMENTS(slides));
}
static GtkWidget *build_lit4_unit7_exercise_page(void) {
static const ChoiceQ qs[] = {
{"Co se s literaturou stalo po roce 1989?",
{"Cenzura zesílila",
"Skončila cenzura a vrátily se samizdat a exil",
"Zanikla veškerá próza",
"Povinně se psal jen budovatelský román"},
4, 1},
{"Kdo napsal Báječná léta pod psa?",
{"Michal Viewegh", "Bohumil Hrabal", "Karel Hynek Mácha", "Jan Neruda"},
4, 0},
{"Který román napsal Jáchym Topol?",
{"Sestra", "Babička", "Máj", "Král Oidipus"},
4, 0},
{"Proč literatura po roce 1989 ztratila výsadní politickou roli?",
{"Protože pravda se směla říkat i jinde než v opisech",
"Protože zanikl český jazyk",
"Protože se vrátila jen latina",
"Protože maturita literaturu zrušila"},
4, 0},
};
static const char *hints[] = {
"Listopad 1989 otevírá nakladatelství i archivy.",
"Vieweghova kniha je humoristická kronika normalizace.",
"Sestra je syrový román o svobodě po roce 1989.",
"Dokud byla cenzura, kniha často nahrazovala veřejnou debatu.",
};
return lit_mcq_page(3, 6, "lit4unit7", "lit4_ex7_title", "lit4_quiz7_head",
qs, hints, 4);
}
static GtkWidget *build_lit4_unit8_page(void) {
static const NetSlide slides[] = {
{
"1 / 3 • Postup", "Jak číst text k maturitě",
"Tip: nejdřív řekněte, co text je, teprve potom, co si o něm myslíte.",
{
"Určete literární druh a žánr a dobu, do které text patří.",
"Pojmenujte téma a hlavní motivy, ne jen děj větu po větě.",
"U prózy si všimněte vypravěče, kompozice a postav.",
"U lyriky rozlište autora a lyrický subjekt.",
NULL,
},
},
{
"2 / 3 • Jazyk", "Čím text působí",
"Tip: jeden konkrétní prostředek, který umíte pojmenovat, je víc než obecná chvála.",
{
"Hledejte metaforu, přirovnání, symbol, kontrast nebo opakování.",
"U verše určete rým, stopu, nebo řekněte, že jde o volný verš.",
"Všimněte si slovníku: knižní, hovorový, biblický, ironický.",
"Kompozice může být chronologická, retrospektivní, nebo pásmo obrazů.",
NULL,
},
},
{
"3 / 3 • Kontext", "Text není ostrov",
"Tip: vlastní názor má stát na textu, ne místo něj.",
{
"Zařaďte ukázku k autorovi, směru a historické situaci.",
"Srovnání s jiným dílem ukáže, že látce rozumíte.",
"Řekněte, co text sděluje dnes, a opřete to o konkrétní místo.",
"Struktura odpovědi: zařazení, téma, jazyk, kontext, vlastní soud.",
NULL,
},
},
};
return lit_unit_page(3, &lit4_lessons[7], "lit4_unit8", "lit4_unit8_sub",
slides, G_N_ELEMENTS(slides));
}
static GtkWidget *build_lit4_unit8_exercise_page(void) {
static const ChoiceQ qs[] = {
{"Čím má začít rozbor textu?",
{"Určením druhu, žánru a doby",
"Převyprávěním celého dějepisu",
"Vlastním dojmem bez textu",
"Seznamem všech autorů století"},
4, 0},
{"Koho nesmíme zaměnit v lyrice?",
{"Autora a lyrický subjekt",
"Nakladatele a tiskaře",
"Čtenáře a cenzora",
"Rým a stopu"},
4, 0},
{"Co je volný verš?",
{"Verš vázaný povinným sdruženým rýmem",
"Verš bez pravidelného rýmu a stopy",
"Jen antický hexametr",
"Dramatická replika"},
4, 1},
{"Jak má vypadat vlastní názor u maturity?",
{"Má nahradit rozbor",
"Má vycházet z konkrétního místa v textu",
"Má být co nejdelší bez argumentu",
"Má zůstat nevysloven"},
4, 1},
};
static const char *hints[] = {
"Zařazení je rám, bez kterého jazykový rozbor visí ve vzduchu.",
"Lyrický subjekt je hlas básně, ne automaticky občanský průkaz autora.",
"Volný verš je běžný od avantgardy po současnost.",
"Soud bez citace z textu maturita nepočítá jako rozbor.",
};
return lit_mcq_page(3, 7, "lit4unit8", "lit4_ex8_title", "lit4_quiz8_head",
qs, hints, 4);
}
void add_lit4_pages(GtkStack *stack) {
typedef GtkWidget *(*LitBuilder)(void);
static const struct {
const char *unit_name;
const char *ex_name;
LitBuilder build_unit;
LitBuilder build_ex;
} pages[] = {
{"lit4unit1", "lit4ex1", build_lit4_unit1_page, build_lit4_unit1_exercise_page},
{"lit4unit2", "lit4ex2", build_lit4_unit2_page, build_lit4_unit2_exercise_page},
{"lit4unit3", "lit4ex3", build_lit4_unit3_page, build_lit4_unit3_exercise_page},
{"lit4unit4", "lit4ex4", build_lit4_unit4_page, build_lit4_unit4_exercise_page},
{"lit4unit5", "lit4ex5", build_lit4_unit5_page, build_lit4_unit5_exercise_page},
{"lit4unit6", "lit4ex6", build_lit4_unit6_page, build_lit4_unit6_exercise_page},
{"lit4unit7", "lit4ex7", build_lit4_unit7_page, build_lit4_unit7_exercise_page},
{"lit4unit8", "lit4ex8", build_lit4_unit8_page, build_lit4_unit8_exercise_page},
};
for (guint i = 0; i < G_N_ELEMENTS(pages); i++) {
gtk_stack_add_named(stack, pages[i].build_unit(), pages[i].unit_name);
gtk_stack_add_named(stack, pages[i].build_ex(), pages[i].ex_name);
}
}

947
src/literatura.c Normal file
View file

@ -0,0 +1,947 @@
#include "graduately.h"
/* Literature for Český jazyk a literatura.
* Four years follow the chronology used in secondary-school syllabi
* (RVP G, literární komunikace, and RVP for vocational schools,
* estetické vzdělávání): antiquity through the present, then a lesson
* on interpreting a text. Each lesson is a short overview and a quiz. */
typedef struct {
const char *map_page;
const char *back_page;
const char *title_key;
const char *sub_key;
const char *unit_keys[LIT_N];
char **progress_path;
NetLesson *lessons;
GtkWidget *scroll;
GtkWidget *fixed;
GtkWidget *rail;
GtkWidget *nodes[LIT_N];
GtkWidget *labels[LIT_N];
double cx[LIT_N];
double cy[LIT_N];
int cols;
int rows;
int cw;
int ch;
guint idle;
double last_avail;
int last_cols;
int last_rows;
int last_cw;
int last_ch;
cairo_surface_t *rail_cache;
int cache_w;
int cache_h;
int note_last_w;
} LitTrack;
static LitTrack lit_tracks[4];
static void lit_ensure(void);
static void lit_point(LitTrack *T, double t, double *ox, double *oy) {
int k = (int)t;
double u = t - (double)k;
double u2, u3;
double p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y;
if (k < 0) { k = 0; u = 0.0; }
if (k >= LIT_N - 1) { k = LIT_N - 2; u = 1.0; }
p1x = T->cx[k]; p1y = T->cy[k];
p2x = T->cx[k + 1]; p2y = T->cy[k + 1];
if (k - 1 >= 0) { p0x = T->cx[k - 1]; p0y = T->cy[k - 1]; }
else { p0x = p1x - (p2x - p1x); p0y = p1y - (p2y - p1y); }
if (k + 2 < LIT_N) { p3x = T->cx[k + 2]; p3y = T->cy[k + 2]; }
else { p3x = p2x + (p2x - p1x); p3y = p2y + (p2y - p1y); }
u2 = u * u;
u3 = u2 * u;
*ox = 0.5 * (2.0 * p1x + (-p0x + p2x) * u
+ (2.0 * p0x - 5.0 * p1x + 4.0 * p2x - p3x) * u2
+ (-p0x + 3.0 * p1x - 3.0 * p2x + p3x) * u3);
*oy = 0.5 * (2.0 * p1y + (-p0y + p2y) * u
+ (2.0 * p0y - 5.0 * p1y + 4.0 * p2y - p3y) * u2
+ (-p0y + 3.0 * p1y - 3.0 * p2y + p3y) * u3);
}
static void lit_path(LitTrack *T, cairo_t *cr, double t0, double t1) {
const double steps_per_unit = 24.0;
int n = (int)((t1 - t0) * steps_per_unit);
double x, y;
int s;
if (n < 1)
n = 1;
lit_point(T, t0, &x, &y);
cairo_move_to(cr, x, y);
for (s = 1; s <= n; s++) {
lit_point(T, t0 + (t1 - t0) * (double)s / (double)n, &x, &y);
cairo_line_to(cr, x, y);
}
}
static void lit_geometry(LitTrack *T, double avail) {
const double phase = 2.0 * G_PI * 1.7 / (double)(LIT_N - 1);
int rows;
int r, c, i;
for (rows = 1; rows <= LIT_N; rows++) {
int cols = (LIT_N + rows - 1) / rows;
if (2.0 * ROAD_MX + (cols - 1) * PATH_SPAC <= avail + 1.0)
break;
}
if (rows > LIT_N)
rows = LIT_N;
T->rows = rows;
T->cols = (LIT_N + rows - 1) / rows;
if (T->cols < 1)
T->cols = 1;
T->cw = (int)(2.0 * ROAD_MX + (T->cols - 1) * PATH_SPAC);
T->ch = (int)(2.0 * ROAD_MY + (rows - 1) * ROAD_GAP);
for (r = 0; r < rows; r++) {
int base = r * T->cols;
int len = MIN(T->cols, LIT_N - base);
int fwd = (r % 2) == 0;
for (c = 0; c < len; c++) {
int cc = fwd ? c : (T->cols - 1 - c);
i = base + c;
T->cx[i] = ROAD_MX + cc * PATH_SPAC;
T->cy[i] = ROAD_MY + r * ROAD_GAP
+ ROAD_WAVE * sin((double)i * phase);
}
}
}
static void lit_apply_layout(LitTrack *T) {
if (!T->fixed)
return;
if (T->cols == T->last_cols && T->rows == T->last_rows &&
T->cw == T->last_cw && T->ch == T->last_ch)
return;
T->last_cols = T->cols;
T->last_rows = T->rows;
T->last_cw = T->cw;
T->last_ch = T->ch;
if (T->rail_cache) {
cairo_surface_destroy(T->rail_cache);
T->rail_cache = NULL;
}
for (int i = 0; i < LIT_N; i++) {
if (!T->nodes[i] || !T->labels[i])
continue;
gtk_fixed_move(GTK_FIXED(T->fixed), T->nodes[i],
(int)(T->cx[i] - NODE_SIZE / 2.0),
(int)(T->cy[i] - NODE_SIZE / 2.0));
gtk_fixed_move(GTK_FIXED(T->fixed), T->labels[i],
(int)(T->cx[i] - (PATH_SPAC - 20.0) / 2.0),
(int)(T->cy[i] + NODE_SIZE / 2.0 + 10.0));
}
gtk_widget_set_size_request(T->fixed, T->cw, T->ch);
gtk_widget_set_size_request(T->rail, T->cw, T->ch);
gtk_fixed_move(GTK_FIXED(T->fixed), T->rail, 0, 0);
gtk_widget_queue_draw(T->rail);
}
static void lit_relayout(LitTrack *T) {
GtkAdjustment *hadj;
double avail;
if (!T->scroll)
return;
hadj = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(T->scroll));
avail = gtk_adjustment_get_page_size(hadj);
if (avail < 1.0)
return;
if (fabs(avail - T->last_avail) < 1.0)
return;
T->last_avail = avail;
lit_geometry(T, avail);
lit_apply_layout(T);
}
static gboolean lit_relayout_idle(gpointer data) {
LitTrack *T = data;
T->idle = 0;
lit_relayout(T);
return G_SOURCE_REMOVE;
}
static void lit_relayout_later(LitTrack *T) {
if (T->idle == 0)
T->idle = g_idle_add(lit_relayout_idle, T);
}
static void lit_adjust_notify(GtkAdjustment *adj, GParamSpec *ps,
gpointer data) {
(void)adj;
(void)ps;
lit_relayout_later(data);
}
static void lit_render_rail(LitTrack *T, cairo_t *cr) {
const double t_end = (double)(LIT_N - 1);
const Rgb rail = color_from_hex(app_theme.rail);
const Rgb muted = color_from_hex(app_theme.subtext);
cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
cairo_paint(cr);
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND);
cairo_new_path(cr);
lit_path(T, cr, 0.0, t_end);
cairo_set_line_width(cr, 12);
cairo_set_source_rgb(cr, rail.r, rail.g, rail.b);
cairo_stroke(cr);
cairo_set_source_rgba(cr, muted.r, muted.g, muted.b, 0.17);
cairo_set_dash(cr, (double[]){2.0, 40.0}, 2, 0.0);
cairo_new_path(cr);
lit_path(T, cr, 0.0, t_end);
cairo_stroke(cr);
cairo_set_dash(cr, NULL, 0, 0.0);
}
static void lit_draw_rail(GtkDrawingArea *area, cairo_t *cr,
int width, int height, gpointer data) {
LitTrack *T = data;
cairo_t *rcr;
(void)area;
(void)width;
(void)height;
if (!T->rail_cache || T->cache_w != T->cw || T->cache_h != T->ch) {
if (T->rail_cache)
cairo_surface_destroy(T->rail_cache);
T->cache_w = T->cw > 0 ? T->cw : 1;
T->cache_h = T->ch > 0 ? T->ch : 1;
T->rail_cache = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
T->cache_w, T->cache_h);
rcr = cairo_create(T->rail_cache);
lit_render_rail(T, rcr);
cairo_destroy(rcr);
}
cairo_set_source_surface(cr, T->rail_cache, 0, 0);
cairo_paint(cr);
}
void lit_rail_theme_reset(void) {
for (int y = 0; y < 4; y++) {
LitTrack *T = &lit_tracks[y];
if (T->rail_cache) {
cairo_surface_destroy(T->rail_cache);
T->rail_cache = NULL;
}
if (T->rail)
gtk_widget_queue_draw(T->rail);
}
}
static void lit_save(LitTrack *T) {
GKeyFile *kf;
char *path;
gchar *data;
if (!T->progress_path || !*T->progress_path)
return;
path = *T->progress_path;
kf = g_key_file_new();
for (int i = 0; i < LIT_N; i++) {
gchar key[8];
g_snprintf(key, sizeof(key), "%d", i + 1);
g_key_file_set_boolean(kf, "done", key, T->lessons[i].done);
}
if (g_mkdir_with_parents(PROGRESS_DIR, 0755) != 0) {
g_key_file_free(kf);
return;
}
data = g_key_file_to_data(kf, NULL, NULL);
g_key_file_free(kf);
if (data) {
GError *err = NULL;
g_file_set_contents(path, data, -1, &err);
if (err)
g_error_free(err);
g_free(data);
}
}
static void lit_load_one(LitTrack *T) {
GKeyFile *kf;
GError *err = NULL;
const char *path;
if (!T->progress_path || !*T->progress_path)
return;
path = *T->progress_path;
kf = g_key_file_new();
if (!g_key_file_load_from_file(kf, path, G_KEY_FILE_NONE, &err)) {
if (err)
g_error_free(err);
g_key_file_free(kf);
return;
}
for (int i = 0; i < LIT_N; i++) {
gchar key[8];
g_snprintf(key, sizeof(key), "%d", i + 1);
T->lessons[i].done = g_key_file_get_boolean(kf, "done", key, NULL);
}
g_key_file_free(kf);
}
void lit_load_progress(void) {
lit_ensure();
for (int y = 0; y < 4; y++)
lit_load_one(&lit_tracks[y]);
}
static void lit_refresh(LitTrack *T) {
for (int i = 0; i < LIT_N; i++) {
GtkWidget *node = T->nodes[i];
GtkWidget *icon = T->lessons[i].done_icon;
if (!node)
continue;
if (T->lessons[i].done) {
gtk_widget_remove_css_class(node, "current");
gtk_widget_add_css_class(node, "done");
if (icon)
gtk_widget_set_visible(icon, TRUE);
} else {
gtk_widget_remove_css_class(node, "done");
gtk_widget_add_css_class(node, "current");
if (icon)
gtk_widget_set_visible(icon, FALSE);
}
}
}
static void lit_mark_done(LitTrack *T, int lesson_id) {
if (lesson_id < 0 || lesson_id >= LIT_N)
return;
if (T->lessons[lesson_id].done)
return;
T->lessons[lesson_id].done = TRUE;
lit_save(T);
lit_refresh(T);
refresh_stats_ui();
}
void progress_for_lit(ProgressSum *out) {
if (!out)
return;
lit_ensure();
for (int y = 0; y < 4; y++) {
LitTrack *T = &lit_tracks[y];
out->total_ex += LIT_N;
out->open_units += LIT_N;
for (int i = 0; i < LIT_N; i++) {
if (T->lessons[i].done) {
out->done_ex++;
out->done_units++;
}
}
}
}
static void lit_open_unit(GtkButton *button, gpointer data) {
NetLesson *L = data;
(void)button;
if (!L)
return;
L->idx = 0;
if (L->stack) {
char name[16];
g_snprintf(name, sizeof(name), "s%u", L->idx);
gtk_stack_set_visible_child_name(GTK_STACK(L->stack), name);
if (L->prev_btn)
gtk_widget_set_sensitive(L->prev_btn, FALSE);
if (L->next_btn)
gtk_button_set_label(GTK_BUTTON(L->next_btn), tr("net_slide_next"));
}
gtk_stack_set_visible_child_name(main_stack, L->unit_page);
}
static void lit_add_node(LitTrack *T, GtkFixed *fixed, int index) {
GtkWidget *card;
GtkWidget *vbox;
GtkWidget *number;
GtkWidget *icon;
GtkWidget *name;
char *text;
card = gtk_button_new();
gtk_widget_add_css_class(card, "unit-node");
gtk_widget_add_css_class(card, "current");
gtk_widget_set_can_focus(card, FALSE);
gtk_widget_set_size_request(card, (int)NODE_SIZE, (int)NODE_SIZE);
vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 2);
gtk_widget_set_halign(vbox, GTK_ALIGN_CENTER);
gtk_widget_set_valign(vbox, GTK_ALIGN_CENTER);
gtk_button_set_child(GTK_BUTTON(card), vbox);
text = g_strdup_printf("%d", index + 1);
number = gtk_label_new(text);
g_free(text);
gtk_widget_add_css_class(number, "unit-number");
gtk_box_append(GTK_BOX(vbox), number);
icon = icon_area_new(draw_check_icon, 0.1176, 0.1176, 0.1804, 18);
gtk_widget_set_visible(icon, FALSE);
gtk_box_append(GTK_BOX(vbox), icon);
T->lessons[index].done_icon = icon;
g_signal_connect(card, "clicked", G_CALLBACK(lit_open_unit),
&T->lessons[index]);
T->nodes[index] = card;
gtk_fixed_put(fixed, card, 0, 0);
name = gtk_label_new(NULL);
i18n_bind(name, T->unit_keys[index], 0);
gtk_widget_set_size_request(name, (int)(PATH_SPAC - 20.0), -1);
gtk_widget_set_halign(name, GTK_ALIGN_CENTER);
gtk_label_set_justify(GTK_LABEL(name), GTK_JUSTIFY_CENTER);
gtk_label_set_wrap(GTK_LABEL(name), TRUE);
gtk_label_set_max_width_chars(GTK_LABEL(name), 18);
gtk_widget_add_css_class(name, "unit-name");
T->labels[index] = name;
gtk_fixed_put(fixed, name, 0, 0);
}
static GtkWidget *lit_build_map(LitTrack *T) {
GtkWidget *page;
lit_ensure();
GtkWidget *scroll;
GtkWidget *wrap;
GtkWidget *fixed;
GtkWidget *rail;
GtkAdjustment *ha;
GtkAdjustment *va;
T->last_avail = -1.0;
lit_geometry(T, 1000.0);
page = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_widget_set_hexpand(page, TRUE);
gtk_widget_set_vexpand(page, TRUE);
gtk_widget_set_margin_start(page, 32);
gtk_widget_set_margin_end(page, 32);
gtk_widget_set_margin_top(page, 24);
gtk_widget_set_margin_bottom(page, 24);
gtk_box_append(GTK_BOX(page),
top_bar(T->back_page, T->title_key, T->sub_key));
scroll = gtk_scrolled_window_new();
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_widget_set_vexpand(scroll, TRUE);
gtk_widget_set_margin_top(scroll, 14);
gtk_box_append(GTK_BOX(page), scroll);
T->scroll = scroll;
wrap = gtk_center_box_new();
gtk_widget_set_vexpand(wrap, TRUE);
gtk_widget_set_hexpand(wrap, TRUE);
gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(scroll), wrap);
fixed = gtk_fixed_new();
gtk_widget_set_halign(fixed, GTK_ALIGN_CENTER);
gtk_widget_set_valign(fixed, GTK_ALIGN_CENTER);
gtk_widget_set_size_request(fixed, T->cw, T->ch);
gtk_center_box_set_center_widget(GTK_CENTER_BOX(wrap), fixed);
T->fixed = fixed;
rail = gtk_drawing_area_new();
gtk_widget_set_size_request(rail, T->cw, T->ch);
gtk_drawing_area_set_draw_func(GTK_DRAWING_AREA(rail), lit_draw_rail,
T, NULL);
gtk_fixed_put(GTK_FIXED(fixed), rail, 0, 0);
T->rail = rail;
for (int i = 0; i < LIT_N; i++)
lit_add_node(T, GTK_FIXED(fixed), i);
ha = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(scroll));
va = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(scroll));
g_signal_connect(ha, "notify::page-size",
G_CALLBACK(lit_adjust_notify), T);
g_signal_connect(va, "notify::page-size",
G_CALLBACK(lit_adjust_notify), T);
lit_apply_layout(T);
lit_relayout_later(T);
lit_refresh(T);
return page;
}
static GtkWidget *lit_year_button(int year, const char *target,
const char *title_key, const char *sub_key) {
GtkWidget *btn;
GtkWidget *row;
GtkWidget *num;
GtkWidget *texts;
GtkWidget *title;
GtkWidget *sub;
char *num_text;
btn = gtk_button_new();
gtk_widget_add_css_class(btn, "unit-node");
gtk_widget_add_css_class(btn, "current");
gtk_widget_set_can_focus(btn, FALSE);
gtk_widget_set_hexpand(btn, TRUE);
gtk_widget_set_size_request(btn, -1, 84);
row = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 14);
gtk_widget_set_halign(row, GTK_ALIGN_START);
gtk_widget_set_valign(row, GTK_ALIGN_CENTER);
gtk_widget_set_margin_start(row, 18);
gtk_widget_set_margin_end(row, 18);
gtk_button_set_child(GTK_BUTTON(btn), row);
num_text = g_strdup_printf("%d", year);
num = gtk_label_new(num_text);
g_free(num_text);
gtk_widget_add_css_class(num, "unit-number");
gtk_widget_set_valign(num, GTK_ALIGN_CENTER);
gtk_box_append(GTK_BOX(row), num);
texts = gtk_box_new(GTK_ORIENTATION_VERTICAL, 2);
gtk_widget_set_halign(texts, GTK_ALIGN_START);
gtk_widget_set_hexpand(texts, TRUE);
gtk_box_append(GTK_BOX(row), texts);
title = gtk_label_new(NULL);
i18n_bind(title, title_key, 0);
gtk_widget_set_halign(title, GTK_ALIGN_START);
gtk_widget_add_css_class(title, "unit-name");
gtk_box_append(GTK_BOX(texts), title);
sub = gtk_label_new(NULL);
i18n_bind(sub, sub_key, 0);
gtk_widget_set_halign(sub, GTK_ALIGN_START);
gtk_label_set_wrap(GTK_LABEL(sub), TRUE);
gtk_label_set_xalign(GTK_LABEL(sub), 0.0);
gtk_widget_add_css_class(sub, "hint");
gtk_box_append(GTK_BOX(texts), sub);
g_object_set_data_full(G_OBJECT(btn), "target", g_strdup(target), g_free);
g_signal_connect(btn, "clicked", G_CALLBACK(on_nav_clicked), NULL);
return btn;
}
GtkWidget *build_lityears_page(void) {
GtkWidget *page;
GtkWidget *scroll;
GtkWidget *list;
static const char *targets[] = {"litmap", "lit2map", "lit3map", "lit4map"};
static const char *titles[] = {
"lit_year1", "lit_year2", "lit_year3", "lit_year4",
};
static const char *subs[] = {"lit_sub", "lit2_sub", "lit3_sub", "lit4_sub"};
page = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_widget_set_hexpand(page, TRUE);
gtk_widget_set_vexpand(page, TRUE);
gtk_widget_set_margin_start(page, 32);
gtk_widget_set_margin_end(page, 32);
gtk_widget_set_margin_top(page, 24);
gtk_widget_set_margin_bottom(page, 24);
gtk_box_append(GTK_BOX(page),
top_bar("czechmap", "Literatura", "lit_years_sub"));
scroll = gtk_scrolled_window_new();
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
gtk_widget_set_vexpand(scroll, TRUE);
gtk_widget_set_margin_top(scroll, 18);
gtk_box_append(GTK_BOX(page), scroll);
list = gtk_box_new(GTK_ORIENTATION_VERTICAL, 12);
gtk_widget_set_halign(list, GTK_ALIGN_CENTER);
gtk_widget_set_valign(list, GTK_ALIGN_CENTER);
gtk_widget_set_size_request(list, 420, -1);
gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(scroll), list);
for (int y = 0; y < 4; y++)
gtk_box_append(GTK_BOX(list),
lit_year_button(y + 1, targets[y], titles[y], subs[y]));
return page;
}
GtkWidget *build_litmap_page(void) { return lit_build_map(&lit_tracks[0]); }
GtkWidget *build_lit2map_page(void) { return lit_build_map(&lit_tracks[1]); }
GtkWidget *build_lit3map_page(void) { return lit_build_map(&lit_tracks[2]); }
GtkWidget *build_lit4map_page(void) { return lit_build_map(&lit_tracks[3]); }
static void lit_slide_apply(NetLesson *L) {
char name[16];
if (!L || !L->stack)
return;
g_snprintf(name, sizeof(name), "s%u", L->idx);
gtk_stack_set_visible_child_name(GTK_STACK(L->stack), name);
if (L->prev_btn) {
gtk_button_set_label(GTK_BUTTON(L->prev_btn), tr("net_slide_prev"));
gtk_widget_set_sensitive(L->prev_btn, L->idx > 0);
}
if (L->next_btn) {
gtk_button_set_label(
GTK_BUTTON(L->next_btn),
L->idx + 1 >= L->n_slides ? tr("net_slide_start")
: tr("net_slide_next"));
}
}
static void lit_slide_prev(GtkButton *button, gpointer data) {
NetLesson *L = data;
(void)button;
if (!L || L->idx == 0)
return;
L->idx--;
lit_slide_apply(L);
}
static void lit_slide_next(GtkButton *button, gpointer data) {
NetLesson *L = data;
(void)button;
if (!L)
return;
if (L->idx + 1 < L->n_slides) {
L->idx++;
lit_slide_apply(L);
} else {
gtk_stack_set_visible_child_name(main_stack, L->ex_page);
}
}
static void lit_rescale(LitTrack *T, int w) {
int body, head, kick;
if (w < 160)
w = 160;
body = w / 46;
if (body < 14) body = 14;
if (body > 26) body = 26;
head = body + 14;
if (head > 46) head = 46;
kick = body - 3;
if (kick < 11) kick = 11;
for (int i = 0; i < LIT_N; i++)
net_rescale_lesson_notes(&T->lessons[i], body, head, kick);
}
static gboolean lit_note_tick(GtkWidget *w, GdkFrameClock *clock,
gpointer data) {
LitTrack *T = data;
int width = gtk_widget_get_allocated_width(w);
(void)clock;
if (width != T->note_last_w) {
T->note_last_w = width;
lit_rescale(T, width);
}
return G_SOURCE_CONTINUE;
}
GtkWidget *lit_unit_page(int year, NetLesson *L, const char *title_key,
const char *sub_key, const NetSlide *slides,
guint n_slides) {
LitTrack *T;
lit_ensure();
T = &lit_tracks[year];
GtkWidget *page;
GtkWidget *scroll;
GtkWidget *nav;
net_lesson_notes_ensure(L);
net_notes_target = L;
L->n_slides = n_slides;
page = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_widget_set_margin_start(page, 28);
gtk_widget_set_margin_end(page, 28);
gtk_widget_set_margin_top(page, 20);
gtk_widget_set_margin_bottom(page, 20);
gtk_box_append(GTK_BOX(page), top_bar(T->map_page, title_key, sub_key));
scroll = gtk_scrolled_window_new();
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
gtk_widget_set_vexpand(scroll, TRUE);
gtk_widget_set_margin_top(scroll, 10);
gtk_box_append(GTK_BOX(page), scroll);
L->stack = gtk_stack_new();
gtk_stack_set_transition_type(GTK_STACK(L->stack),
GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT_RIGHT);
gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(scroll), L->stack);
for (guint s = 0; s < n_slides; s++) {
GtkWidget *stage = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
GtkWidget *card;
char name[16];
gtk_widget_set_vexpand(stage, TRUE);
g_snprintf(name, sizeof(name), "s%u", s);
gtk_stack_add_named(GTK_STACK(L->stack), stage, name);
card = gtk_box_new(GTK_ORIENTATION_VERTICAL, 16);
gtk_widget_add_css_class(card, "notes-card");
gtk_widget_set_valign(card, GTK_ALIGN_CENTER);
gtk_box_append(GTK_BOX(stage), card);
net_note_kicker(card, slides[s].kicker);
net_note_title(card, slides[s].title);
for (int i = 0; i < 8 && slides[s].line[i]; i++)
net_note_line(card, slides[s].line[i], FALSE);
if (slides[s].tip)
net_note_line(card, slides[s].tip, TRUE);
}
gtk_widget_add_tick_callback(L->stack, lit_note_tick, T, NULL);
T->note_last_w = -1;
lit_rescale(T, 0);
net_notes_target = NULL;
nav = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10);
gtk_box_set_homogeneous(GTK_BOX(nav), TRUE);
gtk_widget_set_margin_top(nav, 10);
gtk_box_append(GTK_BOX(page), nav);
L->prev_btn = gtk_button_new_with_label(tr("net_slide_prev"));
gtk_widget_add_css_class(L->prev_btn, "btn-primary");
g_signal_connect(L->prev_btn, "clicked", G_CALLBACK(lit_slide_prev), L);
gtk_box_append(GTK_BOX(nav), L->prev_btn);
L->next_btn = gtk_button_new_with_label(tr("net_slide_next"));
gtk_widget_add_css_class(L->next_btn, "btn-primary");
g_signal_connect(L->next_btn, "clicked", G_CALLBACK(lit_slide_next), L);
gtk_box_append(GTK_BOX(nav), L->next_btn);
L->idx = 0;
lit_slide_apply(L);
return page;
}
void lit_lessons_apply_lang(void) {
lit_ensure();
for (int y = 0; y < 4; y++) {
for (int i = 0; i < LIT_N; i++)
lit_slide_apply(&lit_tracks[y].lessons[i]);
}
}
typedef struct {
const ChoiceQ *qs;
int n;
int n_opts;
LitTrack *track;
int lesson_id;
GtkWidget *feedback;
GtkToggleButton **toggles;
GtkWidget **hints;
} LitMcqCtx;
static void lit_mcq_check(GtkButton *button, gpointer data) {
LitMcqCtx *ctx = data;
int ok = 0;
(void)button;
for (int i = 0; i < ctx->n; i++) {
int active = -1;
for (int o = 0; o < ctx->n_opts; o++) {
GtkToggleButton *tb = ctx->toggles[i * ctx->n_opts + o];
gtk_widget_remove_css_class(GTK_WIDGET(tb), "ok");
gtk_widget_remove_css_class(GTK_WIDGET(tb), "wrong");
if (gtk_toggle_button_get_active(tb))
active = o;
}
if (active == ctx->qs[i].correct) {
ok++;
gtk_widget_add_css_class(
GTK_WIDGET(ctx->toggles[i * ctx->n_opts + active]), "ok");
} else if (active >= 0) {
gtk_widget_add_css_class(
GTK_WIDGET(ctx->toggles[i * ctx->n_opts + active]), "wrong");
}
if (ctx->hints && ctx->hints[i])
gtk_widget_set_visible(ctx->hints[i], TRUE);
}
if (ok == ctx->n) {
set_feedback(ctx->feedback, TRUE, tr("feedback_ok"));
lit_mark_done(ctx->track, ctx->lesson_id);
} else {
set_feedback(ctx->feedback, FALSE, tr("feedback_retry_short"));
}
}
GtkWidget *lit_mcq_page(int year, int lesson_id, const char *back_page,
const char *title_key, const char *heading_key,
const ChoiceQ *qs, const char **hints, int n) {
GtkWidget *page;
GtkWidget *scroll;
GtkWidget *body;
GtkWidget *check;
GtkWidget *btns;
GtkWidget *head;
GtkWidget *intro;
LitMcqCtx *ctx = g_new0(LitMcqCtx, 1);
int n_opts = qs[0].n_options;
lit_ensure();
page = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_widget_set_margin_start(page, 32);
gtk_widget_set_margin_end(page, 32);
gtk_widget_set_margin_top(page, 24);
gtk_widget_set_margin_bottom(page, 24);
gtk_box_append(GTK_BOX(page), top_bar(back_page, title_key, NULL));
scroll = gtk_scrolled_window_new();
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_widget_set_vexpand(scroll, TRUE);
gtk_widget_set_margin_top(scroll, 12);
gtk_box_append(GTK_BOX(page), scroll);
body = gtk_box_new(GTK_ORIENTATION_VERTICAL, 14);
gtk_widget_set_halign(body, GTK_ALIGN_FILL);
gtk_widget_set_hexpand(body, TRUE);
gtk_widget_set_margin_start(body, 4);
gtk_widget_set_margin_end(body, 4);
gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(scroll), body);
head = gtk_label_new(NULL);
i18n_bind(head, heading_key, 0);
gtk_widget_set_halign(head, GTK_ALIGN_START);
gtk_label_set_wrap(GTK_LABEL(head), TRUE);
gtk_widget_set_margin_top(head, 4);
gtk_widget_add_css_class(head, "quiz-heading");
gtk_box_append(GTK_BOX(body), head);
intro = gtk_label_new(NULL);
i18n_bind(intro, "net_quiz_intro", 0);
gtk_widget_set_halign(intro, GTK_ALIGN_START);
gtk_label_set_wrap(GTK_LABEL(intro), TRUE);
gtk_widget_add_css_class(intro, "quiz-intro");
gtk_widget_set_margin_bottom(intro, 4);
gtk_box_append(GTK_BOX(body), intro);
ctx->qs = qs;
ctx->n = n;
ctx->n_opts = n_opts;
ctx->track = &lit_tracks[year];
ctx->lesson_id = lesson_id;
ctx->toggles = g_new0(GtkToggleButton *, n * n_opts);
ctx->hints = g_new0(GtkWidget *, n);
for (int i = 0; i < n; i++) {
GtkWidget *card = mcq_append_question(body, i + 1, &qs[i],
&ctx->toggles[i * n_opts]);
ctx->hints[i] = meaning_add(card, hints[i]);
}
btns = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
gtk_widget_set_margin_top(btns, 8);
gtk_widget_set_margin_bottom(btns, 8);
gtk_box_append(GTK_BOX(body), btns);
check = gtk_button_new();
i18n_bind(check, "check", 1);
gtk_widget_add_css_class(check, "btn-primary");
gtk_widget_set_halign(check, GTK_ALIGN_START);
gtk_box_append(GTK_BOX(btns), check);
g_signal_connect(check, "clicked", G_CALLBACK(lit_mcq_check), ctx);
ctx->feedback = gtk_label_new("");
gtk_widget_set_halign(ctx->feedback, GTK_ALIGN_START);
gtk_box_append(GTK_BOX(body), ctx->feedback);
return page;
}
static gboolean lit_ready;
static void lit_tracks_init(void) {
static const char *keys0[] = {
"lit_unit1", "lit_unit2", "lit_unit3", "lit_unit4",
"lit_unit5", "lit_unit6", "lit_unit7", "lit_unit8",
};
static const char *keys1[] = {
"lit2_unit1", "lit2_unit2", "lit2_unit3", "lit2_unit4",
"lit2_unit5", "lit2_unit6", "lit2_unit7", "lit2_unit8",
};
static const char *keys2[] = {
"lit3_unit1", "lit3_unit2", "lit3_unit3", "lit3_unit4",
"lit3_unit5", "lit3_unit6", "lit3_unit7", "lit3_unit8",
};
static const char *keys3[] = {
"lit4_unit1", "lit4_unit2", "lit4_unit3", "lit4_unit4",
"lit4_unit5", "lit4_unit6", "lit4_unit7", "lit4_unit8",
};
static const char *const *all_keys[4] = {keys0, keys1, keys2, keys3};
static const char *maps[] = {"litmap", "lit2map", "lit3map", "lit4map"};
static const char *titles[] = {
"lit_year1", "lit_year2", "lit_year3", "lit_year4",
};
static const char *subs[] = {"lit_sub", "lit2_sub", "lit3_sub", "lit4_sub"};
NetLesson *lessons[4] = {
lit_lessons, lit2_lessons, lit3_lessons, lit4_lessons,
};
char **paths[4] = {
&app_progress_lit, &app_progress_lit2,
&app_progress_lit3, &app_progress_lit4,
};
for (int y = 0; y < 4; y++) {
LitTrack *T = &lit_tracks[y];
T->map_page = maps[y];
T->back_page = "lityears";
T->title_key = titles[y];
T->sub_key = subs[y];
T->progress_path = paths[y];
T->lessons = lessons[y];
T->last_avail = -1.0;
T->last_cols = -1;
T->note_last_w = -1;
for (int i = 0; i < LIT_N; i++)
T->unit_keys[i] = all_keys[y][i];
}
}
static void lit_ensure(void) {
if (lit_ready)
return;
lit_ready = TRUE;
lit_tracks_init();
}

View file

@ -388,6 +388,10 @@ static gboolean run_smoke_test(gpointer data) {
"netyears", "netmap", "hwyears", "hwmap", "onyears", "onmap", "on2map",
"on3map", "on4map",
"czechmap",
"lityears", "litmap", "lit2map", "lit3map", "lit4map",
"litunit1", "litex1", "litunit8", "litex8",
"lit2unit1", "lit2ex1", "lit3unit1", "lit3ex1",
"lit4unit1", "lit4ex1", "lit4unit8", "lit4ex8",
"mluvnice", "readinglist",
"cetba1984", "cetba1984quiz", "cetba1984dej",
"cetbaFuks", "cetbaFuksQuiz", "cetbaFuksDej",
@ -522,6 +526,15 @@ void activate(GtkApplication *app, gpointer user_data) {
gtk_stack_add_named(main_stack, build_on4map_page(), "on4map");
add_on4_pages(main_stack);
gtk_stack_add_named(main_stack, build_czechmap_page(), "czechmap");
gtk_stack_add_named(main_stack, build_lityears_page(), "lityears");
gtk_stack_add_named(main_stack, build_litmap_page(), "litmap");
add_lit_pages(main_stack);
gtk_stack_add_named(main_stack, build_lit2map_page(), "lit2map");
add_lit2_pages(main_stack);
gtk_stack_add_named(main_stack, build_lit3map_page(), "lit3map");
add_lit3_pages(main_stack);
gtk_stack_add_named(main_stack, build_lit4map_page(), "lit4map");
add_lit4_pages(main_stack);
gtk_stack_add_named(main_stack, build_mluvnice_page(), "mluvnice");
for (int n = 1; n <= 20; n++) {
char name[16];

View file

@ -58,6 +58,7 @@ void load_progress(void) {
on2_load_progress();
on3_load_progress();
on4_load_progress();
lit_load_progress();
}
/* Redraw the exercise rails of every unit that already has a page. */

View file

@ -237,7 +237,40 @@ static void catalog_rebuild(void) {
catalog_add_key("Český jazyk a literatura", "search_subject",
"czechmap", FALSE, 0, "cestina czech");
catalog_add_key("Literatura", "search_lesson", "czechmap", TRUE, 1, NULL);
catalog_add_key("Literatura", "search_lesson", "lityears", FALSE, 1,
"literatura");
catalog_add_key("lit_year1", "search_lesson", "litmap", FALSE, 1, "rocnik");
catalog_add_key("lit_year2", "search_lesson", "lit2map", FALSE, 1, "rocnik");
catalog_add_key("lit_year3", "search_lesson", "lit3map", FALSE, 1, "rocnik");
catalog_add_key("lit_year4", "search_lesson", "lit4map", FALSE, 1, "rocnik");
for (i = 1; i <= LIT_N; i++) {
g_snprintf(key, sizeof(key), "lit_unit%d", i);
g_snprintf(page, sizeof(page), "litunit%d", i);
catalog_add_key(key, "search_lesson", page, FALSE, 2, "literatura");
g_snprintf(page, sizeof(page), "litex%d", i);
catalog_add(tr(key), tr("search_exercise"), page, FALSE, 3, "kviz quiz");
}
for (i = 1; i <= LIT_N; i++) {
g_snprintf(key, sizeof(key), "lit2_unit%d", i);
g_snprintf(page, sizeof(page), "lit2unit%d", i);
catalog_add_key(key, "search_lesson", page, FALSE, 2, "literatura");
g_snprintf(page, sizeof(page), "lit2ex%d", i);
catalog_add(tr(key), tr("search_exercise"), page, FALSE, 3, "kviz quiz");
}
for (i = 1; i <= LIT_N; i++) {
g_snprintf(key, sizeof(key), "lit3_unit%d", i);
g_snprintf(page, sizeof(page), "lit3unit%d", i);
catalog_add_key(key, "search_lesson", page, FALSE, 2, "literatura");
g_snprintf(page, sizeof(page), "lit3ex%d", i);
catalog_add(tr(key), tr("search_exercise"), page, FALSE, 3, "kviz quiz");
}
for (i = 1; i <= LIT_N; i++) {
g_snprintf(key, sizeof(key), "lit4_unit%d", i);
g_snprintf(page, sizeof(page), "lit4unit%d", i);
catalog_add_key(key, "search_lesson", page, FALSE, 2, "literatura");
g_snprintf(page, sizeof(page), "lit4ex%d", i);
catalog_add(tr(key), tr("search_exercise"), page, FALSE, 3, "kviz quiz");
}
catalog_add_key("Mluvnice", "search_lesson", "mluvnice", FALSE, 1,
"gramatika grammar");
catalog_add_key("Maturitní četba", "search_book", "readinglist", FALSE, 1,

View file

@ -71,8 +71,10 @@ void refresh_stats_ui(void) {
progress_for_hw(&all);
else if (s == ON_SUBJ)
progress_for_on(&all);
else if (s == CZ_SUBJ)
else if (s == CZ_SUBJ) {
progress_for_mluvnice(&all);
progress_for_lit(&all);
}
else
progress_for_units(sub_unit_start[s], sub_unit_count[s], &all);
}
@ -113,8 +115,10 @@ void refresh_stats_ui(void) {
progress_for_hw(&sp);
else if (s == ON_SUBJ)
progress_for_on(&sp);
else if (s == CZ_SUBJ)
else if (s == CZ_SUBJ) {
progress_for_mluvnice(&sp);
progress_for_lit(&sp);
}
else
progress_for_units(sub_unit_start[s], sub_unit_count[s], &sp);
if (has_content) {

View file

@ -431,5 +431,6 @@ void apply_theme(void) {
on3_rail_theme_reset();
on4_rail_theme_reset();
czech_rail_theme_reset();
lit_rail_theme_reset();
book_rail_theme_reset();
}

View file

@ -26,6 +26,10 @@ char *app_progress_on3;
char *app_progress_on4;
char *app_progress_mluvnice;
char *app_progress_cetba;
char *app_progress_lit;
char *app_progress_lit2;
char *app_progress_lit3;
char *app_progress_lit4;
static char *dup_dirname(const char *path) {
char *tmp = g_strdup(path);
@ -168,6 +172,10 @@ static void set_progress_paths(const char *write_root) {
g_free(app_progress_on4);
g_free(app_progress_mluvnice);
g_free(app_progress_cetba);
g_free(app_progress_lit);
g_free(app_progress_lit2);
g_free(app_progress_lit3);
g_free(app_progress_lit4);
app_progress_dir = g_build_filename(write_root, PROGRESS_DIR_NAME, NULL);
app_progress_u1 = g_build_filename(app_progress_dir, "unit1.conf", NULL);
@ -182,6 +190,10 @@ static void set_progress_paths(const char *write_root) {
app_progress_on4 = g_build_filename(app_progress_dir, "on4.conf", NULL);
app_progress_mluvnice = g_build_filename(app_progress_dir, "mluvnice.conf", NULL);
app_progress_cetba = g_build_filename(app_progress_dir, "cetba.conf", NULL);
app_progress_lit = g_build_filename(app_progress_dir, "lit.conf", NULL);
app_progress_lit2 = g_build_filename(app_progress_dir, "lit2.conf", NULL);
app_progress_lit3 = g_build_filename(app_progress_dir, "lit3.conf", NULL);
app_progress_lit4 = g_build_filename(app_progress_dir, "lit4.conf", NULL);
}
/* Resolve read-only asset root, chdir there, and point progress at a writable