Головна/Завдання/Частина 3/Запис пакета
Запис пакета: що в ньому лежить і як його читати
Штаб живе записами: своїми локальними, еталонним і заліковими. Формат один і той самий. Тут - що в ньому є, чим його читати і звідки беруться свої записи залікових партій.
1Склад запису
records/
reference/ еталонний запис приймання
match-1.runlog match-2.runlog match-3.runlog
belief-1.ndjson belief-2.ndjson belief-3.ndjson
pack.jsonЛокальний пакет (npm run play) пише таку саму теку (part2/06-local-pack.md, розділ 5). Імена файлів - ті, що перелічені в pack.json, поле matches.
| Файл | Що в ньому |
|---|---|
match-N.runlog | журнал партії N: маніфест, кадри команд усіх місць, зал, епізоди наказу, відмови воротаря |
belief-N.ndjson | щоденник віри бота фокуса в партії N: рядок на такт |
pack.json | зведення пакета: частки, рахунки, статті, жереб, зал, ротація, розміри і sha256 журналів, плюс поле belief - чий щоденник лежить поруч |
2Журнал партії
Журнал - CBOR, сім полів: версія проводу, маніфест як є, склад (чиї рішення записано), кадри команд за тактами сирими байтами, зал (ніки за слотами), епізоди наказу [слот, від, до] і відмови воротаря [слот, такт, номер команди, код]. Усі сім полів описано в частині 2 (part2/04-protocol.md, розділ 10; про відмови - 10.4 і 10.5).
Відмови пишуться заради читача: у кадрі лежить команда, а не відповідь, і вивести причину з кадру не можна. Коди - ті самі, що на проводі (part2/04-protocol.md, 6.6): 1 сміття, 2 стеля, 6 канал, 21 відмова і так далі. Прийняті команди до списку не йдуть, нульового коду не буває.
Бій відмови не змінюють: реплей проганяє ті самі кадри через того самого воротаря і виносить ті самі вердикти сам. Старий запис із шести полів читається як раніше, з порожнім списком відмов.
Байти каналу беруться звідти ж: кадр команд слота на такті - це його довжина в байтах. Команд у кадрі стільки, скільки їх розібрав кодек (decodeOrders у @zoria/protocol).
3Правда світу
Правду рахує рушій, а не запис: журнал несе команди, світ із них виводиться. Курсор із SDK робить це за вас:
import { createEngine } from '@zoria/engine';
import { openJournal } from '@zoria/sdk';
const cursor = openJournal(createEngine, bytes); // bytes - match-N.runlog
cursor.seek(210); // стати на такт 210
const world = cursor.engine.SIM.world; // own, lit, minutes, needles, energy
const result = cursor.summary(); // рахунок, місця, статтіКурсор тримає контрольні точки (за замовчуванням кожні 50 тактів) і перемотує назад стрибком на точку з наздоганянням: перемотування на 300 тактів назад коштує не повної перебудови партії, а наздоганяння від найближчої точки. Число точок і крок - налаштування курсора, не правило світу.
Що читати у світі: world.own - власник голки за сотою, world.lit - вага нитки голки (горить, жарини, вінець), world.minutes - хвилини зв'язку, world.needles - голки, що горять, world.energy - заряд, world.stolen, world.pactTax - здобич і податок. Імена і зміст - правила частини 2.
Журнал іншого рушія або інших чисел світу не відтворюється: курсор відкидає його з кодом ENGINE_MISMATCH або CONFIG_MISMATCH. Це норма після зсуву світу, а не поломка (part2/04-protocol.md, 10.2). Запис сезону зроблено рушієм 264a77c2a5405955f5aba04be240325d65cfe5d25269ae2f7c6a9fc7f4ff0e26.
4Віра бота
Щоденник віри пише ваш бот - рядок NDJSON на такт, форма BeliefFrame (part2/03-sdk.md, розділ 8; вимога P2-05). В еталонному записі він є; у вашому локальному він є, якщо бот його пише.
Чий щоденник лежить у теці, каже поле belief зведення:
"belief": { "seat": 0, "nick": "nazar_k",
"files": ["belief-1.ndjson", "belief-2.ndjson", "belief-3.ndjson"] }seat - місце в порядку roster; слот фокуса в партії N береться як rotations[N-1][seat]. Ніки за слотами тієї партії лежать у залі журналу: зал пакета - порядок учасників, зал журналу - літери A, B, C.
Щоденник дельта-кодований: повний кадр раз на 200 тактів (full: true), решта рядків несуть тільки зміни. Щоб дізнатися віру на такті T, читають останній повний кадр не пізніше T і накочують зміни до T.
| Поле | Що несе |
|---|---|
t | такт |
full | true у повного кадру |
pulse | energy, chan, ear, minutes, needles - прилади такту |
own | віра про володіння голками: сота → літера слота або null (нічийна) |
dark | віра про мовчання голки: сота → true (мовчить) або false |
foe | контакти такту: [ім'я машини, літера слота, q, r] |
units | свої машини: [ім'я, q, r, залишок шляху] |
noisy | скільки шумних плям у кадрі |
pact | літера слота партнера за угодою або null |
cries | кличі такту: [літера слота, номер фрази] |
Щоденник позначає учасника літерою слота цієї партії - A, B або C, - а не ніком; K - Ключник. Нік за літерою дає зал журналу тієї самої партії (4.1): за ротацією в кожній партії пакета в учасника інша літера. Звідти ж драйвер бере нік для якорів cell-owner-truth і cell-owner-belief. Повний кадр несе в own і dark усі голки віри; рядок між повними - тільки соти, що змінилися, тож false у dark знімає мовчання.
Звідси й беруться категорії Ш1: точне - те, що у вірі збігається з правдою на цьому такті; пам'ять - те, що у вірі є, але в правді вже інакше (наприклад, контакт із foe двадцять тактів тому); мовчання - голка, у якої у вірі dark дорівнює true. Четвертої категорії - голки, якої у вірі немає зовсім, - у цьому світі не буває: список голок долини публічний маніфестом, і він приходить кожному ботові до першого такту. Тому Ш1-5 питає мовчання, а не невідомість.
Вік пам'яті про чужу машину - це T мінус такт останнього контакту з нею у foe. Вік пам'яті про голку щоденник окремим полем не несе: голка потрапляє в own у той такт, коли віра про неї змінилася.
5Еталонний запис і пара пресетів
npx zaria-kit records кладе в records шість речей:
| Каталог | Що це |
|---|---|
reference/ | еталонний запис приймання: пакет із трьох партій, рушій 264a77c2a5405955f5aba04be240325d65cfe5d25269ae2f7c6a9fc7f4ff0e26, sha256 1079e82de6ac6ef0c02f3aaf45c33d196c25999605a38e3809c22a82d5e00052 |
records.json | список матеріалу: імена, жереби, частки і sha256 журналів |
preset-a/ | той самий жереб, наш бот на пресеті рівний |
preset-b/ | той самий жереб, наш бот на пресеті обхідник |
hq-ref.html | зібраний бандл нашого штабу: планка кадру (02-hq-tasks.md, 4.2) |
example/ | еталонний пакет частини 2: три архетипи, записані рушієм випуску (part2/06-local-pack.md, розділ 6); у прийманні не бере участі |
На reference/ рахуються задачі Ш1-Ш3 і Ш5 та міряється кадр; на парі preset-a і preset-b - задачі Ш4. Усі три записи відкриваються через господаря показу списком ZARIA_HQ.packs().
Запис один на сезон. Його зроблено після зсуву світу 05.10 (зсув нульовий, доповнення 3), далі він не змінюється; його sha256 публікується разом із драйвером. Матеріал їде в киті готовим: перерахунок на іншій машині зробив би ваше приймання не таким, як наше.
Бот фокуса еталонного запису навмисне пробує заборонені команди - раз на сім тактів подає те, чого зробити не можна. Інакше в записі не було б жодної відмови воротаря: чесна голова звіряє канал перед подачею, - і задачам Ш3-3 і Ш3-4 не було б на чому стояти. Світ від цих команд не змінюється: воротар їх відкидає.
6Свої залікові записи
Записи вашого пакета приходять у кабінет, щойно пакет закрито. Журнали чужих пакетів відкриваються всім, коли зіграно всі пакети кола; до того їх читає лише трійка пакета. Щоденник віри бачить лише його власник. Записи партій другого етапу закриті для всіх, і для своєї трійки теж, до кінця Випробування (scoring.md, 6.7).
| Маршрут | Що віддає |
|---|---|
GET /api/v1/me/games | ваші ігри: час, суперники, результат пакета |
GET /api/v1/me/games/{id}/pack | зведення пакета і список його записів {file, bytes, sha256, receivedAt, kind, mine} |
GET /api/v1/me/games/{id}/records/{file} | байти одного запису, application/octet-stream, ETag - його sha256 |
Зведення пакета приходить тієї самої форми, що й pack.json локального пакета, мінус походження коду сусідів: чий це репозиторій і який коміт - не справа читача.
Щоденник віри вашого бота за залікову партію ми знімаємо з вашої машини до відкату знімка і кладемо поруч із записами пакета: у списку записів він стоїть тими самими іменами, що й у локальному пакеті (belief-1.ndjson ... belief-3.ndjson, поле kind - щоденник), і завантажується тією самою ручкою. Строк у нього той самий, що й у запису пакета (6.1). Щоденники сусідів вам не приходять - ні байтами, ні рядком у списку: віра - це ваш файл, а не спільний.
Партія, яку вів наказ, і партія без присяги в записі є: частка 0 і епізоди наказу видно, як у локальному пакеті.
Записи завантажує ваш клієнт - це ті самі маршрути кабінету, що ви вже вмієте звати з частиною 1. Відкрити завантажене показом можна своїм господарем (01-hq-contract.md, 1.3) або з кабінету, передавши файли в рамку показу.