Перейти к основному содержимому

Генераторы

Тег <gen> — это «фабрика» данных. Атрибут type выбирает, какой генератор использовать; каждый остальной атрибут — параметр этого генератора. Генератор производит значения последовательности:

<sequence name="Status">
<gen type="text" value="new,active,closed"/>
</sequence>
./run demo.tdc
active
new
closed
active
closed

Примеры вывода на этой странице иллюстративны — точные значения зависят от сида и могут меняться между версиями ядра. Стабильна форма результата: формат, количество значений и распределение.

Где может жить генератор

<gen> живёт там, где объявляются данные:

  • внутри <sequence> — простой, составной по значению, составной или условной — заполняет count значений (или столько, сколько в отфильтрованном подмножестве, если у последовательности задан parent). «Массив длиной count» — это модель, которой удобно рассуждать; движок по умолчанию выдаёт значения по одному, пока файл течёт, и массив не держит;
  • внутри <case> у <mix> — одна ветка процентного разбиения.

В одном теле последовательности может жить несколько <gen>, и что каждый из них означает, решает name. Оставьте генератор без имени — его значение склеивается в собственное значение последовательности вместе с литералами <data> рядом: составная по значению. Дайте name — он становится отдельным полем, которое читается как ${{Имя.Поле}}: составная последовательность. Оба вида свободно смешиваются в одном теле.

Прямо в блоке вывода генератор не разрешён. <gen> как непосредственный ребёнок <line> — это ошибка TDC131: блок только форматирует текст, он не генерирует. Чтобы подставить сгенерированное значение в вывод, объявите именованную последовательность и сошлитесь на неё через ${{Имя}} — см. Вывод и форматирование.

Общие атрибуты

Эти атрибуты работают на любом генераторе; остальные зависят от type.

АтрибутОбязательныйЧто делает
typeдаКакой генератор использовать (см. таблицу ниже)
nameнетДелает генератор полем своей последовательности, читается как ${{Имя.Поле}}. Без него значение попадает в собственное значение последовательности
ifнетУсловие ветки внутри условной последовательности — срабатывает первый истинный <gen>
commentнетСвободный комментарий, движок его игнорирует

Генераторы

У каждого типа своя страница со всеми параметрами и разобранными примерами.

typeЧто производит
textЗначение из набора — равномерно или по точным percent
numberЦелое число в диапазоне или строка фиксированной ширины из цифр
templateВстроенные правдоподобные данные и технические идентификаторы
fileЗначения из ваших собственных файлов и колонок CSV
dateДата или дата-время в диапазоне и заданном формате
symbolСтрока из символов набора или именованного алфавита
regexСтрока по конечному регулярному выражению
advanced_regexRegex плюс взвешенный выбор между альтернативами
increment / decrementВозрастающий и убывающий счётчики
timeseriesВременной ряд — тренд + сезонность + шум
patternРаспределение в форме нарисованной кривой
httpЗначения отвечает ваш собственный сервис, пачками
runningИтог, переносимый по колонке, — остаток, рекорд

О пресетах. Старого type="preset" больше нет. Алгоритмические идентификаторы — UUID, IBAN, номера банковских карт, git SHA, национальные идентификаторы — теперь являются путями template: глобальные под префиксом common. (например, common.id.uuid), страновые — под своей страной (например, russia.tax.inn_person для ИНН). Полный каталог — на страницах template и справочника генераторов.

Объявленные доли или розыгрыш из источника

В той таблице рядом стоят генераторы двух разных сортов, и на вопрос «как часто встречается каждое значение» они отвечают по-разному. Стоит понимать, что у вас в руках.

Вы объявили доли — получите их точно. Там, где значения перечислены в самом конфиге, TDC раскладывает квоту по строкам и перемешивает её. percent="30,70" — это 30 и 70, а не «примерно». Если долей не задать, они равные, и равные тоже точные:

10 значений на 1000 строк
text:  100 100 100 100 100 100 100 100 100 100

Так работают text, number и <mix>.

Вы указали на источник — получите розыгрыш. Файл или пул — это набор, в который вы лезете по разу на строку, независимо. На тех же 1000 строках счёт ложится так, как выпадет:

те же 10 значений, но из источника
file:   81  88  93  97  98 102 103 105 111 122
pool:   90  92  95  97 100 102 104 105 106 109

Это не ослабленная версия первого. Никто не объявлял пропорцию, значит и соблюдать нечего — источник ведёт себя как рука в шапке, и именно поэтому выглядит настоящей нагрузкой, а не графиком дежурств.

Когда источнику нужны пропорции, он берёт их из самих данных. CSV, который знает, как часто продаётся каждый товар, говорит об этом колонкой, а weight="sales" заставляет розыгрыш ей следовать — точно, как percent. Это честное место для цифр: у справочника на 3000 позиций частоты лежат в файле, а не у вас в конфиге.

Форматирование на любом генераторе

Несколько атрибутов работают на любом type. Значение генерируется как обычно, а затем переоформляется на выходе — генератору всё равно, какой из этих атрибутов вы к нему прикрепили.

case= / mask= — регистр букв и маски отображения

Когда брать. Сырое значение верно, но должно выглядеть определённым образом: колонка, которая обязана быть целиком в верхнем регистре, или простое число, которое должно читаться как оформленный идентификатор.

case= меняет регистр букв; mask= разбивает и переставляет символы по фиксированному шаблону. Оба оформляют весь генератор. Пример ниже прогоняет одни и те же четыре города через три последовательности — сырьё, затем тот же список с case="lower" и case="upper". order="sequential" держит города в ногу, чтобы колонки совпадали.

<sequence name="Raw"><gen type="text" value="Moscow,Berlin,Paris,Rome" order="sequential"/></sequence>
<sequence name="Low"><gen type="text" value="Moscow,Berlin,Paris,Rome" order="sequential" case="lower"/></sequence>
<sequence name="Up"><gen type="text" value="Moscow,Berlin,Paris,Rome" order="sequential" case="upper"/></sequence>
...
<data>${{Raw}} -> case="lower": ${{Low}} | case="upper": ${{Up}}</data>
./run cities.tdc
Moscow  ->  case="lower": moscow  |  case="upper": MOSCOW
Berlin  ->  case="lower": berlin  |  case="upper": BERLIN
Paris   ->  case="lower": paris   |  case="upper": PARIS
Rome    ->  case="lower": rome    |  case="upper": ROME

mask= делает тот же трюк для «красивых» идентификаторов — голое 37898432363 с mask="xxx-xxx-xxx xx" выходит как 378-984-323 63. Все слоты маски (x, w, *), все режимы регистра и многошаговые цепочки фильтров полностью разобраны на Маски и регистр.

order= / cycle= — порядок значений

Когда брать. Значения должны выходить в фиксированном порядке, а не случайно — названия месяцев в календарном порядке, справочный список, пройденный сверху вниз, или две колонки, которые обязаны оставаться выровненными (как в примере выше).

По умолчанию order="random". Поставьте order="sequential" — и строка i берёт i-е значение по порядку, возвращаясь к началу, когда список заканчивается. cycle="false" превращает это возвращение в явную ошибку — удобно, когда исчерпание значений должно быть сбоем, а не тихим повтором.

<sequence name="Rand"><gen type="text" value="янв,фев,мар"/></sequence>
<sequence name="Seq"><gen type="text" value="янв,фев,мар" order="sequential"/></sequence>
...
<data>random=${{Rand}} sequential=${{Seq}}</data>
./run order.tdc (7 строк)
random=фев   sequential=янв
random=фев   sequential=фев
random=мар   sequential=мар
random=янв   sequential=янв
random=фев   sequential=фев
random=мар   sequential=мар
random=янв   sequential=янв

То же касается файлов: <gen type="file" src="cities.txt" order="sequential"/> проходит файл строка за строкой. Подробности — Маски и регистр.

missing= / anomaly= — пропуски и выбросы

Когда брать. Нужны данные, которые выглядят как в реальном мире — где часть полей пуста, а несколько значений сидят далеко за пределами нормального диапазона. missing= вставляет пустые ячейки (пропуски полностью случайного характера); anomaly= вставляет выбросы, чтобы у последующего конвейера или модели было что-то ненормальное, с чем нужно справиться. Оба прикрепляются к генератору как case= и применяются после того, как значение произведено.

Эти ручки формируют реалистичность, а не базовое значение, и цепляются к любому генератору. Различаются они тем, с чем могут работать: missing= очищает ячейку, что бы в ней ни лежало, а anomaly= умножает — и потому срабатывает только на значениях, которые читаются как числа. Числовая строка из списка text будет умножена; имя пройдёт без изменений и без предупреждения. Полные правила — в Аномалиях и пропусках.