Glasshouse
루팅된 LG webOS TV용 대시보드·프라이버시 제어·Home Assistant 연동
각국 인구 피라미드와 출생 계절·요일 패턴을 반영한 인구통계적 생일·연령을 제공, C++23 헤더 전용, 결정적
Demographically plausible birthdays and ages from each country's age pyramid, birth seasonality and weekday patterns. C++23, header-only, deterministic.
개발 도구C++ · PythonGitHub @dasmig온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Requires C++23 (e.g.,
-std=c++23for GCC/Clang,/std:c++latestfor MSVC).
API Reference · Usage Guide · Data and Method · Releases
Demographically plausible birthdays and ages, from each country's age pyramid, birth seasonality and weekday patterns.
Demographically Plausible Birthdays. Generates random birthdays using a multi-axis pipeline: country-specific age pyramids, monthly birth seasonality, and weekday deficit from C-section rates.
Population-Weighted Country Selection. Countries are selected with probability proportional to their population, mirroring real-world demographics — a birth from India or China is far more likely than one from Iceland.
Rich Birth Data. Every generated birth includes: ISO date (YYYY-MM-DD), year, month, day, age, biological sex, weekday, life expectancy remaining, generational cohort label, and country code.
UN WPP 2024 Data. Age pyramids and life expectancy sourced from the United Nations World Population Prospects 2024 revision via the PPgp/wpp2024 R package.
Monthly Seasonality. Latitude-based sinusoidal model — Northern Hemisphere peaks in September, Southern Hemisphere peaks in March.
Weekday Deficit. Weekend births are less probable in countries with high C-section / scheduled delivery rates, reflecting real-world hospital scheduling patterns.
Uniform Selection. Use birth_request{.weighted = false} for equal-probability country selection.
Per-Call Requests. Use birth_request with get_birth(request) or get_birth(request, seed) to combine country, sex, year or age filters with per-call weighting and reference date. All generation choices live on the request.
Deterministic Seeding. Per-call get_birth(request, seed) for reproducible results, and birth::seed() for replaying a previous generation with the same request. Unseeded requests use ordinary random generation.
Batch Generation. Generate thousands of results from one seed, on several threads with the same output for any thread count, optionally unique by a key, and stream them as JSON Lines or CSV (see the usage guide).
Identical Everywhere. A seed gives the same birth on every compiler, standard library and CPU (GCC, Clang, MSVC, Emscripten; x86-64 and ARM64), checked by known-answer tests. Ages are relative to a fixed reference date, not the clock.
Extensible Data. Load your own TSV layers on top of the shipped data to add, change or remove countries (), checked before they are applied.
birthgen.hpp is the library released here. Keep core.hpp and the core/ directory (dasmig-core) in the same directory. Add
#include <dasmig/birthgen.hpp>
to the files you want to use it in, and supply the resources folder (or define DASMIG_BIRTH_EMBED).
#include <dasmig/birthgen.hpp>
#include <iostream>
// For convenience.
using bthg = dasmig::bthg;
// Manually load a specific dataset tier if necessary.
bthg::instance().load(dasmig::dataset::lite); // ~195 sovereign states
// OR
bthg::instance().load(dasmig::dataset::full); // ~235 countries & territories
// Generate a random birth (population-weighted country selection).
auto b = bthg::instance().get_birth(dasmig::birth_request{});
std::cout << b.date_string() << " — "
<< b.country_code << ", age " << +b.age
<< ", " << b.cohort << '\n';
// Generate a birth from a specific country.
auto us = bthg::instance().get_birth(dasmig::birth_request{.country_code = "US"});
std::cout << "US: " << us << '\n'; // implicit string conversion
// Request a specific sex.
auto m = bthg::instance().get_birth(dasmig::birth_request{
.country_code = "BR", .bio_sex = dasmig::sex::male});
// Request a specific birth year.
auto y = bthg::instance().get_birth(dasmig::birth_request{
.country_code = "JP", .year = dasmig::year_t{1990}});
// Request both sex and year.
auto sy = bthg::instance().get_birth(dasmig::birth_request{
.country_code = "DE", .bio_sex = dasmig::sex::female, .year = dasmig::year_t{1985}});
// Request an age range (e.g. adults 18–65).
auto ar = bthg::instance().get_birth(dasmig::birth_request{
.country_code = "US", .ages = dasmig::age_range{18, 65}});
// Access all available fields.
std::cout << "Sex: " << (b.bio_sex == dasmig::sex::male ? "M" : "F") << '\n';
std::cout << "Weekday: " << +b.weekday << " (0=Sun..6=Sat)" << '\n';
std::cout << "LE left: " << b.le_remaining << " years" << '\n';
// Deterministic generation — same request, seed and data produce the same birth.
auto seeded = bthg::instance().get_birth(dasmig::birth_request{}, 42);
// Per-call filters and settings.
dasmig::birth_request request{
.country_code = "US",
.bio_sex = dasmig::sex::female,
.ages = dasmig::age_range{18, 65},
.weighted = false,
.reference_date = std::chrono::year{2040} / std::chrono::January / std::chrono::day{1}};
auto requested = bthg::instance().get_birth(request, 42);
auto requested_replay = bthg::instance().get_birth(request, requested.seed());
// Replay a previous birth using its seed.
auto replay = bthg::instance().get_birth(dasmig::birth_request{}, seeded.seed());
// Deterministic sequences use an explicit seed for every call.
for (std::uint64_t seed = 100; seed < 103; ++seed)
std::cout << bthg::instance().get_birth(dasmig::birth_request{}, seed) << '\n';
// Switch to uniform random selection (equal probability per country).
auto uniform = bthg::instance().get_birth(dasmig::birth_request{.weighted = false});
// Independent instance — separate data and random engine.
bthg my_gen;
my_gen.load("path/to/resources/lite");
auto c = my_gen.get_birth(dasmig::birth_request{});
birth_request{} uses population-weighted selection and birth_request::default_reference_date (2023-07-01). Omit country_code for a random country; set year = dasmig::year_t{1990} for a fixed year instead of ages. Specifying both year and ages throws std::invalid_argument. get_birth(request) draws a seed from the generator's random engine; get_birth(request, seed) does not advance it. Replay requires the same request, seed and loaded data.
The positional/no-argument get_birth overloads and generator-wide weighted() / reference_date() getter/setters and seed() / unseed() controls have been removed. Pass an explicit request on every call, including birth_request{} for defaults; move weighting and reference-date choices onto that request, and pass deterministic seeds as the second argument. Result fields, seeded output and data APIs are unchanged. See Migrating to request-first generation.
For the complete feature guide — fields, seeding, weighting, and more — see the Usage Guide.
Each call to get_birth() runs this pipeline:
std::chrono.max(0, LE_at_birth − age).The birth data is sourced from:
| Source | License | Contribution |
|---|---|---|
| PPgp/wpp2024 (UN WPP 2024) | CC BY 3.0 IGO | Age pyramids, life expectancy at birth |
| REST Countries v3.1 | Open Source | ISO codes, latitude, independence status |
| WHO Global Health Observatory | Reference | C-section rates by country |
See LICENSE_DATA.txt for details.
To regenerate datasets:
python scripts/prepare_births.py # generate both tiers
python scripts/prepare_births.py --tier lite # lite only
python scripts/prepare_births.py --tier full # full only
make # example
make test # tests
make bench # benchmarks, results in build/bench.tsv
make test-embed # tests with the lite tier compiled in
make coverage # code coverage
make lint # clang-tidy
make docs # API docs
make embed # regenerate dasmig/birthgen_data.hpp from resources/lite
For targeted checks after make test: ./build/test_runner "[request],[kat]".
Tested with:
-std=c++23)-std=c++23)/std:c++latest)| Dependency | Version | Bundled | Purpose |
|---|---|---|---|
| dasmig-core | 1.4 | Yes (core.hpp, core/) | Platform-independent random engine and distributions, data layers, JSON |
| Catch2 | 3.x | Yes (amalgamated) | Unit testing |
| Library | Description |
|---|---|
| address-generator | Postal addresses with real streets by place |
| biodata-generator | Procedural human physical characteristics |
| city-generator | Weighted city selection by population |
| country-generator | Weighted country selection by population |
| device-generator | Devices, browsers, user agents and IP addresses that fit together |
| email-generator | Email addresses in each country's style |
| entity-generator | ECS-based entity generation |
| interest-generator | Religion, hobbies and favourite media by country, age and sex |
| name-generator | Culturally appropriate full names |
| nickname-generator | Gamer-style nicknames |
| occupation-generator | Employment status, education and occupation by country, age and sex |
| persona-generator |
This library is released under the MIT License.
MIT License
Copyright (c) 2020-2026 Diego Dasso Migotto
extend()JSON and Replay. to_json() on every result, and a signature() recording the seed and the data it came from.
Compiled-in Data. Define DASMIG_BIRTH_EMBED to build the lite tier into the program, for WebAssembly and other builds without files.
Multi-Instance Support. Construct independent bthg instances with their own data and random engine.
| Complete characters composed from the other generators |
| phone-generator | Phone numbers valid in each country's numbering plan |
| relationship-generator | Families around a person: parents, siblings, partners and children |
| trait-generator | Personality traits with conflicts, synergies and Big Five axes |
| user-generator | Complete user records: account, username, email, phone and address |