mirror of
https://github.com/pepaskopec-blip/Graduately.git
synced 2026-10-27 15:14:35 +00:00
Move lessons out of the C sources into JSON so the web client can use the same material as the desktop app, and point release builds at desktop/. Co-authored-by: Cursor <cursoragent@cursor.com>
114 lines
3.2 KiB
JavaScript
114 lines
3.2 KiB
JavaScript
import { readFileSync } from 'node:fs';
|
||
import { parseArray, parseArrayInFunction, trimNulls } from '../lib/cparse.mjs';
|
||
|
||
/**
|
||
* Maturita reading list ("Četba"): one lesson per book.
|
||
*
|
||
* Each book page shows four reference cards followed by two exercises, so the
|
||
* cards become the lesson's theory slides and the quiz and plot ordering
|
||
* become its two tasks.
|
||
*/
|
||
|
||
/**
|
||
* Lesson numbers continue after Mluvnice, so every Czech lesson has a distinct
|
||
* number for the statistics page; the reading path numbers its own nodes.
|
||
*/
|
||
const BOOKS = [
|
||
{
|
||
id: 'orwell-1984',
|
||
number: 2,
|
||
title: 'George Orwell – 1984',
|
||
page: 'build_cetba1984_page',
|
||
quiz: 'lit_qs',
|
||
plot: 'lit_plot_items',
|
||
plotMeaning: 'lit_plot_meaning',
|
||
cards: [
|
||
['about', 'O knize'],
|
||
['world', 'Svět a strana'],
|
||
['people', 'Postavy'],
|
||
['terms', 'Klíčové pojmy'],
|
||
],
|
||
},
|
||
{
|
||
id: 'fuks-spalovac-mrtvol',
|
||
number: 3,
|
||
title: 'Ladislav Fuks – Spalovač mrtvol',
|
||
page: 'build_cetba_fuks_page',
|
||
quiz: 'fuks_qs',
|
||
plot: 'fuks_plot_items',
|
||
plotMeaning: 'fuks_plot_meaning',
|
||
cards: [
|
||
['about', 'O knize'],
|
||
['world', 'Doba a svět'],
|
||
['people', 'Postavy'],
|
||
['terms', 'Klíčové motivy'],
|
||
],
|
||
},
|
||
];
|
||
|
||
/** `LitQ`: question, opts[4], correct, explanation. */
|
||
function litChoice(row, label) {
|
||
const [prompt, options, correct, expl] = row;
|
||
const list = trimNulls(options ?? []).map(String);
|
||
|
||
if (typeof correct !== 'number' || correct < 0 || correct >= list.length) {
|
||
throw new Error(`${label}: correct index ${correct} out of range for ${list.length} options`);
|
||
}
|
||
|
||
return {
|
||
kind: 'choice',
|
||
prompt: String(prompt),
|
||
options: list,
|
||
correct,
|
||
...(expl ? { hint: String(expl) } : {}),
|
||
};
|
||
}
|
||
|
||
export function extractCetba(desktopDir) {
|
||
const src = readFileSync(`${desktopDir}/cetba.c`, 'utf8');
|
||
|
||
return BOOKS.map((book) => {
|
||
const slides = book.cards.map(([arrayName, cardTitle]) => ({
|
||
kicker: book.title,
|
||
title: cardTitle,
|
||
tip: null,
|
||
lines: trimNulls(parseArrayInFunction(src, book.page, arrayName)).map(String),
|
||
}));
|
||
|
||
const plotMeanings = parseArray(src, book.plotMeaning).map(String);
|
||
|
||
return {
|
||
id: book.id,
|
||
subject: 'czech',
|
||
number: book.number,
|
||
title: { cs: book.title, en: book.title },
|
||
subtitle: {
|
||
cs: 'Projděte si přehled a pak si vyzkoušejte kvíz a řazení děje.',
|
||
en: 'Read the overview, then try the quiz and the plot ordering.',
|
||
},
|
||
slides,
|
||
tasks: [
|
||
{
|
||
number: 1,
|
||
title: 'Kvíz',
|
||
heading: 'Kvíz ke knize',
|
||
subtitleKey: 'lit_quiz_sub',
|
||
items: parseArray(src, book.quiz)
|
||
.map((row, i) => litChoice(row, `${book.id} q${i + 1}`)),
|
||
},
|
||
{
|
||
number: 2,
|
||
title: 'Děj',
|
||
heading: 'Seřaďte děj',
|
||
subtitleKey: 'lit_plot_sub',
|
||
items: parseArray(src, book.plot).map(([prompt, words], i) => ({
|
||
kind: 'assembly',
|
||
prompt: prompt ? String(prompt) : '',
|
||
words: trimNulls(words).map(String),
|
||
...(plotMeanings[i] ? { meaning: plotMeanings[i] } : {}),
|
||
})),
|
||
},
|
||
],
|
||
};
|
||
});
|
||
}
|