Weighted person names, valid personal ids and date() in both locales #21

Merged
lilleman merged 38 commits from person-ids-date into main 2026-09-18 20:45:51 +02:00
3 changed files with 59 additions and 16 deletions
Showing only changes of commit 6b0a2a60a8 - Show all commits
+17 -8
View File
@@ -34,15 +34,24 @@ replacement, and each removed path, column or flag.
`en_US.address` read those records, so `en_US.address.street` no longer carries `en_US.address` read those records, so `en_US.address.street` no longer carries
`name` and `suffix`, and a locale folder loads only beside `geo`. `name` and `suffix`, and a locale folder loads only beside `geo`.
- `{date(from,to,'layout')}` and `{time('layout')}`: a second between two days, or - `{date(from,to,'layout')}` and `{time('layout')}`: a second between two days, or
within one, in a quoted Go layout. `sv_SE.date`, `en_US.date`, `sv_SE.time` and within one, in a single-quoted Go layout, drawn in UTC; `from` may equal `to`.
`en_US.time` render through them, so `date.year`, `date.month`, `date.day` and `sv_SE.date`, `en_US.date`, `sv_SE.time` and `en_US.time` render through them, so
`time.hour` are no longer paths, and `misc.datetime` is an RFC 3339 instant. `date.year`, `date.month`, `date.day`, `time.hour`, `time.minute`, `time.minute.t`,
`time.sec` and `time.ampm` are no longer paths — a part of a date is now its own
`{date(…,'2006')}`. `misc.datetime` is an RFC 3339 instant.
- `sex`, `first-name` and `last-name` tables in `sv_SE` and `en_US`, weighted by - `sex`, `first-name` and `last-name` tables in `sv_SE` and `en_US`, weighted by
bearers from SCB, the SSA and the Census Bureau; `first-name` links to `sex`, and a bearers from SCB, the SSA and the Census Bureau; `first-name` links to `sex`, and a
name both sexes carry is a row under each. `person` reads them, so its columns are name both sexes carry is a row under each. `person` reads them, so its columns are
`first`, `last`, `prefix` and `sex`, and `person.femalefirst` and `first`, `last`, `prefix` and `sex`; `person.femalefirst` and `person.malefirst` are
`person.malefirst` are no longer paths. no longer paths — draw `sex[f].first-name` and `sex[m].first-name` instead.
`en_US.title` links to `sex` as well, so `en_US.person.prefix` draws `Mr` or `Ms`
without contradicting the record's `sex`.
- `sv_SE.personnummer` and `sv_SE.samordningsnummer`, Skatteverket's test series - `sv_SE.personnummer` and `sv_SE.samordningsnummer`, Skatteverket's test series
from a `sv_SE.birth-number` table under `sex`, in place of `sv_SE.ssn`; `en_US.ssn` from a `sv_SE.birth-number` table under `sex`, in place of `sv_SE.ssn`, whose
in the ranges the SSA assigns, and `en_US.itin`. `en_US.person.prefix` no longer `ssn.mmdd`, `ssn.mmdd.m` and `ssn.mmdd.d` go with it. `en_US.ssn` now draws the
draws `Mr`, `Mrs`, `Ms` or `Miss`, which could contradict the record's `sex`. ranges the SSA assigns and carries the columns `area`, `group` and `serial`, so
`--format csv en_US.ssn` writes a header where it used to fail; `en_US.itin` is new.
- An error names a spelling that runs: a layout is named single-quoted and free of
its own quotes, a row of a table with no key is named as the path that selects it,
`sv_SE.sex[f].first-name[Kim]`, and a category with no columns names the record
that gives it one.
+35 -5
View File
@@ -22,6 +22,7 @@ fejkdata 'geo.SE.locality[Lund].street' # Fjelievägen — a linked tabl
fejkdata --data-path ./mydata sv_SE.word # layer a directory over the shipped data fejkdata --data-path ./mydata sv_SE.word # layer a directory over the shipped data
fejkdata --no-shipped-data -d ./mydata --list # only your data fejkdata --no-shipped-data -d ./mydata --list # only your data
fejkdata 'name: {/sv_SE.person.last}' # name: <a surname> — an inline template fejkdata 'name: {/sv_SE.person.last}' # name: <a surname> — an inline template
fejkdata "{date(1990-01-01,2010-12-31,'2006-01-02')}" # 2003-11-27 — the argument in "…", the layout in '…'
fejkdata '{"format":"name: {x}","x":["bosse","lina"]}' # name: bosse or name: lina fejkdata '{"format":"name: {x}","x":["bosse","lina"]}' # name: bosse or name: lina
``` ```
@@ -237,7 +238,16 @@ draws a woman's name, and a name both sexes carry is a row under each, so
`person` reads one draw of the three, so its `first` and `sex` columns agree, and so `person` reads one draw of the three, so its `first` and `sex` columns agree, and so
does a `personnummer` in the same render: its birth number, `sv_SE.birth-number` does a `personnummer` in the same render: its birth number, `sv_SE.birth-number`
under `sex`, is Skatteverket's test series, 238 for a woman and 239 for a man, which no under `sex`, is Skatteverket's test series, 238 for a woman and 239 for a man, which no
real person is ever given. real person is ever given. `en_US.title` links to `sex` too, so a person's prefix
never contradicts it.
A person of a chosen sex is assembled from the tables — `sex[f].first-name` beside
`last-name` — while a shipped `personnummer` agrees with the sex its own render
*drew*, not with one a path selects. That test series is also small: a personnummer
is one of about 70,000 values, a day in 1930–2025 against the two birth numbers, so a
fixture past a few hundred rows repeats one and a `UNIQUE` column needs a category of
your own. `sv_SE.date` and `en_US.date` are uniform over 1970-01-01 to 2029-12-31,
`misc.datetime` over 2000-01-01 to 2029-12-31.
A `geo` folder holds one tree per country under its alpha-2 code: five A `geo` folder holds one tree per country under its alpha-2 code: five
[linked tables](#linked-tables) named alike, and an `address` record over one [linked tables](#linked-tables) named alike, and an `address` record over one
@@ -536,12 +546,14 @@ them a birthdate:
Renders e.g. `811218-2389`. A layout is Go's: the reference time `Mon Jan 2 Renders e.g. `811218-2389`. A layout is Go's: the reference time `Mon Jan 2
15:04:05 MST 2006` spelled as the output should look, quoted, since a layout may 15:04:05 MST 2006` spelled as the output should look, quoted, since a layout may
carry the comma that separates arguments, with English names. Every second carry the comma that separates arguments, with English names. Every second
between the two days is reachable, so a layout with a clock draws the time too. between the two days is reachable, so a layout with a clock draws the time too, and
`from` may equal `to`, which is that one day. The instant is UTC, so a zone in the
layout prints `UTC` or `Z`.
The quotes delimit a layout outside a selector only, so `[O'Fallon]` in an The quotes delimit a layout outside a selector only, so `[O'Fallon]` in an
argument stays a name. Rejected at `New`: a bound that is no calendar date, or not argument stays a name. Rejected at `New`: a bound that is no calendar date, or not
before the other; an unquoted layout, naming the quoted one; a layout naming no field, which is text; before the other; an unquoted layout, naming the single-quoted one; a layout naming no field, which is
for `date` a layout naming no date field, naming `time`; and for `time` a layout text, as is one day in a layout with no clock; for `date` a layout naming no date
naming a date field, naming `date`. `{seq()}` spans `Fake` field, naming `time`; and for `time` a layout naming a date field, naming `date`. `{seq()}` spans `Fake`
calls and `repeat`, resets with a new generator, and is the natural primary key for calls and `repeat`, resets with a new generator, and is the natural primary key for
the SQL example above. the SQL example above.
@@ -721,6 +733,15 @@ datatype and nullability, and each table's key, name, weight and parent columns;
changes it or `data/` adds its `CHANGELOG.md` entry, which CI checks. A removed, changes it or `data/` adds its `CHANGELOG.md` entry, which CI checks. A removed,
renamed or retyped line is a major. renamed or retyped line is a major.
## Audience
App developers writing tests and fixtures, in Go and at a shell:
- a **bulk fixture author**, thousands of rows into CSV or SQL
- a **Go test author**, filling a struct with `FakeStruct`
- a **hand fixture author**, one value at a shell
- a **validator-facing author**, who needs a value a real checker accepts
## Goals ## Goals
1. **Valid by construction** — every value passes the check its real consumer 1. **Valid by construction** — every value passes the check its real consumer
@@ -1063,12 +1084,21 @@ renamed or retyped line is a major.
bigger neighbour ship no address; counting the land outside every place too would bigger neighbour ship no address; counting the land outside every place too would
drop a quarter of the places, whose codes straddle unincorporated land, for a drop a quarter of the places, whose codes straddle unincorporated land, for a
postal city the USPS mostly names the same way. postal city the USPS mostly names the same way.
- **`--list` stays a plain list of paths.** It is what a script reads, so every line
has to be a path that `Fake` takes; a marker for the tables a `[selector]` follows,
or a legend above them, would make the output something to parse before use.
`--help` names the selector spelling instead, and the Table section teaches it.
- **A layout is always quoted.** A layout may carry the comma that separates - **A layout is always quoted.** A layout may carry the comma that separates
arguments, `'January 2, 2006'`, and one spelling for every layout beats a rule arguments, `'January 2, 2006'`, and one spelling for every layout beats a rule
about which ones need the quotes, so the bare spelling is refused naming the about which ones need the quotes, so the bare spelling is refused naming the
quoted one. The layout is Go's reference time because the library renders with quoted one. The layout is Go's reference time because the library renders with
it and a Go caller already knows it; its names are English, and a locale's own it and a Go caller already knows it; its names are English, and a locale's own
month and weekday names are data. month and weekday names are data.
- **A title is a table under `sex`.** A prefix drawn apart would put `Mr` on a record
whose `sex` column says `female`, which is the disagreement the record exists to
prevent; the tables this set already has are what a title needs, so `en_US.title`
links to `sex` as `first-name` does. Swedish has no everyday sexed honorific, so
`sv_SE` keeps an unsexed `dr` and `prof`.
- **No builtin reads the clock, so a date is bounded by days, never by an age.** - **No builtin reads the clock, so a date is bounded by days, never by an age.**
An `age(min,max)` would make a seeded fixture change with the day it runs on, An `age(min,max)` would make a seeded fixture change with the day it runs on,
which is what a seed exists to prevent; a birthdate for someone 20 to 60 is which is what a seed exists to prevent; a birthdate for someone 20 to 60 is
+7 -3
View File
@@ -164,9 +164,13 @@ address, phone, national id, company and date names each.
1. Table node, key and name selection, parent links, consistent draws, the 1. Table node, key and name selection, parent links, consistent draws, the
choice-of-rows fence, `DATA-LICENSES.md`, `data-import/` — done. choice-of-rows fence, `DATA-LICENSES.md`, `data-import/` — done.
2. `geo/SE` and `geo/US`, and `address` in both locales on top of them — done. 2. `geo/SE` and `geo/US`, and `address` in both locales on top of them — done.
3. Weighted person names and valid ids in both locales; `date()` — done. Middle 3. Weighted person names and valid ids in both locales; `date()` — done. Left for
names wait for a draw group that shares its family's pins, so a second name later: middle names, and drawing a shipped `personnummer` inside a *selected*
is drawn under the same sex. sex, both of which want a draw group that shares its family's pins — until then
the conflict error can name a rewrite that returns a different value when the
read it conflicts with sits inside another category. Give the national ids one
record shape in step 6, and report a struct column's draw conflict with the path
spelling a tag takes rather than the reference spelling.
4. `misc` conversions and the new `misc` tables. 4. `misc` conversions and the new `misc` tables.
5. The remaining locale categories: company, phone, finance, vehicle, words. 5. The remaining locale categories: company, phone, finance, vehicle, words.
6. Records with building-block columns across the shipped set; shape re-pin. 6. Records with building-block columns across the shipped set; shape re-pin.