mirror of
https://github.com/pepaskopec-blip/Graduately.git
synced 2026-10-27 15:14:35 +00:00
Add year-4 civics lessons on the economy, the world and philosophy.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
0ee2f8e960
commit
50a23c334b
27 changed files with 2317 additions and 32 deletions
|
|
@ -70,7 +70,7 @@ Intel Mac, jiná architektura nebo úpravy kódu → [sestavení ze zdroje](#ses
|
||||||
(82 knih: zápisky, kvíz, sestavení děje); literární teorie je zatím zamčená
|
(82 knih: zápisky, kvíz, sestavení děje); literární teorie je zatím zamčená
|
||||||
- **Občanská nauka** — 1. ročník, 17 lekcí (člověk v lidském společenství);
|
- **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);
|
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 je zamčený
|
4. ročník, 16 lekcí (hospodářství, svět a filozofie)
|
||||||
- statistiky, hledání (lupa nebo `Cmd/Ctrl+K`), 10 témat, tmavý/světlý režim, čeština/angličtina
|
- statistiky, hledání (lupa nebo `Cmd/Ctrl+K`), 10 témat, tmavý/světlý režim, čeština/angličtina
|
||||||
- ukončení: `Cmd/Super+Q` nebo `Alt+F4`
|
- ukončení: `Cmd/Super+Q` nebo `Alt+F4`
|
||||||
|
|
||||||
|
|
@ -266,7 +266,8 @@ Intel Mac, another architecture, or hacking on the code →
|
||||||
(82 books: notes, quiz, plot ordering); literature theory is still locked
|
(82 books: notes, quiz, plot ordering); literature theory is still locked
|
||||||
- **Civics** — year 1, 17 lessons (the individual and society);
|
- **Civics** — year 1, 17 lessons (the individual and society);
|
||||||
year 2, 16 lessons (the citizen in a democratic state);
|
year 2, 16 lessons (the citizen in a democratic state);
|
||||||
year 3, 16 lessons (the individual and the law); year 4 is locked
|
year 3, 16 lessons (the individual and the law);
|
||||||
|
year 4, 16 lessons (the economy, the world and philosophy)
|
||||||
- statistics, search (magnifier or `Cmd/Ctrl+K`), 10 palettes, dark/light mode, Czech/English
|
- statistics, search (magnifier or `Cmd/Ctrl+K`), 10 palettes, dark/light mode, Czech/English
|
||||||
- quit with `Cmd/Super+Q` or `Alt+F4`
|
- quit with `Cmd/Super+Q` or `Alt+F4`
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -141,6 +141,11 @@ class AppViewModel(app: Application) : AndroidViewModel(app) {
|
||||||
refresh()
|
refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun markOn4(id: Int) {
|
||||||
|
progress.markOn4(id)
|
||||||
|
refresh()
|
||||||
|
}
|
||||||
|
|
||||||
fun markMluv(n: Int) {
|
fun markMluv(n: Int) {
|
||||||
progress.markMluv(n)
|
progress.markMluv(n)
|
||||||
refresh()
|
refresh()
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ import org.maturita.maturita.ui.NetQuizScreen
|
||||||
import org.maturita.maturita.ui.NetYearsScreen
|
import org.maturita.maturita.ui.NetYearsScreen
|
||||||
import org.maturita.maturita.ui.On2QuizScreen
|
import org.maturita.maturita.ui.On2QuizScreen
|
||||||
import org.maturita.maturita.ui.On3QuizScreen
|
import org.maturita.maturita.ui.On3QuizScreen
|
||||||
|
import org.maturita.maturita.ui.On4QuizScreen
|
||||||
import org.maturita.maturita.ui.OnQuizScreen
|
import org.maturita.maturita.ui.OnQuizScreen
|
||||||
import org.maturita.maturita.ui.OnYearsScreen
|
import org.maturita.maturita.ui.OnYearsScreen
|
||||||
import org.maturita.maturita.ui.PlotScreen
|
import org.maturita.maturita.ui.PlotScreen
|
||||||
|
|
@ -273,6 +274,20 @@ private fun MaturitaAppBody(vm: AppViewModel) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is Route.On3Ex -> On3QuizScreen(vm, r.id)
|
is Route.On3Ex -> On3QuizScreen(vm, r.id)
|
||||||
|
Route.On4Map -> LessonListScreen(
|
||||||
|
vm, vm.tr("on_year4"), vm.tr("on4_sub"),
|
||||||
|
vm.content.on4.map { l ->
|
||||||
|
val id = l.int("id")
|
||||||
|
LessonRow(vm.tr(l.str("titleKey")), vm.progress.on4Done(id), Route.On4Lesson(id))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
is Route.On4Lesson -> {
|
||||||
|
val l = vm.content.on4Lesson(r.id)
|
||||||
|
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||||
|
vm.replace(Route.On4Ex(r.id))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is Route.On4Ex -> On4QuizScreen(vm, r.id)
|
||||||
Route.CzechMap -> CzechMapScreen(vm)
|
Route.CzechMap -> CzechMapScreen(vm)
|
||||||
Route.Mluvnice -> LessonListScreen(
|
Route.Mluvnice -> LessonListScreen(
|
||||||
vm, vm.tr("Mluvnice"), vm.tr("mluv_sub"),
|
vm, vm.tr("Mluvnice"), vm.tr("mluv_sub"),
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,9 @@ sealed class Route(val page: String) {
|
||||||
data object On3Map : Route("on3map")
|
data object On3Map : Route("on3map")
|
||||||
data class On3Lesson(val id: Int) : Route("on3unit$id")
|
data class On3Lesson(val id: Int) : Route("on3unit$id")
|
||||||
data class On3Ex(val id: Int) : Route("on3ex$id")
|
data class On3Ex(val id: Int) : Route("on3ex$id")
|
||||||
|
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 CzechMap : Route("czechmap")
|
data object CzechMap : Route("czechmap")
|
||||||
data object Mluvnice : Route("mluvnice")
|
data object Mluvnice : Route("mluvnice")
|
||||||
data class MluvEx(val n: Int) : Route("mluve$n")
|
data class MluvEx(val n: Int) : Route("mluve$n")
|
||||||
|
|
@ -41,8 +44,8 @@ sealed class Route(val page: String) {
|
||||||
/** Screens with their own bottom action bar; the navigation bar stays hidden there. */
|
/** Screens with their own bottom action bar; the navigation bar stays hidden there. */
|
||||||
val isExercise: Boolean
|
val isExercise: Boolean
|
||||||
get() = this is GermanEx || this is Vocab || this is NetEx || this is HwEx ||
|
get() = this is GermanEx || this is Vocab || this is NetEx || this is HwEx ||
|
||||||
this is OnEx || this is On2Ex || this is On3Ex || this is MluvEx || this is BookQuiz || this is BookPlot ||
|
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 NetLesson || this is HwLesson || this is OnLesson || this is On2Lesson || this is On3Lesson || this is On4Lesson
|
||||||
|
|
||||||
/** Full stack from the practice root to this screen, so back always goes up one level. */
|
/** Full stack from the practice root to this screen, so back always goes up one level. */
|
||||||
fun stack(): List<Route> = when (this) {
|
fun stack(): List<Route> = when (this) {
|
||||||
|
|
@ -71,6 +74,9 @@ sealed class Route(val page: String) {
|
||||||
On3Map -> listOf(Subjects, OnYears, On3Map)
|
On3Map -> listOf(Subjects, OnYears, On3Map)
|
||||||
is On3Lesson -> listOf(Subjects, OnYears, On3Map, this)
|
is On3Lesson -> listOf(Subjects, OnYears, On3Map, this)
|
||||||
is On3Ex -> listOf(Subjects, OnYears, On3Map, On3Lesson(id), this)
|
is On3Ex -> listOf(Subjects, OnYears, On3Map, On3Lesson(id), this)
|
||||||
|
On4Map -> listOf(Subjects, OnYears, On4Map)
|
||||||
|
is On4Lesson -> listOf(Subjects, OnYears, On4Map, this)
|
||||||
|
is On4Ex -> listOf(Subjects, OnYears, On4Map, On4Lesson(id), this)
|
||||||
CzechMap -> listOf(Subjects, CzechMap)
|
CzechMap -> listOf(Subjects, CzechMap)
|
||||||
Mluvnice -> listOf(Subjects, CzechMap, Mluvnice)
|
Mluvnice -> listOf(Subjects, CzechMap, Mluvnice)
|
||||||
is MluvEx -> listOf(Subjects, CzechMap, Mluvnice, this)
|
is MluvEx -> listOf(Subjects, CzechMap, Mluvnice, this)
|
||||||
|
|
@ -95,6 +101,7 @@ fun routeFromPage(page: String): Route? = when (page) {
|
||||||
"onmap" -> Route.OnMap
|
"onmap" -> Route.OnMap
|
||||||
"on2map" -> Route.On2Map
|
"on2map" -> Route.On2Map
|
||||||
"on3map" -> Route.On3Map
|
"on3map" -> Route.On3Map
|
||||||
|
"on4map" -> Route.On4Map
|
||||||
"czechmap" -> Route.CzechMap
|
"czechmap" -> Route.CzechMap
|
||||||
"mluvnice" -> Route.Mluvnice
|
"mluvnice" -> Route.Mluvnice
|
||||||
"readinglist" -> Route.ReadingList
|
"readinglist" -> Route.ReadingList
|
||||||
|
|
@ -126,6 +133,12 @@ fun routeFromPage(page: String): Route? = when (page) {
|
||||||
Regex("""hwex(\d+)""").matchEntire(page)?.let {
|
Regex("""hwex(\d+)""").matchEntire(page)?.let {
|
||||||
return Route.HwEx(it.groupValues[1].toInt())
|
return Route.HwEx(it.groupValues[1].toInt())
|
||||||
}
|
}
|
||||||
|
Regex("""on4unit(\d+)""").matchEntire(page)?.let {
|
||||||
|
return Route.On4Lesson(it.groupValues[1].toInt())
|
||||||
|
}
|
||||||
|
Regex("""on4ex(\d+)""").matchEntire(page)?.let {
|
||||||
|
return Route.On4Ex(it.groupValues[1].toInt())
|
||||||
|
}
|
||||||
Regex("""on3unit(\d+)""").matchEntire(page)?.let {
|
Regex("""on3unit(\d+)""").matchEntire(page)?.let {
|
||||||
return Route.On3Lesson(it.groupValues[1].toInt())
|
return Route.On3Lesson(it.groupValues[1].toInt())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ class Content(root: JSONObject) {
|
||||||
val on = raw.arr("on")
|
val on = raw.arr("on")
|
||||||
val on2 = raw.arr("on2")
|
val on2 = raw.arr("on2")
|
||||||
val on3 = raw.arr("on3")
|
val on3 = raw.arr("on3")
|
||||||
|
val on4 = raw.arr("on4")
|
||||||
val mluvnice = raw.arr("mluvnice")
|
val mluvnice = raw.arr("mluvnice")
|
||||||
val books = raw.arr("books")
|
val books = raw.arr("books")
|
||||||
val changelog = raw.arr("changelog")
|
val changelog = raw.arr("changelog")
|
||||||
|
|
@ -42,6 +43,7 @@ class Content(root: JSONObject) {
|
||||||
fun onLesson(id: Int) = on.firstOrNull { it.int("id") == id }
|
fun onLesson(id: Int) = on.firstOrNull { it.int("id") == id }
|
||||||
fun on2Lesson(id: Int) = on2.firstOrNull { it.int("id") == id }
|
fun on2Lesson(id: Int) = on2.firstOrNull { it.int("id") == id }
|
||||||
fun on3Lesson(id: Int) = on3.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 mluv(n: Int) = mluvnice.firstOrNull { it.int("id") == n }
|
fun mluv(n: Int) = mluvnice.firstOrNull { it.int("id") == n }
|
||||||
fun book(id: String) = books.firstOrNull { it.str("id") == id }
|
fun book(id: String) = books.firstOrNull { it.str("id") == id }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,9 @@ class ProgressStore(context: Context) {
|
||||||
fun on3Done(id: Int) = prefs.getBoolean("on3.$id", false)
|
fun on3Done(id: Int) = prefs.getBoolean("on3.$id", false)
|
||||||
fun markOn3(id: Int) { prefs.edit().putBoolean("on3.$id", true).apply() }
|
fun markOn3(id: Int) { prefs.edit().putBoolean("on3.$id", true).apply() }
|
||||||
|
|
||||||
|
fun on4Done(id: Int) = prefs.getBoolean("on4.$id", false)
|
||||||
|
fun markOn4(id: Int) { prefs.edit().putBoolean("on4.$id", true).apply() }
|
||||||
|
|
||||||
fun mluvDone(n: Int) = prefs.getBoolean("mluv.$n", false)
|
fun mluvDone(n: Int) = prefs.getBoolean("mluv.$n", false)
|
||||||
fun markMluv(n: Int) { prefs.edit().putBoolean("mluv.$n", true).apply() }
|
fun markMluv(n: Int) { prefs.edit().putBoolean("mluv.$n", true).apply() }
|
||||||
|
|
||||||
|
|
@ -103,6 +106,14 @@ fun summarize(content: Content, p: ProgressStore): ProgressSum {
|
||||||
sum.doneUnits += 1
|
sum.doneUnits += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
content.on4.forEach { l ->
|
||||||
|
sum.totalEx += 1
|
||||||
|
sum.openUnits += 1
|
||||||
|
if (p.on4Done(l.int("id"))) {
|
||||||
|
sum.doneEx += 1
|
||||||
|
sum.doneUnits += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
sum.totalEx += content.mluvnice.size
|
sum.totalEx += content.mluvnice.size
|
||||||
sum.openUnits += 1
|
sum.openUnits += 1
|
||||||
val md = content.mluvnice.count { p.mluvDone(it.int("id")) }
|
val md = content.mluvnice.count { p.mluvDone(it.int("id")) }
|
||||||
|
|
|
||||||
|
|
@ -884,6 +884,18 @@ fun On3QuizScreen(vm: AppViewModel, id: Int) {
|
||||||
DispatchExercise(vm, spec, vm.tr(lesson.str("exTitleKey"))) { vm.markOn3(id) }
|
DispatchExercise(vm, spec, vm.tr(lesson.str("exTitleKey"))) { vm.markOn3(id) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun On4QuizScreen(vm: AppViewModel, id: Int) {
|
||||||
|
val lesson = vm.content.on4Lesson(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"))) { vm.markOn4(id) }
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun HwQuizScreen(vm: AppViewModel, id: Int) {
|
fun HwQuizScreen(vm: AppViewModel, id: Int) {
|
||||||
val lesson = vm.content.hwLesson(id) ?: return
|
val lesson = vm.content.hwLesson(id) ?: return
|
||||||
|
|
|
||||||
|
|
@ -300,11 +300,12 @@ private fun subjectSum(vm: AppViewModel, s: J): ProgressSum {
|
||||||
sum.totalEx = vm.content.hw.size
|
sum.totalEx = vm.content.hw.size
|
||||||
sum.doneEx = vm.content.hw.count { vm.progress.hwDone(it.int("id")) }
|
sum.doneEx = vm.content.hw.count { vm.progress.hwDone(it.int("id")) }
|
||||||
}
|
}
|
||||||
"onyears", "onmap", "on2map", "on3map" -> {
|
"onyears", "onmap", "on2map", "on3map", "on4map" -> {
|
||||||
sum.totalEx = vm.content.on.size + vm.content.on2.size + vm.content.on3.size
|
sum.totalEx = vm.content.on.size + vm.content.on2.size + vm.content.on3.size + vm.content.on4.size
|
||||||
sum.doneEx = vm.content.on.count { vm.progress.onDone(it.int("id")) } +
|
sum.doneEx = vm.content.on.count { vm.progress.onDone(it.int("id")) } +
|
||||||
vm.content.on2.count { vm.progress.on2Done(it.int("id")) } +
|
vm.content.on2.count { vm.progress.on2Done(it.int("id")) } +
|
||||||
vm.content.on3.count { vm.progress.on3Done(it.int("id")) }
|
vm.content.on3.count { vm.progress.on3Done(it.int("id")) } +
|
||||||
|
vm.content.on4.count { vm.progress.on4Done(it.int("id")) }
|
||||||
}
|
}
|
||||||
"czechmap" -> {
|
"czechmap" -> {
|
||||||
sum.totalEx = vm.content.mluvnice.size
|
sum.totalEx = vm.content.mluvnice.size
|
||||||
|
|
@ -496,7 +497,7 @@ private fun buildSearch(vm: AppViewModel): List<Hit> {
|
||||||
add(vm.tr("on_year1"), vm.tr("search_lesson"), "onmap", extra = "rocnik")
|
add(vm.tr("on_year1"), vm.tr("search_lesson"), "onmap", extra = "rocnik")
|
||||||
add(vm.tr("on_year2"), vm.tr("search_lesson"), "on2map", extra = "rocnik")
|
add(vm.tr("on_year2"), vm.tr("search_lesson"), "on2map", extra = "rocnik")
|
||||||
add(vm.tr("on_year3"), vm.tr("search_lesson"), "on3map", extra = "rocnik")
|
add(vm.tr("on_year3"), vm.tr("search_lesson"), "on3map", extra = "rocnik")
|
||||||
add(vm.tr("on_year4"), vm.tr("search_lesson"), "onyears", locked = true, extra = "rocnik")
|
add(vm.tr("on_year4"), vm.tr("search_lesson"), "on4map", extra = "rocnik")
|
||||||
vm.content.on.forEach { l ->
|
vm.content.on.forEach { l ->
|
||||||
add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "onunit${l.int("id")}", extra = "obcanka")
|
add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "onunit${l.int("id")}", extra = "obcanka")
|
||||||
add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "onex${l.int("id")}")
|
add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "onex${l.int("id")}")
|
||||||
|
|
@ -509,6 +510,10 @@ private fun buildSearch(vm: AppViewModel): List<Hit> {
|
||||||
add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "on3unit${l.int("id")}", extra = "obcanka")
|
add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "on3unit${l.int("id")}", extra = "obcanka")
|
||||||
add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "on3ex${l.int("id")}")
|
add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "on3ex${l.int("id")}")
|
||||||
}
|
}
|
||||||
|
vm.content.on4.forEach { l ->
|
||||||
|
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("Mluvnice"), vm.tr("search_lesson"), "mluvnice")
|
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")}") }
|
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")
|
add(vm.tr("Maturitní četba"), vm.tr("search_book"), "readinglist")
|
||||||
|
|
@ -615,9 +620,7 @@ fun OnYearsScreen(vm: AppViewModel) {
|
||||||
NavRow(title = vm.tr("on_year1"), subtitle = vm.tr("on_sub"), leading = { Text("1.", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.OnMap) }
|
NavRow(title = vm.tr("on_year1"), subtitle = vm.tr("on_sub"), leading = { Text("1.", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.OnMap) }
|
||||||
NavRow(title = vm.tr("on_year2"), subtitle = vm.tr("on2_sub"), leading = { Text("2.", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.On2Map) }
|
NavRow(title = vm.tr("on_year2"), subtitle = vm.tr("on2_sub"), leading = { Text("2.", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.On2Map) }
|
||||||
NavRow(title = vm.tr("on_year3"), subtitle = vm.tr("on3_sub"), leading = { Text("3.", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.On3Map) }
|
NavRow(title = vm.tr("on_year3"), subtitle = vm.tr("on3_sub"), leading = { Text("3.", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.On3Map) }
|
||||||
}
|
NavRow(title = vm.tr("on_year4"), subtitle = vm.tr("on4_sub"), leading = { Text("4.", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.On4Map) }
|
||||||
items(listOf("on_year4")) { key ->
|
|
||||||
NavRow(title = vm.tr(key), subtitle = vm.tr("on_year_locked_sub"), locked = true, onClick = null)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,15 +6,17 @@
|
||||||
# cs: bullet
|
# cs: bullet
|
||||||
# en: bullet
|
# en: bullet
|
||||||
|
|
||||||
|
--- 2026-10-03
|
||||||
|
cs: Občanská nauka: 4. ročník, 16 lekcí (hospodářství, svět a filozofie)
|
||||||
|
en: Civics: year 4, 16 lessons (the economy, the world and philosophy)
|
||||||
|
|
||||||
--- 2026-10-02
|
--- 2026-10-02
|
||||||
cs: Občanská nauka: 1. ročník, 17 lekcí (člověk v lidském společenství)
|
cs: Občanská nauka: 1. ročník, 17 lekcí (člověk v lidském společenství)
|
||||||
cs: Občanská nauka: 2. ročník, 16 lekcí (člověk jako občan)
|
cs: Občanská nauka: 2. ročník, 16 lekcí (člověk jako občan)
|
||||||
cs: Občanská nauka: 3. ročník, 16 lekcí (člověk a právo)
|
cs: Občanská nauka: 3. ročník, 16 lekcí (člověk a právo)
|
||||||
cs: Občanská nauka: 4. ročník je zatím zamčený
|
|
||||||
en: Civics: year 1, 17 lessons (the individual and society)
|
en: Civics: year 1, 17 lessons (the individual and society)
|
||||||
en: Civics: year 2, 16 lessons (the citizen in a democratic state)
|
en: Civics: year 2, 16 lessons (the citizen in a democratic state)
|
||||||
en: Civics: year 3, 16 lessons (the individual and the law)
|
en: Civics: year 3, 16 lessons (the individual and the law)
|
||||||
en: Civics: year 4 is still locked
|
|
||||||
|
|
||||||
--- 2026-09-25
|
--- 2026-09-25
|
||||||
cs: Technické vybavení: pět lekcí o digitalizaci zvuku (vzorkování, kvantování, PCM)
|
cs: Technické vybavení: pět lekcí o digitalizaci zvuku (vzorkování, kvantování, PCM)
|
||||||
|
|
|
||||||
|
|
@ -143,6 +143,11 @@ final class AppModel: ObservableObject {
|
||||||
refresh()
|
refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func markOn4(_ id: Int) {
|
||||||
|
progress.markOn4(id)
|
||||||
|
refresh()
|
||||||
|
}
|
||||||
|
|
||||||
func markMluv(_ n: Int) {
|
func markMluv(_ n: Int) {
|
||||||
progress.markMluv(n)
|
progress.markMluv(n)
|
||||||
refresh()
|
refresh()
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ final class Content {
|
||||||
let on: [J]
|
let on: [J]
|
||||||
let on2: [J]
|
let on2: [J]
|
||||||
let on3: [J]
|
let on3: [J]
|
||||||
|
let on4: [J]
|
||||||
let mluvnice: [J]
|
let mluvnice: [J]
|
||||||
let books: [J]
|
let books: [J]
|
||||||
let changelog: [J]
|
let changelog: [J]
|
||||||
|
|
@ -68,6 +69,7 @@ final class Content {
|
||||||
on = raw.arr("on")
|
on = raw.arr("on")
|
||||||
on2 = raw.arr("on2")
|
on2 = raw.arr("on2")
|
||||||
on3 = raw.arr("on3")
|
on3 = raw.arr("on3")
|
||||||
|
on4 = raw.arr("on4")
|
||||||
mluvnice = raw.arr("mluvnice")
|
mluvnice = raw.arr("mluvnice")
|
||||||
books = raw.arr("books")
|
books = raw.arr("books")
|
||||||
changelog = raw.arr("changelog")
|
changelog = raw.arr("changelog")
|
||||||
|
|
@ -79,6 +81,7 @@ final class Content {
|
||||||
func onLesson(_ id: Int) -> J? { on.first { $0.int("id") == id } }
|
func onLesson(_ id: Int) -> J? { on.first { $0.int("id") == id } }
|
||||||
func on2Lesson(_ id: Int) -> J? { on2.first { $0.int("id") == id } }
|
func on2Lesson(_ id: Int) -> J? { on2.first { $0.int("id") == id } }
|
||||||
func on3Lesson(_ id: Int) -> J? { on3.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 mluv(_ n: Int) -> J? { mluvnice.first { $0.int("id") == n } }
|
func mluv(_ n: Int) -> J? { mluvnice.first { $0.int("id") == n } }
|
||||||
func book(_ id: String) -> J? { books.first { $0.str("id") == id } }
|
func book(_ id: String) -> J? { books.first { $0.str("id") == id } }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,9 @@ final class ProgressStore {
|
||||||
func on3Done(_ id: Int) -> Bool { defaults.bool(forKey: "on3.\(id)") }
|
func on3Done(_ id: Int) -> Bool { defaults.bool(forKey: "on3.\(id)") }
|
||||||
func markOn3(_ id: Int) { defaults.set(true, forKey: "on3.\(id)") }
|
func markOn3(_ id: Int) { defaults.set(true, forKey: "on3.\(id)") }
|
||||||
|
|
||||||
|
func on4Done(_ id: Int) -> Bool { defaults.bool(forKey: "on4.\(id)") }
|
||||||
|
func markOn4(_ id: Int) { defaults.set(true, forKey: "on4.\(id)") }
|
||||||
|
|
||||||
func mluvDone(_ n: Int) -> Bool { defaults.bool(forKey: "mluv.\(n)") }
|
func mluvDone(_ n: Int) -> Bool { defaults.bool(forKey: "mluv.\(n)") }
|
||||||
func markMluv(_ n: Int) { defaults.set(true, forKey: "mluv.\(n)") }
|
func markMluv(_ n: Int) { defaults.set(true, forKey: "mluv.\(n)") }
|
||||||
|
|
||||||
|
|
@ -110,6 +113,14 @@ func summarize(_ content: Content, _ p: ProgressStore) -> ProgressSum {
|
||||||
sum.doneUnits += 1
|
sum.doneUnits += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for l in content.on4 {
|
||||||
|
sum.totalEx += 1
|
||||||
|
sum.openUnits += 1
|
||||||
|
if p.on4Done(l.int("id")) {
|
||||||
|
sum.doneEx += 1
|
||||||
|
sum.doneUnits += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
sum.totalEx += content.mluvnice.count
|
sum.totalEx += content.mluvnice.count
|
||||||
sum.openUnits += 1
|
sum.openUnits += 1
|
||||||
let md = content.mluvnice.filter { p.mluvDone($0.int("id")) }.count
|
let md = content.mluvnice.filter { p.mluvDone($0.int("id")) }.count
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,9 @@ enum Route: Hashable {
|
||||||
case on3Map
|
case on3Map
|
||||||
case on3Lesson(Int)
|
case on3Lesson(Int)
|
||||||
case on3Ex(Int)
|
case on3Ex(Int)
|
||||||
|
case on4Map
|
||||||
|
case on4Lesson(Int)
|
||||||
|
case on4Ex(Int)
|
||||||
case czechMap
|
case czechMap
|
||||||
case mluvnice
|
case mluvnice
|
||||||
case mluvEx(Int)
|
case mluvEx(Int)
|
||||||
|
|
@ -68,6 +71,9 @@ enum Route: Hashable {
|
||||||
case .on3Map: return "on3map"
|
case .on3Map: return "on3map"
|
||||||
case .on3Lesson(let id): return "on3unit\(id)"
|
case .on3Lesson(let id): return "on3unit\(id)"
|
||||||
case .on3Ex(let id): return "on3ex\(id)"
|
case .on3Ex(let id): return "on3ex\(id)"
|
||||||
|
case .on4Map: return "on4map"
|
||||||
|
case .on4Lesson(let id): return "on4unit\(id)"
|
||||||
|
case .on4Ex(let id): return "on4ex\(id)"
|
||||||
case .czechMap: return "czechmap"
|
case .czechMap: return "czechmap"
|
||||||
case .mluvnice: return "mluvnice"
|
case .mluvnice: return "mluvnice"
|
||||||
case .mluvEx(let n): return "mluve\(n)"
|
case .mluvEx(let n): return "mluve\(n)"
|
||||||
|
|
@ -136,6 +142,12 @@ enum Route: Hashable {
|
||||||
return [.onYears, .on3Map, .on3Lesson(id)]
|
return [.onYears, .on3Map, .on3Lesson(id)]
|
||||||
case .on3Ex(let id):
|
case .on3Ex(let id):
|
||||||
return [.onYears, .on3Map, .on3Lesson(id), .on3Ex(id)]
|
return [.onYears, .on3Map, .on3Lesson(id), .on3Ex(id)]
|
||||||
|
case .on4Map:
|
||||||
|
return [.onYears, .on4Map]
|
||||||
|
case .on4Lesson(let id):
|
||||||
|
return [.onYears, .on4Map, .on4Lesson(id)]
|
||||||
|
case .on4Ex(let id):
|
||||||
|
return [.onYears, .on4Map, .on4Lesson(id), .on4Ex(id)]
|
||||||
case .czechMap:
|
case .czechMap:
|
||||||
return [.czechMap]
|
return [.czechMap]
|
||||||
case .mluvnice:
|
case .mluvnice:
|
||||||
|
|
@ -168,6 +180,7 @@ func routeFromPage(_ page: String) -> Route? {
|
||||||
case "onmap": return .onMap
|
case "onmap": return .onMap
|
||||||
case "on2map": return .on2Map
|
case "on2map": return .on2Map
|
||||||
case "on3map": return .on3Map
|
case "on3map": return .on3Map
|
||||||
|
case "on4map": return .on4Map
|
||||||
case "czechmap": return .czechMap
|
case "czechmap": return .czechMap
|
||||||
case "mluvnice": return .mluvnice
|
case "mluvnice": return .mluvnice
|
||||||
case "readinglist": return .readingList
|
case "readinglist": return .readingList
|
||||||
|
|
@ -211,6 +224,12 @@ func routeFromPage(_ page: String) -> Route? {
|
||||||
if let m = page.wholeMatch(of: /hwex(\d+)/), let n = Int(m.1) {
|
if let m = page.wholeMatch(of: /hwex(\d+)/), let n = Int(m.1) {
|
||||||
return .hwEx(n)
|
return .hwEx(n)
|
||||||
}
|
}
|
||||||
|
if let m = page.wholeMatch(of: /on4unit(\d+)/), let n = Int(m.1) {
|
||||||
|
return .on4Lesson(n)
|
||||||
|
}
|
||||||
|
if let m = page.wholeMatch(of: /on4ex(\d+)/), let n = Int(m.1) {
|
||||||
|
return .on4Ex(n)
|
||||||
|
}
|
||||||
if let m = page.wholeMatch(of: /on3unit(\d+)/), let n = Int(m.1) {
|
if let m = page.wholeMatch(of: /on3unit(\d+)/), let n = Int(m.1) {
|
||||||
return .on3Lesson(n)
|
return .on3Lesson(n)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -682,6 +682,25 @@ struct On3QuizScreen: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct On4QuizScreen: View {
|
||||||
|
@ObservedObject var vm: AppModel
|
||||||
|
let id: Int
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
if let lesson = vm.content.on4Lesson(id) {
|
||||||
|
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"))) {
|
||||||
|
vm.markOn4(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct HwQuizScreen: View {
|
struct HwQuizScreen: View {
|
||||||
@ObservedObject var vm: AppModel
|
@ObservedObject var vm: AppModel
|
||||||
let id: Int
|
let id: Int
|
||||||
|
|
|
||||||
|
|
@ -423,11 +423,12 @@ private func subjectSum(_ vm: AppModel, _ s: J) -> ProgressSum {
|
||||||
case "hwyears", "hwmap":
|
case "hwyears", "hwmap":
|
||||||
sum.totalEx = vm.content.hw.count
|
sum.totalEx = vm.content.hw.count
|
||||||
sum.doneEx = vm.content.hw.filter { vm.progress.hwDone($0.int("id")) }.count
|
sum.doneEx = vm.content.hw.filter { vm.progress.hwDone($0.int("id")) }.count
|
||||||
case "onyears", "onmap", "on2map", "on3map":
|
case "onyears", "onmap", "on2map", "on3map", "on4map":
|
||||||
sum.totalEx = vm.content.on.count + vm.content.on2.count + vm.content.on3.count
|
sum.totalEx = vm.content.on.count + vm.content.on2.count + vm.content.on3.count + vm.content.on4.count
|
||||||
sum.doneEx = vm.content.on.filter { vm.progress.onDone($0.int("id")) }.count
|
sum.doneEx = vm.content.on.filter { vm.progress.onDone($0.int("id")) }.count
|
||||||
+ vm.content.on2.filter { vm.progress.on2Done($0.int("id")) }.count
|
+ vm.content.on2.filter { vm.progress.on2Done($0.int("id")) }.count
|
||||||
+ vm.content.on3.filter { vm.progress.on3Done($0.int("id")) }.count
|
+ vm.content.on3.filter { vm.progress.on3Done($0.int("id")) }.count
|
||||||
|
+ vm.content.on4.filter { vm.progress.on4Done($0.int("id")) }.count
|
||||||
case "czechmap":
|
case "czechmap":
|
||||||
sum.totalEx = vm.content.mluvnice.count
|
sum.totalEx = vm.content.mluvnice.count
|
||||||
sum.doneEx = vm.content.mluvnice.filter { vm.progress.mluvDone($0.int("id")) }.count
|
sum.doneEx = vm.content.mluvnice.filter { vm.progress.mluvDone($0.int("id")) }.count
|
||||||
|
|
@ -569,7 +570,7 @@ private func buildSearch(_ vm: AppModel) -> [Hit] {
|
||||||
add(vm.tr("on_year1"), vm.tr("search_lesson"), "onmap", extra: "rocnik")
|
add(vm.tr("on_year1"), vm.tr("search_lesson"), "onmap", extra: "rocnik")
|
||||||
add(vm.tr("on_year2"), vm.tr("search_lesson"), "on2map", extra: "rocnik")
|
add(vm.tr("on_year2"), vm.tr("search_lesson"), "on2map", extra: "rocnik")
|
||||||
add(vm.tr("on_year3"), vm.tr("search_lesson"), "on3map", extra: "rocnik")
|
add(vm.tr("on_year3"), vm.tr("search_lesson"), "on3map", extra: "rocnik")
|
||||||
add(vm.tr("on_year4"), vm.tr("search_lesson"), "onyears", locked: true, extra: "rocnik")
|
add(vm.tr("on_year4"), vm.tr("search_lesson"), "on4map", extra: "rocnik")
|
||||||
for l in vm.content.on {
|
for l in vm.content.on {
|
||||||
add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "onunit\(l.int("id"))", extra: "obcanka")
|
add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "onunit\(l.int("id"))", extra: "obcanka")
|
||||||
add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "onex\(l.int("id"))")
|
add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "onex\(l.int("id"))")
|
||||||
|
|
@ -582,6 +583,10 @@ private func buildSearch(_ vm: AppModel) -> [Hit] {
|
||||||
add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "on3unit\(l.int("id"))", extra: "obcanka")
|
add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "on3unit\(l.int("id"))", extra: "obcanka")
|
||||||
add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "on3ex\(l.int("id"))")
|
add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "on3ex\(l.int("id"))")
|
||||||
}
|
}
|
||||||
|
for l in vm.content.on4 {
|
||||||
|
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("Mluvnice"), vm.tr("search_lesson"), "mluvnice")
|
add(vm.tr("Mluvnice"), vm.tr("search_lesson"), "mluvnice")
|
||||||
add(vm.tr("Maturitní četba"), vm.tr("search_book"), "readinglist")
|
add(vm.tr("Maturitní četba"), vm.tr("search_book"), "readinglist")
|
||||||
for b in vm.content.books {
|
for b in vm.content.books {
|
||||||
|
|
@ -812,13 +817,8 @@ struct OnYearsScreen: View {
|
||||||
NavigationLink(value: Route.on3Map) {
|
NavigationLink(value: Route.on3Map) {
|
||||||
ListRowLabel(title: vm.tr("on_year3"), subtitle: vm.tr("on3_sub"))
|
ListRowLabel(title: vm.tr("on_year3"), subtitle: vm.tr("on3_sub"))
|
||||||
}
|
}
|
||||||
ForEach(["on_year4"], id: \.self) { key in
|
NavigationLink(value: Route.on4Map) {
|
||||||
Label {
|
ListRowLabel(title: vm.tr("on_year4"), subtitle: vm.tr("on4_sub"))
|
||||||
ListRowLabel(title: vm.tr(key), subtitle: vm.tr("on_year_locked_sub"))
|
|
||||||
} icon: {
|
|
||||||
Image(systemName: "lock.fill")
|
|
||||||
}
|
|
||||||
.foregroundStyle(.secondary)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigationTitle(vm.tr("Občanská nauka"))
|
.navigationTitle(vm.tr("Občanská nauka"))
|
||||||
|
|
@ -1460,6 +1460,27 @@ struct RouteDestination: View {
|
||||||
}
|
}
|
||||||
case .on3Ex(let id):
|
case .on3Ex(let id):
|
||||||
On3QuizScreen(vm: vm, id: id)
|
On3QuizScreen(vm: vm, id: id)
|
||||||
|
case .on4Map:
|
||||||
|
LessonListScreen(
|
||||||
|
vm: vm,
|
||||||
|
title: vm.tr("on_year4"),
|
||||||
|
subtitle: vm.tr("on4_sub"),
|
||||||
|
rows: vm.content.on4.map { l in
|
||||||
|
let id = l.int("id")
|
||||||
|
return LessonRow(
|
||||||
|
id: "o4\(id)",
|
||||||
|
title: vm.tr(l.str("titleKey")),
|
||||||
|
done: vm.progress.on4Done(id),
|
||||||
|
destination: .on4Lesson(id)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
case .on4Lesson(let id):
|
||||||
|
if let l = vm.content.on4Lesson(id) {
|
||||||
|
SlidesScreen(vm: vm, title: vm.tr(l.str("titleKey")), subtitle: vm.tr(l.str("subKey")), slides: l.arr("slides"), next: .on4Ex(id))
|
||||||
|
}
|
||||||
|
case .on4Ex(let id):
|
||||||
|
On4QuizScreen(vm: vm, id: id)
|
||||||
case .czechMap:
|
case .czechMap:
|
||||||
CzechMapScreen(vm: vm)
|
CzechMapScreen(vm: vm)
|
||||||
case .mluvnice:
|
case .mluvnice:
|
||||||
|
|
|
||||||
|
|
@ -1120,6 +1120,18 @@ def main() -> int:
|
||||||
"quiz": choice_items(A(f"build_on3_unit{i}_exercise_page.qs")),
|
"quiz": choice_items(A(f"build_on3_unit{i}_exercise_page.qs")),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
on4_lessons = []
|
||||||
|
for i in range(1, 17):
|
||||||
|
on4_lessons.append({
|
||||||
|
"id": i,
|
||||||
|
"titleKey": f"on4_unit{i}",
|
||||||
|
"subKey": f"on4_unit{i}_sub",
|
||||||
|
"exTitleKey": f"on4_ex{i}_title",
|
||||||
|
"quizHeadKey": f"on4_quiz{i}_head",
|
||||||
|
"slides": slides_items(A(f"build_on4_unit{i}_page.slides")),
|
||||||
|
"quiz": choice_items(A(f"build_on4_unit{i}_exercise_page.qs")),
|
||||||
|
})
|
||||||
|
|
||||||
hw_lessons = []
|
hw_lessons = []
|
||||||
for i in range(1, 30):
|
for i in range(1, 30):
|
||||||
hw_lessons.append({
|
hw_lessons.append({
|
||||||
|
|
@ -1541,6 +1553,7 @@ def main() -> int:
|
||||||
"on": on_lessons,
|
"on": on_lessons,
|
||||||
"on2": on2_lessons,
|
"on2": on2_lessons,
|
||||||
"on3": on3_lessons,
|
"on3": on3_lessons,
|
||||||
|
"on4": on4_lessons,
|
||||||
"mluvnice": mluvnice,
|
"mluvnice": mluvnice,
|
||||||
"books": books,
|
"books": books,
|
||||||
"changelog": parse_changelog(ROOT / "data" / "changelog.txt"),
|
"changelog": parse_changelog(ROOT / "data" / "changelog.txt"),
|
||||||
|
|
@ -1578,6 +1591,7 @@ def main() -> int:
|
||||||
print(f" on lessons: {sum(1 for L in on_lessons if L['slides'])}")
|
print(f" on lessons: {sum(1 for L in on_lessons if L['slides'])}")
|
||||||
print(f" on2 lessons: {sum(1 for L in on2_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" 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'])}")
|
||||||
print(f" mluvnice: {len(mluvnice)}")
|
print(f" mluvnice: {len(mluvnice)}")
|
||||||
print(f" books quiz items: {[len(b['quiz']) for b in books]}")
|
print(f" books quiz items: {[len(b['quiz']) for b in books]}")
|
||||||
print(f" changelog entries: {len(payload.get('changelog', []))}")
|
print(f" changelog entries: {len(payload.get('changelog', []))}")
|
||||||
|
|
@ -1626,6 +1640,11 @@ def main() -> int:
|
||||||
missing.append(f"on3{L['id']} slides")
|
missing.append(f"on3{L['id']} slides")
|
||||||
if not L["quiz"]:
|
if not L["quiz"]:
|
||||||
missing.append(f"on3{L['id']} quiz")
|
missing.append(f"on3{L['id']} quiz")
|
||||||
|
for L in on4_lessons:
|
||||||
|
if not L["slides"]:
|
||||||
|
missing.append(f"on4{L['id']} slides")
|
||||||
|
if not L["quiz"]:
|
||||||
|
missing.append(f"on4{L['id']} quiz")
|
||||||
for m in mluvnice:
|
for m in mluvnice:
|
||||||
if m["type"] in ("typed", "reveal") and not m.get("items"):
|
if m["type"] in ("typed", "reveal") and not m.get("items"):
|
||||||
missing.append(f"mluv{m['id']}")
|
missing.append(f"mluv{m['id']}")
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ extern char *app_progress_hw;
|
||||||
extern char *app_progress_on;
|
extern char *app_progress_on;
|
||||||
extern char *app_progress_on2;
|
extern char *app_progress_on2;
|
||||||
extern char *app_progress_on3;
|
extern char *app_progress_on3;
|
||||||
|
extern char *app_progress_on4;
|
||||||
extern char *app_progress_mluvnice;
|
extern char *app_progress_mluvnice;
|
||||||
extern char *app_progress_cetba;
|
extern char *app_progress_cetba;
|
||||||
#define PROGRESS_DIR app_progress_dir
|
#define PROGRESS_DIR app_progress_dir
|
||||||
|
|
@ -64,6 +65,7 @@ extern char *app_progress_cetba;
|
||||||
#define PROGRESS_ON app_progress_on
|
#define PROGRESS_ON app_progress_on
|
||||||
#define PROGRESS_ON2 app_progress_on2
|
#define PROGRESS_ON2 app_progress_on2
|
||||||
#define PROGRESS_ON3 app_progress_on3
|
#define PROGRESS_ON3 app_progress_on3
|
||||||
|
#define PROGRESS_ON4 app_progress_on4
|
||||||
#define NODE_SIZE 88.0
|
#define NODE_SIZE 88.0
|
||||||
#define PATH_SPAC 240.0
|
#define PATH_SPAC 240.0
|
||||||
#define ROAD_MX 150.0 /* horizontal canvas margin */
|
#define ROAD_MX 150.0 /* horizontal canvas margin */
|
||||||
|
|
@ -127,6 +129,8 @@ extern char *app_progress_cetba;
|
||||||
#define ON2_LESSONS 16
|
#define ON2_LESSONS 16
|
||||||
#define ON3_UNITS 16
|
#define ON3_UNITS 16
|
||||||
#define ON3_LESSONS 16
|
#define ON3_LESSONS 16
|
||||||
|
#define ON4_UNITS 16
|
||||||
|
#define ON4_LESSONS 16
|
||||||
#define HW_SLIDES 3
|
#define HW_SLIDES 3
|
||||||
#define HW2_SLIDES 6
|
#define HW2_SLIDES 6
|
||||||
#define HW3_SLIDES 2
|
#define HW3_SLIDES 2
|
||||||
|
|
@ -773,6 +777,8 @@ extern NetLesson on2_lessons[ON2_LESSONS];
|
||||||
extern GtkWidget *on2_nodes[ON2_UNITS];
|
extern GtkWidget *on2_nodes[ON2_UNITS];
|
||||||
extern NetLesson on3_lessons[ON3_LESSONS];
|
extern NetLesson on3_lessons[ON3_LESSONS];
|
||||||
extern GtkWidget *on3_nodes[ON3_UNITS];
|
extern GtkWidget *on3_nodes[ON3_UNITS];
|
||||||
|
extern NetLesson on4_lessons[ON4_LESSONS];
|
||||||
|
extern GtkWidget *on4_nodes[ON4_UNITS];
|
||||||
extern GtkWidget *net_note_host;
|
extern GtkWidget *net_note_host;
|
||||||
extern int net_note_last_w;
|
extern int net_note_last_w;
|
||||||
extern GtkWidget *net_scroll;
|
extern GtkWidget *net_scroll;
|
||||||
|
|
@ -886,6 +892,14 @@ void on3_rail_theme_reset(void);
|
||||||
void on3_lessons_apply_lang(void);
|
void on3_lessons_apply_lang(void);
|
||||||
GtkWidget *build_on3map_page(void);
|
GtkWidget *build_on3map_page(void);
|
||||||
void add_on3_pages(GtkStack *stack);
|
void add_on3_pages(GtkStack *stack);
|
||||||
|
void on4_load_progress(void);
|
||||||
|
void on4_save_progress(void);
|
||||||
|
void mark_on4_done(int lesson_id);
|
||||||
|
void refresh_on4_completion_ui(void);
|
||||||
|
void on4_rail_theme_reset(void);
|
||||||
|
void on4_lessons_apply_lang(void);
|
||||||
|
GtkWidget *build_on4map_page(void);
|
||||||
|
void add_on4_pages(GtkStack *stack);
|
||||||
void czech_rail_theme_reset(void);
|
void czech_rail_theme_reset(void);
|
||||||
void hw_lessons_apply_lang(void);
|
void hw_lessons_apply_lang(void);
|
||||||
GtkWidget *build_hwyears_page(void);
|
GtkWidget *build_hwyears_page(void);
|
||||||
|
|
|
||||||
100
src/i18n.c
100
src/i18n.c
|
|
@ -1000,6 +1000,104 @@ const TrEntry tr_ui[] = {
|
||||||
{"on3_ex16_title", "Kvíz: mladiství, oběť a svědek", "Quiz: juveniles, victims and witnesses"},
|
{"on3_ex16_title", "Kvíz: mladiství, oběť a svědek", "Quiz: juveniles, victims and witnesses"},
|
||||||
{"on3_quiz16_head", "Kvíz k mladistvým, oběti a svědkovi",
|
{"on3_quiz16_head", "Kvíz k mladistvým, oběti a svědkovi",
|
||||||
"Quiz on juveniles, victims and witnesses"},
|
"Quiz on juveniles, victims and witnesses"},
|
||||||
|
{"on4_sub", "Hospodářství, svět a filozofie. Vyberte lekci na cestě.",
|
||||||
|
"The economy, the world and philosophy. Pick a lesson on the path."},
|
||||||
|
{"on4_unit1", "Trh", "The market"},
|
||||||
|
{"on4_unit1_sub", "2 snímky o nabídce, poptávce a ceně a pak kvíz.",
|
||||||
|
"2 slides on supply, demand and price, then a quiz."},
|
||||||
|
{"on4_ex1_title", "Kvíz: trh", "Quiz: the market"},
|
||||||
|
{"on4_quiz1_head", "Kvíz k trhu",
|
||||||
|
"Quiz on the market"},
|
||||||
|
{"on4_unit2", "HDP a cyklus", "GDP and the cycle"},
|
||||||
|
{"on4_unit2_sub", "2 snímky o hrubém domácím produktu, růstu a recesi a pak kvíz.",
|
||||||
|
"2 slides on gross domestic product, growth and recession, then a quiz."},
|
||||||
|
{"on4_ex2_title", "Kvíz: HDP a cyklus", "Quiz: GDP and the cycle"},
|
||||||
|
{"on4_quiz2_head", "Kvíz k HDP a cyklu",
|
||||||
|
"Quiz on GDP and the cycle"},
|
||||||
|
{"on4_unit3", "Peníze a inflace", "Money and inflation"},
|
||||||
|
{"on4_unit3_sub", "2 snímky o koruně, euru a inflaci a pak kvíz.",
|
||||||
|
"2 slides on the koruna, the euro and inflation, then a quiz."},
|
||||||
|
{"on4_ex3_title", "Kvíz: peníze a inflace", "Quiz: money and inflation"},
|
||||||
|
{"on4_quiz3_head", "Kvíz k penězům a inflaci",
|
||||||
|
"Quiz on money and inflation"},
|
||||||
|
{"on4_unit4", "Banky a ČNB", "Banks and the CNB"},
|
||||||
|
{"on4_unit4_sub", "2 snímky o centrální bance, úvěrech a ochraně vkladů a pak kvíz.",
|
||||||
|
"2 slides on the central bank, loans and deposit protection, then a quiz."},
|
||||||
|
{"on4_ex4_title", "Kvíz: banky a ČNB", "Quiz: banks and the CNB"},
|
||||||
|
{"on4_quiz4_head", "Kvíz k bankám a ČNB",
|
||||||
|
"Quiz on banks and the CNB"},
|
||||||
|
{"on4_unit5", "Daně a rozpočet", "Taxes and the budget"},
|
||||||
|
{"on4_unit5_sub", "2 snímky o daních, DPH, schodku a dluhu a pak kvíz.",
|
||||||
|
"2 slides on taxes, VAT, the deficit and the debt, then a quiz."},
|
||||||
|
{"on4_ex5_title", "Kvíz: daně a rozpočet", "Quiz: taxes and the budget"},
|
||||||
|
{"on4_quiz5_head", "Kvíz k daním a rozpočtu",
|
||||||
|
"Quiz on taxes and the budget"},
|
||||||
|
{"on4_unit6", "Podnikání", "Enterprise"},
|
||||||
|
{"on4_unit6_sub", "2 snímky o živnosti, s.r.o. a akciové společnosti a pak kvíz.",
|
||||||
|
"2 slides on trades, limited companies and joint-stock companies, then a quiz."},
|
||||||
|
{"on4_ex6_title", "Kvíz: podnikání", "Quiz: enterprise"},
|
||||||
|
{"on4_quiz6_head", "Kvíz k podnikání",
|
||||||
|
"Quiz on enterprise"},
|
||||||
|
{"on4_unit7", "Trh práce", "The labour market"},
|
||||||
|
{"on4_unit7_sub", "2 snímky o mzdě, nezaměstnanosti a Úřadu práce a pak kvíz.",
|
||||||
|
"2 slides on wages, unemployment and the Labour Office, then a quiz."},
|
||||||
|
{"on4_ex7_title", "Kvíz: trh práce", "Quiz: the labour market"},
|
||||||
|
{"on4_quiz7_head", "Kvíz k trhu práce",
|
||||||
|
"Quiz on the labour market"},
|
||||||
|
{"on4_unit8", "Rozpočet domácnosti", "The household budget"},
|
||||||
|
{"on4_unit8_sub", "2 snímky o příjmech, výdajích a rezervě a pak kvíz.",
|
||||||
|
"2 slides on income, spending and a reserve, then a quiz."},
|
||||||
|
{"on4_ex8_title", "Kvíz: rozpočet domácnosti", "Quiz: the household budget"},
|
||||||
|
{"on4_quiz8_head", "Kvíz k rozpočtu domácnosti",
|
||||||
|
"Quiz on the household budget"},
|
||||||
|
{"on4_unit9", "Úvěry a pojištění", "Loans and insurance"},
|
||||||
|
{"on4_unit9_sub", "2 snímky o úroku, RPSN a povinném pojištění a pak kvíz.",
|
||||||
|
"2 slides on interest, the APRC and compulsory insurance, then a quiz."},
|
||||||
|
{"on4_ex9_title", "Kvíz: úvěry a pojištění", "Quiz: loans and insurance"},
|
||||||
|
{"on4_quiz9_head", "Kvíz k úvěrům a pojištění",
|
||||||
|
"Quiz on loans and insurance"},
|
||||||
|
{"on4_unit10", "Evropská unie", "The European Union"},
|
||||||
|
{"on4_unit10_sub", "2 snímky o členství, Schengenu, euru a institucích a pak kvíz.",
|
||||||
|
"2 slides on membership, Schengen, the euro and the institutions, then a quiz."},
|
||||||
|
{"on4_ex10_title", "Kvíz: Evropská unie", "Quiz: the European Union"},
|
||||||
|
{"on4_quiz10_head", "Kvíz k Evropské unii",
|
||||||
|
"Quiz on the European Union"},
|
||||||
|
{"on4_unit11", "NATO a OSN", "NATO and the UN"},
|
||||||
|
{"on4_unit11_sub", "2 snímky o obranné alianci, společné obraně a OSN a pak kvíz.",
|
||||||
|
"2 slides on the defence alliance, collective defence and the UN, then a quiz."},
|
||||||
|
{"on4_ex11_title", "Kvíz: NATO a OSN", "Quiz: NATO and the UN"},
|
||||||
|
{"on4_quiz11_head", "Kvíz k NATO a OSN",
|
||||||
|
"Quiz on NATO and the UN"},
|
||||||
|
{"on4_unit12", "Globalizace", "Globalisation"},
|
||||||
|
{"on4_unit12_sub", "2 snímky o propojení světa, přínosech a rizicích a pak kvíz.",
|
||||||
|
"2 slides on an interconnected world, its benefits and its risks, then a quiz."},
|
||||||
|
{"on4_ex12_title", "Kvíz: globalizace", "Quiz: globalisation"},
|
||||||
|
{"on4_quiz12_head", "Kvíz ke globalizaci",
|
||||||
|
"Quiz on globalisation"},
|
||||||
|
{"on4_unit13", "Filozofie", "Philosophy"},
|
||||||
|
{"on4_unit13_sub", "2 snímky o filozofických otázkách, Sókratovi a Aristotelovi a pak kvíz.",
|
||||||
|
"2 slides on philosophical questions, Socrates and Aristotle, then a quiz."},
|
||||||
|
{"on4_ex13_title", "Kvíz: filozofie", "Quiz: philosophy"},
|
||||||
|
{"on4_quiz13_head", "Kvíz k filozofii",
|
||||||
|
"Quiz on philosophy"},
|
||||||
|
{"on4_unit14", "Etika", "Ethics"},
|
||||||
|
{"on4_unit14_sub", "2 snímky o mravnosti, svědomí, svobodě a odpovědnosti a pak kvíz.",
|
||||||
|
"2 slides on morality, conscience, freedom and responsibility, then a quiz."},
|
||||||
|
{"on4_ex14_title", "Kvíz: etika", "Quiz: ethics"},
|
||||||
|
{"on4_quiz14_head", "Kvíz k etice",
|
||||||
|
"Quiz on ethics"},
|
||||||
|
{"on4_unit15", "Víra a svědomí", "Faith and conscience"},
|
||||||
|
{"on4_unit15_sub", "2 snímky o víře, ateismu a svobodě svědomí a pak kvíz.",
|
||||||
|
"2 slides on faith, atheism and freedom of conscience, then a quiz."},
|
||||||
|
{"on4_ex15_title", "Kvíz: víra a svědomí", "Quiz: faith and conscience"},
|
||||||
|
{"on4_quiz15_head", "Kvíz k víře a svědomí",
|
||||||
|
"Quiz on faith and conscience"},
|
||||||
|
{"on4_unit16", "Hodnoty", "Values"},
|
||||||
|
{"on4_unit16_sub", "2 snímky o hodnotách, pravdě, solidaritě a svobodě a pak kvíz.",
|
||||||
|
"2 slides on values, truth, solidarity and freedom, then a quiz."},
|
||||||
|
{"on4_ex16_title", "Kvíz: hodnoty", "Quiz: values"},
|
||||||
|
{"on4_quiz16_head", "Kvíz k hodnotám",
|
||||||
|
"Quiz on values"},
|
||||||
{"czech_sub", "Vyberte oblast a začněte procvičovat.",
|
{"czech_sub", "Vyberte oblast a začněte procvičovat.",
|
||||||
"Pick an area and start practicing."},
|
"Pick an area and start practicing."},
|
||||||
{"Literatura", "Literatura", "Literature"},
|
{"Literatura", "Literatura", "Literature"},
|
||||||
|
|
@ -2026,6 +2124,7 @@ void hw_lessons_apply_lang(void);
|
||||||
void on_lessons_apply_lang(void);
|
void on_lessons_apply_lang(void);
|
||||||
void on2_lessons_apply_lang(void);
|
void on2_lessons_apply_lang(void);
|
||||||
void on3_lessons_apply_lang(void);
|
void on3_lessons_apply_lang(void);
|
||||||
|
void on4_lessons_apply_lang(void);
|
||||||
void net_rail_theme_reset(void);
|
void net_rail_theme_reset(void);
|
||||||
|
|
||||||
void apply_language(void) {
|
void apply_language(void) {
|
||||||
|
|
@ -2043,5 +2142,6 @@ void apply_language(void) {
|
||||||
on_lessons_apply_lang();
|
on_lessons_apply_lang();
|
||||||
on2_lessons_apply_lang();
|
on2_lessons_apply_lang();
|
||||||
on3_lessons_apply_lang();
|
on3_lessons_apply_lang();
|
||||||
|
on4_lessons_apply_lang();
|
||||||
search_apply_lang();
|
search_apply_lang();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -386,7 +386,7 @@ static gboolean run_smoke_test(gpointer data) {
|
||||||
static const char *pages[] = {
|
static const char *pages[] = {
|
||||||
"welcome", "subjects", "roadmap", "stats",
|
"welcome", "subjects", "roadmap", "stats",
|
||||||
"netyears", "netmap", "hwyears", "hwmap", "onyears", "onmap", "on2map",
|
"netyears", "netmap", "hwyears", "hwmap", "onyears", "onmap", "on2map",
|
||||||
"on3map",
|
"on3map", "on4map",
|
||||||
"czechmap",
|
"czechmap",
|
||||||
"mluvnice", "readinglist",
|
"mluvnice", "readinglist",
|
||||||
"cetba1984", "cetba1984quiz", "cetba1984dej",
|
"cetba1984", "cetba1984quiz", "cetba1984dej",
|
||||||
|
|
@ -401,6 +401,7 @@ static gboolean run_smoke_test(gpointer data) {
|
||||||
"onunit1", "onex1", "onunit17", "onex17",
|
"onunit1", "onex1", "onunit17", "onex17",
|
||||||
"on2unit1", "on2ex1", "on2unit16", "on2ex16",
|
"on2unit1", "on2ex1", "on2unit16", "on2ex16",
|
||||||
"on3unit1", "on3ex1", "on3unit16", "on3ex16",
|
"on3unit1", "on3ex1", "on3unit16", "on3ex16",
|
||||||
|
"on4unit1", "on4ex1", "on4unit16", "on4ex16",
|
||||||
"unit1", "unit2", "unit3",
|
"unit1", "unit2", "unit3",
|
||||||
"u1e1", "u1e13", "u2e1", "u2e19", "u3e1", "u3e15",
|
"u1e1", "u1e13", "u2e1", "u2e19", "u3e1", "u3e15",
|
||||||
"u1vocab", "u2vocab", "u3vocab",
|
"u1vocab", "u2vocab", "u3vocab",
|
||||||
|
|
@ -518,6 +519,8 @@ void activate(GtkApplication *app, gpointer user_data) {
|
||||||
add_on2_pages(main_stack);
|
add_on2_pages(main_stack);
|
||||||
gtk_stack_add_named(main_stack, build_on3map_page(), "on3map");
|
gtk_stack_add_named(main_stack, build_on3map_page(), "on3map");
|
||||||
add_on3_pages(main_stack);
|
add_on3_pages(main_stack);
|
||||||
|
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_czechmap_page(), "czechmap");
|
||||||
gtk_stack_add_named(main_stack, build_mluvnice_page(), "mluvnice");
|
gtk_stack_add_named(main_stack, build_mluvnice_page(), "mluvnice");
|
||||||
for (int n = 1; n <= 20; n++) {
|
for (int n = 1; n <= 20; n++) {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
/* Year 1 of Občanská nauka.
|
/* Year 1 of Občanská nauka.
|
||||||
* Thematic unit "Člověk v lidském společenství" from the SOV framework
|
* Thematic unit "Člověk v lidském společenství" from the SOV framework
|
||||||
* (společenskovědní vzdělávání) and the MŠMT model syllabus, which schools
|
* (společenskovědní vzdělávání) and the MŠMT model syllabus, which schools
|
||||||
* place in the first year. Years 2 and 3 are open; year 4 stays locked. */
|
* place in the first year. Years 2, 3 and 4 are open. */
|
||||||
|
|
||||||
#define ON_ENTRY(n) \
|
#define ON_ENTRY(n) \
|
||||||
{ .n_slides = 2, .unit_page = "onunit" #n, .ex_page = "onex" #n }
|
{ .n_slides = 2, .unit_page = "onunit" #n, .ex_page = "onex" #n }
|
||||||
|
|
@ -412,7 +412,7 @@ GtkWidget *build_onyears_page(void) {
|
||||||
GtkWidget *scroll;
|
GtkWidget *scroll;
|
||||||
GtkWidget *list;
|
GtkWidget *list;
|
||||||
int y;
|
int y;
|
||||||
static const char *targets[] = {"onmap", "on2map", "on3map", NULL};
|
static const char *targets[] = {"onmap", "on2map", "on3map", "on4map"};
|
||||||
|
|
||||||
page = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
page = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||||
gtk_widget_set_hexpand(page, TRUE);
|
gtk_widget_set_hexpand(page, TRUE);
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@
|
||||||
/* Year 2 of Občanská nauka.
|
/* Year 2 of Občanská nauka.
|
||||||
* Thematic unit "Člověk jako občan v demokratickém státě" from the MŠMT
|
* Thematic unit "Člověk jako občan v demokratickém státě" from the MŠMT
|
||||||
* model syllabus (č.j. 18 396/2002-23) and the SOV civic framework, which
|
* model syllabus (č.j. 18 396/2002-23) and the SOV civic framework, which
|
||||||
* schools place in the second year. Law is year 3; the economy and
|
* schools place in the second year. Law is year 3. The economy, the
|
||||||
* philosophy stay in the fourth year. */
|
* world and philosophy are year 4. */
|
||||||
|
|
||||||
#define ON2_ENTRY(n) \
|
#define ON2_ENTRY(n) \
|
||||||
{ .n_slides = 2, .unit_page = "on2unit" #n, .ex_page = "on2ex" #n }
|
{ .n_slides = 2, .unit_page = "on2unit" #n, .ex_page = "on2ex" #n }
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
/* Year 3 of Občanská nauka.
|
/* Year 3 of Občanská nauka.
|
||||||
* Thematic unit "Člověk a právo" from the MŠMT model syllabus
|
* Thematic unit "Člověk a právo" from the MŠMT model syllabus
|
||||||
* (č.j. 18 396/2002-23) and the SOV civic framework, which schools place
|
* (č.j. 18 396/2002-23) and the SOV civic framework, which schools place
|
||||||
* in the third year. The economy and philosophy stay in the fourth year. */
|
* in the third year. The economy, the world and philosophy are year 4. */
|
||||||
|
|
||||||
#define ON3_ENTRY(n) \
|
#define ON3_ENTRY(n) \
|
||||||
{ .n_slides = 2, .unit_page = "on3unit" #n, .ex_page = "on3ex" #n }
|
{ .n_slides = 2, .unit_page = "on3unit" #n, .ex_page = "on3ex" #n }
|
||||||
|
|
|
||||||
1909
src/obcanka4.c
Normal file
1909
src/obcanka4.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -57,6 +57,7 @@ void load_progress(void) {
|
||||||
on_load_progress();
|
on_load_progress();
|
||||||
on2_load_progress();
|
on2_load_progress();
|
||||||
on3_load_progress();
|
on3_load_progress();
|
||||||
|
on4_load_progress();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Redraw the exercise rails of every unit that already has a page. */
|
/* Redraw the exercise rails of every unit that already has a page. */
|
||||||
|
|
@ -426,8 +427,8 @@ void mark_on_done(int lesson_id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void progress_for_on(ProgressSum *out) {
|
void progress_for_on(ProgressSum *out) {
|
||||||
out->total_ex += ON_LESSONS + ON2_LESSONS + ON3_LESSONS;
|
out->total_ex += ON_LESSONS + ON2_LESSONS + ON3_LESSONS + ON4_LESSONS;
|
||||||
out->open_units += ON_LESSONS + ON2_LESSONS + ON3_LESSONS;
|
out->open_units += ON_LESSONS + ON2_LESSONS + ON3_LESSONS + ON4_LESSONS;
|
||||||
for (int i = 0; i < ON_LESSONS; i++) {
|
for (int i = 0; i < ON_LESSONS; i++) {
|
||||||
if (on_lessons[i].done) {
|
if (on_lessons[i].done) {
|
||||||
out->done_ex++;
|
out->done_ex++;
|
||||||
|
|
@ -446,6 +447,12 @@ void progress_for_on(ProgressSum *out) {
|
||||||
out->done_units++;
|
out->done_units++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (int i = 0; i < ON4_LESSONS; i++) {
|
||||||
|
if (on4_lessons[i].done) {
|
||||||
|
out->done_ex++;
|
||||||
|
out->done_units++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void on2_load_progress(void) {
|
void on2_load_progress(void) {
|
||||||
|
|
@ -607,3 +614,83 @@ void mark_on3_done(int lesson_id) {
|
||||||
refresh_on3_completion_ui();
|
refresh_on3_completion_ui();
|
||||||
refresh_stats_ui();
|
refresh_stats_ui();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void on4_load_progress(void) {
|
||||||
|
GKeyFile *kf = g_key_file_new();
|
||||||
|
GError *err = NULL;
|
||||||
|
|
||||||
|
if (!g_key_file_load_from_file(kf, PROGRESS_ON4, G_KEY_FILE_NONE, &err)) {
|
||||||
|
if (err)
|
||||||
|
g_error_free(err);
|
||||||
|
g_key_file_free(kf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < ON4_LESSONS; i++) {
|
||||||
|
gchar key[8];
|
||||||
|
|
||||||
|
g_snprintf(key, sizeof(key), "%d", i + 1);
|
||||||
|
on4_lessons[i].done = g_key_file_get_boolean(kf, "done", key, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_key_file_free(kf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void on4_save_progress(void) {
|
||||||
|
GKeyFile *kf = g_key_file_new();
|
||||||
|
|
||||||
|
for (int i = 0; i < ON4_LESSONS; i++) {
|
||||||
|
gchar key[8];
|
||||||
|
|
||||||
|
g_snprintf(key, sizeof(key), "%d", i + 1);
|
||||||
|
g_key_file_set_boolean(kf, "done", key, on4_lessons[i].done);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_mkdir_with_parents(PROGRESS_DIR, 0755) != 0) {
|
||||||
|
g_key_file_free(kf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gchar *data = g_key_file_to_data(kf, NULL, NULL);
|
||||||
|
g_key_file_free(kf);
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
GError *err = NULL;
|
||||||
|
g_file_set_contents(PROGRESS_ON4, data, -1, &err);
|
||||||
|
if (err)
|
||||||
|
g_error_free(err);
|
||||||
|
g_free(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void refresh_on4_completion_ui(void) {
|
||||||
|
for (int i = 0; i < ON4_LESSONS; i++) {
|
||||||
|
GtkWidget *node = on4_nodes[i];
|
||||||
|
GtkWidget *icon = on4_lessons[i].done_icon;
|
||||||
|
|
||||||
|
if (!node)
|
||||||
|
continue;
|
||||||
|
if (on4_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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mark_on4_done(int lesson_id) {
|
||||||
|
if (lesson_id < 0 || lesson_id >= ON4_LESSONS)
|
||||||
|
return;
|
||||||
|
if (on4_lessons[lesson_id].done)
|
||||||
|
return;
|
||||||
|
on4_lessons[lesson_id].done = TRUE;
|
||||||
|
on4_save_progress();
|
||||||
|
refresh_on4_completion_ui();
|
||||||
|
refresh_stats_ui();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -205,7 +205,7 @@ static void catalog_rebuild(void) {
|
||||||
catalog_add_key("on_year1", "search_lesson", "onmap", FALSE, 1, "rocnik");
|
catalog_add_key("on_year1", "search_lesson", "onmap", FALSE, 1, "rocnik");
|
||||||
catalog_add_key("on_year2", "search_lesson", "on2map", FALSE, 1, "rocnik");
|
catalog_add_key("on_year2", "search_lesson", "on2map", FALSE, 1, "rocnik");
|
||||||
catalog_add_key("on_year3", "search_lesson", "on3map", FALSE, 1, "rocnik");
|
catalog_add_key("on_year3", "search_lesson", "on3map", FALSE, 1, "rocnik");
|
||||||
catalog_add_key("on_year4", "search_lesson", "onyears", TRUE, 1, "rocnik");
|
catalog_add_key("on_year4", "search_lesson", "on4map", FALSE, 1, "rocnik");
|
||||||
for (i = 1; i <= ON_LESSONS; i++) {
|
for (i = 1; i <= ON_LESSONS; i++) {
|
||||||
g_snprintf(key, sizeof(key), "on_unit%d", i);
|
g_snprintf(key, sizeof(key), "on_unit%d", i);
|
||||||
g_snprintf(page, sizeof(page), "onunit%d", i);
|
g_snprintf(page, sizeof(page), "onunit%d", i);
|
||||||
|
|
@ -227,6 +227,13 @@ static void catalog_rebuild(void) {
|
||||||
g_snprintf(page, sizeof(page), "on3ex%d", i);
|
g_snprintf(page, sizeof(page), "on3ex%d", i);
|
||||||
catalog_add(tr(key), tr("search_exercise"), page, FALSE, 3, "kviz quiz");
|
catalog_add(tr(key), tr("search_exercise"), page, FALSE, 3, "kviz quiz");
|
||||||
}
|
}
|
||||||
|
for (i = 1; i <= ON4_LESSONS; i++) {
|
||||||
|
g_snprintf(key, sizeof(key), "on4_unit%d", i);
|
||||||
|
g_snprintf(page, sizeof(page), "on4unit%d", i);
|
||||||
|
catalog_add_key(key, "search_lesson", page, FALSE, 2, "obcanka");
|
||||||
|
g_snprintf(page, sizeof(page), "on4ex%d", i);
|
||||||
|
catalog_add(tr(key), tr("search_exercise"), page, FALSE, 3, "kviz quiz");
|
||||||
|
}
|
||||||
|
|
||||||
catalog_add_key("Český jazyk a literatura", "search_subject",
|
catalog_add_key("Český jazyk a literatura", "search_subject",
|
||||||
"czechmap", FALSE, 0, "cestina czech");
|
"czechmap", FALSE, 0, "cestina czech");
|
||||||
|
|
|
||||||
|
|
@ -429,6 +429,7 @@ void apply_theme(void) {
|
||||||
on_rail_theme_reset();
|
on_rail_theme_reset();
|
||||||
on2_rail_theme_reset();
|
on2_rail_theme_reset();
|
||||||
on3_rail_theme_reset();
|
on3_rail_theme_reset();
|
||||||
|
on4_rail_theme_reset();
|
||||||
czech_rail_theme_reset();
|
czech_rail_theme_reset();
|
||||||
book_rail_theme_reset();
|
book_rail_theme_reset();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ char *app_progress_hw;
|
||||||
char *app_progress_on;
|
char *app_progress_on;
|
||||||
char *app_progress_on2;
|
char *app_progress_on2;
|
||||||
char *app_progress_on3;
|
char *app_progress_on3;
|
||||||
|
char *app_progress_on4;
|
||||||
char *app_progress_mluvnice;
|
char *app_progress_mluvnice;
|
||||||
char *app_progress_cetba;
|
char *app_progress_cetba;
|
||||||
|
|
||||||
|
|
@ -164,6 +165,7 @@ static void set_progress_paths(const char *write_root) {
|
||||||
g_free(app_progress_on);
|
g_free(app_progress_on);
|
||||||
g_free(app_progress_on2);
|
g_free(app_progress_on2);
|
||||||
g_free(app_progress_on3);
|
g_free(app_progress_on3);
|
||||||
|
g_free(app_progress_on4);
|
||||||
g_free(app_progress_mluvnice);
|
g_free(app_progress_mluvnice);
|
||||||
g_free(app_progress_cetba);
|
g_free(app_progress_cetba);
|
||||||
|
|
||||||
|
|
@ -177,6 +179,7 @@ static void set_progress_paths(const char *write_root) {
|
||||||
app_progress_on = g_build_filename(app_progress_dir, "on.conf", NULL);
|
app_progress_on = g_build_filename(app_progress_dir, "on.conf", NULL);
|
||||||
app_progress_on2 = g_build_filename(app_progress_dir, "on2.conf", NULL);
|
app_progress_on2 = g_build_filename(app_progress_dir, "on2.conf", NULL);
|
||||||
app_progress_on3 = g_build_filename(app_progress_dir, "on3.conf", NULL);
|
app_progress_on3 = g_build_filename(app_progress_dir, "on3.conf", NULL);
|
||||||
|
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_mluvnice = g_build_filename(app_progress_dir, "mluvnice.conf", NULL);
|
||||||
app_progress_cetba = g_build_filename(app_progress_dir, "cetba.conf", NULL);
|
app_progress_cetba = g_build_filename(app_progress_dir, "cetba.conf", NULL);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue