# -*- coding: utf-8 -*-
"""Український текст для Level 4 A1 — «Створення світу».

Ключі — `p<сторінка>b<блок>`, як їх дає `extract.py`.
Специфікації:
    {'flow': ...}   — абзац з автопереносом ({sN} перемикає стиль)
    {'lines': [...]}— зберегти сітку рядків: рядок → сегменти (текст, стиль[, x])
    {'drop': True}  — тільки стерти

Біблійні цитати — переклад Турконяка (УБТ, 2020), рішення замовника від
6 серпня; діє на всі буклети серії.

Не перекладається: бренд `bibletime`, `bes`, `www.besweb.com`, реєстраційні
дані, номери сторінок, бокси балів, імена персонажів (B.E.S., Q, Pause, Beam).
Маркер завдання лишається «Q:» — це та сама літера, що на футболці персонажа
Q, який ставить запитання; заміна на «З:» розірвала б звʼязок із малюнком.
"""

TR = {}
POST = []
WIPES = []


def Q(key, *text_lines, qs=0, ts=1, tail=()):
    """Блок завдання.

    У шаблоні «Q:» — це **окремий рядок**, який ділить базову лінію з першим
    рядком тексту. Тому одному рядку шаблону має відповідати рівно один
    сегмент (§2.4, правило 2), інакше рядки наїжджають один на одного —
    саме на цьому збірка v01 і посипалася в 42 блоках.

    `tail` — рядки після тексту (напр. «1.» під запитанням).
    """
    TR[key] = {'lines': [[('Q:', qs)]] + [[(t, ts)] for t in text_lines]
               + [[seg] for seg in tail]}


def N(key, num, *text_lines, s=0):
    """Нумерований пункт: номер — теж окремий рядок на спільній базовій лінії."""
    TR[key] = {'lines': [[(num, s)]] + [[(t, s)] for t in text_lines]}


def rows(key, *text_lines, s=0):
    """Кілька рядків одного стилю, по одному сегменту на рядок."""
    TR[key] = {'lines': [[(t, s)] for t in text_lines]}


def header_small(page, block, with_name=False):
    """Шапка сторінок 2–8: bible|time, підпис рівня, номер серії."""
    lines = []
    if with_name:
        lines.append([("Ім'я:", 0)])
    i = 1 if with_name else 0
    lines.append([('bible', i), ('time', i + 1)])
    lines.append([('Рівень 4 — біблійні історії', i + 2)])
    lines.append([('A1', i + 3)])
    TR[f'p{page}b{block}'] = {'lines': lines}


# ═══════════════════════════════════════════════════════════ сторінка 1
TR['p0b0'] = {'lines': [
    [('bible', 0), ('time', 1)],
    [('www.besweb.com', 2)],
    [('Рівень 4 — біблійні історії', 3)],
    [('A1', 4)],
]}
TR['p0b1'] = {'lines': [[('Рівень 4', 0)]]}
rows('p0b2', 'Впиши тут своє імʼя та адресу.', 'Вік:', "Ім'я:", 'Адреса:')
TR['p0b2']['lines'][1][0] = ('Вік:', 1)
TR['p0b2']['lines'][2][0] = ("Ім'я:", 1)
TR['p0b2']['lines'][3][0] = ('Адреса:', 1)
rows('p0b3', 'Учитель:', 'Переклад Біблії, яким виконано урок:')
TR['p0b4'] = {'lines': [[('ТЕМА 1:', 0), (' Створення світу', 1)]]}
TR['p0b5'] = {'lines': [[('На початку', 0)]]}
TR['p0b7'] = {'lines': [
    [('КЛЮЧОВІ ВІРШІ:', 0)], [('Євреїв 1: 10', 1)], [('Ісаї 45: 18', 1)]]}
TR['p0b9'] = {'lines': [[('ЧИТАЙ:', 0)], [('Буття 1: 1-31', 1)]]}
TR['p0b12'] = {'flow': 'Богові знадобилося лише шість днів, щоб створити все!'}
Q('p0b13',
  'Нижче — перелік того, що створив Бог.',
  'Запиши кожне поруч із днем, коли воно було створене.')
TR['p0b14'] = {'lines': [[('моря      сонце      дерева й рослини      риби      птахи      місяць', 0)]]}
TR['p0b15'] = {'lines': [[('день      суша      ніч      зорі      людина      небо (в. 8)', 0)]]}
for _i, _b in enumerate(range(16, 22), start=1):
    TR[f'p0b{_b}'] = {'lines': [[(f'День {_i}:', 0)]]}
TR['p0b22'] = {'flow': 'У першому розділі Буття деякі слова повторюються знову і знову. '
                       'Це показує, що вони важливі.'}
Q('p0b23',
  'Уважно прочитай розділ і випиши два вислови або твердження,',
  'які повторюються постійно.')
TR['p0b24'] = {'center': True, 'lines': [
    [('«Ти, Господи, на початку заснував', 0)],
    [('землю, і небеса — це діла', 0)],
    [('Твоїх рук».', 0)],
    [('Євреїв 1: 10', 1)],
]}

# ═══════════════════════════════════════════════════════════ сторінка 2
TR['p1b1'] = {'lines': [[('УСЬОГО:', 0)]]}
header_small(1, 2)
TR['p1b7'] = {'flow': 'Цей перший розділ Біблії дуже важливий, бо:'}
TR['p1b8'] = {'flow': (
    '1. Бог лише промовив — і за Його наказом постали світ і все живе.\n'
    'Це тому, що {s1}Бог всемогутній.{s0}\n'
    '2. Усе, що Він створив, було досконале, і Бог бачив, що це добре.\n'
    '3. Богові знадобилося лише шість днів, щоб створити все.\n'
    '4. Кожна форма життя може відтворювати лише свій вид. Слова першого розділу '
    'Буття спростовують багато теорій та ідей, вигаданих, щоб пояснити, звідки '
    'узялися світ і життя. Кожну форму життя Бог створив окремо.')}
Q('p1b9', 'КРОСВОРД')
TR['p1b10'] = {'flow': 'Вершиною творіння стало створення людини.'}
Q('p1b11', 'Склади слова з переставлених літер і доповни те, що сказав Бог:')
TR['p1b12'] = {'lines': [[('заброом           юбоподо           мабири           махатпи', 0)]]}
TR['p1b13'] = {'lines': [[('Бог сказав: «Створімо людину за Нашим ................. і за Нашою .................. ,', 0)]]}
TR['p1b14'] = {'lines': [[('і хай панують над ................. моря, і над ................. неба, і над худобою,', 0)]]}
TR['p1b15'] = {'lines': [[('і над усіма плазунами, що плазують по землі».', 0)]]}
Q('p1b16', 'Із того, що сказано у вірші 26, — чим ми відрізняємося від тварин?')
Q('p1b17',
  'Подивися на ключові вірші. У другому з них Бог заявляє, що Він —',
  'єдиний Бог. Випиши слова, якими Він це стверджує.')
TR['p1b18'] = {'flow': (
    'Багато хто думає, що перші розділи Буття — єдине місце в Біблії, де можна '
    'прочитати про створення світу. Це не так. Є багато інших уривків — і в '
    'Старому, і в Новому Заповіті, — які пояснюють творіння. (Дивись нижче.)')}
rows('p1b19', 'Радимо прочитати також:',
     '• Псалом 24: 1-2 •  Колосян 1: 15-19 • Євреїв 11: 1-3')
# Підказки кросворда. Кількість пропусків тут навмисно не проставлена: вона
# залежить від українських відповідей і буде виставлена разом із перемальованою
# сіткою (див. TODO у звіті).
TR['p1b25'] = {'lines': [
    [('ПО ВЕРТИКАЛІ', 0)],
    [('1. «Нехай земля', 1)],
    [('вродить дерева,', 1)],
    [('що приносять', 1)],
    [('_ _ _ _ ». (в. 11)', 1)],
]}
rows('p1b26', '2. «І Бог по_ _ _ _ _ _ _ _ _', 'їх». (в. 28)')
rows('p1b27', '3. Те, що Бог', 'створив. (в. 3)')
TR['p1b28'] = {'lines': [
    [('ПО ГОРИЗОНТАЛІ', 0)],
    [('3. Це було в кожній', 1)],
    [('живій істоті, яку', 1)],
    [('створив Бог. (в. 30)', 1)],
]}
rows('p1b29', '4. «_ _ _ Божий', 'ширяв над', 'водою».', '', '(в. 2)')
rows('p1b30', '5. «Нехай птахи', 'літають над', '_ _ _ _ _ _ ».', '(в. 20)')

# ═══════════════════════════════════════════════════════════ сторінка 3
header_small(2, 1, with_name=True)
TR['p2b3'] = {'lines': [[('Радимо прочитати також: • Вихід 20: 8-11 • Псалом 103: 14 • Колосян 1: 16', 0)]]}
TR['p2b4'] = {'flow': (
    'Перша книга Біблії, як ми вже бачили, називається Буття, що означає '
    '«початки». Це дуже влучна назва, бо в першому розділі ми прочитали про '
    'перший день, перше життя, першу людину і перші Божі слова до людини, '
    'яку Він створив.')}
Q('p2b5', 'КРОСВОРД')
TR['p2b6'] = {'flow': (
    'Отже, Бог був єдиним Творцем землі. Жодна інша сила не була до цього '
    'причетна, і саме тому все було досконале й повністю завершене!')}
Q('p2b7', 'Який вірш 2-го розділу каже, що Бог освятив сьомий день?')
Q('p2b8', 'Чому Він це зробив?')
Q('p2b9',
  'Випиши перше речення заповіді, яку Бог дав Мойсеєві і яка нагадує',
  'нам, якої ваги Бог надав сьомому дню. (Дивись Вихід 20: 8.)')
TR['p2b10'] = {'lines': [[('ТЕМА 2:', 0), (' Створення світу', 1)]]}
TR['p2b11'] = {'lines': [[('Завершене Богом', 0)]]}
TR['p2b13'] = {'lines': [[('КЛЮЧОВІ ВІРШІ:', 0)], [('Івана 1: 1-3', 1)]]}
TR['p2b15'] = {'lines': [
    [('ЧИТАЙ:', 0)], [('Буття 1: 27-31', 1)], [('2: 1-9', 1)]]}
TR['p2b25'] = {'lines': [
    [('ПО ГОРИЗОНТАЛІ', 0)],
    [('3. Бог ............ людину за', 1)],
    [('Своїм образом.', 1)],
]}
TR['p2b26'] = {'lines': [[('5. Остання частина дня.', 0)]]}
rows('p2b27', '6. День, коли творіння було', 'завершене.')
TR['p2b28'] = {'lines': [
    [('ПО ВЕРТИКАЛІ', 0)],
    [('1. Бог створив ............ і', 1)],
    [('жінку.', 1)],
]}
rows('p2b29', '2. Бог відпочив ............... дня.', '')
rows('p2b30', '4. Бог створив дерева, щоб вони', 'давали це ................. (в. 29)')

# ═══════════════════════════════════════════════════════════ сторінка 4
TR['p3b1'] = {'lines': [[('УСЬОГО:', 0)]]}
header_small(3, 2)
TR['p3b7'] = {'flow': (
    'Решта біблійного читання (розділ 2: 1-9) дає нам більше подробиць про '
    'Боже творіння.')}
Q('p3b8',
  'Запиши відповіді на подані запитання, а потім обведи їх у ФІЛВОРДІ.',
  'Слова заховані вгору, вниз, вперед, назад і по діагоналі.')
Q('p3b15', 'Які два особливі дерева згадано у вірші 9?', tail=[('1.', 2)])
TR['p3b16'] = {'lines': [[('2.', 0)]]}
Q('p3b17',
  'Подивись на ключові вірші й зверни увагу: Євангеліє від Івана',
  'починається так само, як 1-й розділ Буття. Тут пояснено, що Слово',
  'Боже, яке є Божим Сином, було Творцем. Встав ці слова у пропуски,',
  'щоб показати, про що говорять ключові вірші:')
TR['p3b18'] = {'lines': [[('Бог  Слово  постало  ніщо  початку  Бога  постало  початку', 0)]]}
TR['p3b19'] = {'lines': [[('«На ____________ було Слово, і _________ було в ______ ,', 0)]]}
TR['p3b20'] = {'lines': [[('і Слово було ____________ .', 0)]]}
TR['p3b21'] = {'lines': [[('Воно було в Бога на ______________ .', 0)]]}
TR['p3b22'] = {'lines': [[('Усе через Нього ___________ ,', 0)]]}
TR['p3b23'] = {'lines': [[('і без Нього ______________ не постало, що ___________ ».', 0)]]}
Q('p3b24', 'Хто є тим Словом, про яке тут ідеться?')
TR['p3b25'] = {'flow': (
    'Це ще одне нагадування про велич творіння. Тут сказано, що Бог Син '
    'створив усе. Нам варто частіше зупинятися і хвалити Бога, коли ми бачимо '
    'чудеса творіння у квітах, тваринах і краєвидах нашого прекрасного світу. '
    'Як сумно, що ми багатьма способами зіпсували досконале Боже творіння.')}

# ═══════════════════════════════════════════════════════════ сторінка 5
header_small(4, 1, with_name=True)
TR['p4b2'] = {'lines': [[('ТЕМА 3:', 0), (' Створення світу', 1)]]}
TR['p4b3'] = {'lines': [[('Гріх входить у світ', 0)]]}
TR['p4b5'] = {'lines': [
    [('КЛЮЧОВІ ВІРШІ:', 0)], [('Римлян 3: 23', 1)], [('6: 23', 1)]]}
TR['p4b7'] = {'lines': [
    [('ЧИТАЙ:', 0)], [('Буття 2: 14-19', 1)], [('3: 1-7', 1)]]}
rows('p4b12',
     'Радимо прочитати також: • Римлян 5: 12-14, 18 і 19  •  1 Тимофія 2: 13 і 14',
     '• Якова 1: 14 і 15')
TR['p4b13'] = {'flow': 'Ця тема допоможе нам зрозуміти, що сталося після створення людей.'}
Q('p4b14',
  'У розділі 2: 15 сказано, який обовʼязок Бог дав Адамові в Едемському',
  'саду. Який саме?')
Q('p4b15', 'Напиши ПРАВДА або НЕПРАВДА до кожного твердження:')
TR['p4b16'] = {'lines': [[('• Бог сказав, що Адам може їсти плоди з кожного дерева в саду.', 0)]]}
rows('p4b17',
     '• Бог сказав, що їсти з дерева пізнання добра і зла означатиме',
     'смерть.')
TR['p4b18'] = {'lines': [[('• Бог дозволив Адамові дати імена всім птахам і тваринам.', 0)]]}
TR['p4b19'] = {'lines': [[('• Бог сказав, що Адамові краще жити в Едемському саду самому.', 0)]]}
Q('p4b20', 'Впиши пропущені слова в СІТКУ СЛІВ.')
N('p4b21', '1.', 'Жінка відповіла, що вони можуть їсти плоди з _ _ _ _ _ (в. 2).')
N('p4b22', '2.', 'Істота, що підійшла до жінки (Єви), була хитріша за')
TR['p4b23'] = {'lines': [[('всіх інших, яких _ _ _ _ _ _ _ Господь Бог.', 0)]]}
N('p4b24', '3.', 'Адам і Єва були в _ _ _ _ Едемському.')
N('p4b25', '4.', 'Їхні очі (ЛИСЯВІДКРИ) — і вони зрозуміли,')
TR['p4b26'] = {'lines': [[('що нагі. Склади слово з переставлених літер.', 0)]]}
N('p4b27', '5.', 'Вони зшили фігове _ _ _ _ _ .')
N('p4b28', '6.', 'Адам був Євиним _ _ _ _ _ _ _ _ .')
N('p4b29', '7.', 'І чоловік, і жінка виявилися')
TR['p4b30'] = {'lines': [[(' _ _ _ _ _ _ _ _ _ _ до Божої заповіді.', 0)]]}
Q('p4b31',
  'Прочитай по сітці, яка істота спокусила жінку',
  'не послухатися Бога.')

# ═══════════════════════════════════════════════════════════ сторінка 6
TR['p5b1'] = {'lines': [[('УСЬОГО:', 0)]]}
header_small(5, 2)
TR['p5b6'] = {'flow': 'Змій був дияволом (якого ще звуть сатаною) у подобі тварини.'}
Q('p5b7',
  'Підкресли два твердження, які найкраще описують те, що сатана',
  'зробив першим чоловікові й жінці.')
TR['p5b8'] = {'lines': [[('Він благословив їх.      Він обманув їх.      Він допоміг їм.      Він збрехав їм.', 0)]]}
Q('p5b9',
  'Знайди Івана 8: 44 і напиши СВОЇМИ СЛОВАМИ, як Господь Ісус',
  'описує сатану.')
TR['p5b10'] = {'flow': (
    'Ми нічим не відрізняємося від перших людей, бо так само не слухаємося '
    'Божих заповідей і йдемо своїм шляхом, як і вони.')}
Q('p5b11',
  'Випиши перший ключовий вірш і підкресли слова, якими Бог описує',
  'наслідок гріхів, що їх ми всі скоїли.')
Q('p5b12', 'Познач визначення, яке НАЙКРАЩЕ пояснює, що таке гріх.')
TR['p5b13'] = {'lines': [[('Гріх — це все, за що людину можуть посадити до вʼязниці.', 0)]]}
TR['p5b14'] = {'lines': [[('Гріх — це зло, яке робили люди за біблійних часів.', 0)]]}
TR['p5b15'] = {'lines': [[('Гріх — це непослух Богові й невідповідність Його досконалій мірі.', 0)]]}
TR['p5b16'] = {'lines': [[('Гріх — це дрібні помилки, які ми робимо в житті.', 0)]]}
Q('p5b17',
  'Випиши другий ключовий вірш і добре подумай, про що він каже.',
  'Обведи слово, яке говорить про кару за гріх.',
  'Воно нагадує про Божу кару, якої нам усім не минути через наш гріх, —',
  'якщо ми не довіримося Господу Ісусу й не приймемо Його дар вічного життя.')
rows('p5b18',
     'Ці вірші кажуть, що ми маємо обрати',
     'або «заплату за гріх», або «дар',
     'вічного життя».')

# ═══════════════════════════════════════════════════════════ сторінка 7
header_small(6, 1, with_name=True)
TR['p6b2'] = {'lines': [[('ТЕМА 4:', 0), (' Створення світу', 1)]]}
TR['p6b3'] = {'lines': [[('Наслідки гріха', 0)]]}
TR['p6b5'] = {'lines': [
    [('КЛЮЧОВІ ВІРШІ:', 0)], [('1 Коринтян 15: 22', 1)], [('Римлян 6: 23', 1)]]}
TR['p6b7'] = {'lines': [[('ЧИТАЙ:', 0)], [('Буття 3: 7-24', 1)]]}
TR['p6b12'] = {'lines': [[('Радимо прочитати також: • Екклезіяста 12: 1   • Римлян 5: 12-23', 0)]]}
TR['p6b13'] = {'flow': 'Гріх завжди буде покараний, і перший гріх Адама та Єви не став винятком.'}
TR['p6b14'] = {'flow': (
    '{s0}«І відкрилися очі їм обом».{s1} (Вірш 7) Це не означає, що доти вони ходили '
    'із заплющеними очима! У вірші 22 Бог пояснює, що саме вони тепер «бачать» — '
    'те, чого не бачили раніше.')}
Q('p6b15', 'Що, за словами Бога у вірші 22, вони тепер знають?')
Q('p6b16', 'Як Адам і Єва повелися, коли їхні очі відкрилися? (Вірш 7)', ts=0)
Q('p6b17',
  'Що вони зробили, коли почули голос Господа Бога, який ходив',
  'по саду?', ts=0)
Q('p6b18', 'Яке запитання поставив Бог? (Дивись вірш 9.)')
Q('p6b19',
  'Бог запитав не тому, що не знав відповіді. Він хотів, щоб вони самі',
  'визнали свій вчинок. Але вони визнали його лише наполовину, бо',
  'ніхто з них не хотів брати на себе відповідальність за скоєне.', ts=0)
TR['p6b20'] = {'lines': [[('Кого звинуватив Адам?', 0)]]}
TR['p6b21'] = {'lines': [[('Кого звинуватила Єва?', 0)]]}
TR['p6b22'] = {'flow': (
    'Інколи ми буваємо трохи схожі на Адама та Єву: намагаємося перекласти '
    'провину за свій гріх на когось іншого. Але Бога не обманеш! Він виніс '
    'вирок і Адамові, і Єві, а також змієві — за те, що вони зробили.')}

# ═══════════════════════════════════════════════════════════ сторінка 8
TR['p7b0'] = {'lines': [[('Бали', 0), (' (вписує вчитель)', 1)]]}
for _i in range(1, 5):
    TR[f'p7b{_i}'] = {'lines': [[(f'ТЕМА {_i}:', 0)]]}
TR['p7b5'] = {'lines': [[('Разом', 0)]]}
TR['p7b6'] = {'lines': [[('Загалом', 0)]]}
rows('p7b7', 'Коментар учителя:', 'Надішли свої уроки на адресу:')
TR['p7b8'] = {'lines': [[('УСЬОГО:', 0)]]}
TR['p7b9'] = {'lines': [
    [('©', 0), (' Bible Educational Services. Відвідай ', 1), ('www.besweb.com', 2),
     (' або телефонуй +44 (0) 28 6632 2462.', 1)],
    [('Registered Charity UK CIO 1186004', 1)],
    [('РІВЕНЬ 4 A1', 3)],
    [('01/2025', 4)],
]}
Q('p7b12',
  'Знайди у віршах 23 і 24 слова, які підходять у пропуски в реченнях',
  'нижче.')
TR['p7b13'] = {'lines': [[('І ............... ............................... його Господь Бог із раю Едемського,', 0)]]}
TR['p7b14'] = {'lines': [[('щоб .............. землю, з якої він був узятий. І вигнав Він людину, і поставив', 0)]]}
TR['p7b15'] = {'lines': [[('на схід від раю Едемського ............................... і ....................  .....................', 0)]]}
TR['p7b16'] = {'lines': [[('що обертався, аби охороняти дорогу до дерева ................. .', 0)]]}
TR['p7b17'] = {'lines': [
    [('', 0), ('Ключові вірші', 1), (' пояснюють, як гріх Адама та Єви впливає на нас і сьогодні.', 0)],
]}
Q('p7b18', 'Що стається з усіма, хто «в Адамі»? (1 Коринтян 15: 22)')
Q('p7b19', 'У тому самому вірші — що стається з усіма, хто «у Христі»?')
TR['p7b20'] = {'lines': [[('Бути «в» Адамі чи у Христі означає бути поєднаним з Адамом або з Христом.', 0)]]}
Q('p7b21', 'Як у Римлян 6: 23 названо смерть?')
Q('p7b22', 'А як названо вічне життя?')
Q('p7b23', 'Хто є єдиним, через кого ми можемо мати вічне життя?')
TR['p7b24'] = {'flow': (
    'Ці теми показують, що ми, як Адам і Єва, усі згрішили.\n'
    'Їм довелося понести власну кару.\n'
    'Господь Ісус помер на хресті, щоб понести нашу кару.\n'
    'Ми приймаємо Його як Спасителя — і нам прощено!')}
TR['p7b25'] = {'center': True, 'lines': [
    [('«Віруй у Господа Ісуса —', 0)],
    [('і будеш спасенний».', 0)],
    [('Дії 16: 31', 1)],
]}


# ═══════════════════════════════════════════════════════════ філворд, стор. 4
#
# Літери сітки — це звичайні текстові спани з відомими x, тож український
# філворд підставляється в ті самі позиції; перемальовувати нічого не треба.
# Форма рядків у шаблоні нерівна (десь 8 спанів в одному рядку, десь 7+1),
# тому спец будується з самого шаблону, а не вгадується.
import json as _json                                            # noqa: E402
import random as _random                                        # noqa: E402
import os as _os                                                # noqa: E402

_WS_ROWS = [f'p3b{i}' for i in range(26, 34)]
ALPHABET = 'АБВГДЕЄЖЗИІЇЙКЛМНОПРСТУФХЦЧШЩЮЯ'
ALL_DIRS = [(0, 1), (1, 0), (0, -1), (-1, 0), (1, 1), (-1, -1), (1, -1), (-1, 1)]

# Відповіді за Турконяком, Буття 2: 7-9. Довжина найдовшого — 7, сітка 8×8.
# Вісім слів — рівно вісім пропусків у підказках нижче; порядок той самий.
WS_WORDS = ['СТВОРИВ', 'ПОРОХУ', 'ВДИХНУВ', 'ПОДИХ',
            'НАСАДИВ', 'РАЙ', 'ЕДЕМІ', 'ДЕРЕВО']


def _make_wordsearch(rows, cols, words, seed):
    rnd = _random.Random(seed)
    grid = [[None] * cols for _ in range(rows)]
    for w in sorted(words, key=len, reverse=True):
        for _ in range(40000):
            dr, dc = rnd.choice(ALL_DIRS)
            r, c = rnd.randrange(rows), rnd.randrange(cols)
            er, ec = r + dr * (len(w) - 1), c + dc * (len(w) - 1)
            if not (0 <= er < rows and 0 <= ec < cols):
                continue
            if any(grid[r + dr * i][c + dc * i] not in (None, ch)
                   for i, ch in enumerate(w)):
                continue
            for i, ch in enumerate(w):
                grid[r + dr * i][c + dc * i] = ch
            break
        else:
            raise RuntimeError('не вдалося розмістити ' + w)
    for r in range(rows):
        for c in range(cols):
            if grid[r][c] is None:
                grid[r][c] = rnd.choice(ALPHABET)
    return grid


def _find(grid, word):
    """Програмна перевірка, що слово справді знаходиться (§2.7, п. 4)."""
    R, C = len(grid), len(grid[0])
    for r in range(R):
        for c in range(C):
            for dr, dc in ALL_DIRS:
                er, ec = r + dr * (len(word) - 1), c + dc * (len(word) - 1)
                if 0 <= er < R and 0 <= ec < C and all(
                        grid[r + dr * i][c + dc * i] == ch
                        for i, ch in enumerate(word)):
                    return True
    return False


def _fill_grid():
    here = _os.path.dirname(_os.path.abspath(__file__))
    tpl = _json.load(open(_os.path.join(here, 'work', 'Level4_A1', 'template.json'),
                          encoding='utf-8'))
    idx = {f"p{p['page']}b{b['i']}": b for p in tpl for b in p['blocks']}
    # Вісім слів у сітку 8×8 жадібний алгоритм кладе не з кожного зерна —
    # перебираємо, доки не ляжуть усі, і **перевіряємо результат пошуком**
    # (§2.7, п. 4): інструкція обіцяє, що слова там є.
    for seed in range(1, 2000):
        try:
            grid = _make_wordsearch(8, 8, WS_WORDS, seed)
        except RuntimeError:
            continue
        if all(_find(grid, w) for w in WS_WORDS):
            break
    else:
        raise RuntimeError('не вдалося скласти філворд 8×8 із цих слів')
    # Літери центруємо в клітинках: якщо лишити англійські координати, центри
    # «пливуть» на кілька пунктів (ширини гліфів різні), сітка виглядає
    # неохайно, а детектор філворда розсипає її на частини.
    import fitz as _fitz
    from puzzlekit import centre_in_cells
    font = _fitz.Font(fontfile='/System/Library/Fonts/Supplemental/Arial Bold.ttf')
    slots, letters = [], []
    for r, key in enumerate(_WS_ROWS):
        blk = idx[key]
        it = iter(grid[r])
        for li, ln in enumerate(blk['lines']):
            for si, sp in enumerate(ln['spans']):
                slots.append((round(sp['y']), sp['x'], sp['w'], key, li, si))
                letters.append(next(it))
    xs = centre_in_cells(slots, letters, font, 14.0)
    pos = 0
    for r, key in enumerate(_WS_ROWS):
        blk = idx[key]
        rows_out = []
        for li, ln in enumerate(blk['lines']):
            segs = []
            for si, sp in enumerate(ln['spans']):
                segs.append((letters[pos], sp['s'], xs[key][(li, si)]))
                pos += 1
            rows_out.append(segs)
        TR[key] = {'lines': rows_out}


_fill_grid()

# Підказки філворда: кожне запитання дає слово із сітки.
rows('p3b9',  '1. Господь Бог с _ _ _ _ _ _ людину.')
rows('p3b10', '2. Він створив людину з п _ _ _ _ _ земного.')
rows('p3b11', '3&4. Він в _ _ _ _ _ _ у її обличчя п _ _ _ _ життя.')
rows('p3b12', '5&6. Господь Бог н _ _ _ _ _ _  р _ _ .', '(в. 8)')
rows('p3b13', '7. Він був на сході, в  Е _ _ _ _ .')
rows('p3b14', '8. Там Він зростив із землі всяке',
     'д _ _ _ _ _ , гарне на вигляд.')


# ═══════════════════════════════════════════════ кросворди й сітка слів
#
# Сітки в оригіналі намальовані векторами під англійські довжини слів, тому
# переносяться не координати, а **механіка**: стару сітку закриваємо, нову
# складаємо генератором під українські відповіді (§2.6).
from puzzlekit import (cover, draw_cells, draw_grid, draw_rows,   # noqa: E402
                       extent, number, place_crossword)

BLUE = (0.18799, 0.33500, 0.63799)      # фірмовий колір рівня 4, як у сітках

# Стор. 2, Буття 1. Орієнтацію генератор обирає сам: із жорстким поділом
# «три вниз, три вбік» звʼязний кросворд неможливий — між трьома вертикальними
# й трьома горизонтальними словами лише чотири літерні збіги, а для звʼязності
# шести слів треба щонайменше пʼять. Вільна орієнтація дає повний звʼязок,
# і — за збігом — теж три на три.
P2_WORDS = ['ПЛІД', 'БЛАГОСЛОВИВ', 'СВІТЛО', 'ЖИТТЯ', 'ДУХ', 'ЗЕМЛЕЮ']
P2_AT = (221.9, 229.0)      # стара сітка: 185.9…385.9, нову центруємо в ній
P2_CELL = 18.3

# Стор. 3, Буття 1: 27 — 2: 9.
P3_WORDS = [('СТВОРИВ', 'a'), ('ВЕЧІР', 'a'), ('СЬОМИЙ', 'a'),
            ('ЧОЛОВІКА', 'd'), ('СЬОМОГО', 'd'), ('НАСІННЯ', 'd')]
P3_AT = (80.1, 313.3)
P3_CELL = 18.7

# Стор. 5. Читання по вертикалі не переноситься: SERPENT — сім літер, ЗМІЙ —
# чотири. Рішення замовника від 6 серпня: сім тверджень лишаємо, а відповідь
# «хто спокусив» виноситься в окремі чотири клітинки.
# ДЕРЕВ, СТВОРИВ, РАЮ, ВІДКРИЛИСЯ, ЛИСТЯ, ЧОЛОВІКОМ, НЕПОКІРНІ.
# Найдовше слово — 10 літер: більше в ширину не влазить, бо праворуч
# від сітки стоять бокси балів (x = 511.7).
P5_LENGTHS = [5, 7, 3, 10, 5, 9, 9]
P5_AT = (386.0, 470.0)
P5_CELL = 12.0
P5_ANSWER_AT = (86.5, 739.7)                # ЗМІЙ — 4 клітинки замість 7

COVERS = {
    1: [(180, 222, 392, 437)],                       # кросворд стор. 2 + номери
    2: [(52, 306, 315, 525)],                        # кросворд стор. 3 + номери
    # Сітка слів тягнеться до y=739, а не до 616, як здалося з першого
    # заміру: він був обмежений пробним прямокутником. Міряти габарит
    # треба по ВСІХ клітинках сторінки, а не всередині здогадки.
    4: [(368, 455, 508, 750), (80, 733, 285, 768)],  # сітка слів + ряд відповіді
}


def apply_covers(page):
    """Закрити стару графіку ДО набору тексту (§2.1, правило 1)."""
    rects = COVERS.get(page.number)
    if rects:
        cover(page, rects, WIPES)


def _draw_puzzles(doc, only=None):
    def want(pno):
        return only is None or pno in only

    report = []
    if want(1):
        placed, missed = place_crossword(P2_WORDS, seed=7)
        nums, _, _ = number(placed)
        draw_grid(doc[1], placed, nums, P2_AT, P2_CELL, BLUE)
        report.append(('стор. 2', extent(placed)[2:], missed))
    if want(2):
        placed, missed = place_crossword(P3_WORDS, seed=0)
        nums, _, _ = number(placed)
        draw_grid(doc[2], placed, nums, P3_AT, P3_CELL, BLUE)
        report.append(('стор. 3', extent(placed)[2:], missed))
    if want(4):
        draw_rows(doc[4], P5_AT, P5_CELL, P5_LENGTHS, BLUE, gap=1.5)
        draw_cells(doc[4], P5_ANSWER_AT, 21.7, 4, BLUE, pitch=28.05)
    for name, size, missed in report:
        print(f'  {name}: сітка {size[0]}×{size[1]}'
              + (f', НЕ ЗВʼЯЗАНО: {missed}' if missed else ''))


POST.append(_draw_puzzles)

# ── підказки під нову нумерацію ───────────────────────────────────────────
# Стор. 2: горизонталь 2 ПЛІД, 5 СВІТЛО, 6 ЖИТТЯ; вертикаль 1 БЛАГОСЛОВИВ,
# 3 ДУХ, 4 ЗЕМЛЕЮ. Блоки підказок стоять стовпчиком, тож текст ллється крізь
# них підряд: розрив між блоками читається як порожній рядок між підказками.
rows('p1b25', 'ПО ВЕРТИКАЛІ', '1. «І Бог', '____________ їх».', '(в. 28)', '')
TR['p1b25']['lines'][0] = [('ПО ВЕРТИКАЛІ', 0)]
for _i in range(1, 5):
    TR['p1b25']['lines'][_i] = [(TR['p1b25']['lines'][_i][0][0], 1)]
rows('p1b26', '3. «___ Божий ширяв', 'над водою». (в. 2)')
rows('p1b27', '4. Птахи літають над', '______ . (в. 20)')
TR['p1b28'] = {'lines': [
    [('ПО ГОРИЗОНТАЛІ', 0)],
    [('2. «Дерева, що', 1)],
    [('приносять ____».', 1)],
    [('(в. 11)', 1)],
]}
rows('p1b29', '5. Те, що Бог створив.', '(в. 3)', '', '', '')
rows('p1b30', '6. Це було в кожній', 'живій істоті, яку', 'створив Бог.', '(в. 30)')

# Стор. 3: горизонталь 1 ВЕЧІР, 4 СТВОРИВ, 5 СЬОМИЙ;
# вертикаль 2 ЧОЛОВІКА, 3 НАСІННЯ, 4 СЬОМОГО.
TR['p2b25'] = {'lines': [
    [('ПО ГОРИЗОНТАЛІ', 0)],
    [('1. Остання частина дня.', 1)],
    [('4. Бог ............ людину за', 1)],
]}
rows('p2b26', 'Своїм образом.')
rows('p2b27', '5. День, коли творіння', 'було завершене.')
TR['p2b28'] = {'lines': [
    [('ПО ВЕРТИКАЛІ', 0)],
    [('2. Бог створив ............ і', 1)],
    [('жінку.', 1)],
]}
rows('p2b29', '3. Бог створив дерева, щоб', 'вони давали це ....... (в. 29)')
rows('p2b30', '4. Бог відпочив ............... дня.', '')

# Стор. 5: твердження мають закінчуватися ліворуч від нової сітки.
N('p4b21', '1.', 'Жінка відповіла, що вони можуть їсти плоди з _ _ _ _ _ (в. 2).')
N('p4b22', '2.', 'Істота, що підійшла до жінки (Єви), була хитріша')
TR['p4b23'] = {'lines': [[('за всіх інших, яких _ _ _ _ _ _ _ Господь Бог.', 0)]]}
N('p4b24', '3.', 'Адам і Єва були в _ _ _ Едемському.')
N('p4b25', '4.', 'Їхні очі (ЛИСЯВІДКРИ) — і вони зрозуміли,')
TR['p4b26'] = {'lines': [[('що нагі. Склади слово з переставлених літер.', 0)]]}
N('p4b27', '5.', 'Вони зшили фігове _ _ _ _ _ .')
N('p4b28', '6.', 'Адам був Євиним _ _ _ _ _ _ _ _ _ .')
N('p4b29', '7.', 'І чоловік, і жінка виявилися')
TR['p4b30'] = {'lines': [[(' _ _ _ _ _ _ _ _ _ до Божої заповіді.', 0)]]}
for _k in range(21, 31):
    TR[f'p4b{_k}']['right'] = 372.0
Q('p4b31', 'Яка істота спокусила жінку не послухатися Бога?',
  'Впиши відповідь у клітинки.')
