288 lines
11 KiB
Markdown
288 lines
11 KiB
Markdown
# Opis repozytorium pojedynczej karty
|
||
|
||
Każda karta jest osobnym repozytorium lub samodzielnym katalogiem. Jej źródłem
|
||
prawdy jest `json/card_source.json`; pliki TeX i HTML są artefaktami
|
||
generowanymi.
|
||
|
||
## Minimalne drzewo
|
||
|
||
```text
|
||
moja-karta/
|
||
├── README.md
|
||
├── json/card_source.json
|
||
├── doc/
|
||
├── web/
|
||
└── src/
|
||
```
|
||
|
||
## Obowiązkowe warstwy danych
|
||
|
||
### Metadane
|
||
|
||
Obiekt `card` identyfikuje serię, numer, wersję, UUID, autora i status.
|
||
Obiekt `generated` wskazuje ścieżki wyjściowe TeX/HTML/CSS. Pole `template`
|
||
wybiera layout.
|
||
|
||
Opcjonalny obiekt `title_block` włącza tabliczkę zasobu o skonfigurowanej
|
||
wysokości 2,6 lub 3 cm na każdej stronie, także pierwszej, bibliografii,
|
||
słownika i stronach kontynuacji. Tabliczka zastępuje dużą tabelę metadanych
|
||
strony tytułowej.
|
||
Zawiera kategorię, tytuł, metadane karty, numer strony oraz widoczny,
|
||
kanoniczny URL. Ten sam URL jest kodowany lokalnie w QR: jako SVG w HTML i
|
||
przez pakiet `qrcode` w TeX. Opcjonalny `repository_url` dodaje drugi QR do
|
||
repozytorium. W layoutach klasycznym HTML i PDF komórki QR mają po 24 mm,
|
||
a kody po 22 mm: Gitea znajduje się po lewej, a wyrenderowany zasób po prawej.
|
||
Ramka ma 167 mm i biegnie między marginesami bocznymi po 21,5 mm. W HTML widok ekranowy ma rozmiar A4 (210 × 297 mm) i
|
||
nagłówek na każdej logicznej karcie, a wydruk używa `@page { size: A4; }` oraz
|
||
pól marginesu, dlatego nagłówek powtarza się również po automatycznym podziale
|
||
długiej sekcji.
|
||
|
||
Pole `height_cm` przyjmuje `2.6` (kompaktowy nagłówek z QR 22 mm i równym
|
||
światłem) albo `3`; pola `repeat_on_every_page: true` i
|
||
`replace_front_matter: true` dokumentują ten kontrakt. `show_qr: true` wymaga
|
||
kanonicznego adresu HTTP(S) w `url` albo pary `url_host_uuid`/`doc_uuid`, z
|
||
której powstaje `https://<url_host_uuid>/<doc_uuid>`.
|
||
`show_repository_qr: true` wymaga `repository_url`. Adres podglądu `localhost`
|
||
nie powinien być publikowany na karcie.
|
||
|
||
### Publikacja lokalna i globalna
|
||
|
||
UUID hosta/workspace oraz UUID karty są stabilną tożsamością zasobu, a nie
|
||
tożsamością konkretnego serwera. Viewer podczas zajęć otwiera kartę przez
|
||
względny adres lokalnego ingressu K3s; kanoniczny adres globalny pozostaje w
|
||
metadanych, QR i udostępnianych odsyłaczach. Utrata Internetu nie może blokować
|
||
katalogu, przełączania kart, API sterowania, symulatora, dowodów ani raportu.
|
||
|
||
Pełny kontrakt topologii, routingu, magazynowania i przyszłej synchronizacji
|
||
opisuje [OFFLINE-FIRST-DEPLOYMENT.md](OFFLINE-FIRST-DEPLOYMENT.md).
|
||
|
||
### Status i wersja tasków w zakresie karty
|
||
|
||
Wiersze `front_page_scope.scope_table.rows[]` mogą opisywać stan opracowania
|
||
pojedynczego tasku. JSON przechowuje stabilny angielski klucz `status`, a
|
||
renderer pokazuje jego krótką polską etykietę w HTML i PDF.
|
||
|
||
| Klucz | Etykieta | Znaczenie |
|
||
|---|---|---|
|
||
| `not-started` | brak | task nie został jeszcze opracowany |
|
||
| `draft` | robocze | istnieje niepełna wersja robocza |
|
||
| `in-progress` | w trakcie | task jest aktualnie opracowywany |
|
||
| `review` | do przeglądu | materiał czeka na sprawdzenie |
|
||
| `ready` | opracowane | materiał jest sprawdzony i gotowy do użycia |
|
||
| `blocked` | zablokowane | dalsza praca wymaga rozwiązania zależności |
|
||
|
||
Pole `version` ma format `vNN.NN`, na przykład `v00.01`. Drugi człon
|
||
zwiększamy przy zaakceptowanej rewizji treści lub materiałów tasku. Pierwszy
|
||
człon zwiększamy, gdy zmienia się kontrakt dydaktyczny albo wymagany rezultat;
|
||
po takim zwiększeniu drugi człon zaczyna się od `00`.
|
||
|
||
```json
|
||
{
|
||
"chapter": "5.4",
|
||
"task": "Task04",
|
||
"idea_tex": "arytmetyka adresów, alokator",
|
||
"priority": "obowiązkowe",
|
||
"status": "in-progress",
|
||
"version": "v00.01",
|
||
"key": true
|
||
}
|
||
```
|
||
|
||
Status i wersję zmieniamy wyłącznie w źródłowym `card_source.json`; pliki
|
||
HTML, TeX i PDF pozostają artefaktami generatora.
|
||
|
||
### Efekty i kryteria
|
||
|
||
- `educational_requirements` — wymagania `WE`;
|
||
- `learning_effects` — efekty `EN` lub `EK`;
|
||
- `assessment_criteria` — mierzalne kryteria `KW`;
|
||
- `educational_requirements.*.learning_tree` — połączenia renderowane na
|
||
marginesach.
|
||
|
||
Każdy wpis `learning_tree.ogolne[]` lub `learning_tree.zawodowe[]` ma stabilne
|
||
`tree_id`, odwołanie `effect_ref`, etykietę `display` oraz co najmniej jedno
|
||
powiązane `KW`.
|
||
|
||
### Sekcje i kroki
|
||
|
||
Pole `sections[]` porządkuje treść. Kroki `sections[].steps[]` mają:
|
||
|
||
- `id` i `title`;
|
||
- `tree_refs` wskazujące drzewka z marginesów;
|
||
- opcjonalne odwołania do wymagań, efektów, kryteriów, równań i figur.
|
||
|
||
### Referencje zewnętrzne bez kopiowania treści
|
||
|
||
Karta może ładować kanoniczne rejestry współdzielonych strategii, kart, treści
|
||
i wzorów. Lokalny plik JSON służy do walidacji oraz deterministycznego buildu:
|
||
|
||
```json
|
||
{
|
||
"reference_registries": [
|
||
{
|
||
"uuid": "03403a8a-e20d-5b17-9004-26d9fe6c3003",
|
||
"source": "../../../tools/debugging-strategies/json/reference_registry.json"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
Krok przechowuje tylko rodzaj, UUID rejestru i UUID wpisu:
|
||
|
||
```json
|
||
{
|
||
"references": [
|
||
{
|
||
"kind": "strategy",
|
||
"registry_uuid": "03403a8a-e20d-5b17-9004-26d9fe6c3003",
|
||
"uuid": "1ecfc474-4fbd-5a56-8ef1-80ae557761d0"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
Generator pobiera z rejestru etykietę, tytuł, ścieżkę i publiczny adres.
|
||
Strategię pokazuje jako kod `Mxx`, kartę jako jej nazwę, a treść lub wzór jako
|
||
kanoniczną etykietę. W TeX/PDF i HTML etykieta jest hiperłączem. Nazw ani URL-i
|
||
nie kopiujemy do `card_source.json`; brak rejestru, UUID albo lokalnego pliku
|
||
przerywa generowanie.
|
||
|
||
Layouty 5a/5b obsługują również:
|
||
|
||
- `model_block.steps` — kroki modelowania;
|
||
- `code_block.blocks[].web_steps` — interaktywne kroki HTML;
|
||
- `hardware_procedure[]` — tabela `step/action/condition` w TeX i HTML.
|
||
|
||
`code_block.blocks[]` jest rzeczywistym podziałem na bloki: każdy wpis jest
|
||
renderowany jako osobna, opisana ramka w sekcji implementacyjnej, a jego
|
||
`web_steps` zasila niezależną checklistę HTML. Kolejność głównych bloków
|
||
strony jest opisana przez `block_map` wybranego szablonu.
|
||
|
||
### Zrzuty ekranu i inne assety sekcji
|
||
|
||
Zrzutów nie wpisujemy jako ręcznego `\\includegraphics` w wygenerowanym TeX.
|
||
Sekcja może deklarować listę `assets`, a generator umieszcza każdy element w
|
||
TeX/PDF i HTML, kopiuje plik do `figures/` strony oraz dodaje link do pełnego
|
||
rozmiaru:
|
||
|
||
```json
|
||
{
|
||
"title": "Pomiar w debuggerze",
|
||
"content_tex": "Zatrzymaj program przed pierwszą alokacją.",
|
||
"assets": [
|
||
{
|
||
"path": "assets/task04-first-allocation-annotated.png",
|
||
"caption": "Task04 przed pierwszym przydziałem pamięci.",
|
||
"label": "fig:task04-first-allocation",
|
||
"alt": "Termdebug: kod C, listing, rejestry i allocbuf",
|
||
"kind": "screenshot",
|
||
"width": 1.0
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
- `path` jest liczony względem katalogu `doc/` karty; standardem jest
|
||
`doc/assets/`;
|
||
- obsługiwane są PNG, JPG/JPEG i PDF;
|
||
- `width` jest ułamkiem szerokości kolumny od `0.1` do `1.0`;
|
||
- `label` jest stabilnym identyfikatorem używanym przez `figure_refs`;
|
||
- `full_size_link` domyślnie włącza otwieranie zrzutu HTML w pełnym rozmiarze.
|
||
|
||
Jeśli każda figura ma odpowiadać osobnej stronie wydruku, sekcja deklaruje
|
||
`"asset_page_mode": "one-per-page"`. Generator wtedy wstawia jawne podziały
|
||
stron w TeX i buduje osobne płótna A4 w React/HTML. Diagram interaktywny sam
|
||
renderuje zwarty, jednakowy nagłówek na każdej części; zewnętrzny nagłówek
|
||
sekcji nie przesuwa pierwszego kafla względem pozostałych.
|
||
|
||
Orientację wybiera sekcja przez `"page_orientation": "portrait"` albo
|
||
`"landscape"`. Jest to własność fizycznej strony, a nie zamiennik dla
|
||
`page_grid`: pojedynczy szeroki diagram może dostać landscape, pionowa
|
||
hierarchia portrait, a dopiero model nieczytelny po właściwym dobraniu
|
||
orientacji otrzymuje jawne złożenie kilku stron.
|
||
|
||
Diagram większy od bezpiecznego pola A4 deklaruje `page_grid` przy assetcie:
|
||
|
||
```json
|
||
"page_grid": {
|
||
"columns": 2,
|
||
"rows": 2,
|
||
"cuts_x": [660],
|
||
"cuts_y": [440],
|
||
"page_width": 660,
|
||
"page_height": 760,
|
||
"step_tiles": {"class-base": 1, "runtime-proof": 4}
|
||
}
|
||
```
|
||
|
||
`cuts_x` i `cuts_y` są współrzędnymi SVG, a `step_tiles` przypisuje każdy krok
|
||
interaktywny dokładnie do jednego fizycznego kafla (numeracja wierszowa od 1).
|
||
Generator odrzuca kafel większy od pola A4 oraz szew przecinający zamknięty
|
||
blok UML. React może złożyć strony w `spread_group`, zachowując jeden kursor i
|
||
jedną numerację rysunku; wydruk nadal zawiera niezależne kartki A4.
|
||
|
||
Włączony spread jest automatycznie dopasowywany do szerokości widoku, tak aby
|
||
wszystkie strony jednego wiersza i ich łączenia były widoczne równocześnie.
|
||
Nagłówki stron pokazują pulsujące kierunki kontynuacji `← ↑ ↓ →`; środkowa
|
||
strona szeregu może wskazywać obie strony, a złożenie wielowierszowe także górę
|
||
i dół. Wskaźniki są wyłącznie nawigacją ekranową i znikają w druku.
|
||
|
||
### Boczne szyny paneli
|
||
|
||
Narzędzia pomocnicze HTML używają wspólnego systemu paneli bocznych zamiast
|
||
modalnej zasłony. Cienka kolorowa szyna otwiera panel w trybie `Auto` po
|
||
najechaniu; kliknięcie przełącza go w `Fixed`. Kolejny klik, przycisk zamknięcia
|
||
albo `Esc` odpina panel. Renderer może wystawić kilka niezależnych szyn po obu
|
||
stronach (obecnie: katalog i spis treści po lewej, przebieg i raport po prawej).
|
||
Panele nakładają się na widok tylko podczas pracy i są zawsze usuwane z
|
||
wydruku. Nie zmieniają geometrii stron A4 ani kafelków diagramu.
|
||
|
||
Końcowy słownik jest domyślnie obecny w React/HTML dla zgodności. Karta, która
|
||
ma zawierać wyłącznie jawnie wymienione strony, ustawia na poziomie głównym
|
||
`"render_dictionary": false`.
|
||
|
||
### Zadania
|
||
|
||
`tasks` jest słownikiem zadań, a `tasks_order` określa ich kolejność. Każde
|
||
zadanie posiada polecenie `prompt_tex`, kryterium zaliczenia i odwołania do
|
||
modelu edukacyjnego.
|
||
|
||
Rozbudowane zadanie przechowuje przebieg dydaktyczny w uporządkowanym
|
||
`tasks.<id>.flow[]`:
|
||
|
||
- `kind: "block"` grupuje jedną część objaśnienia lub demonstracji;
|
||
- opcjonalne `block.steps[]` zachowują kolejność czynności wewnątrz bloku;
|
||
- `kind: "exercise"` jest samodzielną pracą ucznia należącą bezpośrednio do
|
||
zadania i podaje `prompt_tex`, `evidence_tex` oraz `criterion`;
|
||
- `exercise.based_on[]` może wskazać wcześniejsze bloki lub ich kroki.
|
||
|
||
Bloki i ćwiczenia są rodzeństwem w jednym `flow`, dzięki czemu renderer nie
|
||
gubi kolejności nauczania. `steps` nie może występować bezpośrednio w obiekcie
|
||
zadania. Dawne `prompt_tex` i `criterion` pozostają wymagane dla zgodności ze
|
||
starszymi konsumentami; gdy istnieje `flow`, renderer używa jego treści.
|
||
|
||
## Zalecany README karty
|
||
|
||
README konkretnej karty powinien zawierać:
|
||
|
||
1. nazwę, numer i miejsce w serii;
|
||
2. cel oraz rezultat obserwowalny;
|
||
3. mapowanie do źródeł i efektów nauczania;
|
||
4. listę kroków/zadań;
|
||
5. polecenia generowania i testowania;
|
||
6. warunek `PASS`;
|
||
7. informację, które pliki są źródłowe, a które generowane.
|
||
|
||
Gotowy przykład znajduje się w `examples/card/README.md`.
|
||
|
||
## Generowanie
|
||
|
||
Z katalogu repozytorium `card-layouts`:
|
||
|
||
```bash
|
||
python3 tools/render_card.py /sciezka/do/mojej-karty
|
||
```
|
||
|
||
Generator najpierw sprawdza spójność identyfikatorów WE/EN/EK/KW, kroków,
|
||
zadań, rejestrów UUID i odwołań, a dopiero potem zapisuje oba formaty.
|