Make great documentation goal 1.2, and plan the README's reorganisation and the nested-template gaps #33
+2
-2
@@ -69,8 +69,8 @@ replacement, and each removed path, column or flag.
|
||||
- `geo.SE` and `geo.US`: five linked tables per country, `region`, `municipality`,
|
||||
`locality`, `postal-code` and `street`, weighted by population and address counts
|
||||
and built from SCB, GeoNames, Trafikverket NVDB and the US Census Bureau, and an
|
||||
`address` record binding one street and reading its locality, postal code and region
|
||||
through it. `sv_SE.address` and `en_US.address` bind those records once, so
|
||||
`address` record binding one locality and drawing its street and postal code inside
|
||||
it. `sv_SE.address` and `en_US.address` bind those records once, so
|
||||
`en_US.address.street` no longer carries `name` and `suffix`, and a locale folder
|
||||
loads only beside `geo`.
|
||||
- `{date(from,to,'layout')}` and `{time('layout')}`: a second between two days, or
|
||||
|
||||
@@ -238,8 +238,7 @@ too, so a person's prefix never contradicts it. A `personnummer`'s birth number,
|
||||
for a man, which no real person is ever given.
|
||||
|
||||
A person of a chosen sex is assembled from the tables — `sex[f].first-name` beside
|
||||
`last-name` — while a shipped `personnummer` draws its own sex, apart from any `person`
|
||||
beside it. That test series is also small: a personnummer
|
||||
`last-name`. Skatteverket's 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,
|
||||
@@ -249,9 +248,9 @@ your own. `sv_SE.date` and `en_US.date` are uniform over 1970-01-01 to 2029-12-3
|
||||
inside a sex.
|
||||
|
||||
A `geo` folder holds one tree per country under its alpha-2 code: five
|
||||
[linked tables](#linked-tables) named alike, and an `address` record binding one street and
|
||||
reading its locality, postal code and region through it, which the locale's `address`
|
||||
binds once and prints whole.
|
||||
[linked tables](#linked-tables) named alike, and an `address` record binding one locality
|
||||
and drawing its street and postal code inside it, which the locale's `address` binds once
|
||||
and prints whole.
|
||||
|
||||
| Table | `geo.SE` | `geo.US` | Weight |
|
||||
|-------|----------|----------|--------|
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"format": "{street} {street-number}\n{postal-code} {locality}",
|
||||
"street": "{.street as s}{s.name}",
|
||||
"street": "{.locality as l}{l.street.name}",
|
||||
"street-number": [
|
||||
"{int(1,9)}",
|
||||
"{int(10,99)}",
|
||||
@@ -9,6 +9,6 @@
|
||||
{ "format": "{int(10,99)}{upper(1)}", "weight": 0.1 },
|
||||
{ "format": "{int(100,999)}{upper(1)}", "weight": 0.05 }
|
||||
],
|
||||
"postal-code": "{s..locality.postal-code.code}",
|
||||
"locality": "{s..locality.name}"
|
||||
"postal-code": "{l.postal-code.code}",
|
||||
"locality": "{l.name}"
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"format": "{street-number} {street}\n{locality}, {region} {postal-code}",
|
||||
"street": "{.street as s}{s.name}",
|
||||
"street": "{.locality as l}{l.street.name}",
|
||||
"street-number": [
|
||||
"{int(10,99)}",
|
||||
{ "format": "{int(100,999)}", "weight": 2 },
|
||||
{ "format": "{int(1000,9999)}", "weight": 0.5 },
|
||||
{ "format": "{int(10,99)}{int(100,999)}", "weight": 0.3 }
|
||||
],
|
||||
"locality": "{s..locality.name}",
|
||||
"region": "{s..locality..municipality..region.abbr}",
|
||||
"postal-code": "{s..locality.postal-code.code}"
|
||||
"locality": "{l.name}",
|
||||
"region": "{l..municipality..region.abbr}",
|
||||
"postal-code": "{l.postal-code.code}"
|
||||
}
|
||||
|
||||
+24
-9
@@ -268,9 +268,10 @@ func TestShippedPersonNames(t *testing.T) {
|
||||
seen := map[string]bool{}
|
||||
for i := 0; i < 2000; i++ {
|
||||
seen[fake(t, f, locale+".sex[f].first-name")] = true
|
||||
first, sex := fake(t, f, locale+".person.first"), fake(t, f, locale+".person.sex")
|
||||
if first == "" || sex == "" {
|
||||
t.Fatalf("%s.person lacks a first name or a sex", locale)
|
||||
got := fakeTemplate(t, f, `{/`+locale+`.person.first}|{/`+locale+`.person.sex}`)
|
||||
first, sex, _ := strings.Cut(got, "|")
|
||||
if v := fake(t, f, locale+".sex["+sex+"].first-name["+first+"]"); v != first {
|
||||
t.Fatalf("%s: %q: %q is not a %s name", locale, got, first, sex)
|
||||
}
|
||||
}
|
||||
if len(seen) < 300 || !seen["Anna"] && locale == "sv_SE" || !seen["Mary"] && locale == "en_US" {
|
||||
@@ -339,22 +340,36 @@ func TestShippedSwedishAddress(t *testing.T) {
|
||||
// one address category are two addresses.
|
||||
func TestShippedAddressIsOneNamedPick(t *testing.T) {
|
||||
f := newGenerator(t, "data", WithSeed(3))
|
||||
for _, c := range []struct{ locale, country, template string }{
|
||||
{"sv_SE", "SE", "{a.street}|{a.postal-code}|{a.locality}||{b.street}"},
|
||||
{"en_US", "US", "{a.street}|{a.postal-code}|{a.locality}|{a.region}|{b.street}"},
|
||||
for _, c := range []struct{ locale, country, template, largest string }{
|
||||
{"sv_SE", "SE", "{a.street}|{a.postal-code}|{a.locality}||{b.street}", "Stockholm"},
|
||||
{"en_US", "US", "{a.street}|{a.postal-code}|{a.locality}|{a.region}|{b.street}", "New York"},
|
||||
} {
|
||||
places := geoPlaces(t, c.country)
|
||||
apart := false
|
||||
for i := 0; i < 300; i++ {
|
||||
apart, localities := false, map[string]int{}
|
||||
for i := 0; i < 2000; i++ {
|
||||
got := fakeTemplate(t, f, `{/`+c.locale+`.address as a}{/`+c.locale+`.address as b}`+c.template)
|
||||
parts := strings.Split(got, "|")
|
||||
if !places[strings.Join(parts[:4], "|")] {
|
||||
t.Fatalf("%s.address: %q is no street, postal code, locality and region of one place", c.locale, got)
|
||||
}
|
||||
apart = apart || parts[0] != parts[4]
|
||||
localities[parts[2]]++
|
||||
region := "{/" + c.locale + ".address.region}"
|
||||
if c.country == "SE" {
|
||||
region = ""
|
||||
}
|
||||
got = fakeTemplate(t, f, `{/`+c.locale+`.address.street}|{/`+c.locale+`.address.postal-code}|{/`+c.locale+`.address.locality}|`+region)
|
||||
if !places[got] {
|
||||
t.Fatalf("%s.address: field paths %q are no street, postal code, locality and region of one place", c.locale, got)
|
||||
}
|
||||
}
|
||||
if !apart {
|
||||
t.Errorf("%s: two names bound to address drew one street in 300 renders, want two addresses", c.locale)
|
||||
t.Errorf("%s: two names bound to address drew one street in 2000 renders, want two addresses", c.locale)
|
||||
}
|
||||
for l, n := range localities {
|
||||
if n > localities[c.largest] {
|
||||
t.Errorf("%s.address drew %s %d times and %s %d, want the locality weighted by population", c.locale, l, n, c.largest, localities[c.largest])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -861,8 +861,8 @@ name is an error listing both keys; select by type instead.
|
||||
A Luhn-valid personnummer over a random birth number may be a living person's; 238 and
|
||||
239 after any date are blocked from assignment, so the shipped `personnummer` and
|
||||
`samordningsnummer` use those. They sit in a `birth-number` table under `sex` rather
|
||||
than as a column of it: the render's shared draw of the family is what makes the number
|
||||
and the name agree on sex, and `sex` stays one shape across locales instead of
|
||||
than as a column of it, so a pick of a sex can read the number, which `todo.md` item 28
|
||||
has `personnummer` do to agree with a person's sex, and `sex` stays one shape across locales instead of
|
||||
collecting every sex-keyed id fact. A samordningsnummer's day, the birthday plus 60, is
|
||||
drawn from 61 to 88, valid in every month, rather than computed from the date drawn.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user