|
persona-generator 4.1.3
Complete characters composed from the other dasmig generators for C++23
|
persona-generator draws a complete character in one call by running the other dasmig generators in dependency order. This guide covers the request, the result, how the draws are conditioned, replay, and using your own data.
persona_request{} asks for the defaults: a country drawn by population among the supported countries, and an age, sex, city, name, body, interests, occupation and three traits drawn for it.
| Field | Default | Meaning |
|---|---|---|
country | drawn | ISO 3166-1 alpha-2 code, any case |
person_sex | drawn | dasmig::sex::female or male |
ages | drawn from the country's age pyramid | age_range{.min, .max}, inclusive, in completed years |
reference_date | 2023-07-01 | The date ages are computed at. The library never reads the clock |
traits | 3 | How many personality traits |
relations | unset | A dasmig::family_request: also draw the persona's family (see Relatives) |
The request is never stored: one call cannot change the next.
A persona holds the typed result of every library, so no JSON parsing is needed to use it:
| Member | Type | From |
|---|---|---|
name | std::string (UTF-8) | name-generator |
country_info | dasmig::country | country-generator |
city_info, admin1 | dasmig::city, state or province name | city-generator |
birthday | dasmig::birth | birth-generator |
body | dasmig::biodata | biodata-generator |
traits | dasmig::personality | trait-generator |
interests | dasmig::interest | interest-generator |
job | dasmig::occupation | occupation-generator |
age() and person_sex() read the birth. A persona converts to std::string and streams as a one-line summary (Jéssica Tomaz Cardozo, 34, female, São Paulo, Brazil, Farm labourer, BRL 12,900 a year; the income is occupation-generator's, for the employed). admin1 is empty unless city-generator has its admin1 names loaded (load_admin1()).
to_json() writes name, sex, age, admin1 and signature, and each library's result under country, city, birth, biodata, personality, interest and occupation, exactly as that library writes it (so a country is country_code in biodata, interest and occupation) (see its guide for the fields).
The pipeline is declared as entity-generator fields (field(...).depends_on(...)), which checks the dependencies and orders the draws. Each part draws from a stream split from the persona's seed by the field's key, so forcing one choice does not shift the unrelated ones: the same seed with person_sex = female and with male gives the same country, city and personality.
get_persona(request, seed) is const and only calls const members of the libraries, so it may run on several threads. get_persona(request) draws its seed from the generator's engine and needs external synchronisation.
signature() is <seed>-<data>: data combines the data hashes of the eight libraries and the request, so a seed replays only against the same data and request.
The generator holds no data. It calls the eight libraries' instances, by default their singletons, so whatever they hold is the persona's:
To keep different data side by side, give the generator your own instances (they must outlive it):
has_data() is true when all eight can generate; data_hash() combines their hashes.
psg::supported_countries() lists the 79 countries a random persona is drawn from: those for which all eight libraries have data in their lite tier. Asking for another country is allowed; the libraries then use what they have, or reject it. South Korea, for example, is left out because name-generator's lite tier has no Korean male names; with the full tier loaded it can be requested. A country name-generator has no culture for (New Zealand, Thailand) is rejected with std::invalid_argument, rather than given a name from another culture.
Every seeded getter has batch forms: get_persona_batch return a std::vector, and for_each_persona streams the items to a sink in index order without holding the batch.
i is exactly get_persona(request, core::item_seed(batch_seed, first + i)). A range can be generated directly (first = 1000 starts at item 1000), two batches that follow each other equal one, and the output is the same for any threads (0 means the hardware count). Without a batch_seed one is drawn like the single getter draws its own.core::batch_options has count, first, threads and unique. The request describes one item; the options describe the batch..unique = core::unique_rule::by<persona>(key) regenerates an item whose key already appeared in the batch, with a deterministic retry seed, and throws std::runtime_error naming the item when the attempts run out.core::jsonl_writer writes one to_json() per line, core::csv_writer flattens each result's JSON into dotted columns. Any callable (std::uint64_t index, persona&) works.Set request.relations to draw the people around the persona with relationship-generator:
The persona fills in the request's anchor (country, sex, birth date and name), so the parents share the persona's family name by the country's convention, and the request's reference_date replaces the family's. The rest of the family_request is yours. relatives is empty and to_json() has no relatives key unless the request asked for it, and the rest of the persona and its signature() are the same with and without it. The family is drawn from a seed split from the persona's, so it replays with the persona's seed; its own signature is inside relatives.
Set stepparents (a parent's new partner, and with siblings their children: half-siblings with the parent and stepsiblings from before, which need relationship-generator 1.2.0) and home (who the persona lives with, as household in the JSON) on the family_request to add them; both are off by default and need relationship-generator 1.1.0 or later.
Without relations, relationship-generator is not used and its data is not needed: load() ignores a missing tier of it. With relations, get_persona throws std::runtime_error if it has no data (the lite tier is compiled in with DASMIG_RELATIONSHIP_EMBED). It uses its own birth-generator and name-generator instances, the singletons by default, as the persona does.
Version 3 composes biodata-generator 5, which draws skin, hair and eyes together (light hair goes with light eyes and fair skin, dark with dark), so the same seed gives a different skin, hair and eye colour than in v2. Everything else is unchanged: the data hash, the country, sex, age, names, jobs and traits for a seed, and the API. The libraries are now name-generator 4.2.2, city-generator 4.2.0, entity-generator 4.2.0, birth-generator and country-generator 3.1.2, interest-generator and occupation-generator 3.0.1, trait-generator 2.1.2 and biodata-generator 5.0.0. Update known answers that include the body.
| Error | When |
|---|---|
std::runtime_error | A library has no data loaded |
std::invalid_argument | ages.min > ages.max, an unknown country, or another input a library rejects |