|
Interest Generator 3.0.1
Religion, hobbies and favourite media by country, age and sex for C++23
|
This guide covers every feature of the interest-generator library. For a quick overview, see the README. For the full API reference, run doxygen Doxyfile from the repository root and open doc/api/html/index.html.
Copy dasmig/interestgen.hpp, dasmig/core.hpp and the dasmig/core/ directory into your include path, keeping them together. Supply resources/ next to the program, or define DASMIG_INTEREST_EMBED to compile the lite tier in.
instance() loads the lite tier on first use (or full if there is no lite), from the compiled-in copy or from the first of resources/, ../resources, interest-generator/resources and ../interest-generator/resources that has it.
Each load replaces the data and every layer loaded before. A tier is five tables (religion, interests, affinity, age_bands, regions); a directory with only religion.tsv still loads and then draws no hobbies or media. The lite tier has 195 countries and 104 hobbies and genres; full has 248 and 188, with the detailed religions. See Data and Method.
Generation has exactly two overloads: get_interest(request) and get_interest(request, seed). Every per-call choice lives in dasmig::interest_request; it does not change the instance's configuration. Every field has a default:
| Field | Default | Meaning |
|---|---|---|
country | empty | ISO 3166-1 alpha-2 code in capitals (the key of country-generator). Empty draws a country uniformly from those loaded; the data has no population, so for a population-weighted world pass the country country-generator chose |
age | unknown | Age in completed years (birth-generator's age). Unknown applies no age factor and no age limit. Younger than 5 draws no hobbies or media |
person_sex | unknown | dasmig::sex (shared with biodata-generator and birth-generator). Unknown applies no sex factor |
hobbies | 3 | How many hobbies |
media | 2 | How many genres in each of film, games, books and music |
Use a request for every call, including the default case:
The country-only, seed-only and no-argument overloads have been removed. Data loading and layers still belong to the instance; generation options do not.
How a draw works:
weight column; a row with weight 0 is loaded but never drawn.weight, multiplied by factors for the person's sex, age band, country (or else region) and religion group, for the item and for its activity class. A missing factor is 1. Items are drawn without replacement, and only those the person is old enough (and young enough) for. If fewer than asked have a positive weight, fewer are returned.get_interest(request, seed) gives the same result for the same seed, request and data, on every platform, independent of previous calls.get_interest(request) draws a fresh call seed from the instance's entropy-seeded random engine. There are no generator-level seed() or unseed() controls. For a reproducible sequence, supply an explicit seed for each request.v.seed() is the seed a result was generated from. Replay with get_interest(request, v.seed()), retaining the original request, including an empty country when one was drawn randomly.The shipped data is a base layer. Files with the same columns as the shipped tables can be loaded on top of it to add countries, religions, hobbies or genres, change shares or factors, or remove rows, without editing the shipped files. Each table has a key, and a row with the same key replaces the loaded row:
table | File | Key | Required columns |
|---|---|---|---|
religion | religion.tsv | country_code, religion | group, weight (optional: year, basis) |
interests | interests.tsv | kind, key | label, weight (optional: class, category, tags, min_age, max_age) |
affinity | affinity.tsv | target, dimension, value | factor (optional: basis) |
age_bands | age_bands.tsv | band | min_age, max_age |
regions | regions.tsv | country_code | region |
kind is hobby, film, game, book or music. An affinity target is an item key, or class: and an activity class (it then applies to every item of that class); dimension is sex (male, female), age_band, region, country or religion (a group such as christian).
dasmig::core::tsv_error with the file, line and column, and the data stays as it was.unresolved() lists them to catch misspelt names.layers(table) lists what is loaded for a table: source, mode, rows added, replaced and removed, and warnings such as unknown columns.load(...) replaces the base and drops every layer.Every result records the seed and the data it came from:
to_json() gives the result as JSON, the form the WebAssembly layer and the game consume. Seeds are strings because JavaScript numbers cannot hold every 64-bit value. to_json(writer) writes into an existing dasmig::core::json_writer, for composing larger documents.
Define DASMIG_INTEREST_EMBED before including the header to compile the lite tier into the program. load(dataset::lite) and instance() then use it and need no files. The compiled-in data has the same data_hash() as the file, so seeds replay the same either way.
dasmig/interestgen_data.hpp is generated from resources/lite by make embed; CI checks it is up to date.
Each intg instance is independent. Concurrent calls to get_interest() on the same instance require external synchronisation (e.g. a std::mutex).
Every seeded getter has batch forms: get_interest_batch return a std::vector, and for_each_interest streams the items to a sink in index order without holding the batch.
i is exactly get_interest(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<interest>(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, interest&) works.| Exception | When |
|---|---|
std::runtime_error | Any generation call before data is loaded |
std::invalid_argument | The country code has no data (codes are two capital letters), or every share of the country has weight 0, or no country has a positive weight (random country); extend(path) with a file that is not one of the table names |
dasmig::core::tsv_error | A malformed table file or layer (message gives file, line and column); the data is unchanged |