Group the existing hardware lessons under year 1 and lock later years.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
pepaskopec-blip 2026-09-25 21:32:40 +02:00
commit 9e072cb8ae
14 changed files with 191 additions and 17 deletions

View file

@ -65,7 +65,7 @@ Intel Mac, jiná architektura nebo úpravy kódu → [sestavení ze zdroje](#ses
Hause): cvičení, nápovědy, vokabeltraining Hause): cvičení, nápovědy, vokabeltraining
- **Správa počítačových sítí** — 1. ročník, 27 lekcí (VLSM + teorie a kvízy); - **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é ročníky 2–4 jsou zamčené
- **Technické vybavení** — 29 lekcí (architektura, data, skříň a deska, karty, disky, vstupní zařízení) - **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 - **Č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á (82 knih: zápisky, kvíz, sestavení děje); literární teorie je zatím zamčená
- 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
@ -259,7 +259,7 @@ Intel Mac, another architecture, or hacking on the code →
exercises, hints, vocabulary training exercises, hints, vocabulary training
- **Computer networks** — year 1, 27 lessons (VLSM + theory/quizzes); - **Computer networks** — year 1, 27 lessons (VLSM + theory/quizzes);
years 2–4 are locked years 2–4 are locked
- **Computer hardware** — 29 lessons (architecture, data, case and board, cards, drives, input devices) - **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 - **Czech language** — grammar (20 exercises) and required reading
(82 books: notes, quiz, plot ordering); literature theory is still locked (82 books: notes, quiz, plot ordering); literature theory is still locked
- 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

View file

@ -210,8 +210,9 @@ private fun MaturitaAppBody(vm: AppViewModel) {
} }
} }
is Route.NetEx -> NetQuizScreen(vm, r.id) is Route.NetEx -> NetQuizScreen(vm, r.id)
Route.HwYears -> HwYearsScreen(vm)
Route.HwMap -> LessonListScreen( Route.HwMap -> LessonListScreen(
vm, vm.tr("Technické vybavení"), vm.tr("hw_sub"), vm, vm.tr("hw_year1"), vm.tr("hw_sub"),
vm.content.hw.map { l -> vm.content.hw.map { l ->
val id = l.int("id") val id = l.int("id")
LessonRow(vm.tr(l.str("titleKey")), vm.progress.hwDone(id), Route.HwLesson(id)) LessonRow(vm.tr(l.str("titleKey")), vm.progress.hwDone(id), Route.HwLesson(id))

View file

@ -13,6 +13,7 @@ sealed class Route(val page: String) {
data object NetMap : Route("netmap") data object NetMap : Route("netmap")
data class NetLesson(val id: Int) : Route("netunit$id") data class NetLesson(val id: Int) : Route("netunit$id")
data class NetEx(val id: Int) : Route("netex$id") data class NetEx(val id: Int) : Route("netex$id")
data object HwYears : Route("hwyears")
data object HwMap : Route("hwmap") data object HwMap : Route("hwmap")
data class HwLesson(val id: Int) : Route("hwunit$id") data class HwLesson(val id: Int) : Route("hwunit$id")
data class HwEx(val id: Int) : Route("hwex$id") data class HwEx(val id: Int) : Route("hwex$id")
@ -45,9 +46,10 @@ sealed class Route(val page: String) {
NetMap -> listOf(Subjects, NetYears, NetMap) NetMap -> listOf(Subjects, NetYears, NetMap)
is NetLesson -> listOf(Subjects, NetYears, NetMap, this) is NetLesson -> listOf(Subjects, NetYears, NetMap, this)
is NetEx -> listOf(Subjects, NetYears, NetMap, NetLesson(id), this) is NetEx -> listOf(Subjects, NetYears, NetMap, NetLesson(id), this)
HwMap -> listOf(Subjects, HwMap) HwYears -> listOf(Subjects, HwYears)
is HwLesson -> listOf(Subjects, HwMap, this) HwMap -> listOf(Subjects, HwYears, HwMap)
is HwEx -> listOf(Subjects, HwMap, HwLesson(id), this) is HwLesson -> listOf(Subjects, HwYears, HwMap, this)
is HwEx -> listOf(Subjects, HwYears, HwMap, HwLesson(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)
@ -66,6 +68,7 @@ fun routeFromPage(page: String): Route? = when (page) {
"roadmap" -> Route.Roadmap "roadmap" -> Route.Roadmap
"netyears" -> Route.NetYears "netyears" -> Route.NetYears
"netmap" -> Route.NetMap "netmap" -> Route.NetMap
"hwyears" -> Route.HwYears
"hwmap" -> Route.HwMap "hwmap" -> Route.HwMap
"czechmap" -> Route.CzechMap "czechmap" -> Route.CzechMap
"mluvnice" -> Route.Mluvnice "mluvnice" -> Route.Mluvnice

View file

@ -294,7 +294,7 @@ private fun subjectSum(vm: AppViewModel, s: J): ProgressSum {
sum.totalEx = vm.content.netLessons.size sum.totalEx = vm.content.netLessons.size
sum.doneEx = vm.content.netLessons.count { vm.progress.netDone(it.int("id")) } sum.doneEx = vm.content.netLessons.count { vm.progress.netDone(it.int("id")) }
} }
"hwmap" -> { "hwyears", "hwmap" -> {
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")) }
} }
@ -477,6 +477,10 @@ private fun buildSearch(vm: AppViewModel): List<Hit> {
add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "netunit${l.int("id")}", extra = "site") add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "netunit${l.int("id")}", extra = "site")
add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "netex${l.int("id")}") add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "netex${l.int("id")}")
} }
add(vm.tr("hw_year1"), vm.tr("search_lesson"), "hwmap", extra = "rocnik")
add(vm.tr("hw_year2"), vm.tr("search_lesson"), "hwyears", locked = true, extra = "rocnik")
add(vm.tr("hw_year3"), vm.tr("search_lesson"), "hwyears", locked = true, extra = "rocnik")
add(vm.tr("hw_year4"), vm.tr("search_lesson"), "hwyears", locked = true, extra = "rocnik")
vm.content.hw.forEach { l -> vm.content.hw.forEach { l ->
add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "hwunit${l.int("id")}", extra = "hardware") add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "hwunit${l.int("id")}", extra = "hardware")
add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "hwex${l.int("id")}") add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "hwex${l.int("id")}")
@ -565,6 +569,20 @@ fun NetYearsScreen(vm: AppViewModel) {
} }
} }
@Composable
fun HwYearsScreen(vm: AppViewModel) {
DetailScaffold(vm, vm.tr("Technické vybavení"), vm.tr("hw_years_sub")) { inner ->
LazyColumn(contentPadding = PaddingValues(top = inner.calculateTopPadding(), bottom = inner.calculateBottomPadding() + 16.dp)) {
item {
NavRow(title = vm.tr("hw_year1"), subtitle = vm.tr("hw_sub"), leading = { Text("1.", style = MaterialTheme.typography.titleMedium) }) { vm.go(Route.HwMap) }
}
items(listOf("hw_year2", "hw_year3", "hw_year4")) { key ->
NavRow(title = vm.tr(key), subtitle = vm.tr("hw_year_locked_sub"), locked = true, onClick = null)
}
}
}
}
@Composable @Composable
fun CzechMapScreen(vm: AppViewModel) { fun CzechMapScreen(vm: AppViewModel) {
DetailScaffold(vm, vm.tr("Český jazyk a literatura"), vm.tr("czech_sub")) { inner -> DetailScaffold(vm, vm.tr("Český jazyk a literatura"), vm.tr("czech_sub")) { inner ->

View file

@ -9,8 +9,10 @@
--- 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)
cs: Technické vybavení: skříň, zdroj, deska, CPU, karty, disky a vstupní zařízení cs: Technické vybavení: skříň, zdroj, deska, CPU, karty, disky a vstupní zařízení
cs: Technické vybavení: dosavadní lekce jsou 1. ročník, další ročníky jsou zatím zamčené
en: Hardware: five lessons on digitizing sound (sampling, quantization, PCM) en: Hardware: five lessons on digitizing sound (sampling, quantization, PCM)
en: Hardware: case, PSU, board, CPU, cards, drives and input devices en: Hardware: case, PSU, board, CPU, cards, drives and input devices
en: Hardware: current lessons are year 1; later years are still locked
--- 2026-09-23 --- 2026-09-23
cs: Repozitář se jmenuje Graduately; instalátory a updater míří tam cs: Repozitář se jmenuje Graduately; instalátory a updater míří tam

View file

@ -19,6 +19,7 @@ enum Route: Hashable {
case netMap case netMap
case netLesson(Int) case netLesson(Int)
case netEx(Int) case netEx(Int)
case hwYears
case hwMap case hwMap
case hwLesson(Int) case hwLesson(Int)
case hwEx(Int) case hwEx(Int)
@ -43,6 +44,7 @@ enum Route: Hashable {
case .netMap: return "netmap" case .netMap: return "netmap"
case .netLesson(let id): return "netunit\(id)" case .netLesson(let id): return "netunit\(id)"
case .netEx(let id): return "netex\(id)" case .netEx(let id): return "netex\(id)"
case .hwYears: return "hwyears"
case .hwMap: return "hwmap" case .hwMap: return "hwmap"
case .hwLesson(let id): return "hwunit\(id)" case .hwLesson(let id): return "hwunit\(id)"
case .hwEx(let id): return "hwex\(id)" case .hwEx(let id): return "hwex\(id)"
@ -86,12 +88,14 @@ enum Route: Hashable {
return [.netYears, .netMap, .netLesson(id)] return [.netYears, .netMap, .netLesson(id)]
case .netEx(let id): case .netEx(let id):
return [.netYears, .netMap, .netLesson(id), .netEx(id)] return [.netYears, .netMap, .netLesson(id), .netEx(id)]
case .hwYears:
return [.hwYears]
case .hwMap: case .hwMap:
return [.hwMap] return [.hwYears, .hwMap]
case .hwLesson(let id): case .hwLesson(let id):
return [.hwMap, .hwLesson(id)] return [.hwYears, .hwMap, .hwLesson(id)]
case .hwEx(let id): case .hwEx(let id):
return [.hwMap, .hwLesson(id), .hwEx(id)] return [.hwYears, .hwMap, .hwLesson(id), .hwEx(id)]
case .czechMap: case .czechMap:
return [.czechMap] return [.czechMap]
case .mluvnice: case .mluvnice:
@ -118,6 +122,7 @@ func routeFromPage(_ page: String) -> Route? {
case "roadmap": return .roadmap case "roadmap": return .roadmap
case "netyears": return .netYears case "netyears": return .netYears
case "netmap": return .netMap case "netmap": return .netMap
case "hwyears": return .hwYears
case "hwmap": return .hwMap case "hwmap": return .hwMap
case "czechmap": return .czechMap case "czechmap": return .czechMap
case "mluvnice": return .mluvnice case "mluvnice": return .mluvnice

View file

@ -420,7 +420,7 @@ private func subjectSum(_ vm: AppModel, _ s: J) -> ProgressSum {
case "netyears": case "netyears":
sum.totalEx = vm.content.netLessons.count sum.totalEx = vm.content.netLessons.count
sum.doneEx = vm.content.netLessons.filter { vm.progress.netDone($0.int("id")) }.count sum.doneEx = vm.content.netLessons.filter { vm.progress.netDone($0.int("id")) }.count
case "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 "czechmap": case "czechmap":
@ -553,6 +553,10 @@ private func buildSearch(_ vm: AppModel) -> [Hit] {
add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "netunit\(l.int("id"))", extra: "site") add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "netunit\(l.int("id"))", extra: "site")
add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "netex\(l.int("id"))") add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "netex\(l.int("id"))")
} }
add(vm.tr("hw_year1"), vm.tr("search_lesson"), "hwmap", extra: "rocnik")
add(vm.tr("hw_year2"), vm.tr("search_lesson"), "hwyears", locked: true, extra: "rocnik")
add(vm.tr("hw_year3"), vm.tr("search_lesson"), "hwyears", locked: true, extra: "rocnik")
add(vm.tr("hw_year4"), vm.tr("search_lesson"), "hwyears", locked: true, extra: "rocnik")
for l in vm.content.hw { for l in vm.content.hw {
add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "hwunit\(l.int("id"))", extra: "hardware") add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "hwunit\(l.int("id"))", extra: "hardware")
add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "hwex\(l.int("id"))") add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "hwex\(l.int("id"))")
@ -750,6 +754,29 @@ struct NetYearsScreen: View {
} }
} }
struct HwYearsScreen: View {
@ObservedObject var vm: AppModel
var body: some View {
List {
NavigationLink(value: Route.hwMap) {
ListRowLabel(title: vm.tr("hw_year1"), subtitle: vm.tr("hw_sub"))
}
ForEach(["hw_year2", "hw_year3", "hw_year4"], id: \.self) { key in
Label {
ListRowLabel(title: vm.tr(key), subtitle: vm.tr("hw_year_locked_sub"))
} icon: {
Image(systemName: "lock.fill")
}
.foregroundStyle(.secondary)
}
}
.navigationTitle(vm.tr("Technické vybavení"))
.navigationSubtitle(vm.tr("hw_years_sub"))
.appListStyle()
}
}
struct LessonRow: Identifiable { struct LessonRow: Identifiable {
let id: String let id: String
let title: String let title: String
@ -1295,10 +1322,12 @@ struct RouteDestination: View {
} }
case .netEx(let id): case .netEx(let id):
NetQuizScreen(vm: vm, id: id) NetQuizScreen(vm: vm, id: id)
case .hwYears:
HwYearsScreen(vm: vm)
case .hwMap: case .hwMap:
LessonListScreen( LessonListScreen(
vm: vm, vm: vm,
title: vm.tr("Technické vybavení"), title: vm.tr("hw_year1"),
subtitle: vm.tr("hw_sub"), subtitle: vm.tr("hw_sub"),
rows: vm.content.hw.map { l in rows: vm.content.hw.map { l in
let id = l.int("id") let id = l.int("id")

View file

@ -1479,7 +1479,7 @@ def main() -> int:
subjects = [ subjects = [
{"key": "Deutsch", "open": True, "target": "roadmap", "icon": "de"}, {"key": "Deutsch", "open": True, "target": "roadmap", "icon": "de"},
{"key": "Správa počítačových sítí", "open": True, "target": "netyears", "icon": "wifi"}, {"key": "Správa počítačových sítí", "open": True, "target": "netyears", "icon": "wifi"},
{"key": "Technické vybavení", "open": True, "target": "hwmap", "icon": "chip"}, {"key": "Technické vybavení", "open": True, "target": "hwyears", "icon": "chip"},
{"key": "Český jazyk a literatura", "open": True, "target": "czechmap", "icon": "cz"}, {"key": "Český jazyk a literatura", "open": True, "target": "czechmap", "icon": "cz"},
{"key": "Občanská nauka", "open": False, "target": None, "icon": "lock"}, {"key": "Občanská nauka", "open": False, "target": None, "icon": "lock"},
{"key": "English", "open": False, "target": None, "icon": "lock"}, {"key": "English", "open": False, "target": None, "icon": "lock"},

105
src/hw.c
View file

@ -324,6 +324,109 @@ void hw_add_node(GtkFixed *fixed, int index) {
gtk_fixed_put(fixed, name, 0, 0); gtk_fixed_put(fixed, name, 0, 0);
} }
static GtkWidget *hw_year_button(int year, gboolean locked) {
static const char *year_keys[] = {
"hw_year1", "hw_year2", "hw_year3", "hw_year4",
};
GtkWidget *btn;
GtkWidget *row;
GtkWidget *num;
GtkWidget *texts;
GtkWidget *title;
char *num_text;
btn = gtk_button_new();
gtk_widget_add_css_class(btn, "unit-node");
gtk_widget_set_can_focus(btn, FALSE);
gtk_widget_set_hexpand(btn, TRUE);
gtk_widget_set_size_request(btn, -1, 72);
gtk_widget_set_sensitive(btn, !locked);
if (locked)
gtk_widget_add_css_class(btn, "locked");
else
gtk_widget_add_css_class(btn, "current");
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, year_keys[year - 1], 0);
gtk_widget_set_halign(title, GTK_ALIGN_START);
gtk_widget_add_css_class(title, "unit-name");
gtk_box_append(GTK_BOX(texts), title);
if (locked) {
GtkWidget *sub = gtk_label_new(NULL);
GtkWidget *icon = icon_area_new(draw_lock_icon, 0.3451, 0.3569,
0.4392, 18);
i18n_bind(sub, "hw_year_locked_sub", 0);
gtk_widget_set_halign(sub, GTK_ALIGN_START);
gtk_widget_add_css_class(sub, "unit-name-locked");
gtk_box_append(GTK_BOX(texts), sub);
gtk_widget_set_valign(icon, GTK_ALIGN_CENTER);
gtk_box_append(GTK_BOX(row), icon);
} else {
g_object_set_data_full(G_OBJECT(btn), "target",
g_strdup("hwmap"), g_free);
g_signal_connect(btn, "clicked", G_CALLBACK(on_nav_clicked), NULL);
}
return btn;
}
GtkWidget *build_hwyears_page(void) {
GtkWidget *page;
GtkWidget *scroll;
GtkWidget *list;
int y;
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("subjects", "Technické vybavení", "hw_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, 360, -1);
gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(scroll), list);
for (y = 1; y <= 4; y++)
gtk_box_append(GTK_BOX(list), hw_year_button(y, y > 1));
return page;
}
GtkWidget *build_hwmap_page(void) { GtkWidget *build_hwmap_page(void) {
GtkWidget *page; GtkWidget *page;
GtkWidget *scroll; GtkWidget *scroll;
@ -344,7 +447,7 @@ GtkWidget *build_hwmap_page(void) {
gtk_widget_set_margin_bottom(page, 24); gtk_widget_set_margin_bottom(page, 24);
gtk_box_append(GTK_BOX(page), gtk_box_append(GTK_BOX(page),
top_bar("subjects", "Technické vybavení", "hw_sub")); top_bar("hwyears", "hw_year1", "hw_sub"));
scroll = gtk_scrolled_window_new(); scroll = gtk_scrolled_window_new();
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),

View file

@ -521,6 +521,13 @@ const TrEntry tr_ui[] = {
"This assignment does not fit into a /24 network — tap “Show solution” to see why."}, "This assignment does not fit into a /24 network — tap “Show solution” to see why."},
{"hw_sub", "Vyberte lekci na cestě a začněte procvičovat.", {"hw_sub", "Vyberte lekci na cestě a začněte procvičovat.",
"Pick a unit on the path and start practicing."}, "Pick a unit on the path and start practicing."},
{"hw_years_sub", "Vyberte ročník a začněte procvičovat.",
"Pick a school year and start practicing."},
{"hw_year1", "1. ročník", "Year 1"},
{"hw_year2", "2. ročník", "Year 2"},
{"hw_year3", "3. ročník", "Year 3"},
{"hw_year4", "4. ročník", "Year 4"},
{"hw_year_locked_sub", "Zatím bez obsahu", "No content yet"},
{"hw_unit1", "Architektura počítače", "Computer architecture"}, {"hw_unit1", "Architektura počítače", "Computer architecture"},
{"hw_unit1_sub", "3 snímky o Von Neumannovi a schématu a pak kvíz.", {"hw_unit1_sub", "3 snímky o Von Neumannovi a schématu a pak kvíz.",
"3 slides about von Neumann and the model, then a quiz."}, "3 slides about von Neumann and the model, then a quiz."},

View file

@ -385,7 +385,7 @@ static gboolean shot_later(gpointer data) {
static gboolean run_smoke_test(gpointer data) { 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", "hwmap", "czechmap", "netyears", "netmap", "hwyears", "hwmap", "czechmap",
"mluvnice", "readinglist", "mluvnice", "readinglist",
"cetba1984", "cetba1984quiz", "cetba1984dej", "cetba1984", "cetba1984quiz", "cetba1984dej",
"cetbaFuks", "cetbaFuksQuiz", "cetbaFuksDej", "cetbaFuks", "cetbaFuksQuiz", "cetbaFuksDej",
@ -504,6 +504,7 @@ void activate(GtkApplication *app, gpointer user_data) {
gtk_stack_add_named(main_stack, build_stats_page(), "stats"); gtk_stack_add_named(main_stack, build_stats_page(), "stats");
gtk_stack_add_named(main_stack, build_netyears_page(), "netyears"); gtk_stack_add_named(main_stack, build_netyears_page(), "netyears");
gtk_stack_add_named(main_stack, build_netmap_page(), "netmap"); gtk_stack_add_named(main_stack, build_netmap_page(), "netmap");
gtk_stack_add_named(main_stack, build_hwyears_page(), "hwyears");
gtk_stack_add_named(main_stack, build_hwmap_page(), "hwmap"); gtk_stack_add_named(main_stack, build_hwmap_page(), "hwmap");
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");

View file

@ -843,6 +843,7 @@ void progress_for_hw(ProgressSum *out);
void hw_rail_theme_reset(void); void hw_rail_theme_reset(void);
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_hwmap_page(void); GtkWidget *build_hwmap_page(void);
GtkWidget *build_czechmap_page(void); GtkWidget *build_czechmap_page(void);
void mluvnice_init(void); void mluvnice_init(void);

View file

@ -31,7 +31,7 @@ static const char *subject_page(int i) {
if (i == NET_SUBJ) if (i == NET_SUBJ)
return "netyears"; return "netyears";
if (i == HW_SUBJ) if (i == HW_SUBJ)
return "hwmap"; return "hwyears";
if (i == CZ_SUBJ) if (i == CZ_SUBJ)
return "czechmap"; return "czechmap";
return "subjects"; return "subjects";
@ -187,6 +187,10 @@ static void catalog_rebuild(void) {
catalog_add(tr(key), tr("search_exercise"), page, FALSE, 3, "kviz quiz"); catalog_add(tr(key), tr("search_exercise"), page, FALSE, 3, "kviz quiz");
} }
catalog_add_key("hw_year1", "search_lesson", "hwmap", FALSE, 1, "rocnik");
catalog_add_key("hw_year2", "search_lesson", "hwyears", TRUE, 1, "rocnik");
catalog_add_key("hw_year3", "search_lesson", "hwyears", TRUE, 1, "rocnik");
catalog_add_key("hw_year4", "search_lesson", "hwyears", TRUE, 1, "rocnik");
for (i = 1; i <= HW_LESSONS; i++) { for (i = 1; i <= HW_LESSONS; i++) {
g_snprintf(key, sizeof(key), "hw_unit%d", i); g_snprintf(key, sizeof(key), "hw_unit%d", i);
g_snprintf(page, sizeof(page), "hwunit%d", i); g_snprintf(page, sizeof(page), "hwunit%d", i);

View file

@ -184,7 +184,7 @@ static const char *subject_target(int i) {
if (i == NET_SUBJ) if (i == NET_SUBJ)
return "netyears"; return "netyears";
if (i == HW_SUBJ) if (i == HW_SUBJ)
return "hwmap"; return "hwyears";
if (i == CZ_SUBJ) if (i == CZ_SUBJ)
return "czechmap"; return "czechmap";
return NULL; return NULL;