@finbheara/archive-client 0.52.0 → 0.53.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -4
- package/dist/chunks/{index-csh5d5m4.js → index-aj1n1q7j.js} +158 -25
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/dist/types/dancers.d.ts +1 -0
- package/dist/types/feises.d.ts +1 -0
- package/dist/types/school-tables.d.ts +8 -0
- package/dist/types/stream.d.ts +2 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -90,6 +90,7 @@ c.features; // [{ feature: "dancers", state: "full" | "missing", missing: [...
|
|
|
90
90
|
| `results.stream`, `majors.stream` | `results.stream`, `results.entries` | 255 |
|
|
91
91
|
| `results.stream.competition`, `majors.stream.competition` | the competition fields a streamed row carries (`competition_line`, `dance_printed`, `dance`, `recalled_only`, `comp_flags`, `competitors_basis`); absent, never refused, without them | 270 |
|
|
92
92
|
| `feises.dates` | `feises.dates` | 245 |
|
|
93
|
+
| `feises.name` | the `name` `feises.find` and `feises.series` answer: the release's reading, the label as printed except where it lost a letter (U+FFFD) the feis's own pages print clean; `name_printed` beside it is the label verbatim. Without it `name` is the label, never refused | 350 |
|
|
93
94
|
| `dancers.records` | `dancers.records` | 215 |
|
|
94
95
|
| `dancers.records.names` | the `names_printed` a record of `dancers.records` carries; absent, never refused, without it | 215 |
|
|
95
96
|
| `dancers.years` | `dancers.years` | 245 |
|
|
@@ -98,6 +99,7 @@ c.features; // [{ feature: "dancers", state: "full" | "missing", missing: [...
|
|
|
98
99
|
| `results.major`, `majors.major` | the `major` a row of `results.stream` and `results.entries` carries (1 where its competition is a main event of a T1-T3 event, exactly the rows `majors.sqlite` holds); absent without it, and the stream filter `major` is refused by name without it | 345 |
|
|
99
100
|
| `results.relative_place_err`, `majors.relative_place_err` | the `relative_place_err` a row of `results.stream` and `results.entries` carries (how far below `relative_place` the true value may sit, 0 over an exact field); absent, never refused, without it | 350 |
|
|
100
101
|
| `results.marks_printed`, `majors.marks_printed` | the `marks_printed` a row of `results.stream` and `results.entries` carries (the marks total a row served or printed, iFeis's beside its `points` and a Bucharest transcript row's, one string verbatim); absent, never refused, without it | 350 |
|
|
102
|
+
| `results.status_printed`, `majors.status_printed` | the `status_printed` a row of `results.stream` and `results.entries` carries (a transcribed row's status cell as printed, verbatim, in printed order, `[]` where none); absent, never refused, without it | 350 |
|
|
101
103
|
| `results.round_points_printed`, `majors.round_points_printed` | the `round_points_printed` a row of `results.stream` and `results.entries` carries (the per-round points a platform served, FeisFWD's, in its slot order, a slot served nothing in null); absent, never refused, without it | 350 |
|
|
102
104
|
| `dancers.records.birth_consistency`, `dancers.years.birth_consistency` | the `birth_consistency` (0-100, floored: the percent of the dancer's, or the dancer-year's, readable rows that fit the birth window) and its denominator `birth_consistency_rows` a record of `dancers.records` and a dancer-year of `dancers.years` carry; absent, never refused, without it | 345 |
|
|
103
105
|
| `dancers.records.birth_deadband`, `dancers.years.birth_deadband` | the `birth_deadband_rows` a record of `dancers.records` and a dancer-year of `dancers.years` carry (the readable rows a one-year dance-up alone keeps off the birth window, outside `birth_consistency` and its denominator); absent, never refused, without it | 345 |
|
|
@@ -122,6 +124,7 @@ c.features; // [{ feature: "dancers", state: "full" | "missing", missing: [...
|
|
|
122
124
|
| `schools.registry` | `schools.list` | 260 |
|
|
123
125
|
| `schools.prints`, `schools.redirects` | `schools.prints`; `schools.redirects` | 184 |
|
|
124
126
|
| `schools.lineage` | `schools.links`, `schools.line`, `schools.lineage` | 184 |
|
|
127
|
+
| `school-graph` | the tables `schools.redirects`, `schools.lineage`, `schools.links`, `schools.line` and a dancer question's lineage read in place of the jsonl, the same answers; the jsonl, never refused, without them | none yet |
|
|
125
128
|
| `schools.associations` | `schools.associations` | 215 |
|
|
126
129
|
|
|
127
130
|
A spec is `pinned` (the default: the user-local pin, else the latest), `latest`, a cut number
|
|
@@ -258,8 +261,8 @@ await rel.feises.find({ id: "<feis, series instance or brand id>" }); // a reti
|
|
|
258
261
|
await rel.feises.find({ name: "*Spring*", year: 2024 });
|
|
259
262
|
```
|
|
260
263
|
|
|
261
|
-
One answer per feis id:
|
|
262
|
-
and captures it has.
|
|
264
|
+
One answer per feis id: its `name` and the label as printed (`name_printed`), dates, location,
|
|
265
|
+
series ids, regions, and how many competitions, rows and captures it has. A name glob reads both.
|
|
263
266
|
|
|
264
267
|
```ts
|
|
265
268
|
const s = await rel.feises.series("Ardvarna Spring"); // a name, a host code ("fweb:ABC", "fweb:ABC26"), any feis id
|
|
@@ -323,6 +326,20 @@ await rel.schools.associations({ school_id: "<id>" });
|
|
|
323
326
|
// association_type, src_type, src, candidate_school_id, candidate_rung, ... }] }
|
|
324
327
|
```
|
|
325
328
|
|
|
329
|
+
THE SCHOOL GRAPH'S TABLES (feature `school-graph`): a release whose `results.sqlite` carries
|
|
330
|
+
`school_nodes`, `school_edges` and `school_aliases` answers `redirects`, `lineage`, `links`,
|
|
331
|
+
`line` and a dancer question's lineage from them, and one without them from
|
|
332
|
+
`school-redirects.jsonl` and `school-lineage.jsonl`, as before. The answers are the same rows in
|
|
333
|
+
the same order: a redirect is an alias of kind `fold` or `reslug`, or a former school (a node
|
|
334
|
+
with `closed_into`) to the school that absorbed it, each landing on a live school in one hop; a
|
|
335
|
+
lineage edge is a `school_edges` row of a lineage kind (`rename`, `absorb`, `merger`, `split`,
|
|
336
|
+
`branch`, `related`) with no `lag_months`, given as its two ends, its `decision` the first of its
|
|
337
|
+
`decision_rows`. A former school's absorbed-by line (the one with `lag_months`), a `distinct`,
|
|
338
|
+
`disbanded`, banner or tie line, and a `shelf`, `site_fold`, path, print or `retired` alias are
|
|
339
|
+
none of these, as the jsonl publishes none of them: an id the tables hold only that way answers
|
|
340
|
+
nothing, never a guess. The tables round a `confidence` to 6 places, and the jsonl writes
|
|
341
|
+
`1 - posterior` unrounded, so the two can differ past the sixth place.
|
|
342
|
+
|
|
326
343
|
`prints` is every (print, school id) pair the release's result rows attach in an event-year (the
|
|
327
344
|
print trimmed), with the rows that carry it: an event's (case-blind), a year's, both or every one.
|
|
328
345
|
A row attached to no school is in no pair, and a team result's school is `rel.teams.results`'.
|
|
@@ -380,6 +397,8 @@ r.unlinked; // rows printing a matched name that the release linked to no dan
|
|
|
380
397
|
await rel.dancers.search({ surname: "Quellan" }); // or { like: "a* quellan" }, or { name }
|
|
381
398
|
// at most `limit` (default 50, 0 for all);
|
|
382
399
|
// `truncated` counts the rest
|
|
400
|
+
// a surname folds as the print's key does:
|
|
401
|
+
// `Karłowska` and `Karlowska` ask one key
|
|
383
402
|
await rel.dancers.get(1001); // every print and school of one dancer
|
|
384
403
|
```
|
|
385
404
|
|
|
@@ -407,13 +426,14 @@ names package's Spanish reading (`createNameKinship({ spanishNames: true })`), a
|
|
|
407
426
|
relates is a candidate at `nameLevel: "spanish"`. A release with no `spanish_names` reads every
|
|
408
427
|
school the default way. A name the release already finds answers exactly as before.
|
|
409
428
|
|
|
410
|
-
THE LINEAGE is the release's `school-lineage.jsonl
|
|
429
|
+
THE LINEAGE is the release's `school-lineage.jsonl` (or its `school_edges`, where it carries the
|
|
430
|
+
school graph's tables, the same edges): every line joins its `id` and its `other`,
|
|
411
431
|
whatever its direction (`precedes`, `succeeds`) or shape (a rename, a split, a merger, an absorb,
|
|
412
432
|
a relation), so a file carrying one end of an edge reads as one carrying both. The whole line
|
|
413
433
|
joins: every school reached through any number of edges, in either direction (the two halves of a
|
|
414
434
|
split are joined through their predecessor, the schools of a merger through their successor). An
|
|
415
435
|
earlier row at a joined school alone is no match. `r.school.lineage` lists the ids joined to the
|
|
416
|
-
asked ones. A release that publishes no lineage (feature `schools.lineage`) joins
|
|
436
|
+
asked ones. A release that publishes no lineage (feature `schools.lineage`, nor `school-graph`) joins
|
|
417
437
|
nothing and its answer carries no `lineage`, never refused. The line is read on the same school
|
|
418
438
|
graph as `rel.schools.line` (`@finbheara/domain/school-graph`): untimed, every path, and as of a
|
|
419
439
|
year, every path none of whose steps is dated after it, a rename at any year (`LINE_AS_OF`).
|
|
@@ -653,6 +673,12 @@ or summed, and the places follow the points, not the marks. A Bucharest transcri
|
|
|
653
673
|
carries its printed mark the same way, one adjudicator's mark and no `points` (`"80"`). Null where
|
|
654
674
|
the row carries none and on every other source's row.
|
|
655
675
|
|
|
676
|
+
THE STATUS CELL AS PRINTED, where the release carries it
|
|
677
|
+
(`rel.capability("results.status_printed")`): `status_printed`, a transcribed row's status cell
|
|
678
|
+
verbatim, in printed order (`["Not Recalled"]`, `["-"]`, `["*"]`, `["WQ"]`). `atts` is the
|
|
679
|
+
reading of the same cell, so a cell it reads as nothing (`-`, `Not Recalled`) is told apart from
|
|
680
|
+
a blank cell here. `[]` where the row prints none, and on every platform row.
|
|
681
|
+
|
|
656
682
|
THE COMPETITION FIELDS, where the release carries them (`rel.capability("results.stream.competition")`,
|
|
657
683
|
`"majors.stream.competition"` for scope `majors`), are on every row, null meaning no value:
|
|
658
684
|
|
|
@@ -141,7 +141,6 @@ import {
|
|
|
141
141
|
} from "@finbheara/domain/title";
|
|
142
142
|
import {
|
|
143
143
|
composeNames,
|
|
144
|
-
foldNameKey,
|
|
145
144
|
nameBlockKeys,
|
|
146
145
|
nameKinship as nameKinship2,
|
|
147
146
|
surnameBlock
|
|
@@ -606,6 +605,18 @@ var FEATURES2 = [
|
|
|
606
605
|
since: 350,
|
|
607
606
|
calls: "the same on a row of results.stream and results.entries (scope majors)"
|
|
608
607
|
},
|
|
608
|
+
{
|
|
609
|
+
feature: "results.status_printed",
|
|
610
|
+
needs: ["results:results.status_printed"],
|
|
611
|
+
since: 350,
|
|
612
|
+
calls: "the `status_printed` a row of results.stream and results.entries carries (a transcribed row's status cell as printed, verbatim, in printed order, `[]` where none): absent, never refused, on a release without it"
|
|
613
|
+
},
|
|
614
|
+
{
|
|
615
|
+
feature: "majors.status_printed",
|
|
616
|
+
needs: ["majors:results.status_printed"],
|
|
617
|
+
since: 350,
|
|
618
|
+
calls: "the same on a row of results.stream and results.entries (scope majors)"
|
|
619
|
+
},
|
|
609
620
|
{
|
|
610
621
|
feature: "majors.attach_basis",
|
|
611
622
|
needs: ["majors:results.attach_basis"],
|
|
@@ -624,6 +635,12 @@ var FEATURES2 = [
|
|
|
624
635
|
since: 245,
|
|
625
636
|
calls: "feises.dates"
|
|
626
637
|
},
|
|
638
|
+
{
|
|
639
|
+
feature: "feises.name",
|
|
640
|
+
needs: ["results:feises.name", "results:feises.name_source"],
|
|
641
|
+
since: 350,
|
|
642
|
+
calls: "the `name` feises.find and feises.series answer (the release's reading: the label as printed, except where it lost a letter the feis's own pages print); on a release without it, `name` is the label as printed, never refused"
|
|
643
|
+
},
|
|
627
644
|
{
|
|
628
645
|
feature: "dancers.records",
|
|
629
646
|
needs: [
|
|
@@ -1061,6 +1078,25 @@ var FEATURES2 = [
|
|
|
1061
1078
|
since: 184,
|
|
1062
1079
|
calls: "schools.redirects"
|
|
1063
1080
|
},
|
|
1081
|
+
{
|
|
1082
|
+
feature: "school-graph",
|
|
1083
|
+
needs: [
|
|
1084
|
+
...["alias", "kind", "node_id", "school_id"].map((c) => `results:school_aliases.${c}`),
|
|
1085
|
+
...["node_id", "kind", "minted_reslug_from", "minted_reslug_pass", "closed_into"].map((c) => `results:school_nodes.${c}`),
|
|
1086
|
+
...[
|
|
1087
|
+
"from_id",
|
|
1088
|
+
"to_id",
|
|
1089
|
+
"kind",
|
|
1090
|
+
"valid_from",
|
|
1091
|
+
"provisional",
|
|
1092
|
+
"confidence",
|
|
1093
|
+
"decision_rows",
|
|
1094
|
+
"lag_months"
|
|
1095
|
+
].map((c) => `results:school_edges.${c}`)
|
|
1096
|
+
],
|
|
1097
|
+
since: 365,
|
|
1098
|
+
calls: "schools.redirects, schools.lineage, schools.links, schools.line and the `lineage` school evidence of dancers.resolve and dancers.search read the tables, the same answers as the jsonl; without them, the jsonl, never refused"
|
|
1099
|
+
},
|
|
1064
1100
|
{
|
|
1065
1101
|
feature: "schools.associations",
|
|
1066
1102
|
needs: ["observed-associations.jsonl"],
|
|
@@ -1159,7 +1195,7 @@ var describeEvent = (e) => {
|
|
|
1159
1195
|
var SCHEMA = `
|
|
1160
1196
|
CREATE TABLE feis(
|
|
1161
1197
|
feis_id TEXT PRIMARY KEY, source TEXT NOT NULL, token TEXT NOT NULL, host_id TEXT NOT NULL,
|
|
1162
|
-
name TEXT NOT NULL, date_lo TEXT, date_hi TEXT, date_printed TEXT, year INTEGER,
|
|
1198
|
+
name TEXT NOT NULL, name_printed TEXT NOT NULL, date_lo TEXT, date_hi TEXT, date_printed TEXT, year INTEGER,
|
|
1163
1199
|
location TEXT, instance_id TEXT, brand_id TEXT, regions TEXT NOT NULL,
|
|
1164
1200
|
competitions INTEGER NOT NULL, rows INTEGER NOT NULL, captures INTEGER NOT NULL
|
|
1165
1201
|
);
|
|
@@ -1179,7 +1215,7 @@ function readJsonl(path) {
|
|
|
1179
1215
|
}
|
|
1180
1216
|
var feisesIndex = {
|
|
1181
1217
|
name: "feises",
|
|
1182
|
-
version: "
|
|
1218
|
+
version: "3",
|
|
1183
1219
|
inputs: ["results", "feis-redirects.jsonl"],
|
|
1184
1220
|
says: "every feis by id, platform, code, series and name, with its counts and regions",
|
|
1185
1221
|
build(rel, out) {
|
|
@@ -1194,15 +1230,16 @@ var feisesIndex = {
|
|
|
1194
1230
|
const rows = new Map;
|
|
1195
1231
|
for (const r of src.query("SELECT c.event AS event, sum(r.n) AS n FROM (SELECT competition, count(*) AS n FROM results GROUP BY competition) r JOIN (SELECT DISTINCT competition, event FROM competitions) c ON c.competition = r.competition GROUP BY c.event").all())
|
|
1196
1232
|
rows.set(r.event, r.n);
|
|
1197
|
-
const put = out.prepare("INSERT OR IGNORE INTO feis VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
1233
|
+
const put = out.prepare("INSERT OR IGNORE INTO feis VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
1198
1234
|
const captures = new Map;
|
|
1199
|
-
const
|
|
1235
|
+
const named = columnsOf2(src, "feises").has("name");
|
|
1236
|
+
const feisRows = src.query(`SELECT feis_id, source, host_id, name_printed, ${named ? "name" : "name_printed AS name"}, date_lo, date_hi, date_printed, year, location_printed, feis_instance_id, feis_brand_id FROM feises ORDER BY file, line`).all();
|
|
1200
1237
|
for (const f of feisRows)
|
|
1201
1238
|
captures.set(f.feis_id, (captures.get(f.feis_id) ?? 0) + 1);
|
|
1202
1239
|
for (const f of feisRows) {
|
|
1203
1240
|
const c = counts.get(f.feis_id);
|
|
1204
1241
|
const colon = f.feis_id.indexOf(":");
|
|
1205
|
-
put.run(f.feis_id, f.source, colon === -1 ? f.source : f.feis_id.slice(0, colon), f.host_id, f.name_printed, f.date_lo, f.date_hi, f.date_printed, f.year, f.location_printed, f.feis_instance_id, f.feis_brand_id, JSON.stringify([...c?.regions ?? []].sort()), c?.comps ?? 0, rows.get(f.feis_id) ?? 0, captures.get(f.feis_id) ?? 0);
|
|
1242
|
+
put.run(f.feis_id, f.source, colon === -1 ? f.source : f.feis_id.slice(0, colon), f.host_id, f.name, f.name_printed, f.date_lo, f.date_hi, f.date_printed, f.year, f.location_printed, f.feis_instance_id, f.feis_brand_id, JSON.stringify([...c?.regions ?? []].sort()), c?.comps ?? 0, rows.get(f.feis_id) ?? 0, captures.get(f.feis_id) ?? 0);
|
|
1206
1243
|
}
|
|
1207
1244
|
const red = out.prepare("INSERT OR REPLACE INTO redirect VALUES (?, ?, ?)");
|
|
1208
1245
|
for (const r of readJsonl(rel.path("feis-redirects.jsonl")))
|
|
@@ -1255,8 +1292,8 @@ class FeisFinder2 {
|
|
|
1255
1292
|
args.push(id, id, id);
|
|
1256
1293
|
}
|
|
1257
1294
|
if (q.name !== undefined) {
|
|
1258
|
-
where.push("name LIKE ? ESCAPE '\\'");
|
|
1259
|
-
args.push(globToLike(q.name));
|
|
1295
|
+
where.push("(name LIKE ? ESCAPE '\\' OR name_printed LIKE ? ESCAPE '\\')");
|
|
1296
|
+
args.push(globToLike(q.name), globToLike(q.name));
|
|
1260
1297
|
}
|
|
1261
1298
|
if (q.year !== undefined) {
|
|
1262
1299
|
where.push("year = ?");
|
|
@@ -1564,7 +1601,7 @@ function streamSql(q, shape = {}) {
|
|
|
1564
1601
|
if (q.major !== undefined)
|
|
1565
1602
|
where.push(q.major ? "r.major = 1" : "r.major = 0");
|
|
1566
1603
|
return {
|
|
1567
|
-
sql: `SELECT ${COLUMNS}${shape.competition === true ? COMPETITION_COLUMNS : ""}${shape.competitorsPrinted === true ? ", c.competitors_printed AS competitors_printed" : ""}${shape.attachBasis === true ? ", r.attach_basis AS attach_basis" : ""}${shape.major === true ? ", r.major AS major" : ""}${shape.relativePlaceErr === true ? ", r.relative_place_err AS relative_place_err" : ""}${shape.roundPoints === true ? ", r.round_points_printed AS round_points_printed" : ""}${shape.marks === true ? ", r.marks_printed AS marks_printed" : ""} FROM results r JOIN competitions c ON c.file = r.file AND c.line = r.competition_line${where.length === 0 ? "" : ` WHERE ${where.join(" AND ")}`} ORDER BY r.file, r.line`,
|
|
1604
|
+
sql: `SELECT ${COLUMNS}${shape.competition === true ? COMPETITION_COLUMNS : ""}${shape.competitorsPrinted === true ? ", c.competitors_printed AS competitors_printed" : ""}${shape.attachBasis === true ? ", r.attach_basis AS attach_basis" : ""}${shape.major === true ? ", r.major AS major" : ""}${shape.relativePlaceErr === true ? ", r.relative_place_err AS relative_place_err" : ""}${shape.roundPoints === true ? ", r.round_points_printed AS round_points_printed" : ""}${shape.marks === true ? ", r.marks_printed AS marks_printed" : ""}${shape.status === true ? ", r.status_printed AS status_printed" : ""} FROM results r JOIN competitions c ON c.file = r.file AND c.line = r.competition_line${where.length === 0 ? "" : ` WHERE ${where.join(" AND ")}`} ORDER BY r.file, r.line`,
|
|
1568
1605
|
args
|
|
1569
1606
|
};
|
|
1570
1607
|
}
|
|
@@ -1576,7 +1613,7 @@ function feisDates(db) {
|
|
|
1576
1613
|
}
|
|
1577
1614
|
var text = (v) => v === null || v === "" ? null : v;
|
|
1578
1615
|
function rowOf(r, dates) {
|
|
1579
|
-
const { atts, withdrawn, recalled_only, round_points_printed, ...rest } = r;
|
|
1616
|
+
const { atts, withdrawn, recalled_only, round_points_printed, status_printed, ...rest } = r;
|
|
1580
1617
|
const d = dates.get(r.event);
|
|
1581
1618
|
return {
|
|
1582
1619
|
...rest,
|
|
@@ -1593,6 +1630,7 @@ function rowOf(r, dates) {
|
|
|
1593
1630
|
...round_points_printed === undefined ? {} : {
|
|
1594
1631
|
round_points_printed: round_points_printed === null ? null : JSON.parse(round_points_printed)
|
|
1595
1632
|
},
|
|
1633
|
+
...status_printed === undefined ? {} : { status_printed: JSON.parse(status_printed) },
|
|
1596
1634
|
withdrawn: text(withdrawn),
|
|
1597
1635
|
qualifier: text(rest.qualifier),
|
|
1598
1636
|
primary_source: text(rest.primary_source),
|
|
@@ -1718,6 +1756,7 @@ class ResultFinder2 {
|
|
|
1718
1756
|
const relativePlaceErr = (await this.rel.capability(`${db}.relative_place_err`)).state === "full";
|
|
1719
1757
|
const roundPoints = (await this.rel.capability(`${db}.round_points_printed`)).state === "full";
|
|
1720
1758
|
const marks = (await this.rel.capability(`${db}.marks_printed`)).state === "full";
|
|
1759
|
+
const status = (await this.rel.capability(`${db}.status_printed`)).state === "full";
|
|
1721
1760
|
return {
|
|
1722
1761
|
db: this.rel.db(db),
|
|
1723
1762
|
shape: {
|
|
@@ -1727,7 +1766,8 @@ class ResultFinder2 {
|
|
|
1727
1766
|
major,
|
|
1728
1767
|
relativePlaceErr,
|
|
1729
1768
|
roundPoints,
|
|
1730
|
-
marks
|
|
1769
|
+
marks,
|
|
1770
|
+
status
|
|
1731
1771
|
}
|
|
1732
1772
|
};
|
|
1733
1773
|
}
|
|
@@ -1801,6 +1841,81 @@ class MajorsFinder2 {
|
|
|
1801
1841
|
import {
|
|
1802
1842
|
schoolGraph
|
|
1803
1843
|
} from "@finbheara/domain/school-graph";
|
|
1844
|
+
|
|
1845
|
+
var SCHOOL_GRAPH_FEATURE = "school-graph";
|
|
1846
|
+
var LINEAGE_KINDS = [
|
|
1847
|
+
"rename",
|
|
1848
|
+
"absorb",
|
|
1849
|
+
"merger",
|
|
1850
|
+
"split",
|
|
1851
|
+
"branch",
|
|
1852
|
+
"related"
|
|
1853
|
+
];
|
|
1854
|
+
async function schoolTables(rel) {
|
|
1855
|
+
if ((await rel.capability(SCHOOL_GRAPH_FEATURE)).state !== "full")
|
|
1856
|
+
return null;
|
|
1857
|
+
await rel.fetch("results");
|
|
1858
|
+
return rel.db("results");
|
|
1859
|
+
}
|
|
1860
|
+
var num = (v) => typeof v === "number" ? v : null;
|
|
1861
|
+
var cmp = (a, b) => a < b ? -1 : a > b ? 1 : 0;
|
|
1862
|
+
var suffixOf = (id) => id.slice(id.lastIndexOf("-") + 1);
|
|
1863
|
+
function redirectsOfTables(db) {
|
|
1864
|
+
const rows = db.query(`SELECT a.alias AS old_id, a.school_id AS new_id, a.kind AS kind,
|
|
1865
|
+
n.minted_reslug_from AS reslug_from, n.minted_reslug_pass AS reslug_pass
|
|
1866
|
+
FROM school_aliases a LEFT JOIN school_nodes n ON n.node_id = a.node_id
|
|
1867
|
+
WHERE a.kind IN ('fold', 'reslug') AND a.school_id IS NOT NULL
|
|
1868
|
+
UNION ALL
|
|
1869
|
+
SELECT f.node_id, f.closed_into, NULL,
|
|
1870
|
+
n.minted_reslug_from, n.minted_reslug_pass
|
|
1871
|
+
FROM school_nodes f LEFT JOIN school_nodes n ON n.node_id = f.closed_into
|
|
1872
|
+
WHERE f.kind = 'school' AND f.closed_into IS NOT NULL`).all();
|
|
1873
|
+
const absorber = new Map;
|
|
1874
|
+
for (const r of rows)
|
|
1875
|
+
if (r.kind === null)
|
|
1876
|
+
absorber.set(r.old_id, r.new_id);
|
|
1877
|
+
const live = (id) => {
|
|
1878
|
+
const seen = new Set;
|
|
1879
|
+
let at = id;
|
|
1880
|
+
for (let next = absorber.get(at);next !== undefined && !seen.has(at); next = absorber.get(at)) {
|
|
1881
|
+
seen.add(at);
|
|
1882
|
+
at = next;
|
|
1883
|
+
}
|
|
1884
|
+
return at;
|
|
1885
|
+
};
|
|
1886
|
+
return rows.map((r) => {
|
|
1887
|
+
const named = r.reslug_from === r.old_id;
|
|
1888
|
+
return {
|
|
1889
|
+
old_id: r.old_id,
|
|
1890
|
+
new_id: live(r.new_id),
|
|
1891
|
+
kind: r.kind ?? (named || suffixOf(r.old_id) === suffixOf(r.new_id) ? "reslug" : "fold"),
|
|
1892
|
+
since: num(named ? r.reslug_pass : null)
|
|
1893
|
+
};
|
|
1894
|
+
}).sort((a, b) => cmp(a.old_id, b.old_id) || cmp(a.new_id, b.new_id));
|
|
1895
|
+
}
|
|
1896
|
+
function lineageOfTables(db) {
|
|
1897
|
+
const rows = db.query(`SELECT from_id, to_id, kind, valid_from, provisional, confidence, decision_rows
|
|
1898
|
+
FROM school_edges
|
|
1899
|
+
WHERE kind IN (${LINEAGE_KINDS.map(() => "?").join(", ")}) AND lag_months IS NULL`).all(...LINEAGE_KINDS);
|
|
1900
|
+
const out = [];
|
|
1901
|
+
for (const r of rows) {
|
|
1902
|
+
const rowsBehind = r.decision_rows === null ? [] : JSON.parse(r.decision_rows).map(String);
|
|
1903
|
+
const decision = rowsBehind[0] ?? null;
|
|
1904
|
+
const end = (id, direction, other) => ({
|
|
1905
|
+
id,
|
|
1906
|
+
direction,
|
|
1907
|
+
other,
|
|
1908
|
+
shape: r.kind,
|
|
1909
|
+
year: num(r.valid_from),
|
|
1910
|
+
provisional: r.provisional === 1,
|
|
1911
|
+
decision,
|
|
1912
|
+
confidence: decision === null ? null : num(r.confidence)
|
|
1913
|
+
});
|
|
1914
|
+
out.push(end(r.from_id, "precedes", r.to_id), end(r.to_id, "succeeds", r.from_id));
|
|
1915
|
+
}
|
|
1916
|
+
return out.sort((a, b) => cmp(a.id, b.id) || cmp(a.year ?? -1, b.year ?? -1) || cmp(a.direction, b.direction) || cmp(a.other, b.other) || cmp(a.shape, b.shape));
|
|
1917
|
+
}
|
|
1918
|
+
|
|
1804
1919
|
var LINEAGE_FILE2 = "school-lineage.jsonl";
|
|
1805
1920
|
var REDIRECTS_FILE = "school-redirects.jsonl";
|
|
1806
1921
|
function linksOfLineage2(lines) {
|
|
@@ -1839,6 +1954,14 @@ function backingOf(r) {
|
|
|
1839
1954
|
};
|
|
1840
1955
|
}
|
|
1841
1956
|
async function releaseSchoolGraph2(rel) {
|
|
1957
|
+
const tables = await schoolTables(rel);
|
|
1958
|
+
if (tables !== null) {
|
|
1959
|
+
const to = new Map(redirectsOfTables(tables).map((r) => [r.old_id, r.new_id]));
|
|
1960
|
+
return schoolGraph({
|
|
1961
|
+
links: linksOfLineage2(lineageOfTables(tables)),
|
|
1962
|
+
redirect: (id) => to.get(id) ?? null
|
|
1963
|
+
});
|
|
1964
|
+
}
|
|
1842
1965
|
await rel.require("schools.lineage");
|
|
1843
1966
|
await rel.fetch(LINEAGE_FILE2);
|
|
1844
1967
|
const links = linksOfLineage2(readJsonl(rel.path(LINEAGE_FILE2)));
|
|
@@ -1858,7 +1981,7 @@ import {
|
|
|
1858
1981
|
} from "@finbheara/domain/school";
|
|
1859
1982
|
|
|
1860
1983
|
var str = (v) => typeof v === "string" && v !== "" ? v : null;
|
|
1861
|
-
var
|
|
1984
|
+
var num2 = (v) => typeof v === "number" ? v : null;
|
|
1862
1985
|
var uniq = (xs) => [...new Set(xs)];
|
|
1863
1986
|
async function registrySchools(rel) {
|
|
1864
1987
|
await rel.require("schools.registry");
|
|
@@ -1891,17 +2014,23 @@ async function schoolPrints(rel, q) {
|
|
|
1891
2014
|
return { tag: rel.tag, asked: q, prints };
|
|
1892
2015
|
}
|
|
1893
2016
|
async function schoolRedirects(rel) {
|
|
2017
|
+
const tables = await schoolTables(rel);
|
|
2018
|
+
if (tables !== null)
|
|
2019
|
+
return { tag: rel.tag, redirects: redirectsOfTables(tables) };
|
|
1894
2020
|
await rel.require("schools.redirects");
|
|
1895
2021
|
await rel.fetch("school-redirects.jsonl");
|
|
1896
2022
|
const redirects = readJsonl(rel.path("school-redirects.jsonl")).map((r) => ({
|
|
1897
2023
|
old_id: String(r.old_id),
|
|
1898
2024
|
new_id: String(r.new_id),
|
|
1899
2025
|
kind: String(r.kind),
|
|
1900
|
-
since:
|
|
2026
|
+
since: num2(r.since)
|
|
1901
2027
|
}));
|
|
1902
2028
|
return { tag: rel.tag, redirects };
|
|
1903
2029
|
}
|
|
1904
2030
|
async function schoolLineage(rel) {
|
|
2031
|
+
const tables = await schoolTables(rel);
|
|
2032
|
+
if (tables !== null)
|
|
2033
|
+
return { tag: rel.tag, edges: lineageOfTables(tables) };
|
|
1905
2034
|
await rel.require("schools.lineage");
|
|
1906
2035
|
await rel.fetch("school-lineage.jsonl");
|
|
1907
2036
|
const edges = readJsonl(rel.path("school-lineage.jsonl")).map((r) => ({
|
|
@@ -1909,10 +2038,10 @@ async function schoolLineage(rel) {
|
|
|
1909
2038
|
direction: String(r.direction),
|
|
1910
2039
|
other: String(r.other),
|
|
1911
2040
|
shape: String(r.shape),
|
|
1912
|
-
year:
|
|
2041
|
+
year: num2(r.year),
|
|
1913
2042
|
provisional: r.provisional === true,
|
|
1914
2043
|
decision: str(r.decision),
|
|
1915
|
-
confidence:
|
|
2044
|
+
confidence: num2(r.confidence)
|
|
1916
2045
|
}));
|
|
1917
2046
|
return { tag: rel.tag, edges };
|
|
1918
2047
|
}
|
|
@@ -1926,7 +2055,7 @@ async function observedAssociations(rel, q) {
|
|
|
1926
2055
|
continue;
|
|
1927
2056
|
associations.push({
|
|
1928
2057
|
at: String(r.at),
|
|
1929
|
-
seq:
|
|
2058
|
+
seq: num2(r.seq) ?? 0,
|
|
1930
2059
|
date: str(r.date),
|
|
1931
2060
|
person: str(r.person),
|
|
1932
2061
|
person_printed: typeof r.personPrinted === "string" ? r.personPrinted : "",
|
|
@@ -2171,6 +2300,7 @@ var PACKAGE_KEY_PARTS = [
|
|
|
2171
2300
|
`domain=${domainPkg.version}`
|
|
2172
2301
|
];
|
|
2173
2302
|
var ENCODER = personEncoder({ read: (p, o) => dancerName(p, o) });
|
|
2303
|
+
var surnameBlockOf = (surname) => surnameBlock(dancerName(`${surname}, X`, "surname-first").surnameKey());
|
|
2174
2304
|
var PERSON = { table: "person", value: "id", valueType: "INTEGER PRIMARY KEY" };
|
|
2175
2305
|
var ASKED = ["surname_key", "nn4", "blk_surname"];
|
|
2176
2306
|
var dancersIndex = {
|
|
@@ -2381,6 +2511,9 @@ class DancerResolver2 {
|
|
|
2381
2511
|
}
|
|
2382
2512
|
lineage() {
|
|
2383
2513
|
this.lineageOf ??= (async () => {
|
|
2514
|
+
const tables = await schoolTables(this.rel);
|
|
2515
|
+
if (tables !== null)
|
|
2516
|
+
return schoolGraph2({ links: linksOfLineage2(lineageOfTables(tables)) });
|
|
2384
2517
|
if ((await this.rel.capability("schools.lineage")).state !== "full")
|
|
2385
2518
|
return null;
|
|
2386
2519
|
await this.rel.fetch(LINEAGE_FILE2);
|
|
@@ -2535,7 +2668,7 @@ class DancerResolver2 {
|
|
|
2535
2668
|
const hits = new Map;
|
|
2536
2669
|
const names = createIndex2(db, ENCODER, PERSON);
|
|
2537
2670
|
if (q.surname !== undefined) {
|
|
2538
|
-
const block =
|
|
2671
|
+
const block = surnameBlockOf(q.surname);
|
|
2539
2672
|
if (block !== null)
|
|
2540
2673
|
for (const { value } of names.rows({ blk_surname: [block] }, ["print"]))
|
|
2541
2674
|
hits.set(value, "surname");
|
|
@@ -3785,7 +3918,7 @@ async function parquetColumns(path) {
|
|
|
3785
3918
|
}
|
|
3786
3919
|
|
|
3787
3920
|
var str2 = (v) => typeof v === "string" && v !== "" ? v : null;
|
|
3788
|
-
var
|
|
3921
|
+
var num3 = (v) => typeof v === "number" ? v : null;
|
|
3789
3922
|
var strs = (v) => Array.isArray(v) ? v.filter((x) => typeof x === "string") : [];
|
|
3790
3923
|
var scope = (id) => id === null ? null : id >= FEIS_LOCAL_ID_FLOOR2 ? "per-release" : "stable";
|
|
3791
3924
|
var TEAM_TABLES = [
|
|
@@ -3842,7 +3975,7 @@ var teamsIndex = {
|
|
|
3842
3975
|
for (const r of t.event_years) {
|
|
3843
3976
|
const k = str2(r.event_year);
|
|
3844
3977
|
const event = str2(r.event);
|
|
3845
|
-
const year =
|
|
3978
|
+
const year = num3(r.year);
|
|
3846
3979
|
if (k === null || event === null || year === null)
|
|
3847
3980
|
continue;
|
|
3848
3981
|
ey.set(k, { event, year });
|
|
@@ -3851,19 +3984,19 @@ var teamsIndex = {
|
|
|
3851
3984
|
const putR = out.prepare("INSERT OR IGNORE INTO result VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
3852
3985
|
let ord = 0;
|
|
3853
3986
|
for (const r of t.team_results)
|
|
3854
|
-
putR.run(str2(r.address), str2(r.slug), str2(r.event),
|
|
3987
|
+
putR.run(str2(r.address), str2(r.slug), str2(r.event), num3(r.year), str2(r.card), str2(r.comp_no), str2(r.title), str2(r.category), num3(r.hands), str2(r.letter), str2(r.label), str2(r.name_printed), str2(r.school_printed), str2(r.school_loc), str2(r.school_id), num3(r.place), str2(r.place_printed), num3(r.tie), num3(r.competitors), JSON.stringify(strs(r.atts)), str2(r.age), str2(r.gender), JSON.stringify(strs(r.printed_status)), num3(r.competitors_printed), num3(r.recalled_only), ord++);
|
|
3855
3988
|
const putT = out.prepare("INSERT OR IGNORE INTO roster_team VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
3856
3989
|
for (const r of t.roster_teams) {
|
|
3857
3990
|
const e = ey.get(str2(r.event_year) ?? "");
|
|
3858
|
-
putT.run(str2(r.team), str2(r.kind), e?.event ?? null,
|
|
3991
|
+
putT.run(str2(r.team), str2(r.kind), e?.event ?? null, num3(r.year) ?? e?.year ?? null, str2(r.comp_no), str2(r.title), str2(r.team_index), num3(r.seq), str2(r.school_id), str2(r.school_print_materialized), str2(r.dance), str2(r.school_print_as_of), ord++);
|
|
3859
3992
|
}
|
|
3860
3993
|
const putM = out.prepare("INSERT INTO roster_member VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
|
|
3861
3994
|
for (const r of t.roster_members)
|
|
3862
|
-
putM.run(str2(r.team),
|
|
3995
|
+
putM.run(str2(r.team), num3(r.seq), typeof r.name_printed === "string" ? r.name_printed : "", str2(r.name), num3(r.yob), num3(r.dancer_id), str2(r.gender), ord++);
|
|
3863
3996
|
const putJ = out.prepare("INSERT INTO result_roster VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
3864
3997
|
for (const r of t.team_result_rosters) {
|
|
3865
3998
|
const e = ey.get(str2(r.event_year) ?? "");
|
|
3866
|
-
putJ.run(str2(r.team), e?.event ?? null, e?.year ?? null, str2(r.comp_no), str2(r.school_id), str2(r.result_address), str2(r.join_kind),
|
|
3999
|
+
putJ.run(str2(r.team), e?.event ?? null, e?.year ?? null, str2(r.comp_no), str2(r.school_id), str2(r.result_address), str2(r.join_kind), num3(r.via_split) === 1 ? 1 : 0, num3(r.roster_teams), num3(r.result_teams), str2(r.roster_index), str2(r.result_letter), ord++);
|
|
3867
4000
|
}
|
|
3868
4001
|
for (const s of TEAMS_INDEXES)
|
|
3869
4002
|
out.run(s);
|
|
@@ -3884,10 +4017,10 @@ var eventsIndex = {
|
|
|
3884
4017
|
const put = out.prepare("INSERT OR IGNORE INTO event_year VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
3885
4018
|
for (const r of rows) {
|
|
3886
4019
|
const event = str2(r.event);
|
|
3887
|
-
const year =
|
|
4020
|
+
const year = num3(r.year);
|
|
3888
4021
|
if (event === null || year === null)
|
|
3889
4022
|
continue;
|
|
3890
|
-
put.run(event, year, str2(r.date_lo), str2(r.date_hi), str2(r.resolution), str2(r.source), JSON.stringify(strs(r.date_printed)), str2(r.place), JSON.stringify(strs(r.place_printed)), str2(r.published),
|
|
4023
|
+
put.run(event, year, str2(r.date_lo), str2(r.date_hi), str2(r.resolution), str2(r.source), JSON.stringify(strs(r.date_printed)), str2(r.place), JSON.stringify(strs(r.place_printed)), str2(r.published), num3(r.listed));
|
|
3891
4024
|
}
|
|
3892
4025
|
out.run("CREATE INDEX event_year_event ON event_year(event COLLATE NOCASE)");
|
|
3893
4026
|
}
|
package/dist/cli.js
CHANGED
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
staleWarning2,
|
|
24
24
|
progressMode2,
|
|
25
25
|
progressRenderer2
|
|
26
|
-
} from "./chunks/index-
|
|
26
|
+
} from "./chunks/index-aj1n1q7j.js";
|
|
27
27
|
import"./chunks/index-hghdy980.js";
|
|
28
28
|
|
|
29
29
|
var USAGE_HEADER = "usage: idq <verb> [--cache <dir>] [--repo <owner/name>] [--json] [--live] [--progress tty|plain|none]";
|
package/dist/index.js
CHANGED
package/dist/types/dancers.d.ts
CHANGED
|
@@ -182,6 +182,7 @@ export interface DancerRecord {
|
|
|
182
182
|
schools: DancerSchool[];
|
|
183
183
|
}
|
|
184
184
|
export declare const PACKAGE_KEY_PARTS: readonly string[];
|
|
185
|
+
export declare const surnameBlockOf: (surname: string) => string | null;
|
|
185
186
|
export declare const dancersIndex: IndexBuilder;
|
|
186
187
|
export declare function yearOf(asOf: string | undefined): number | null;
|
|
187
188
|
export interface DancerBulkRecord {
|
package/dist/types/feises.d.ts
CHANGED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Database } from "bun:sqlite";
|
|
2
|
+
import type { Release } from "./release.js";
|
|
3
|
+
import type { LineageEdge, SchoolRedirect } from "./school-bulk.js";
|
|
4
|
+
export declare const SCHOOL_GRAPH_FEATURE = "school-graph";
|
|
5
|
+
export declare const LINEAGE_KINDS: readonly string[];
|
|
6
|
+
export declare function schoolTables(rel: Release): Promise<Database | null>;
|
|
7
|
+
export declare function redirectsOfTables(db: Database): SchoolRedirect[];
|
|
8
|
+
export declare function lineageOfTables(db: Database): LineageEdge[];
|
package/dist/types/stream.d.ts
CHANGED
|
@@ -66,6 +66,7 @@ export interface StreamRow extends Partial<StreamCompetition> {
|
|
|
66
66
|
points_printed: string | null;
|
|
67
67
|
round_points_printed?: (string | null)[] | null;
|
|
68
68
|
marks_printed?: string | null;
|
|
69
|
+
status_printed?: string[];
|
|
69
70
|
platform_dancer_id: string | null;
|
|
70
71
|
primary_source: string | null;
|
|
71
72
|
file: string;
|
|
@@ -83,6 +84,7 @@ export interface StreamShape {
|
|
|
83
84
|
relativePlaceErr?: boolean;
|
|
84
85
|
roundPoints?: boolean;
|
|
85
86
|
marks?: boolean;
|
|
87
|
+
status?: boolean;
|
|
86
88
|
}
|
|
87
89
|
export declare const scopeDb: (s: StreamScope) => "majors" | "results";
|
|
88
90
|
export declare function streamSql(q: StreamQuery, shape?: StreamShape): {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@finbheara/archive-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.53.1",
|
|
4
4
|
"description": "Open a versioned release of an Irish dance results archive: download, verify, decompress and cache it by tag, keep the cache, and resolve feises and schools against it",
|
|
5
5
|
"keywords": ["irish-dance", "results", "release", "cache", "sqlite"],
|
|
6
6
|
"license": "MIT",
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
"prepublishOnly": "bun scripts/build.ts && bun ../../tools/checks/archive-client-tarball.ts"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@finbheara/domain": "0.
|
|
48
|
-
"@finbheara/names": "0.
|
|
47
|
+
"@finbheara/domain": "0.60.1",
|
|
48
|
+
"@finbheara/names": "0.31.0",
|
|
49
49
|
"hyparquet": "1.31.2"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|