mirror of
https://github.com/pepaskopec-blip/Graduately.git
synced 2026-10-28 15:44:34 +00:00
Add the Next.js web app and shared lesson content.
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>
This commit is contained in:
parent
4708c69d9c
commit
f7470d333c
113 changed files with 25817 additions and 9 deletions
159
tools/extract/deutsch-u2.mjs
Normal file
159
tools/extract/deutsch-u2.mjs
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
import { readFileSync } from 'node:fs';
|
||||
import { parseArray, parseString } from '../lib/cparse.mjs';
|
||||
import {
|
||||
choiceItem,
|
||||
freeItem,
|
||||
opt,
|
||||
typedItem,
|
||||
verbFill,
|
||||
vocabSections,
|
||||
} from './deutsch-helpers.mjs';
|
||||
|
||||
/**
|
||||
* Deutsch Unit 2 ("Familie und Freunde").
|
||||
*
|
||||
* Task order, titles and instruction keys come from the `u2exN` builders at the
|
||||
* bottom of exercise_u2.c; each one names the `const` arrays holding its data.
|
||||
*/
|
||||
export function extractDeutschUnit2(desktopDir) {
|
||||
const src = readFileSync(`${desktopDir}/exercise_u2.c`, 'utf8');
|
||||
const tasks = [];
|
||||
|
||||
/** `build_verb_ex`: one pool feeding single-gap sentences. */
|
||||
const verbTask = (number, title, subtitleKey, prefix, { gloss = false } = {}) => {
|
||||
const meanings = parseArray(src, `${prefix}_mean`);
|
||||
const glosses = gloss ? parseArray(src, `${prefix}_gloss`) : null;
|
||||
return {
|
||||
number,
|
||||
title,
|
||||
subtitleKey,
|
||||
pool: parseArray(src, `${prefix}_pool`).map(String),
|
||||
items: parseArray(src, `${prefix}_rows`).map((row, i) =>
|
||||
verbFill(row, meanings[i], glosses && opt(glosses[i])
|
||||
? { glosses: [String(glosses[i])] }
|
||||
: {})),
|
||||
};
|
||||
};
|
||||
|
||||
const choiceTask = (number, title, subtitleKey, prefix) => {
|
||||
const meanings = parseArray(src, `${prefix}_mean`);
|
||||
return {
|
||||
number,
|
||||
title,
|
||||
subtitleKey,
|
||||
items: parseArray(src, `${prefix}_rows`).map((row, i) => choiceItem(row, meanings[i])),
|
||||
};
|
||||
};
|
||||
|
||||
const typedTask = (number, title, subtitleKey, rowsName, bankName) => ({
|
||||
number,
|
||||
title,
|
||||
subtitleKey,
|
||||
...(bankName ? { note: parseString(src, bankName) } : {}),
|
||||
items: parseArray(src, rowsName).map(typedItem),
|
||||
});
|
||||
|
||||
/* 1 — Verben konjugieren: two people, each a headed group over one pool. */
|
||||
{
|
||||
const pool = parseArray(src, 'g01_pool').map(String);
|
||||
const groups = [
|
||||
['Peter Fritsch:', 'g01_peter', 'g01_peter_mean'],
|
||||
['Jana Nová und Pavol Korčák:', 'g01_jana', 'g01_jana_mean'],
|
||||
];
|
||||
|
||||
const items = groups.flatMap(([heading, rowsName, meanName]) => {
|
||||
const meanings = parseArray(src, meanName);
|
||||
return parseArray(src, rowsName).map((row, i) =>
|
||||
verbFill(row, meanings[i], i === 0 ? { heading } : {}));
|
||||
});
|
||||
|
||||
tasks.push({
|
||||
number: 1,
|
||||
title: 'Verben konjugieren',
|
||||
subtitleKey: 'sub_verben',
|
||||
pool,
|
||||
items,
|
||||
});
|
||||
}
|
||||
|
||||
tasks.push(choiceTask(2, 'aus oder in', 'sub_ausin', 'g02'));
|
||||
tasks.push(choiceTask(3, 'Fragewörter', 'sub_wer', 'g03'));
|
||||
tasks.push(verbTask(4, 'sprechen', 'sub_sprich', 'g04'));
|
||||
tasks.push(typedTask(5, 'Nationalitäten', 'sub_nation', 'g05_rows', 'g05_bank'));
|
||||
tasks.push(typedTask(6, 'Woher?', 'sub_woher', 'g06_rows'));
|
||||
tasks.push(typedTask(7, 'Länder schreiben', 'sub_laender', 'g07_rows'));
|
||||
tasks.push(verbTask(8, 'Verben einsetzen', 'sub_verb2', 'g08'));
|
||||
|
||||
/* 9 — Freie Antwort */
|
||||
tasks.push({
|
||||
number: 9,
|
||||
title: 'Freie Antwort',
|
||||
subtitleKey: 'sub_free',
|
||||
items: parseArray(src, 'ex9_free_qs').map(freeItem),
|
||||
});
|
||||
|
||||
tasks.push(verbTask(10, 'Euro', 'sub_euro', 'g10'));
|
||||
tasks.push(typedTask(11, 'Wörter suchen', 'sub_wortsuchen', 'g11_rows'));
|
||||
tasks.push(choiceTask(12, 'Was ist richtig?', 'sub_verb2', 'g12'));
|
||||
|
||||
/* 13 — Ordne zu: a Fragewort dropdown and an answer dropdown per row. */
|
||||
{
|
||||
const meanings = parseArray(src, 'g13_mean');
|
||||
tasks.push({
|
||||
number: 13,
|
||||
title: 'Ordne zu',
|
||||
subtitleKey: 'sub_ordne',
|
||||
pool: parseArray(src, 'g13_fw_pool').map(String),
|
||||
altPool: parseArray(src, 'g13_ans_pool').map(String),
|
||||
items: parseArray(src, 'g13_rows').map(([mid, fw, ans], i) => ({
|
||||
kind: 'fill',
|
||||
segments: ['', ` ${mid} → `, ''],
|
||||
answers: [String(fw), String(ans)],
|
||||
input: 'select',
|
||||
gapPool: ['main', 'alt'],
|
||||
label: `${i + 1}.`,
|
||||
...(opt(meanings[i]) ? { meaning: String(meanings[i]) } : {}),
|
||||
})),
|
||||
});
|
||||
}
|
||||
|
||||
tasks.push(verbTask(14, 'Lückentext', 'sub_luecke', 'g14', { gloss: true }));
|
||||
tasks.push(verbTask(15, 'Verbinde', 'sub_verbinde', 'g15', { gloss: true }));
|
||||
tasks.push(verbTask(16, 'Zahlen', 'sub_zahlpaar', 'g16'));
|
||||
|
||||
/* 17 — Steckbrief */
|
||||
tasks.push({
|
||||
number: 17,
|
||||
title: 'Steckbrief',
|
||||
subtitleKey: 'sub_steckbrief',
|
||||
items: parseArray(src, 's01_rows').map(([stem, sample]) => ({
|
||||
kind: 'profile',
|
||||
stem: String(stem),
|
||||
sample: String(sample),
|
||||
})),
|
||||
});
|
||||
|
||||
/* 18 — Berufe: hangman, one round per profession. */
|
||||
{
|
||||
const words = parseArray(src, 'hm_words').map(String);
|
||||
const tips = parseArray(src, 'hm_tips').map(String);
|
||||
tasks.push({
|
||||
number: 18,
|
||||
title: 'Berufe',
|
||||
subtitleKey: 'sub_berufe',
|
||||
items: words.map((word, i) => ({ kind: 'hangman', word, hint: tips[i] })),
|
||||
});
|
||||
}
|
||||
|
||||
tasks.push(typedTask(19, 'Nationalität', 'sub_bistdu', 's03_rows'));
|
||||
|
||||
return {
|
||||
id: 'unit-02',
|
||||
subject: 'deutsch',
|
||||
number: 2,
|
||||
title: { cs: 'Aus aller Welt', en: 'Aus aller Welt' },
|
||||
slides: [],
|
||||
tasks,
|
||||
vocab: vocabSections(src, 'u2_trans_sections'),
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue