Files
mpabi 8bf8e22448
Check card layouts / check (push) Has been cancelled
feat: publish A1-A8 card viewer and FreeRTOS C generator
2026-07-19 16:43:35 +02:00

11 KiB
Raw Permalink Blame History

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

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.

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.

{
  "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:

{
  "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:

{
  "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:

{
  "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:

"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:

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.