textmachine/frontend/src/mock/scale.ts

93 lines
3.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Нагрузочная фикстура: настоящий масштаб книги стенда — 2284 раздела и 4276 юнитов редактуры
// (замер D39.84). Заведена не для красоты: раскладка нарисована под десяток глав, а списки обязаны
// получить поведение при 10³ элементов ДО того, как экраны нарисованы (BACKLOG Ф-12).
//
// Тексты здесь не цитаты, в отличие от src/mock/book.ts: названия разделов и термины собраны
// из типовых для жанра слов и слогов транслитерации. Пропорции письменностей настоящие —
// иероглиф короче кириллицы, и колонки без этого поедут.
import type { BankTerm, Chapter } from '../api/types';
const pick = (pool: readonly string[], index: number) => pool[index % pool.length] ?? '';
const chapterNames = [
'Нет раскаяния',
'Прозрение пятисот лет',
'Церемония открытия',
'Класс А',
'Деревня Гуюэ',
'Первый гу',
'Аптека',
'Кровь на снегу',
'Утраченный свиток',
'Горная тропа',
'Ночь перед испытанием',
'Скрытая пещера',
'Договор на крови',
'Возвращение старейшины',
'Три чаши вина',
'Сломанный клинок',
'Лисий морок',
'Заброшенный храм',
'Рынок диковин',
'Осенний смотр',
];
/** Черновая волна прошла первые сто с небольшим разделов: витрина показывает трудный случай. */
const draftFront = 110;
export const scaleChapters: Chapter[] = Array.from({ length: 2284 }, (_, index) => {
const number = index + 1;
const unitsTotal = 1 + (number % 3);
return {
id: `r${number}`,
title: `Раздел ${number}. ${pick(chapterNames, index)}`,
unitsDone: number < draftFront ? unitsTotal : number === draftFront ? 1 : 0,
unitsTotal,
noteCount: number % 17 === 0 ? 1 + (number % 3) : 0,
};
});
// Пары «иероглиф — слог транслитерации»: сложенные по двое и по трое, они дают термины настоящей
// длины и настоящего вида, не повторяя ни одного термина из живого банка.
const syllables = [
['方', 'Фан'],
['白', 'Бай'],
['花', 'Хуа'],
['沈', 'Шэнь'],
['古', 'Гу'],
['月', 'Юэ'],
['山', 'Шань'],
['春', 'Чунь'],
['秋', 'Цю'],
['金', 'Цзинь'],
['光', 'Гуан'],
['虫', 'Чун'],
['蛊', 'Гоу'],
['师', 'Ши'],
['学', 'Сюэ'],
['堂', 'Тан'],
['开', 'Кай'],
['窍', 'Цяо'],
['冰', 'Бин'],
['酒', 'Цзю'],
] as const;
const kinds: BankTerm['kind'][] = ['name', 'nickname', 'title', 'place', 'term'];
export const scaleTerms: BankTerm[] = Array.from({ length: 1200 }, (_, index) => {
const first = syllables[index % syllables.length] ?? syllables[0];
const second = syllables[Math.floor(index / syllables.length) % syllables.length] ?? syllables[0];
const tail = Math.floor(index / (syllables.length * syllables.length)) % 3;
const third = tail === 0 ? undefined : syllables[(index + tail) % syllables.length];
return {
source: first[0] + second[0] + (third?.[0] ?? ''),
target: first[1] + second[1].toLowerCase() + (third?.[1].toLowerCase() ?? ''),
kind: pickKind(index),
signed: index % 3 !== 0,
};
});
function pickKind(index: number): BankTerm['kind'] {
return kinds[index % kinds.length] ?? 'term';
}