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>
80 lines
3.4 KiB
Markdown
80 lines
3.4 KiB
Markdown
# content/
|
|
|
|
Shared lesson content for the whole project. One folder, one file per lesson —
|
|
instead of lesson text being buried inside each unit's C source file.
|
|
|
|
`schema.ts` is the single description of every shape here. Both the extractor in
|
|
`tools/` and the web app in `web/` type against it, so a change there shows up as
|
|
a type error on both sides.
|
|
|
|
## Layout
|
|
|
|
```
|
|
content/
|
|
schema.ts TypeScript types for everything below
|
|
themes.json 10 palettes, dark + light (24 colors each)
|
|
subjects.json the 13 subjects, their i18n keys and routes
|
|
paths.json serpentine unit paths per subject
|
|
manifest.json subject and lesson ids
|
|
i18n/
|
|
ui.json UI chrome strings, keyed by identifier
|
|
content.json lesson strings, keyed by the Czech text
|
|
lessons/
|
|
deutsch/unit-01.json … unit-03.json
|
|
networks/unit-01.json … unit-27.json
|
|
hardware/unit-01.json … unit-03.json
|
|
czech/mluvnice.json, orwell-1984.json, fuks-spalovac-mrtvol.json
|
|
```
|
|
|
|
`paths.json` holds one entry per path. A subject usually has exactly one, but
|
|
Czech has two: the top-level area picker and the `reading` branch listing the
|
|
books, distinguished by the `branch` field.
|
|
|
|
## Lesson shape
|
|
|
|
A lesson holds theory `slides` and a list of `tasks`. Each task is one bubble on
|
|
the unit map and contains `items` of a single `kind`:
|
|
|
|
| kind | what it is |
|
|
| ---- | ---------- |
|
|
| `choice` | multiple choice, `correct` indexes `options` |
|
|
| `fill` | sentence split into `segments` with a gap between each; `input` picks dropdown or text |
|
|
| `dialogue` | dialogue lines with one missing word each |
|
|
| `assembly` | build a sentence from scrambled words |
|
|
| `assign` | sort labelled cards into named groups |
|
|
| `free` | open question with a model answer |
|
|
| `typed` | type the answer, `answers` lists accepted spellings |
|
|
| `fields` | one prompt, several labelled fields (Czech grammatical categories) |
|
|
| `reveal` | self-assessed: write an answer, then compare it with the model |
|
|
| `hangman` | guess the word letter by letter |
|
|
| `profile` | "Steckbrief" line with a model answer |
|
|
| `table` | editable grid, some cells prefilled |
|
|
| `subnet` | VLSM subnetting worksheet |
|
|
|
|
`fill` absorbs every gap variant in the desktop app. A few flags steer it:
|
|
`letters` marks gaps holding missing letters inside a word rather than whole
|
|
words, `gapPool` picks the task's `pool` or `altPool` per gap (the "Ordne zu"
|
|
question-word and answer columns), and `heading` starts a labelled group of rows.
|
|
|
|
Two conventions carried over from the desktop app:
|
|
|
|
- **Pipe-separated answers.** `"bin|heiße"` means either spelling is accepted.
|
|
- **Lenient comparison.** Answers are matched after lowercasing, expanding
|
|
`ä ö ü ß` to `ae oe ue ss`, dropping accents and ignoring punctuation, so Czech
|
|
diacritics and German umlauts are optional. See `web/src/lib/answers.ts`.
|
|
|
|
Titles come either as a literal `title` or as a `titleKey` to look up in the
|
|
i18n tables, because German unit names are identical in both languages while
|
|
network lesson names are translated.
|
|
|
|
## Regenerating
|
|
|
|
The C sources in `desktop/` are still where content is authored, so this folder
|
|
is a generated one-way export:
|
|
|
|
```bash
|
|
npm run content # from the repo root, or: node tools/build-content.mjs
|
|
```
|
|
|
|
The extractor parses the C initializers directly and throws on any shape it does
|
|
not recognise, so a bad export fails loudly rather than emitting empty lessons.
|