# Скіл 1 — розбір буклетів A1, рівні 0–4

Розвідка перед перекладом: машинна (шрифти, кольори, геометрія) і візуальна
(усі 36 сторінок переглянуто). Мета — знайти пастки верстки **до** того, як
почнеться переклад, бо кожна знайдена потім коштує перезбірки.

Витяг зроблено:

```bash
.venv/bin/python ua_build/extract.py --a1
```

| Буклет | Стор. | Блоків | Спанів | Контурних прогонів |
|---|---|---|---|---|
| Level0_A1 | 4 | 62 | 129 | 1 |
| Level1_A1 | 8 | 204 | 305 | 7 |
| Level2_A1 | 8 | 241 | 463 | 3 |
| Level3_A1 | 8 | 252 | 461 | 0 |
| Level4_A1 | 8 | 224 | 465 | 0 |

Результат — `ua_build/work/<буклет>/template.json` і `worksheet.txt`.
Усі п'ять — **текстові** PDF, OCR не потрібен. Шрифти скрізь Arial (Regular,
Bold, Italic, BoldItalic, Black) плюс один сторонній — див. нижче.

---

## Що відрізняє рівні

Ці п'ять рядків — причина, чому конвеєр, написаний під рівень 2, на решті
рівнів не працює:

| | L0 | L1 | L2 | L3 | L4 |
|---|---|---|---|---|---|
| фірмовий колір | `#b3579d` | `#f49944` | `#ea515a` | `#009d78` | `#3055a3` |
| слово-заголовок | `STORY` | `STORY` | `STORY` | `LESSON` | `STUDY` |
| маркер завдання `Q:` | немає | немає | є | є | є |
| сторінок | 4 | 8 | 8 | 8 | 8 |
| бокс `KEY VERSE` | немає | немає | є | є | є |

**Колір — не косметика.** `fields_detect.py` шукає варіанти відповіді за
жорстко зашитим `0xea515a` (§3.3, крок 5). На рівні 3 варіанти зелені, на
рівні 4 сині — детектор не знайде жодного. Виправлено: колір тепер береться
з `lessons.py` за номером рівня.

Спільне, що можна лишити константою: бокси балів стоять на `x0 = 509…513` у
всіх п'яти рівнях, тож `CONTENT_RIGHT = 508` тримається.

---

## Що є в кожному буклеті

Три блоки, які повторюються скрізь і які конвеєр має ставити сам, а не
розпізнавати як завдання:

* **бланк повернення** на стор. 1: «Make sure your name and address are written
  here», Age / Name / Address / Class Leader (+ «Bible version used» у L3–L4);
* **смуга B.E.S. & Friends** на стор. 1: чотири персонажі з іменами й
  однорядковими описами («B.E.S. — A wise guide», «Q — Bravely asks
  questions», «Pause — Likes to stop and think», «Beam — An encouraging
  friend»). Імена лишаються, описи перекладаються;
* **таблиця балів** на останній сторінці: Marks (to be entered by leader),
  рядки на кожну історію, Total, Grand Total, Leader's comments, Return your
  lessons to. Лишається друкованою графікою (§3.0).

---

## Механіки, яких конвеєр ще не бачив

Level 2 «У що вірять християни» дав нам десять типів полів. Буклети A1
додають вісімнадцять ситуацій, з яких **сім потребують нового коду**.

### Потребує нового коду

1. **Текст для обведення по крапках** — L0 стор. 2, L1 стор. 1 і 8.
   Шрифт `SassoonInfantDtB`; `Dt` = *dotted*, гліфи складено з крапок, дитина
   обводить. Кирилиці шрифт не має й на цьому маку його немає взагалі.
   **Рішення:** не шукати шрифт, а робити ефект самим — набрати кирилицю
   `Arial Rounded Bold` у режимі обведення (`render_mode = 1`) зі **штриховим
   пунктиром** у графічному стані (`[1 3] 0 d`). Це та сама механіка, що вже
   працює для контурних написів (§3.2), плюс два оператори.
2. **Клітинки з крапкою** — L1 стор. 2 і 7, L2 стор. 7. «Colour the dotted
   squares to find out», «Write the letters with dots in the spaces below»:
   ряд клітинок із надрукованими літерами, під деякими стоїть крапка.
   Це рівно пункт 2 беклогу, який ми відклали як разовий, — а він
   трапляється **тричі з п'яти буклетів A1**. Механізм заливки (`paint`) уже
   є; бракує правила «ряд клітинок із літерами + крапка».
3. **Кросворди з переліком підказок** — L3 стор. 7 (WORD LADDER), L4 стор. 2,
   3 і 5 (CROSSWORD, WORD GRID). Сітка з номерами й окремим списком CLUES
   ACROSS / CLUES DOWN. Порожні клітинки — це `char`, тут усе просто; складне
   інше: **скласти справжній український кросворд** із тими самими
   перетинами. §2.6 каже: якщо спільних літер немає — чесно замінити на
   нумеровану сітку і сказати про це.
4. **Літери, дописані наполовину** — L3 стор. 7: «Finish each of the letters
   to find out what he did next» (`HE KILLED HIS BROTHER`, намальовано
   половинками літер). Це векторна графіка, а не текст; українською її треба
   перемальовувати цілком.
5. **Ланцюжок літер по змійці** — L2 стор. 5: «Use the puzzle to fill in the
   missing words», літери в кружечках уздовж звивистого шляху зі стрілкою
   START. Геометрія нестандартна: клітинки не в ґратці.
6. **Підписи, що лежать на ілюстрації** — L1 стор. 5: рамки `A_ _ _ _` і
   `E_ _ _` стоять просто на малюнку. Детектор рамок їх знайде, але правило
   «рамка з ілюстрацією — не поле» (§3.3) може їх відкинути.
7. **Позначка на карті** — L1 стор. 1: «Mark where you live with an 'X'».
   Ані рамки, ані клітинки; технічно це клікабельна область на всю карту.

### Закривається тим, що вже є

| Механіка | Де | Тип поля |
|---|---|---|
| відповідь у рамку на лінійках | L3, L4 — скрізь | `text` / `area` |
| ТАК/НІ, TRUE/FALSE | L1 с.7, L2 с.7, L3 с.6, L4 с.5 | `bool` |
| обвести правильний варіант | L2 с.5, L3 с.1 і с.5, L4 с.4 | `choice` |
| викреслити неправильні | L2 с.3 | `multi` |
| філворд | L2 с.4, L3 с.2, L4 с.4 | `ws` |
| контурний напис на розмальовку | L0 с.1, L2 с.4 і с.8 | `paint` |
| літери в клітинки | скрізь | `char` |
| банк слів (у хмаринках) | L1 с.5 | `text` + друкований банк |
| анаграма | L3 с.6, L4 с.2 | `text` |
| порахувати й вписати число | L1 с.4 | `char` |
| ✓-квадратик після варіанта | L3 с.1, L4 с.6 | `multi` |
| розмальовка малюнка | L0–L2 | `art` (§3.2a) |
| обвести предмет на малюнку | L0 с.3 | `art` |

### Не виконується на екрані

* **намалювати** — L1 стор. 4 і 6 («Draw a picture in the box», «Draw
  yourself in the box»), L2 стор. 6, L3 стор. 2. Рамка є, а вводу немає;
* **з'єднати лінією / по крапках** — L0 усі чотири сторінки, L1 стор. 3;
* **перша літера кожного предмета** — L2 стор. 5 (яйце, скрипка, око → EVE),
  L3 стор. 4 (дев'ять **растрових фото**). Українською не складається без
  заміни картинок, як і передбачав §2.6.

Окремо: **вільні відповіді про себе** — L1 стор. 6 («I am happy when…»,
«I am good at…»). Правильної відповіді немає, перевірити не можна, але поле
для вводу цілком доречне: це `area`.

---

## Пастки верстки, знайдені очима

* **контурний вірш на L0 стор. 1 — це текст**, `Arial-Black` 48 pt,
  `render_mode = 1`, товщина 0.5. Перекладається як звичайний текст із
  `render: 1`; це не векторний малюнок, як здається на вигляд;
* **«very good.» на L0 стор. 2 — теж текст**, але шрифтом-пунктиром
  (`SassoonInfantDtB` 55 pt, звичайна заливка). Тобто вигляд крапок дає
  **шрифт**, а не режим малювання; переклад вимагає підміни механізму (див.
  пункт 1 вище);
* **чорний прямокутник на L3 стор. 1** біля завдання «Write out Genesis 1: 4
  beside the picture» — це ілюстрація, а не порожня рамка. Правило §3.3
  «рамка з ілюстрацією — не поле» тут спрацює правильно, але перевірити варто;
* **варіанти як малюнки** — L2 стор. 6: чотири дерева з підписами
  Orange / Knowledge of Good and Evil / Cherry / Coconut. Це `choice`, де
  кнопка має накривати малюнок, а не слово;
* **растрові фото в завданнях** — L3 стор. 4 (дев'ять предметів). Змінити не
  можна, тож завдання-акростих на цій сторінці не рятується.

---

## Стан

Зроблено: конфіг уроку (`ua_build/lessons.py`), параметризований витяг
(`ua_build/extract.py`), шаблони й аркуші для всіх п'яти буклетів,
візуальна розвідка всіх 36 сторінок.

Далі — Скіл 2: переклад. Порядок за складністю верстки, від простого до
складного: **L4 → L3 → L2 → L1 → L0**. Рівні 3 і 4 — майже суцільний текст у
рамках, там конвеєр працює як є; рівень 0 найдорожчий, бо там майже все —
графіка й обведення по крапках.

---

## Level4_A1 — пройдено наскрізь до `uk/print`

Файл: `lessons/uk/print/Level4_A1_UA_v04.pdf`, 8 сторінок, 690 КБ
(оригінал 522 КБ — той самий порядок).

Зроблено: 169 із 224 блоків перекладено (решта — бокси балів, номери,
`www.besweb.com` і реєстраційні дані, які не перекладаються). Латиниці поза
брендом не лишилося. Цитати — Турконяк, УБТ 2020.

**Пастка, що коштувала перезбірки.** У першій збірці 42 блоки наклалися один
на одного. Причина: «Q:» у шаблоні — це **окремий рядок**, який ділить базову
лінію з першим рядком тексту. Тобто §2.4, правило 2, у чистому вигляді. Через
це в модулі перекладу зʼявилися помічники `Q()`, `N()` і `rows()`, які будують
спец так, щоб одному рядку шаблону відповідав рівно один сегмент. Разом із
ними — перевірка, що кількість рядків спеца дорівнює кількості рядків шаблону;
її варто ганяти перед кожною збіркою.

**Філворд перероблено повністю.** Літери сітки виявилися звичайними текстовими
спанами з відомими x, тож перемальовувати нічого не довелося: український
філворд 8×8 підставлено в ті самі позиції. Слова за Буттям 2: 7-9 —
СТВОРИВ, ПОРОХУ, ВДИХНУВ, ПОДИХ, НАСАДИВ, РАЙ, ЕДЕМІ, ДЕРЕВО. Жадібний
алгоритм кладе їх не з кожного зерна, тому зерно перебирається, а результат
**перевіряється пошуком** — інструкція обіцяє, що слова там є.

**Три сітки перероблено — генератором, не вручну.** `ua_build/puzzlekit.py`
розкладає слова з максимумом перетинів, нумерує клітинки в порядку читання і
малює сітку фірмовим кольором рівня; стару графіку закриває білим **до** набору
тексту (§2.1). Що з'ясувалося дорогою:

* **на стор. 2 звʼязний кросворд із поділом «три вниз, три вбік» неможливий.**
  Між трьома вертикальними й трьома горизонтальними словами лише чотири
  літерні збіги, а щоб звʼязати шість слів, потрібно щонайменше пʼять. Це не
  невдача алгоритму, а властивість набору слів — доведено перебором. Знявши
  жорстку орієнтацію, генератор дає повний звʼязок, і за збігом теж три на три,
  тож блоки підказок лишилися на місці;
* **жадібний алгоритм детермінований і робить ту саму помилку щоразу.**
  БЛАГОСЛОВИВ завжди забирав єдину Л у слова ЗЕМЛЕЮ, після чого ПЛІД і ДУХ
  могли чіплятися лише одне до одного — тобто в окремий острів. Лікується
  випадковим вибором серед рівноцінних місць плюс другим проходом для слів,
  що не лягли з першого разу;
* **габарит старої сітки міряй по всіх клітинках сторінки, а не всередині
  здогадки.** Сітка слів на стор. 5 виявилася на 123 pt вища, ніж показав
  перший замір, обмежений пробним прямокутником, — і незакрита частина
  лишилася на сторінці;
* **прямокутник закриття не має заходити на бокси балів.** Вони стоять на
  x = 511.7; закриття до 534 обрізало їм ліву стінку. Ширина сітки цим і
  обмежена: 10 клітинок по 12 pt.

Стор. 5: читання по вертикалі не переноситься (SERPENT — сім літер, ЗМІЙ —
чотири). За рішенням замовника сім тверджень лишилися, а відповідь «хто
спокусив» винесена в окремі чотири клітинки.

---

## Level3_A1 — пройдено наскрізь до `uk/print`

Файл: `lessons/uk/print/Level3_A1_UA_v06.pdf`, 8 сторінок, 1 514 КБ
(оригінал 1 379 КБ). 207 із 252 блоків перекладено; латиниці поза брендом
немає; зауважень збірки — нуль.

**Драбинка слів збереглася повністю.** Англійська WORD LADDER — це одне
вертикальне слово, що перетинає чотири горизонтальні. З першим варіантом
перекладу («ЖЕРТВУ») так не виходило: ГОСПОДЬ і КАЇН не мають із ним спільних
літер. З **ПРИНОШЕННЯ** перетинаються всі чотири, і нумерація 1, 3, 4, 5 по
горизонталі та 2 по вертикалі збіглася з оригінальною — тобто блоки підказок
лишилися на місці, без переливання тексту.

Дорогою відкинуто **ДАРУНОК**, хоч він і перетинає всі чотири слова: усі його
літери різні, тож два з чотирьох горизонтальних слів неминуче стають на
**сусідні рядки**, чого кросворд не допускає. Це загальне правило: вертикальне
слово має мати придатні літери **через одну**, а не просто придатні.

**Ще три пастки, кожна коштувала перезбірки.**

* **Латка ховає половину гліфа, а не смугу під ним.** Ефект «допиши літери» в
  оригіналі роблять 15 білих квадратиків 17×18 pt поверх звичайного тексту.
  Перша спроба клала їх під базовою лінією (тобто на порожнє місце) або на
  всю висоту літери — напис або лишався цілим, або зникав. Правильно —
  прямокутник від `y - 0.74·кегль` до `y + 1.5`, завширшки в половину гліфа,
  ліворуч або праворуч навмання;
* **приклади у філворді обведені овалами**, і овали лишаються на старих
  координатах. Тому два перші слова доводиться **змушувати лягати
  горизонтально** (інакше овал довелося б повертати), а самі овали —
  перемальовувати за позицією слова в новій сітці;
* **один блок може містити дві хмаринки.** `p3b37` — це запитання й відповідь
  двох персонажів в одному текстовому блоці. Режим `fit` зливає їх в одну
  колонку й вивалює за межі фігур; потрібна сітка рядків.

**Головне правило, яке варто рознести на всі буклети.** Типова права межа
508 pt — це край основної колонки, але якщо праворуч від абзацу стоїть
ілюстрація чи хмаринка, українськ+ий текст (він на 10–20 % довший) заповзе під
неї. Ознака — **вузький джерельний bbox**. У Level3_A1 так наїхали шість
абзаців. Лікується трьома рядками в кінці файла перекладу:

```python
for _k, _v in TR.items():
    if 'flow' in _v and 'right' not in _v:
        _r = IDX[_k]['bbox'][2]
        if _r < 480:
            _v['right'] = _r + 2.0
```

**Акростих із фото не переноситься** — як і передбачав §2.6. Груша, кролик,
яблуко, морозиво, сонце, яйце дають PRAISE, далі капелюх, морозиво, місяць —
HIM. Українською перші літери не складають нічого, а фото растрові. Рішення:
малюнки лишилися (вони доречні), клітинки закрито, а завдання на ті самі
2 бали стало письмовим — «напиши, за що ти дякуєш Богові за Його творіння».

---

## Level2_A1 — пройдено наскрізь до `uk/print`

Файл: `lessons/uk/print/Level2_A1_UA_v02.pdf`, 8 сторінок, 1 800 КБ
(оригінал 1 651 КБ). 178 із 241 блоку перекладено, латиниці поза брендом
немає, зауважень збірки нуль.

Чотири головоломки, три з них нових для конвеєра.

**Ланцюжок по змійці (стор. 5).** Три ряди кружечків читаються бустрофедоном:
перший ліворуч-праворуч, другий **праворуч-ліворуч**, третій знову
ліворуч-праворуч. Разом 26 кружечків, тобто українська фраза має бути рівно
такої довжини — не приблизно, а точно. Підійшло «Адам жив у саду, який звався
Едем» (26 літер); другий ряд кладеться в шаблон розвернутим.

**Літери з крапкою (стор. 7) — перемальовано цілком.** Спроба зіставити наявні
крапки з літерами провалилася: крапка надрукована **між** двома літерами, і
геометрія не каже, якій із них вона належить (автозіставлення дало 16 крапок
на 34 літери з суперечливими привʼязками). Коли клітинки, літери й крапки
малюємо самі, двозначності немає: 17×2 клітинок, 18 позначених літер складають
«Бог любить нас завжди». Це і є той механізм, якого просив пункт 2 беклогу.

**Філворд 7×6 (стор. 4)** — як у попередніх буклетах, літери підставляються в
наявні позиції: ПТАХИ, РИБИ, ТВАРИНИ, ЛЮДИНА, СПОЧИВ.

**Акростих із трьох фото (стор. 5)** — яйце, скрипка, око дають EVE.
Українською не складається (Я, С, О), фото растрові. Клітинки лишилися, а
завдання стало прямим: «впиши в клітинки імʼя першої жінки» — ЄВА. Механіка
простіша, бали ті самі.

**Дві пастки, обидві — той самий §2.4, правило 2.**

* **кожна літера ланцюжка — окремий РЯДОК шаблону**, а не спан у спільному
  рядку: усі 10 літер мають однакову базову лінію. Спец із одного рядка на
  десять сегментів дав би накладання;
* **три варіанти відповіді на стор. 3 теж окремі рядки** зі спільною базовою
  лінією (x = 120, 227, 343). Рядки розміщуються **незалежно**, тож захист від
  накладання між ними не працює — довжину доводиться тримати самому. «Це було
  погано.» не влізло в 107 pt між варіантами; «Було погано.» влізло.

**Контурні написи** (стор. 4, 6, 8) — `Arial-Black` у режимі обведення. У
шаблоні режим не зберігається, тож його треба ставити явно: `'render': 1` для
блока або четвертим елементом сегмента, коли контурні лише частина рядків.

---

## Пунктирний текст — механізм готовий

`puzzlekit.dotted_text()` — заміна шрифту `SassoonInfantDtB`, якого немає з
кирилицею. Потрібен для рівнів 0 і 1 (L0 стор. 2, L1 стор. 1 і 8).

Дві речі, які довелося зʼясувати дослідом.

**Крапки роблять штрихом нульової довжини з круглим наконечником**
(`1 J` + `[0.01 gap] 0 d`), а не короткою рискою. Риска дає дрібні рисочки, з
яких літера не читається; нульовий штрих із круглим наконечником дає рівне
коло діаметром у товщину лінії.

**Пунктир не виставляється через API** — `insert_text` його не знає. Але
PyMuPDF дописує кожен виклик **окремим потоком вмісту**, тож достатньо
поставити оператори на початок саме цього потоку: вони діють на все обведення
в ньому й ні на що більше. Знайти потік просто — порівняти `page.get_contents()`
до і після виклику.

**Шрифт.** З 94 системних шрифтів із повною українською кирилицею за
характером найближчий — **SF NS Rounded**: округлий, простий, без засічок.
Comic Sans і Chalkboard теж підходять за настроєм, але помітно ширші й
неохайніші в пунктирі.

**Щільність** підібрано порівнянням із оригіналом на 55 pt: діаметр крапки
0.024 кегля, крок 0.069 кегля. Густіше — літера зливається в лінію, рідше —
розсипається.

Одна відмінність лишається свідомо: Sassoon-Dotted малює **скелет** літери
однією лінією, а ми обводимо **контур** гліфа, тобто дві лінії на штрих. На
вигляд це звичайне українське прописне завдання «обведи по крапках».

---

## Level1_A1 — пройдено наскрізь до `uk/print`

Файл: `lessons/uk/print/Level1_A1_UA_v05.pdf`, 8 сторінок, 1 375 КБ
(оригінал 1 302 КБ). 144 із 204 блоків, латиниці поза брендом немає,
зауважень збірки нуль.

Перший буклет, де знадобився **пунктирний текст**: вірш на обкладинці
(35 pt) і два слова в Івана 3: 16 («вірує», «вічне життя»). Працює як
задумано — читається і виглядає як звичайне прописне завдання.

**Пастка обкладинки, яку §1.3 передбачав дослівно.** Блок `p0b0` — «level 1»
кеглем 75 pt **білим по білому**, тобто невидимий. Якби я його переклав і
намалював, на порожньому місці зʼявилося б сміття. Ознака в збірці була одразу:
`width 694 > 566`, тобто напис не влазить навіть у сторінку. Правильно —
`{'drop': True}`. Такий самий блок є в рівнях 3 і 4, там я його просто не
перекладав; варто перевіряти його в кожному буклеті.

**Пунктирне слово в рядку не займає місця.** Воно малюється окремо, вже після
набору, тож хвіст рядка треба зсувати явним `x`, інакше він наїде на слово.
Зсув рахується від ширини тексту перед словом — жорсткі координати оригіналу
не годяться, бо український текст іншої довжини:

```python
def _after(x0, before, word, size=26.0, pad=8.0):
    return (x0 + _BOLD_F.text_length(before, fontsize=13)
            + _ROUND_F.text_length(word, fontsize=size) + pad)
```

**Координати сіток у кожного рівня свої.** Ряд клітинок 17×2 на стор. 7 тут
має крок 27.34 і початок (57.2, 645.3), а не (57.2, 579.7) з рівня 2 —
скопійовані значення поставили сітку поверх інструкції, а стара лишилася під
нею. Міряти треба щоразу.

**Ребус Івана 3: 16** зберігся: серце заміняє «полюбив», глобус — «світ»,
велика «1» — «єдиного». Перший сегмент рядка довелося зсунути з 131 на 140,
бо «1» кеглем 56 pt заходить праворуч до x = 135.

---

## Level0_A1 — пройдено наскрізь до `uk/print`

Файл: `lessons/uk/print/Level0_A1_UA_v02.pdf`, 4 сторінки, 975 КБ
(оригінал 891 КБ). 56 із 62 блоків, зауважень збірки нуль.

Найкоротший буклет і найшвидший: усі механізми вже були готові. Два завдання
з тексту — контурний вірш на розмальовку (`render: 1`) і пунктирний напис
«дуже добре» для обведення. Решта сторінки — малювання й «зʼєднай крапки»,
які перекладу не потребують.

**Блоки `Adult Guidance` перекладено.** Це вказівки дорослому, який веде
заняття; вони надруковані на сторінці й потрібні читачеві. У рівнях 3–4 такий
блок ділить один текстовий блок із «READ», тож помічник `guidance()` уміє
обидві форми.

**Пастка, що коштувала мовчазної втрати даних.** Невидимий білий напис
«level 0» стирати **не можна**. Він повернутий на 90°, тож його прямокутник —
висока смуга вздовж правого краю сторінки (490…591 × 595…814), і редагування
проковтнуло **бокс балів `/ 10`**, який стоїть усередині неї.

Помітити це на око майже неможливо: зникає не текст, а маленька позначка на
краю. Знайшлося лише порівнянням переліку боксів балів у оригіналі й
результаті — і виявилося, що **той самий дефект уже був у Level1_A1**, де
зник `/ 1`. Обидва виправлено: блок лишається недоторканим.

Звідси перевірка, яку варто додати в `qa.py` для всієї партії: **перелік
боксів балів у результаті має збігатися з оригіналом**. Бали — це облік
учителя, і мовчазна втрата однієї позначки псує сторінку непомітно.

---

## Серія A1 — готова

| Буклет | Файл | Стор. | Блоків | Розмір |
|---|---|---|---|---|
| Level0_A1 | `Level0_A1_UA_v02.pdf` | 4 | 56/62 | 891 → 975 КБ |
| Level1_A1 | `Level1_A1_UA_v06.pdf` | 8 | 144/204 | 1 302 → 1 375 КБ |
| Level2_A1 | `Level2_A1_UA_v02.pdf` | 8 | 178/241 | 1 651 → 1 800 КБ |
| Level3_A1 | `Level3_A1_UA_v06.pdf` | 8 | 207/252 | 1 379 → 1 514 КБ |
| Level4_A1 | `Level4_A1_UA_v07.pdf` | 8 | 169/224 | 522 → 690 КБ |

Усі п'ять у `lessons/uk/print/`, латиниці поза брендом немає, зауважень
збірки нуль.

---

## Скіл 3 — інтерактивний шар, серія A1

Файли: `lessons/uk/interactive/Level{0..4}_A1_UA_v01.pdf`. Круговий тест
пройдено на всіх п'яти: заповнили програмно всі поля, зберегли, відкрили,
зчитали — розбіжностей немає. Перетинів полів немає, дублікатів імен немає,
жодне поле не сидить на боксі балів.

| Рівень | Полів | Розклад |
|---|---|---|
| 0 | 36 | `paint` 34, `text` 2 |
| 1 | 81 | `paint` 53, `ws` 13, `text` 11, `area` 4 |
| 2 | 196 | `paint` 104, `ws` 42, `text` 28, `done` 9, `choice` 7, `area` 6 |
| 3 | 152 | `ws` 64, `text` 30, `char` 29, `choice` 13, `area` 7, `done` 5, `bool` 4 |
| 4 | 252 | `char` 113, `ws` 64, `text` 52, `area` 9, `choice` 8, `bool` 4, `done` 2 |

**Що довелося виправити в детекторі.**

* **фірмовий колір рівня був зашитий** (`0xEA515A`, рівень 2). На рівнях 3 і 4
  варіанти відповіді набрані зеленим і синім, тож детектор не знаходив жодного:
  на Level4_A1 було 4 `choice` замість 24. Тепер колір береться з `lessons.py`
  за номером рівня в імені файла;
* **рамка з підписом ЛІВОРУЧ** («День 1: [____]», «Людям — [____]») відкидалася
  як «рамка, заповнена текстом». Через це завдання лишалося без полів, а
  перелік слів поруч ставав «варіантами вибору» — бо писати нібито не було
  куди. Додано різновид `sided`: поле стає в порожню праву частину;
* **пропуск буває крапками, а не лише підкресленнями.** У рівні 4 вживають
  «................», і без цього детектор знову вважав, що писати нікуди;
* **крапки в підказках кросворда — це не пропуски.** Якщо в завданні вже є
  сітка клітинок, відповідь пишеться в сітку, а крапки в тексті підказки
  полів не отримують;
* **клітинки з крапкою** («розфарбуй клітинки з крапкою») — ряд із
  надрукованими літерами, який не є філвордом. Раніше відкидався; тепер кожна
  клітинка стає чекбоксом, як у філворді. Це друга половина пункту 2 беклогу:
  механізм був, бракувало правила. У рівнях 0 і 1 маркера `Q:` немає, тож
  інструкцію шукаємо в найближчому рядку **над** ґраткою.

**Пастка, спільна для Скіла 2 і Скіла 3.** Літери філворда стояли на
англійських координатах — на місці лівого краю чужого гліфа. Ширини різні,
тож центри «пливли» на кілька пунктів. На друку це виглядало неохайно, а
детектор, який міряє крок **між центрами**, розсипав сітку: на Level4_A1 із
восьми рядів розпізнавалися чотири, і половина філворда лишалася без полів.
Виправлено в `puzzlekit.centre_in_cells()` — літери центруються в клітинках;
після цього 64 клітинки з 64.

**Що лишається слабким.**

* **рівень 0 — 36 полів на 4 сторінки.** Там майже все — малювання й
  обведення, тож це очікувано. Але контурний вірш і пунктирний напис детектор
  бачить як `paint` (розфарбувати літеру), тобто на екрані дитина заллє літеру
  кольором замість обвести. Функційно це працює, за задумом — ні. Рішення
  продуктове: лишити як є чи позначити такі завдання як «тільки для друку»;
* **рівень 1, стор. 7** лишилася в дайджесті: сітка 17×2 полів не отримує — і
  правильно, бо відповідь пишеться в клітинки **під** нею, а вони поля мають.
  Але дайджест цього не розрізняє й далі проситиме подивитися очима.
