Saltar al contenido principal

Generadores

Un <gen> es una fábrica de datos. Su atributo type elige cuál generador se usa; todos los demás atributos son parámetros de ese generador. Un generador produce los valores de una secuencia:

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

Las salidas de ejemplo de esta página son ilustrativas: los valores exactos dependen de la semilla y pueden cambiar entre versiones del núcleo. Lo que sí es estable es la forma del resultado: el formato, las cantidades y la distribución.

Dónde puede vivir un generador

Un <gen> vive donde se declaran los datos:

  • dentro de una <sequence> —simple, compuesta por valor, compuesta o condicional—, llenando count valores (o tantos como tenga el subconjunto filtrado, si la secuencia tiene parent). «Un arreglo de count valores» es el modelo con el que conviene razonar; el motor por omisión los produce fila por fila mientras el archivo se transmite, sin guardar nunca el arreglo;
  • dentro de un <case> de un <mix> — una rama de un reparto porcentual.

Varios <gen> pueden compartir un mismo cuerpo de secuencia, y name decide en qué se convierte cada uno. Deje un generador sin nombre y su valor se concatena en el valor propio de la secuencia, junto con cualquier literal <data> a su lado: una secuencia compuesta por valor. Póngale name y pasa a ser un campo propio, que se lee como ${{Secuencia.Campo}}: una secuencia compuesta. Los dos se mezclan libremente en un mismo cuerpo.

No se permite directamente en el bloque de salida. Un <gen> colocado como hijo de <line> es el error TDC131: ese bloque solo da formato al texto, no genera nada. Para poner un valor generado en la salida, declare una secuencia con nombre y refiérase a ella con ${{Nombre}} — vea Salida y formato.

Atributos comunes

Estos atributos funcionan en todos los generadores; el resto dependen de type.

AtributoObligatorioQué hace
typeCuál generador se usa (vea la tabla de abajo)
namenoConvierte el generador en un campo de su secuencia, que se lee como ${{Secuencia.Campo}}. Sin él, el valor se suma al valor propio de la secuencia
ifnoCondición de rama dentro de una secuencia condicional — gana el primer <gen> verdadero
commentnoComentario libre, el motor lo ignora

Los generadores

Cada tipo tiene su propia página, con todos sus parámetros y ejemplos resueltos.

typeProduce
textUn valor de un conjunto — uniforme, o con percent exacto
numberUn entero dentro de un rango, o una cadena de dígitos de ancho fijo
templateDatos realistas integrados e identificadores técnicos
fileValores leídos de sus propios archivos y columnas CSV
dateUna fecha o fecha-hora dentro de un rango y con un formato
symbolUna cadena de caracteres de un conjunto o alfabeto con nombre
regexUna cadena que corresponde a una expresión regular finita
advanced_regexRegex más elección ponderada entre alternativas
increment / decrementContadores ascendentes y descendentes
timeseriesUna serie de tiempo — tendencia + estacionalidad + ruido
patternUna distribución con la forma de una curva dibujada
httpValores que responde su propio servicio, por lotes
runningUn total que se arrastra por la columna — un saldo, un máximo

Sobre los presets. El viejo type="preset" ya no existe. Los identificadores algorítmicos —UUID, IBAN, números de tarjeta de crédito, SHA de git, identificaciones nacionales— ahora son rutas de template: las globales bajo el prefijo common. (por ejemplo common.id.uuid) y las de cada país bajo su país (por ejemplo usa.docs.ssn). El catálogo completo está en las páginas de template y de la referencia de generadores.

Proporciones declaradas, o un sorteo de una fuente

En esa tabla conviven generadores de dos clases, y responden de forma distinta a «¿con qué frecuencia aparece cada valor?». Vale la pena saber cuál tiene en la mano.

Declaró las proporciones — las obtiene exactas. Donde los valores están escritos en la propia configuración, TDC reparte la cuota entre las filas y luego la baraja. percent="30,70" es 30 y 70, no «más o menos». Si no las indica, son iguales, y iguales también es exacto:

10 valores sobre 1000 filas
text:  100 100 100 100 100 100 100 100 100 100

Eso cubre text, number y <mix>.

Apuntó a una fuente — obtiene un sorteo. Un archivo o un pool es un conjunto en el que mete la mano una vez por fila, de forma independiente. Sobre esas mismas 1000 filas los recuentos caen donde los deja el azar:

los mismos 10 valores, leídos de una fuente
file:   81  88  93  97  98 102 103 105 111 122
pool:   90  92  95  97 100 102 104 105 106 109

Esto no es una versión débil de lo primero. Nadie declaró una proporción, así que no hay ninguna que respetar: una fuente se comporta como sacar de un sombrero, y por eso parece uso real y no un cuadrante de turnos.

Cuando una fuente necesita proporciones, las toma de los datos. Un CSV que sabe con qué frecuencia se vende cada artículo lo dice en una columna, y weight="sales" hace que el sorteo la siga — exacto, como percent. Ese es el lugar honesto para los números: un catálogo de 3.000 artículos tiene sus frecuencias en el archivo, no en su configuración.

Formato en cualquier generador

Un puñado de atributos funciona en cualquier type. El valor se genera como siempre y luego se reacomoda de salida — al generador no le importa cuál de estos atributos se le haya puesto.

case= / mask= — mayúsculas/minúsculas y máscaras de presentación

Úselo cuando el valor crudo es correcto pero debe verse de cierta manera: una columna que tiene que ir toda en mayúsculas, o un número simple que debe leerse como un identificador con formato.

case= cambia entre mayúsculas y minúsculas; mask= reparte y reacomoda los caracteres dentro de una plantilla fija. Ambos envuelven al generador completo. El ejemplo de abajo pasa las mismas cuatro ciudades de Estados Unidos por tres secuencias: el valor crudo, y luego la misma lista con case="lower" y case="upper". order="sequential" mantiene las ciudades al mismo paso para que las columnas queden alineadas.

<sequence name="Raw"><gen type="text" value="New York,Chicago,Denver,Austin" order="sequential"/></sequence>
<sequence name="Low"><gen type="text" value="New York,Chicago,Denver,Austin" order="sequential" case="lower"/></sequence>
<sequence name="Up"><gen type="text" value="New York,Chicago,Denver,Austin" order="sequential" case="upper"/></sequence>
...
<data>${{Raw}} -> lower: ${{Low}} | upper: ${{Up}}</data>
./run cities.tdc
New York  ->  lower: new york  |  upper: NEW YORK
Chicago   ->  lower: chicago   |  upper: CHICAGO
Denver    ->  lower: denver    |  upper: DENVER
Austin    ->  lower: austin    |  upper: AUSTIN

Una mask= hace el mismo truco para identificadores «bonitos»: un 37898432363 pelón con mask="xxx-xxx-xxx xx" sale como 378-984-323 63. Cada ranura de máscara (x, w, *), cada modo de case y las cadenas de filtros de varios pasos se explican a fondo en Máscaras y mayúsculas.

order= / cycle= — el orden de los valores

Úselo cuando los valores deban salir en una secuencia fija y no al azar: los nombres de los meses en orden de calendario, una lista de catálogo recorrida de arriba abajo, o dos columnas que tienen que quedar alineadas (como en el ejemplo de arriba).

Por omisión, order="random". Ponga order="sequential" y la fila i toma el i-ésimo valor en orden, volviendo al inicio cuando la lista se acaba. cycle="false" convierte esa vuelta al inicio en un error explícito — útil cuando quedarse sin valores debe ser una falla y no una repetición silenciosa.

<sequence name="Rand"><gen type="text" value="Jan,Feb,Mar"/></sequence>
<sequence name="Seq"><gen type="text" value="Jan,Feb,Mar" order="sequential"/></sequence>
...
<data>random=${{Rand}} sequential=${{Seq}}</data>
./run order.tdc (7 rows)
random=Feb   sequential=Jan
random=Feb   sequential=Feb
random=Mar   sequential=Mar
random=Jan   sequential=Jan
random=Feb   sequential=Feb
random=Mar   sequential=Mar
random=Jan   sequential=Jan

Lo mismo aplica a los archivos: <gen type="file" src="cities.txt" order="sequential"/> recorre el archivo línea por línea. Todos los detalles en Máscaras y mayúsculas.

missing= / anomaly= — vacíos y valores atípicos

Úselo cuando necesite datos que se parezcan al mundo real, donde algunos campos vienen vacíos y unos cuantos valores quedan muy fuera del rango normal. missing= inyecta celdas vacías (huecos que faltan de manera completamente aleatoria); anomaly= inyecta valores atípicos para que un pipeline o un modelo río abajo tenga algo anormal con qué lidiar. Ambos se ponen en el generador igual que case= y se aplican después de producir el valor.

Estas perillas modelan el realismo más que el valor base, y se enganchan a cualquier generador. Se diferencian en aquello sobre lo que pueden actuar: missing= vacía la celda sea cual sea su contenido, mientras que anomaly= multiplica, así que solo muerde en valores que se leen como números. Una cadena numérica de una lista text se multiplica; un nombre pasa sin cambios y sin aviso. Las reglas completas están en Anomalías y valores faltantes.