Add year-4 civics lessons on the economy, the world and philosophy.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
pepaskopec-blip 2026-10-03 14:48:46 +02:00
commit 50a23c334b
27 changed files with 2317 additions and 32 deletions

View file

@ -52,6 +52,7 @@ extern char *app_progress_hw;
extern char *app_progress_on;
extern char *app_progress_on2;
extern char *app_progress_on3;
extern char *app_progress_on4;
extern char *app_progress_mluvnice;
extern char *app_progress_cetba;
#define PROGRESS_DIR app_progress_dir
@ -64,6 +65,7 @@ extern char *app_progress_cetba;
#define PROGRESS_ON app_progress_on
#define PROGRESS_ON2 app_progress_on2
#define PROGRESS_ON3 app_progress_on3
#define PROGRESS_ON4 app_progress_on4
#define NODE_SIZE 88.0
#define PATH_SPAC 240.0
#define ROAD_MX 150.0 /* horizontal canvas margin */
@ -127,6 +129,8 @@ extern char *app_progress_cetba;
#define ON2_LESSONS 16
#define ON3_UNITS 16
#define ON3_LESSONS 16
#define ON4_UNITS 16
#define ON4_LESSONS 16
#define HW_SLIDES 3
#define HW2_SLIDES 6
#define HW3_SLIDES 2
@ -773,6 +777,8 @@ extern NetLesson on2_lessons[ON2_LESSONS];
extern GtkWidget *on2_nodes[ON2_UNITS];
extern NetLesson on3_lessons[ON3_LESSONS];
extern GtkWidget *on3_nodes[ON3_UNITS];
extern NetLesson on4_lessons[ON4_LESSONS];
extern GtkWidget *on4_nodes[ON4_UNITS];
extern GtkWidget *net_note_host;
extern int net_note_last_w;
extern GtkWidget *net_scroll;
@ -886,6 +892,14 @@ void on3_rail_theme_reset(void);
void on3_lessons_apply_lang(void);
GtkWidget *build_on3map_page(void);
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 hw_lessons_apply_lang(void);
GtkWidget *build_hwyears_page(void);

View file

@ -1000,6 +1000,104 @@ const TrEntry tr_ui[] = {
{"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",
"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.",
"Pick an area and start practicing."},
{"Literatura", "Literatura", "Literature"},
@ -2026,6 +2124,7 @@ void hw_lessons_apply_lang(void);
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 net_rail_theme_reset(void);
void apply_language(void) {
@ -2043,5 +2142,6 @@ void apply_language(void) {
on_lessons_apply_lang();
on2_lessons_apply_lang();
on3_lessons_apply_lang();
on4_lessons_apply_lang();
search_apply_lang();
}

View file

@ -386,7 +386,7 @@ static gboolean run_smoke_test(gpointer data) {
static const char *pages[] = {
"welcome", "subjects", "roadmap", "stats",
"netyears", "netmap", "hwyears", "hwmap", "onyears", "onmap", "on2map",
"on3map",
"on3map", "on4map",
"czechmap",
"mluvnice", "readinglist",
"cetba1984", "cetba1984quiz", "cetba1984dej",
@ -401,6 +401,7 @@ static gboolean run_smoke_test(gpointer data) {
"onunit1", "onex1", "onunit17", "onex17",
"on2unit1", "on2ex1", "on2unit16", "on2ex16",
"on3unit1", "on3ex1", "on3unit16", "on3ex16",
"on4unit1", "on4ex1", "on4unit16", "on4ex16",
"unit1", "unit2", "unit3",
"u1e1", "u1e13", "u2e1", "u2e19", "u3e1", "u3e15",
"u1vocab", "u2vocab", "u3vocab",
@ -518,6 +519,8 @@ void activate(GtkApplication *app, gpointer user_data) {
add_on2_pages(main_stack);
gtk_stack_add_named(main_stack, build_on3map_page(), "on3map");
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_mluvnice_page(), "mluvnice");
for (int n = 1; n <= 20; n++) {

View file

@ -3,7 +3,7 @@
/* Year 1 of Občanská nauka.
* 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
* 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) \
{ .n_slides = 2, .unit_page = "onunit" #n, .ex_page = "onex" #n }
@ -412,7 +412,7 @@ GtkWidget *build_onyears_page(void) {
GtkWidget *scroll;
GtkWidget *list;
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);
gtk_widget_set_hexpand(page, TRUE);

View file

@ -3,8 +3,8 @@
/* Year 2 of Občanská nauka.
* 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
* schools place in the second year. Law is year 3; the economy and
* philosophy stay in the fourth year. */
* schools place in the second year. Law is year 3. The economy, the
* world and philosophy are year 4. */
#define ON2_ENTRY(n) \
{ .n_slides = 2, .unit_page = "on2unit" #n, .ex_page = "on2ex" #n }

View file

@ -3,7 +3,7 @@
/* Year 3 of Občanská nauka.
* 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
* 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) \
{ .n_slides = 2, .unit_page = "on3unit" #n, .ex_page = "on3ex" #n }

1909
src/obcanka4.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -57,6 +57,7 @@ void load_progress(void) {
on_load_progress();
on2_load_progress();
on3_load_progress();
on4_load_progress();
}
/* 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) {
out->total_ex += ON_LESSONS + ON2_LESSONS + ON3_LESSONS;
out->open_units += 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 + ON4_LESSONS;
for (int i = 0; i < ON_LESSONS; i++) {
if (on_lessons[i].done) {
out->done_ex++;
@ -446,6 +447,12 @@ void progress_for_on(ProgressSum *out) {
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) {
@ -607,3 +614,83 @@ void mark_on3_done(int lesson_id) {
refresh_on3_completion_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();
}

View file

@ -205,7 +205,7 @@ static void catalog_rebuild(void) {
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_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++) {
g_snprintf(key, sizeof(key), "on_unit%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);
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",
"czechmap", FALSE, 0, "cestina czech");

View file

@ -429,6 +429,7 @@ void apply_theme(void) {
on_rail_theme_reset();
on2_rail_theme_reset();
on3_rail_theme_reset();
on4_rail_theme_reset();
czech_rail_theme_reset();
book_rail_theme_reset();
}

View file

@ -23,6 +23,7 @@ char *app_progress_hw;
char *app_progress_on;
char *app_progress_on2;
char *app_progress_on3;
char *app_progress_on4;
char *app_progress_mluvnice;
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_on2);
g_free(app_progress_on3);
g_free(app_progress_on4);
g_free(app_progress_mluvnice);
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_on2 = g_build_filename(app_progress_dir, "on2.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_cetba = g_build_filename(app_progress_dir, "cetba.conf", NULL);
}