// The default fixture world, and the rule that governs it: **the default fixture is the HARD // case.** A book in the middle of the draft wave, where a naive "N of M done" counter reads zero; // a bank half decided, with a polysemous term arriving as two legal rows; chapters that carry no // label at all. A comfortable fixture makes the screenshot cycle look at something the product // never produces. // // Shapes are the CONTRACT's, wire-side: this file is what the platform would answer, so the // narrowing and the screens are exercised on the real form. // // ⚠ The prose is a short extract from a real run (蛊真人 zh→ru, off-repo). Taken to check the // density of the columns and no more — the source is under copyright (question В-2). import type { components } from '../api/schema'; type Schemas = components['schemas']; export const bookId = 'bk_guzhenren'; // Mid-draft-wave on purpose: editing has not started, so an end-to-end counter would read 0 for // hours. 4276 units over 2284 chapters (measured, D39.84). export const book: Schemas['Book'] = { id: bookId, title: 'Гу Чжэньжэнь', source_lang: 'zh', target_lang: 'ru', genre: 'сянься', chapter_count: 2284, character_count: 7_780_000, added_at: '2026-07-28T09:14:00Z', status: 'translating', progress: { draft: { done: 214, total: 4276 }, edit: { done: 0, total: 4276 }, eta_seconds: 9240, }, note_count: 37, }; const other = ( id: string, title: string, status: Schemas['BookStatus'], extra: Partial = {}, ): Schemas['Book'] => ({ ...book, id, title, status, chapter_count: 0, character_count: 0, progress: { draft: { done: 0, total: 0 }, edit: { done: 0, total: 0 } }, note_count: 0, ...extra, }); // Every status of the vocabulary on one screen — the only honest way to see that eleven values // stay distinguishable, and the reason the label is a word and not a coloured dot. export const books: Schemas['Book'][] = [ book, other('bk_2', 'Мастер божественных пилюль', 'ready'), other('bk_3', 'Второе рождение мечника', 'awaiting_bank'), other('bk_4', 'Хроники северной заставы', 'finalizing'), other('bk_5', 'Тысяча ступеней', 'parsing'), other('bk_6', 'Записки о лисах и духах', 'not_started'), other('bk_7', 'Небесный чиновник', 'paused'), other('bk_8', 'Сломанный меч', 'stopped'), // With a machine reason (0.2.3): a rejected book without one is legal too — that is what a // deployment older than this minor answers — and the intake world carries that case. other('bk_9', 'Повреждённая выгрузка', 'rejected', { reject_reason: 'source_unreadable' }), other('bk_10', 'Оборванный свиток', 'failed'), other('bk_11', 'Свежая загрузка', 'uploading'), ]; export const run: Schemas['Run'] = { id: 'run_41', revision: 1841, status: 'translating', verify_bank: true, ceiling_chapters: 400, paused_reason: null, started_at: '2026-08-08T06:02:00Z', finished_at: null, }; // A chapter has no status — only progress by units. Two of the hard cases live here: a chapter the // book gives no label to, and a chapter the book does not number. Neither may be papered over with // a "Chapter N" template; there is no such form (D39.100 K-3). export const chapters: Schemas['Chapter'][] = [ { id: 'ch_1', number: 1, heading: 'Нет раскаяния', units_total: 2, units_done: 2, note_count: 0 }, { id: 'ch_2', number: 2, heading: 'Прозрение пятисот лет', units_total: 4, units_done: 4, note_count: 3, }, { id: 'ch_3', number: 3, heading: 'Церемония открытия', units_total: 3, units_done: 1, note_count: 0, }, { id: 'ch_4', number: 4, heading: null, units_total: 2, units_done: 0, note_count: 0 }, { id: 'ch_5', number: null, heading: 'Деревня Гуюэ', units_total: 1, units_done: 0, note_count: 1, }, { id: 'ch_6', number: 5, heading: 'Первый гу', units_total: 2, units_done: 0, note_count: 0 }, { id: 'ch_7', number: 6, heading: 'Аптека', units_total: 2, units_done: 0, note_count: 0 }, { id: 'ch_8', number: 7, heading: 'Кровь на снегу', units_total: 3, units_done: 0, note_count: 0, }, { id: 'ch_9', number: 8, heading: 'Утраченный свиток', units_total: 1, units_done: 0, note_count: 0, }, { id: 'ch_10', number: 9, heading: 'Горная тропа', units_total: 2, units_done: 0, note_count: 0 }, ]; export const notes: Schemas['Note'][] = [ { severity: 'glance', message: 'Служебная разметка вычищена автоматически', chapter_id: 'ch_2', unit_id: 'u_2_1', }, { severity: 'attention', message: 'Часть блока не вошла в перевод', chapter_id: 'ch_2', unit_id: 'u_2_2', }, { severity: 'attention', message: 'Блок не переведён: содержимое отклонено', chapter_id: 'ch_2', unit_id: 'u_2_3', }, { severity: 'glance', message: 'Служебная разметка вычищена автоматически', chapter_id: 'ch_5' }, ]; const noteOf = (unitId: string) => notes.find((note) => note.unit_id === unitId) ?? null; // Source lines for chapters the draft wave has not reached: parsing produced the text, translation // has not. Deliberately few and short — see the copyright note at the top of the file. const untouched = ['青茅山下,古月家的少年们排成一列,等待开窍。', '风从北面吹来,带着雪的气味。']; export function unitsOf(chapterId: string): Schemas['Unit'][] { const explicit = units[chapterId]; if (explicit) return explicit; const chapter = chapters.find((row) => row.id === chapterId); return Array.from({ length: chapter?.units_total ?? 0 }, (_, index) => ({ id: `${chapterId}_u${String(index)}`, source: untouched[index % untouched.length] ?? '', target: '', state: 'pending' as const, note: null, })); } const units: Record = { ch_2: [ { id: 'u_2_0', source: '传说中,这个世界存在着一条光阴之河,支撑着这个世界的流转。而利用春秋蝉的力量,就能逆流而上,回到从前。\n' + '对这个传闻,世人众说纷纭。很多人并不相信,有些人则将信将疑。\n' + '几乎没有人真的确信。', target: 'В преданиях говорилось, что в этом мире существует река времени, поддерживающая его течение, и с помощью силы Весенне-осенней цикады можно подняться против потока и вернуться в прошлое.\n' + 'Об этом слухе люди судили по-разному. Многие не верили вовсе, иные верили наполовину.\n' + 'Почти никто не был уверен по-настоящему.', state: 'translated', note: null, }, { id: 'u_2_1', source: '因为每一次使用春秋蝉,都必须付出生命,将整个身躯和所有的修为统统献祭,作为驱动的力量。', target: 'Ведь каждое обращение к Весенне-осенней цикаде требует жизни: тело и всё накопленное умение приносятся в жертву, чтобы дать ей силу.', state: 'translated', note: noteOf('u_2_1'), }, { // Text AND a note together — a class, not an exception. A unit flagged for a member that // dropped out still ships the edited remainder, carrying the reason of the first drop. id: 'u_2_2', source: '但是现在,方源信了,彻底地信了。铁一般的事实摆在他的面前,不容他反驳——他真的重生了!', target: 'Но теперь Фан Юань уверовал полностью и бесповоротно. Перед ним лежал железный факт, не допускающий возражений: он действительно переродился!', state: 'translated', note: noteOf('u_2_2'), }, { // Flagged AND no text: the other branch of the same rule. id: 'u_2_3', source: '这个代价实在太昂贵了,更让人无法接受的是——往往付出了生命,也不知道结果怎样。', target: '', state: 'withheld', note: noteOf('u_2_3'), }, ], ch_3: [ { id: 'u_3_0', source: '开窍礼在清晨开始,古月家的孩子们站在祠堂前。', target: 'Церемония открытия началась на рассвете: дети рода Гуюэ стояли перед родовым залом.', state: 'translated', note: null, }, { id: 'u_3_1', source: untouched[0] ?? '', target: '', state: 'pending', note: null }, { id: 'u_3_2', source: untouched[1] ?? '', target: '', state: 'pending', note: null }, ], };