93 lines
3.9 KiB
TypeScript
93 lines
3.9 KiB
TypeScript
// Нагрузочная фикстура: настоящий масштаб книги стенда — 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';
|
||
}
|