@finbheara/archive-client 0.12.0 → 0.14.0
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 +45 -9
- package/dist/chunks/{index-xtv455ft.js → index-hhhrh1db.js} +200 -31
- package/dist/cli.js +3 -2
- package/dist/index.js +1 -1
- package/dist/types/cli.d.ts +1 -1
- package/dist/types/comps.d.ts +1 -0
- package/dist/types/dancers-names.d.ts +1 -1
- package/dist/types/dancers.d.ts +14 -8
- package/dist/types/index.d.ts +1 -1
- package/dist/types/schools.d.ts +9 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -194,14 +194,19 @@ A release holds a feis-year once its results are captured and carries no calenda
|
|
|
194
194
|
```ts
|
|
195
195
|
const a = await rel.schools.resolve("Ardvarna Academy of Irish Dance (Calgary, AB)", { region: "WCRO" });
|
|
196
196
|
a.arm; // "unique" | "ambiguous" | "none"
|
|
197
|
-
a.candidates; // [{ school_id, display, rows, by, prints, regions, places }]
|
|
197
|
+
a.candidates; // [{ school_id, display, rows, by, prints, regions, places, years? }]
|
|
198
198
|
```
|
|
199
199
|
|
|
200
200
|
The rungs, the first that answers wins: a school id, a retired id followed to the live one, the
|
|
201
201
|
print exactly as the release published it, then the print read by `@finbheara/domain`'s school
|
|
202
202
|
reader at its filing key (`sn3`) and at its real words. `ambiguous` and `none` are answers: a
|
|
203
203
|
best guess is never promoted to `unique`. `region` drops only a candidate the registry places in
|
|
204
|
-
other regions, and keeps one it places nowhere.
|
|
204
|
+
other regions, and keeps one it places nowhere. `year` reads a print at that year, on a print
|
|
205
|
+
rung only: where the print reaches two or more ids, the ids whose rows printed it that year are
|
|
206
|
+
kept (a print one school took over from another names the one that held it then), else the ids
|
|
207
|
+
that printed it last before that year, and where the year is before every one of them, all stay
|
|
208
|
+
(`a.year`: `{ asked, narrowed }`, each candidate's `years: { lo, hi }`). A dancer question reads
|
|
209
|
+
its school print at its own year. A print the reader refuses (a placeholder)
|
|
205
210
|
answers `none` with the reason. An id (or a retired id followed) answers with every print its
|
|
206
211
|
rows were published under and their rows, so it agrees with each print lookup of that school.
|
|
207
212
|
|
|
@@ -262,8 +267,8 @@ year with the asked age, or a dancer the release publishes in the other populati
|
|
|
262
267
|
majors solo competitions and in none of the asked one's (listed in `excluded`, `why: "age"` or
|
|
263
268
|
`"population"`, and a candidate contradicting both says `age`). A dancer published in both, or in
|
|
264
269
|
neither, stays. A population word that names no one population (`mixed`) narrows nothing, and the
|
|
265
|
-
answer says so (`r.population.note`).
|
|
266
|
-
to drop anyone: candidates whose latest school is the asked one, or one the lineage joins to it,
|
|
270
|
+
answer says so (`r.population.note`). Outside the narrowing below, the school is evidence and
|
|
271
|
+
order, never a reason to drop anyone: candidates whose latest school is the asked one, or one the lineage joins to it,
|
|
267
272
|
come first, then those that ever danced for it, then the rest. A school row meets the asked school by its id, else by its print
|
|
268
273
|
(one `rel.schools` resolves to the asked ids), so a latest print the release
|
|
269
274
|
filed under no id is still `same`. `unique` is one candidate left after the age, never a best
|
|
@@ -297,8 +302,31 @@ words):
|
|
|
297
302
|
one candidate is open and the age did not set it aside: the candidates the school refuted then
|
|
298
303
|
move to `excluded` (`why: "school"`). Otherwise the arm stays `ambiguous` with every candidate,
|
|
299
304
|
and where the school and the region single out no one, `preferred` names the only open candidate
|
|
300
|
-
with a row in the asked year or the year before.
|
|
301
|
-
|
|
305
|
+
with a row in the asked year or the year before.
|
|
306
|
+
|
|
307
|
+
A FULL GIVEN NAME with a school the release resolves is narrowed the same way (`r.fullName`, the
|
|
308
|
+
same shape as `r.initials`), with one more hard fact:
|
|
309
|
+
|
|
310
|
+
- `given`: a candidate the name met only through an initial print (`Quellan, A.`) that also
|
|
311
|
+
printed a full given name the names package relates in no way to the asked one is another
|
|
312
|
+
dancer. An initial-only candidate, a variant or a diminutive (`nameKinship`) stays.
|
|
313
|
+
|
|
314
|
+
A candidate at another school is set aside only by the hard school fact, never for being
|
|
315
|
+
elsewhere: a dancer who ever danced for the asked school's line stays open.
|
|
316
|
+
|
|
317
|
+
THE WIDENED PASSES (`r.widened`), only where the name as asked is left with no one, so a widened
|
|
318
|
+
match never answers over an exact one:
|
|
319
|
+
|
|
320
|
+
- `birth-conflict`: a birth window the release flags (`birth.conflict`) is read one year wider on
|
|
321
|
+
each side, and the candidate says so (`candidate.widened`).
|
|
322
|
+
- `name-form`: the name read in its other forms by `@finbheara/names`: `composeNames` (a print
|
|
323
|
+
that left out a second surname, a middle name or a given name's letters, or a double-barrelled
|
|
324
|
+
surname read as its parts) or else `nameKinship` (a given name's variant or diminutive). Such a
|
|
325
|
+
candidate's `nameLevel` is `form` and `evidence.form` lists the tolerances. A form is set
|
|
326
|
+
aside only by the hard school fact (`why: "name-form"`, the fact in `r.fullName.refuted` or
|
|
327
|
+
`r.initials.refuted` where the answer was narrowed): every school row of the dancer, to the
|
|
328
|
+
asked year, reads outside the asked school's line. A dancer with no school row, or a print no
|
|
329
|
+
school reads, is unknown and stays.
|
|
302
330
|
|
|
303
331
|
THE REGIONAL OIREACHTAS (`oireachtas: { region, year? }`). A dancer enters one
|
|
304
332
|
residence-qualifying regional Oireachtas a year. Two regionals in one year are two dancers, the
|
|
@@ -503,12 +531,20 @@ the host likes, so a code is answered from that feis's competitions in the relea
|
|
|
503
531
|
another platform's numbering. The sources, in order:
|
|
504
532
|
|
|
505
533
|
- `syllabus`: the feis-year is in the release, and one of its competitions prints the code
|
|
506
|
-
- `prior-year`: the feis-year is not (next year's, before its results)
|
|
507
|
-
|
|
508
|
-
|
|
534
|
+
- `prior-year`: the feis-year is not (next year's, before its results), and its platform numbers
|
|
535
|
+
every feis by one grammar (QuickFeis: `CODE_READER`, `@finbheara/domain/code`): the newest
|
|
536
|
+
earlier year of the same series printing the code. Give the comp's `title` and `matchTitle`
|
|
537
|
+
checks it against the earlier comp (`check`), and with no title the answer says `unchecked`
|
|
509
538
|
- `title`: the code answers nothing and a `title` was given: the competitions of that syllabus
|
|
510
539
|
the title names, by band and population
|
|
511
540
|
|
|
541
|
+
AN EARLIER YEAR'S CODE IS NEVER READ ON A FEIS-SPECIFIC PLATFORM. FeisWeb, FeisWorx, iFeis and
|
|
542
|
+
the rest renumber their competitions from one year to the next: measured in October 2026, the
|
|
543
|
+
same code at the same series one held year later names another band or level on 13% to 29% of
|
|
544
|
+
codes, a plausible answer and a wrong one. So an unheld feis-year there answers by its `title`
|
|
545
|
+
over the newest earlier syllabus, and a code with no title is `none`, saying why. The code of a
|
|
546
|
+
held feis-year is still read from that feis-year's own competitions.
|
|
547
|
+
|
|
512
548
|
A feis the release holds names itself, its year and its series. A series instance or brand id
|
|
513
549
|
names the series. A feis id the release does not hold is placed in a series by its host code
|
|
514
550
|
(`<token>:<stem><yy>` where the held codes of that stem carry their own year), and a stem two
|
|
@@ -77,7 +77,10 @@ import {
|
|
|
77
77
|
populationRelation
|
|
78
78
|
} from "@finbheara/domain/title";
|
|
79
79
|
import {
|
|
80
|
+
composeNames,
|
|
80
81
|
foldNameKey,
|
|
82
|
+
nameBlockKeys,
|
|
83
|
+
nameKinship,
|
|
81
84
|
surnameBlock
|
|
82
85
|
} from "@finbheara/names/normalize";
|
|
83
86
|
import namesPkg from "@finbheara/names/package.json";
|
|
@@ -91,6 +94,7 @@ var NAME_LEVELS2 = [
|
|
|
91
94
|
...NAME_LEVEL_COLUMNS,
|
|
92
95
|
"initial",
|
|
93
96
|
"middle",
|
|
97
|
+
"form",
|
|
94
98
|
"surname",
|
|
95
99
|
"like"
|
|
96
100
|
];
|
|
@@ -640,7 +644,7 @@ var PERSON = { table: "person", value: "id", valueType: "INTEGER PRIMARY KEY" };
|
|
|
640
644
|
var ASKED = ["surname_key", "nn4", "blk_surname"];
|
|
641
645
|
var dancersIndex = {
|
|
642
646
|
name: "dancers",
|
|
643
|
-
version: "
|
|
647
|
+
version: "5",
|
|
644
648
|
inputs: ["results"],
|
|
645
649
|
keyParts: () => [...PACKAGE_KEY_PARTS],
|
|
646
650
|
says: "every published dancer print at the names package's keys, its dancers, schools and years",
|
|
@@ -652,6 +656,8 @@ var dancersIndex = {
|
|
|
652
656
|
out.run("CREATE TABLE dancer_school(dancer_id INTEGER NOT NULL, school_id TEXT, print TEXT NOT NULL, rows INTEGER NOT NULL, year_lo INTEGER, year_hi INTEGER)");
|
|
653
657
|
out.run("CREATE TABLE dancer_population(dancer_id INTEGER NOT NULL, population TEXT NOT NULL, rows INTEGER NOT NULL, PRIMARY KEY(dancer_id, population)) WITHOUT ROWID");
|
|
654
658
|
out.run("CREATE TABLE dancer_regional(dancer_id INTEGER NOT NULL, year INTEGER NOT NULL, region TEXT NOT NULL, regional INTEGER NOT NULL, PRIMARY KEY(dancer_id, year)) WITHOUT ROWID");
|
|
659
|
+
out.run("CREATE TABLE person_block(block TEXT NOT NULL, person INTEGER NOT NULL)");
|
|
660
|
+
const putBlock = out.prepare("INSERT INTO person_block VALUES (?, ?)");
|
|
655
661
|
const src = rel.db("results");
|
|
656
662
|
const groups = src.query(`SELECT r.name_printed AS p, r.name_order_resolved AS o, r.dancer_id AS d,
|
|
657
663
|
r.school_printed AS sp, r.school_id AS s,
|
|
@@ -673,6 +679,8 @@ var dancersIndex = {
|
|
|
673
679
|
id = ++next;
|
|
674
680
|
names.add(name, id);
|
|
675
681
|
personOf.set(reading, id);
|
|
682
|
+
for (const b of nameBlockKeys(name))
|
|
683
|
+
putBlock.run(b, id);
|
|
676
684
|
}
|
|
677
685
|
personOf.set(k, id);
|
|
678
686
|
}
|
|
@@ -748,6 +756,7 @@ var dancersIndex = {
|
|
|
748
756
|
for (const s of schema.indexes)
|
|
749
757
|
if (ASKED.some((c) => s.endsWith(`(${c})`)))
|
|
750
758
|
out.run(s);
|
|
759
|
+
out.run("CREATE INDEX person_block_block ON person_block(block)");
|
|
751
760
|
out.run("CREATE INDEX print_dancer_person ON print_dancer(person)");
|
|
752
761
|
out.run("CREATE INDEX print_dancer_dancer ON print_dancer(dancer_id)");
|
|
753
762
|
out.run("CREATE INDEX dancer_school_dancer ON dancer_school(dancer_id)");
|
|
@@ -767,6 +776,7 @@ var NAME_WEIGHT = {
|
|
|
767
776
|
nn4: 3,
|
|
768
777
|
initial: 2,
|
|
769
778
|
middle: 1.5,
|
|
779
|
+
form: 1.25,
|
|
770
780
|
surname: 1,
|
|
771
781
|
like: 1
|
|
772
782
|
};
|
|
@@ -907,7 +917,56 @@ class DancerResolver2 {
|
|
|
907
917
|
if (level !== null)
|
|
908
918
|
hits.set(value, level);
|
|
909
919
|
}
|
|
910
|
-
|
|
920
|
+
const exact = await this.answer(db, q, hits);
|
|
921
|
+
if (exact.arm !== "none")
|
|
922
|
+
return exact;
|
|
923
|
+
const born = await this.answer(db, q, hits, true, { birthSlack: true });
|
|
924
|
+
if (born.arm !== "none")
|
|
925
|
+
return { ...born, widened: "birth-conflict" };
|
|
926
|
+
const forms = this.formsOf(db, names, asked, hits);
|
|
927
|
+
if (forms.size === 0)
|
|
928
|
+
return exact;
|
|
929
|
+
const all = new Map(hits);
|
|
930
|
+
for (const id of forms.keys())
|
|
931
|
+
all.set(id, "form");
|
|
932
|
+
const formed = await this.answer(db, q, all, true, { birthSlack: true, forms });
|
|
933
|
+
return formed.arm === "none" ? exact : { ...formed, widened: "name-form" };
|
|
934
|
+
}
|
|
935
|
+
formsOf(db, names, asked, hits) {
|
|
936
|
+
const out = new Map;
|
|
937
|
+
const keys = nameBlockKeys(asked);
|
|
938
|
+
const persons = new Set;
|
|
939
|
+
if (keys.length > 0)
|
|
940
|
+
for (const r of db.query(`SELECT DISTINCT person FROM person_block WHERE block IN (${keys.map(() => "?").join(",")})`).all(...keys))
|
|
941
|
+
persons.add(r.person);
|
|
942
|
+
const rows = new Map;
|
|
943
|
+
for (const { value, row } of names.rows({ surname_key: [asked.surnameKey()] }, [
|
|
944
|
+
"print",
|
|
945
|
+
"reading"
|
|
946
|
+
]))
|
|
947
|
+
rows.set(value, row);
|
|
948
|
+
const ids = [...persons].filter((id) => !hits.has(id) && !rows.has(id));
|
|
949
|
+
for (let i = 0;i < ids.length; i += 500) {
|
|
950
|
+
const chunk = ids.slice(i, i + 500);
|
|
951
|
+
for (const r of db.query(`SELECT id, print, reading FROM person WHERE id IN (${chunk.map(() => "?").join(",")})`).all(...chunk))
|
|
952
|
+
rows.set(r.id, { print: r.print, reading: r.reading });
|
|
953
|
+
}
|
|
954
|
+
for (const [id, row] of rows) {
|
|
955
|
+
if (hits.has(id))
|
|
956
|
+
continue;
|
|
957
|
+
const c = ENCODER.decode(row);
|
|
958
|
+
if (!c.isPerson())
|
|
959
|
+
continue;
|
|
960
|
+
const composed = composeNames(asked, c);
|
|
961
|
+
if (composed.composition !== "conflict" && composed.composition !== "silent") {
|
|
962
|
+
out.set(id, [...composed.via]);
|
|
963
|
+
continue;
|
|
964
|
+
}
|
|
965
|
+
const kin = nameKinship(asked, c);
|
|
966
|
+
if (kin.relation !== "different")
|
|
967
|
+
out.set(id, [...kin.via]);
|
|
968
|
+
}
|
|
969
|
+
return out;
|
|
911
970
|
}
|
|
912
971
|
async search(q) {
|
|
913
972
|
if (q.name !== undefined) {
|
|
@@ -958,7 +1017,7 @@ class DancerResolver2 {
|
|
|
958
1017
|
schools: schoolsOf(db, dancerId)
|
|
959
1018
|
};
|
|
960
1019
|
}
|
|
961
|
-
async answer(db, q, hits, narrow = true) {
|
|
1020
|
+
async answer(db, q, hits, narrow = true, widen = {}) {
|
|
962
1021
|
const asOf = yearOf(q.asOf);
|
|
963
1022
|
const age = q.age === undefined ? undefined : this.readAge(q.age, asOf);
|
|
964
1023
|
const population = q.population === undefined ? undefined : readPopulation2(q.population);
|
|
@@ -967,7 +1026,7 @@ class DancerResolver2 {
|
|
|
967
1026
|
let lineageIds = [];
|
|
968
1027
|
let school;
|
|
969
1028
|
if (q.school !== undefined) {
|
|
970
|
-
const s = await this.rel.schools.resolve(q.school);
|
|
1029
|
+
const s = await this.rel.schools.resolve(q.school, { year: askedYear(q, asOf) });
|
|
971
1030
|
schoolIds = s.candidates.map((c) => c.school_id);
|
|
972
1031
|
const lineage = await this.lineage();
|
|
973
1032
|
if (lineage === null)
|
|
@@ -987,9 +1046,11 @@ class DancerResolver2 {
|
|
|
987
1046
|
unlinked.set(r.print, (unlinked.get(r.print) ?? 0) + r.n);
|
|
988
1047
|
continue;
|
|
989
1048
|
}
|
|
990
|
-
const e = byDancer.get(r.d) ?? { level, prints: [] };
|
|
1049
|
+
const e = byDancer.get(r.d) ?? { level, prints: [], via: new Set };
|
|
991
1050
|
e.level = finer(e.level, level);
|
|
992
1051
|
e.prints.push({ print: r.print, rows: r.n, level });
|
|
1052
|
+
for (const v of widen.forms?.get(person) ?? [])
|
|
1053
|
+
e.via.add(v);
|
|
993
1054
|
byDancer.set(r.d, e);
|
|
994
1055
|
}
|
|
995
1056
|
const dq = db.query("SELECT * FROM dancer WHERE dancer_id = ?");
|
|
@@ -1000,7 +1061,15 @@ class DancerResolver2 {
|
|
|
1000
1061
|
continue;
|
|
1001
1062
|
const schools = schoolsOf(db, id);
|
|
1002
1063
|
const latest = latestSchool(schools, asOf);
|
|
1003
|
-
|
|
1064
|
+
let ageEv = ageEvidence(d, age?.age ?? null);
|
|
1065
|
+
let widenedBirth = false;
|
|
1066
|
+
if (widen.birthSlack && ageEv === "contradicts" && d.birth_conflict !== 0) {
|
|
1067
|
+
const wider = ageEvidence(d, age?.age ?? null, 1);
|
|
1068
|
+
if (wider !== "contradicts") {
|
|
1069
|
+
ageEv = wider;
|
|
1070
|
+
widenedBirth = true;
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1004
1073
|
const pop = populationOf(db, id);
|
|
1005
1074
|
const popEv = populationEvidence(pop, population?.read ?? null);
|
|
1006
1075
|
const schoolEv = schoolIds === null ? "unasked" : schoolIds.length === 0 ? "unresolved" : await this.schoolEvidence(schools, schoolIds, lineageIds, asOf);
|
|
@@ -1021,8 +1090,10 @@ class DancerResolver2 {
|
|
|
1021
1090
|
age: ageEv,
|
|
1022
1091
|
school: schoolEv,
|
|
1023
1092
|
population: popEv,
|
|
1024
|
-
region: regionEv
|
|
1093
|
+
region: regionEv,
|
|
1094
|
+
...e.level === "form" ? { form: [...e.via] } : {}
|
|
1025
1095
|
},
|
|
1096
|
+
...widenedBirth ? { widened: "birth-conflict" } : {},
|
|
1026
1097
|
prints: e.prints.sort((a, b) => b.rows - a.rows || (a.print < b.print ? -1 : 1)),
|
|
1027
1098
|
rows: d.rows,
|
|
1028
1099
|
year_lo: d.year_lo,
|
|
@@ -1049,21 +1120,54 @@ class DancerResolver2 {
|
|
|
1049
1120
|
return false;
|
|
1050
1121
|
});
|
|
1051
1122
|
const year = askedYear(q, asOf);
|
|
1052
|
-
|
|
1053
|
-
|
|
1123
|
+
const band = age?.age?.birthYears() ?? null;
|
|
1124
|
+
const adultBy = adultBornBy(year);
|
|
1125
|
+
const adultAsked = adultBy !== null && adultCategory(q.age, age?.age ?? null);
|
|
1126
|
+
const returningOf = (c) => adultAsked && c.birth.hi !== null && c.birth.hi <= adultBy ? c.birth.lo : null;
|
|
1127
|
+
let line = null;
|
|
1128
|
+
if (schoolIds !== null && schoolIds.length > 0) {
|
|
1054
1129
|
const lineage = await this.lineage();
|
|
1055
|
-
|
|
1056
|
-
|
|
1130
|
+
line = lineage === null ? new Set(schoolIds) : schoolLine(lineage, schoolIds, year);
|
|
1131
|
+
}
|
|
1132
|
+
const formFacts = new Map;
|
|
1133
|
+
if (narrow && widen.forms !== undefined && line !== null) {
|
|
1134
|
+
const next = [];
|
|
1135
|
+
for (const c of kept) {
|
|
1136
|
+
if (c.evidence.nameLevel === "form") {
|
|
1137
|
+
const fact = await this.schoolRefutes(schoolsOf(db, c.dancer_id), line, year, q.school, returningOf(c));
|
|
1138
|
+
if (fact !== null) {
|
|
1139
|
+
formFacts.set(c.dancer_id, fact);
|
|
1140
|
+
excluded.push({ candidate: c, why: "name-form" });
|
|
1141
|
+
continue;
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
next.push(c);
|
|
1145
|
+
}
|
|
1146
|
+
kept = next;
|
|
1147
|
+
}
|
|
1148
|
+
const askedName = dancerName(q.name, q.order === "unknown" ? undefined : q.order);
|
|
1149
|
+
const byInitials = initialsOnly2(askedName);
|
|
1150
|
+
let narrowing;
|
|
1151
|
+
if (narrow && kept.length > 1 && line !== null) {
|
|
1057
1152
|
const slack = q.age !== undefined && !("yob" in q.age) ? DANCE_UP_YEARS : 0;
|
|
1058
1153
|
const open = [];
|
|
1059
1154
|
const held = [];
|
|
1060
1155
|
const refuted = [];
|
|
1061
1156
|
const bySchool = new Set;
|
|
1062
|
-
const
|
|
1063
|
-
|
|
1157
|
+
const givenFact = (c) => {
|
|
1158
|
+
if (byInitials || c.evidence.nameLevel !== "initial")
|
|
1159
|
+
return false;
|
|
1160
|
+
const fact = otherGiven(db, c.dancer_id, askedName);
|
|
1161
|
+
if (fact === null)
|
|
1162
|
+
return false;
|
|
1163
|
+
refuted.push({ dancer_id: c.dancer_id, why: "given", fact });
|
|
1164
|
+
bySchool.add(c.dancer_id);
|
|
1165
|
+
return true;
|
|
1166
|
+
};
|
|
1064
1167
|
const schoolFact = async (c) => {
|
|
1065
|
-
|
|
1066
|
-
|
|
1168
|
+
if (givenFact(c))
|
|
1169
|
+
return true;
|
|
1170
|
+
const fact = await this.schoolRefutes(schoolsOf(db, c.dancer_id), line, year, q.school, returningOf(c));
|
|
1067
1171
|
if (fact === null)
|
|
1068
1172
|
return false;
|
|
1069
1173
|
refuted.push({ dancer_id: c.dancer_id, why: "school", fact });
|
|
@@ -1084,10 +1188,10 @@ class DancerResolver2 {
|
|
|
1084
1188
|
refuted.push({
|
|
1085
1189
|
dancer_id: c.dancer_id,
|
|
1086
1190
|
why: x.why,
|
|
1087
|
-
fact: contradictionFact(x, age, slack)
|
|
1191
|
+
fact: formFacts.get(c.dancer_id) ?? contradictionFact(x, age, slack)
|
|
1088
1192
|
});
|
|
1089
1193
|
}
|
|
1090
|
-
|
|
1194
|
+
narrowing = {
|
|
1091
1195
|
open: [...open.map((c) => c.dancer_id), ...held],
|
|
1092
1196
|
heldByDanceUp: held,
|
|
1093
1197
|
refuted,
|
|
@@ -1096,7 +1200,10 @@ class DancerResolver2 {
|
|
|
1096
1200
|
if (open.length === 1 && held.length === 0) {
|
|
1097
1201
|
for (const c of kept)
|
|
1098
1202
|
if (bySchool.has(c.dancer_id))
|
|
1099
|
-
excluded.push({
|
|
1203
|
+
excluded.push({
|
|
1204
|
+
candidate: c,
|
|
1205
|
+
why: refuted.find((r) => r.dancer_id === c.dancer_id)?.why === "given" ? "given" : "school"
|
|
1206
|
+
});
|
|
1100
1207
|
kept = open;
|
|
1101
1208
|
}
|
|
1102
1209
|
}
|
|
@@ -1126,8 +1233,8 @@ class DancerResolver2 {
|
|
|
1126
1233
|
};
|
|
1127
1234
|
}
|
|
1128
1235
|
}
|
|
1129
|
-
if (preferred === undefined && kept.length > 1 &&
|
|
1130
|
-
const openIds = new Set(
|
|
1236
|
+
if (preferred === undefined && kept.length > 1 && narrowing !== undefined) {
|
|
1237
|
+
const openIds = new Set(narrowing.open);
|
|
1131
1238
|
const hit = kept.filter((c) => openIds.has(c.dancer_id) && c.year_hi !== null && c.year_hi >= year - 1);
|
|
1132
1239
|
if (hit.length === 1) {
|
|
1133
1240
|
const c = hit[0];
|
|
@@ -1149,7 +1256,7 @@ class DancerResolver2 {
|
|
|
1149
1256
|
...population !== undefined ? { population } : {},
|
|
1150
1257
|
...oireachtas !== undefined ? { oireachtas } : {},
|
|
1151
1258
|
...school !== undefined ? { school } : {},
|
|
1152
|
-
...
|
|
1259
|
+
...narrowing !== undefined ? byInitials ? { initials: narrowing } : { fullName: narrowing } : {}
|
|
1153
1260
|
};
|
|
1154
1261
|
}
|
|
1155
1262
|
async readOireachtas(db, o, asOf) {
|
|
@@ -1282,6 +1389,22 @@ function youthRow(s, bornLo) {
|
|
|
1282
1389
|
const by = adultBornBy(s.year_hi);
|
|
1283
1390
|
return by !== null && bornLo > by;
|
|
1284
1391
|
}
|
|
1392
|
+
function otherGiven(db, dancerId, asked) {
|
|
1393
|
+
const r = db.query("SELECT names_printed FROM dancer WHERE dancer_id = ?").get(dancerId);
|
|
1394
|
+
if (r === null)
|
|
1395
|
+
return null;
|
|
1396
|
+
for (const print of JSON.parse(r.names_printed)) {
|
|
1397
|
+
const p = dancerName(print);
|
|
1398
|
+
if (!p.isPerson() || (p.givenFields()[0]?.length ?? 0) < 2)
|
|
1399
|
+
continue;
|
|
1400
|
+
if (nameLevel2(asked, p) !== null)
|
|
1401
|
+
continue;
|
|
1402
|
+
if (nameKinship(asked, p).relation !== "different")
|
|
1403
|
+
continue;
|
|
1404
|
+
return `printed "${print}", another given name than the asked one, and met it only through an initial`;
|
|
1405
|
+
}
|
|
1406
|
+
return null;
|
|
1407
|
+
}
|
|
1285
1408
|
function birthOf(d) {
|
|
1286
1409
|
return {
|
|
1287
1410
|
lo: d.birth_lo,
|
|
@@ -1349,12 +1472,12 @@ function regionEvidence(db, dancerId, region, year) {
|
|
|
1349
1472
|
return { word: "contradicts", region: at(latest) };
|
|
1350
1473
|
return { word: latest.region === region ? "same" : "moved", region: at(latest) };
|
|
1351
1474
|
}
|
|
1352
|
-
function ageEvidence(d, asked) {
|
|
1475
|
+
function ageEvidence(d, asked, slack = 0) {
|
|
1353
1476
|
if (asked === null)
|
|
1354
1477
|
return "unasked";
|
|
1355
1478
|
if (d.birth_lo === null && d.birth_hi === null)
|
|
1356
1479
|
return "unknown";
|
|
1357
|
-
const own = Age.fromYOB(d.birth_lo, d.birth_hi);
|
|
1480
|
+
const own = Age.fromYOB(d.birth_lo === null ? null : d.birth_lo - slack, d.birth_hi === null ? null : d.birth_hi + slack);
|
|
1358
1481
|
if (!own.isAge())
|
|
1359
1482
|
return "unknown";
|
|
1360
1483
|
if (own.fitsIn(asked))
|
|
@@ -1385,6 +1508,7 @@ function contradictionFact(x, age, slack) {
|
|
|
1385
1508
|
}
|
|
1386
1509
|
|
|
1387
1510
|
import { Age as Age2 } from "@finbheara/domain/age";
|
|
1511
|
+
import { createCodeReader } from "@finbheara/domain/code";
|
|
1388
1512
|
import {
|
|
1389
1513
|
codePopulation,
|
|
1390
1514
|
compTitle as compTitle2,
|
|
@@ -1490,6 +1614,7 @@ function canonicalOf2(level, age) {
|
|
|
1490
1614
|
return null;
|
|
1491
1615
|
return `${level / 100}${String(n).padStart(2, "0")}${level === 600 ? "PC" : "OC"}`;
|
|
1492
1616
|
}
|
|
1617
|
+
var CODE_READER = createCodeReader({ standardized: ["quickfeis"] });
|
|
1493
1618
|
var entryOf = (c) => ({
|
|
1494
1619
|
title: c.title ?? "",
|
|
1495
1620
|
...c.age !== null ? { age: c.age } : {},
|
|
@@ -1702,6 +1827,14 @@ class CompResolver2 {
|
|
|
1702
1827
|
return answer("none", null, [], {
|
|
1703
1828
|
why: `the release holds no year of ${place.asked}'s series before ${place.year ?? "?"}`
|
|
1704
1829
|
});
|
|
1830
|
+
const newestYear = earlier[0];
|
|
1831
|
+
const newestIds = await this.idsOf(place.brand_id, newestYear);
|
|
1832
|
+
const newestComps = await this.compsOf(newestIds);
|
|
1833
|
+
const platform = newestComps[0]?.platform ?? null;
|
|
1834
|
+
if (platform === null || CODE_READER.scheme(platform) === "feis-specific") {
|
|
1835
|
+
const noChamps = newestComps.some((c) => c.kind === "championship") ? "" : `, and the ${newestYear} syllabus, read from results, lists no championship`;
|
|
1836
|
+
return byTitle(newestIds, { feis_ids: newestIds, year: newestYear }, `${platform ?? "the series' platform"} numbers each feis-year's competitions its own way: code ${q.code} is read only in the ${place.year ?? "asked"} syllabus, which the release does not hold${noChamps}`);
|
|
1837
|
+
}
|
|
1705
1838
|
for (const y of earlier) {
|
|
1706
1839
|
const ids = await this.idsOf(place.brand_id, y);
|
|
1707
1840
|
const hits = await this.compsOf(ids, q.code);
|
|
@@ -1989,22 +2122,28 @@ var encoderOf = (r) => schoolEncoder({ reader: r.reader });
|
|
|
1989
2122
|
var TABLE = "school_name";
|
|
1990
2123
|
var schoolsIndex = {
|
|
1991
2124
|
name: "schools",
|
|
1992
|
-
version: "
|
|
2125
|
+
version: "3",
|
|
1993
2126
|
inputs: ["results", "school-registry.jsonl", "school-redirects.jsonl"],
|
|
1994
2127
|
says: "every published school print and its ids, read at the school reader's slots",
|
|
1995
2128
|
keyParts: (rel) => [`reader=${rel.schoolReader().id}`],
|
|
1996
2129
|
build(rel, out) {
|
|
1997
2130
|
const choice = rel.schoolReader();
|
|
1998
2131
|
const encoder = encoderOf(choice);
|
|
1999
|
-
out.run("CREATE TABLE print_id(print TEXT NOT NULL, school_id TEXT NOT NULL, rows INTEGER NOT NULL, PRIMARY KEY(print, school_id)) WITHOUT ROWID");
|
|
2132
|
+
out.run("CREATE TABLE print_id(print TEXT NOT NULL, school_id TEXT NOT NULL, rows INTEGER NOT NULL, year_lo INTEGER, year_hi INTEGER, PRIMARY KEY(print, school_id)) WITHOUT ROWID");
|
|
2000
2133
|
out.run("CREATE TABLE registry(school_id TEXT PRIMARY KEY, display TEXT NOT NULL, regions TEXT NOT NULL, places TEXT NOT NULL)");
|
|
2001
2134
|
out.run("CREATE TABLE redirect(old_id TEXT PRIMARY KEY, new_id TEXT NOT NULL, kind TEXT NOT NULL)");
|
|
2002
2135
|
const schema = indexSchema3(encoder, { table: TABLE });
|
|
2003
2136
|
out.run(schema.table);
|
|
2004
|
-
const
|
|
2005
|
-
const
|
|
2137
|
+
const src = rel.db("results");
|
|
2138
|
+
const lined = src.query("PRAGMA table_info(results)").all().some((c) => c.name === "competition_line");
|
|
2139
|
+
const pairs = src.query(lined ? `SELECT trim(r.school_printed) AS p, r.school_id AS s, count(*) AS n,
|
|
2140
|
+
min(c.year) AS lo, max(c.year) AS hi
|
|
2141
|
+
FROM results r LEFT JOIN competitions c ON c.file = r.file AND c.line = r.competition_line
|
|
2142
|
+
WHERE r.school_id IS NOT NULL GROUP BY 1, 2 ORDER BY 1, 2` : `SELECT trim(school_printed) AS p, school_id AS s, count(*) AS n, NULL AS lo, NULL AS hi
|
|
2143
|
+
FROM results WHERE school_id IS NOT NULL GROUP BY 1, 2 ORDER BY 1, 2`).all();
|
|
2144
|
+
const putPair = out.prepare("INSERT INTO print_id VALUES (?, ?, ?, ?, ?)");
|
|
2006
2145
|
for (const r of pairs)
|
|
2007
|
-
putPair.run(r.p, r.s, r.n);
|
|
2146
|
+
putPair.run(r.p, r.s, r.n, r.lo, r.hi);
|
|
2008
2147
|
out.run("CREATE INDEX print_id_school ON print_id(school_id)");
|
|
2009
2148
|
const names = createIndex3(out, encoder, {
|
|
2010
2149
|
table: TABLE
|
|
@@ -2049,6 +2188,23 @@ class SchoolResolver2 {
|
|
|
2049
2188
|
};
|
|
2050
2189
|
const answer = (candidates, extra = {}) => {
|
|
2051
2190
|
let cs = candidates.sort((a, b) => b.rows - a.rows || (a.school_id < b.school_id ? -1 : 1));
|
|
2191
|
+
let year;
|
|
2192
|
+
if (q.year !== undefined && cs.length > 1 && cs.every((c) => c.years !== undefined)) {
|
|
2193
|
+
const y = q.year;
|
|
2194
|
+
const span = (c) => c.years;
|
|
2195
|
+
let kept = cs.filter((c) => {
|
|
2196
|
+
const { lo, hi } = span(c);
|
|
2197
|
+
return lo !== null && hi !== null && lo <= y && y <= hi;
|
|
2198
|
+
});
|
|
2199
|
+
if (kept.length === 0) {
|
|
2200
|
+
const before = cs.filter((c) => span(c).hi !== null && span(c).hi < y);
|
|
2201
|
+
const last = Math.max(...before.map((c) => span(c).hi));
|
|
2202
|
+
kept = before.filter((c) => span(c).hi === last);
|
|
2203
|
+
}
|
|
2204
|
+
year = { asked: y, narrowed: kept.length > 0 && kept.length < cs.length };
|
|
2205
|
+
if (kept.length > 0)
|
|
2206
|
+
cs = kept;
|
|
2207
|
+
}
|
|
2052
2208
|
let region;
|
|
2053
2209
|
if (q.region !== undefined) {
|
|
2054
2210
|
const kept = cs.filter((c) => c.regions.length === 0 || c.regions.includes(q.region));
|
|
@@ -2062,6 +2218,7 @@ class SchoolResolver2 {
|
|
|
2062
2218
|
arm: cs.length === 0 ? "none" : cs.length === 1 ? "unique" : "ambiguous",
|
|
2063
2219
|
candidates: cs,
|
|
2064
2220
|
...region !== undefined ? { region } : {},
|
|
2221
|
+
...year !== undefined ? { year } : {},
|
|
2065
2222
|
...extra
|
|
2066
2223
|
};
|
|
2067
2224
|
};
|
|
@@ -2085,15 +2242,27 @@ class SchoolResolver2 {
|
|
|
2085
2242
|
return answer([byId(live, "redirect")], { redirected: { from: a, to: live } });
|
|
2086
2243
|
const byPrints = (prints, by) => {
|
|
2087
2244
|
const ids = new Map;
|
|
2088
|
-
const q2 = db.query("SELECT school_id, rows FROM print_id WHERE print = ?");
|
|
2245
|
+
const q2 = db.query("SELECT school_id, rows, year_lo AS lo, year_hi AS hi FROM print_id WHERE print = ?");
|
|
2089
2246
|
for (const p of prints)
|
|
2090
2247
|
for (const r of q2.all(p)) {
|
|
2091
|
-
const e = ids.get(r.school_id) ?? {
|
|
2248
|
+
const e = ids.get(r.school_id) ?? {
|
|
2249
|
+
rows: 0,
|
|
2250
|
+
prints: new Set,
|
|
2251
|
+
lo: null,
|
|
2252
|
+
hi: null
|
|
2253
|
+
};
|
|
2092
2254
|
e.rows += r.rows;
|
|
2093
2255
|
e.prints.add(p);
|
|
2256
|
+
if (r.lo !== null && (e.lo === null || r.lo < e.lo))
|
|
2257
|
+
e.lo = r.lo;
|
|
2258
|
+
if (r.hi !== null && (e.hi === null || r.hi > e.hi))
|
|
2259
|
+
e.hi = r.hi;
|
|
2094
2260
|
ids.set(r.school_id, e);
|
|
2095
2261
|
}
|
|
2096
|
-
return [...ids].map(([id, e]) =>
|
|
2262
|
+
return [...ids].map(([id, e]) => ({
|
|
2263
|
+
...candidate(id, by, e.rows, [...e.prints].sort()),
|
|
2264
|
+
years: { lo: e.lo, hi: e.hi }
|
|
2265
|
+
}));
|
|
2097
2266
|
};
|
|
2098
2267
|
const exact = byPrints([a], "print");
|
|
2099
2268
|
if (exact.length > 0)
|
package/dist/cli.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
nameOrderOf,
|
|
5
5
|
openRelease2,
|
|
6
6
|
releases2
|
|
7
|
-
} from "./chunks/index-
|
|
7
|
+
} from "./chunks/index-hhhrh1db.js";
|
|
8
8
|
import"./chunks/index-hne1wadw.js";
|
|
9
9
|
import"./chunks/index-hghdy980.js";
|
|
10
10
|
|
|
@@ -81,7 +81,8 @@ var USAGE = `usage: idq <verb> [--cache <dir>] [--repo <owner/name>] [--json]
|
|
|
81
81
|
the register's and the panels' people: the same answer
|
|
82
82
|
comp [--release <spec>] <feis> <code> [--year <y>] [--title <t>]
|
|
83
83
|
a feis's own comp code to the comp it names, through that
|
|
84
|
-
feis's syllabus (
|
|
84
|
+
feis's syllabus (the prior year's only where the platform
|
|
85
|
+
numbers every feis alike; elsewhere the title)
|
|
85
86
|
syllabus [--release <spec>] <feis> [year]
|
|
86
87
|
one feis-year's comps, in printed order
|
|
87
88
|
syllabus [--release <spec>] --for <series> [year]
|
package/dist/index.js
CHANGED
package/dist/types/cli.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
import type { OpenOptions } from "./release.js";
|
|
3
3
|
import type { StreamQuery } from "./stream.js";
|
|
4
|
-
export declare const USAGE = "usage: idq <verb> [--cache <dir>] [--repo <owner/name>] [--json]\n\n config repo <owner/name> set the user-local repository the releases come from\n list [--remote] the cached releases (size, files, indexes, the pin), and\n with --remote the published tags\n fetch [--release <spec>] [--assets results,majors,<file>...]\n download, verify and cache a release (default: results)\n pin <spec> the user-local pin: what a bare open (spec \"pinned\") opens\n unpin remove the pin (a bare open is then \"latest\")\n current the pin, and whether it is cached\n add <dir> --tag <tag> add a release built locally (its MANIFEST.json and files)\n to the cache under its tag\n index [--release <spec>] [<name>...] [--force]\n build the per-tag indexes (default: every one)\n verify [--release <spec>] re-hash every cached file against its receipt\n capabilities [--release <spec>] what the release carries of what the client reads, from\n its own schema: each feature full or missing (its calls\n refuse, naming the first cut that publishes it)\n prune [--keep N] [--dry-run] remove all but the N newest cached releases (default 1)\n and the pinned one\n rm <tag> [--dry-run] remove one cached release (not the pinned one)\n drop-indexes [<tag>] [--dry-run] remove the index files (of one release, or of every one)\n feis [--release <spec>] [--platform <p>] [--code <c>] [--id <id>] [--name <glob>] [--year <y>]\n the feises a query names\n series [--release <spec>] <name|host code|feis id>\n the series a name, a host code (fweb:ABC) or any feis id\n names: its years, hosts, codes and next instance\n school [--release <spec>] <print|school_id> [--region <code>]\n a school print or id to the published schools\n dancer [--release <spec>] <name> | --surname <s> | --like <glob> | --id <dancer_id>\n [--order surname-first|given-first] [--school <print|id>]\n [--yob <y> | --band <U10> [--year <y>] | --comp <competition>] [--as-of <date>]\n [--population girls|boys] [--oireachtas <region>[:<year>]] [--rows]\n the dancers a name reaches, each with its evidence\n (name level, age, school, population, region) and the arm;\n --oireachtas is the regional the roster is for, its region in\n the release's spelling (SRO, MAO), its year the --as-of year\n where none is given; the results of\n the one dancer where one answers (or --rows for each)\n results [--release <spec>] [--dancer <id>] [--feis <id>] [--comp <competition>]\n [--school <print|id>] [--year <y>] [--limit <n>]\n the published result rows, prints and ids\n majors [--release <spec>] [--event <e>] [--year <y>] [--comp <competition>] [--dancer <id>]\n the majors: every event and its years; an event's\n competitions; a competition's, an event's or a dancer's rows\n stream [--release <spec>] --scope majors|transcribed|platform|all [--entries] [--event <e,...>]\n [--year <y> | --year <from>..<to>] [--tier <t,...>] [--category <c,...>]\n [--level <feis_level,...>] [--dancer <id,...>] [--school <school_id>] [--primary]\n every row a scope holds, one JSON line each, never the\n whole table in memory; --entries one per address (the row\n it stands for, with its recall order)\n records [--release <spec>] [--dancer <id,...>]\n every dancer's record: display, appearances, birth window,\n populations\n records --years [--release <spec>] [--dancer <id,...>] [--year <y>]\n each dancer's region, nationals and place per year\n feis-dates [--release <spec>] every feis's first and last day\n tabulated [--release <spec>] [--min-round <n>]\n the majors addresses the marks sheets tabulate to round n\n or later (default 3)\n teams [--release <spec>] [--event <e>] [--year <y>] [--rosters | --joins]\n the team result rows of an event-year; with --rosters its\n roster teams and their dancers; with --joins how each roster\n team meets the results\n events [--release <spec>] [--event <e>] [--year <y>]\n each event-year's dates and place\n teacher [--release <spec>] <name|TD number>\n the staff lists' people: where they taught, the register,\n where they sat\n adjudicator [--release <spec>] <name|TD number>\n the register's and the panels' people: the same answer\n comp [--release <spec>] <feis> <code> [--year <y>] [--title <t>]\n a feis's own comp code to the comp it names, through that\n feis's syllabus (
|
|
4
|
+
export declare const USAGE = "usage: idq <verb> [--cache <dir>] [--repo <owner/name>] [--json]\n\n config repo <owner/name> set the user-local repository the releases come from\n list [--remote] the cached releases (size, files, indexes, the pin), and\n with --remote the published tags\n fetch [--release <spec>] [--assets results,majors,<file>...]\n download, verify and cache a release (default: results)\n pin <spec> the user-local pin: what a bare open (spec \"pinned\") opens\n unpin remove the pin (a bare open is then \"latest\")\n current the pin, and whether it is cached\n add <dir> --tag <tag> add a release built locally (its MANIFEST.json and files)\n to the cache under its tag\n index [--release <spec>] [<name>...] [--force]\n build the per-tag indexes (default: every one)\n verify [--release <spec>] re-hash every cached file against its receipt\n capabilities [--release <spec>] what the release carries of what the client reads, from\n its own schema: each feature full or missing (its calls\n refuse, naming the first cut that publishes it)\n prune [--keep N] [--dry-run] remove all but the N newest cached releases (default 1)\n and the pinned one\n rm <tag> [--dry-run] remove one cached release (not the pinned one)\n drop-indexes [<tag>] [--dry-run] remove the index files (of one release, or of every one)\n feis [--release <spec>] [--platform <p>] [--code <c>] [--id <id>] [--name <glob>] [--year <y>]\n the feises a query names\n series [--release <spec>] <name|host code|feis id>\n the series a name, a host code (fweb:ABC) or any feis id\n names: its years, hosts, codes and next instance\n school [--release <spec>] <print|school_id> [--region <code>]\n a school print or id to the published schools\n dancer [--release <spec>] <name> | --surname <s> | --like <glob> | --id <dancer_id>\n [--order surname-first|given-first] [--school <print|id>]\n [--yob <y> | --band <U10> [--year <y>] | --comp <competition>] [--as-of <date>]\n [--population girls|boys] [--oireachtas <region>[:<year>]] [--rows]\n the dancers a name reaches, each with its evidence\n (name level, age, school, population, region) and the arm;\n --oireachtas is the regional the roster is for, its region in\n the release's spelling (SRO, MAO), its year the --as-of year\n where none is given; the results of\n the one dancer where one answers (or --rows for each)\n results [--release <spec>] [--dancer <id>] [--feis <id>] [--comp <competition>]\n [--school <print|id>] [--year <y>] [--limit <n>]\n the published result rows, prints and ids\n majors [--release <spec>] [--event <e>] [--year <y>] [--comp <competition>] [--dancer <id>]\n the majors: every event and its years; an event's\n competitions; a competition's, an event's or a dancer's rows\n stream [--release <spec>] --scope majors|transcribed|platform|all [--entries] [--event <e,...>]\n [--year <y> | --year <from>..<to>] [--tier <t,...>] [--category <c,...>]\n [--level <feis_level,...>] [--dancer <id,...>] [--school <school_id>] [--primary]\n every row a scope holds, one JSON line each, never the\n whole table in memory; --entries one per address (the row\n it stands for, with its recall order)\n records [--release <spec>] [--dancer <id,...>]\n every dancer's record: display, appearances, birth window,\n populations\n records --years [--release <spec>] [--dancer <id,...>] [--year <y>]\n each dancer's region, nationals and place per year\n feis-dates [--release <spec>] every feis's first and last day\n tabulated [--release <spec>] [--min-round <n>]\n the majors addresses the marks sheets tabulate to round n\n or later (default 3)\n teams [--release <spec>] [--event <e>] [--year <y>] [--rosters | --joins]\n the team result rows of an event-year; with --rosters its\n roster teams and their dancers; with --joins how each roster\n team meets the results\n events [--release <spec>] [--event <e>] [--year <y>]\n each event-year's dates and place\n teacher [--release <spec>] <name|TD number>\n the staff lists' people: where they taught, the register,\n where they sat\n adjudicator [--release <spec>] <name|TD number>\n the register's and the panels' people: the same answer\n comp [--release <spec>] <feis> <code> [--year <y>] [--title <t>]\n a feis's own comp code to the comp it names, through that\n feis's syllabus (the prior year's only where the platform\n numbers every feis alike; elsewhere the title)\n syllabus [--release <spec>] <feis> [year]\n one feis-year's comps, in printed order\n syllabus [--release <spec>] --for <series> [year]\n a series' syllabus for a year: that year's where held,\n else the newest, saying which and what it is read from\n resolve comp [<feis> <code>] [--year <y>] [--title <t>]\n resolve dancer [<name>] [--school <s>] [--comp <feis>/<code> | --yob <y> | --band <b> --year <y>]\n [--order <o>] [--as-of <date>] [--population girls|boys]\n [--oireachtas <region>[:<year>]]\n resolve registrations\n JSONL out, one answer per line; with no positional the\n questions are JSONL on stdin, one per line (a comp:\n {feis, code, year?, title?}, a dancer: {name, school?, age?,\n population?, oireachtas?}, a registration: {name, school?,\n codes[], feis, year?, population?, oireachtas?})\n\n <spec>: pinned (the default) | latest | a cut (42, 42.1) | a tag (archive-YYYY.MM.DD-N)";
|
|
5
5
|
export interface Parsed {
|
|
6
6
|
positional: string[];
|
|
7
7
|
flags: Map<string, string>;
|
package/dist/types/comps.d.ts
CHANGED
|
@@ -121,6 +121,7 @@ interface CompRow {
|
|
|
121
121
|
}
|
|
122
122
|
export declare function compOf(r: CompRow, codes?: readonly string[]): Comp;
|
|
123
123
|
export declare function canonicalOf(level: number | null, age: string | null): string | null;
|
|
124
|
+
export declare const CODE_READER: import("@finbheara/domain/code").CodeReader;
|
|
124
125
|
export declare class CompResolver {
|
|
125
126
|
private readonly rel;
|
|
126
127
|
constructor(rel: Release);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type PersonName, type TransitiveLevel } from "@finbheara/names/normalize";
|
|
2
|
-
export type NameLevel = TransitiveLevel | "initial" | "middle" | "surname" | "like";
|
|
2
|
+
export type NameLevel = TransitiveLevel | "initial" | "middle" | "form" | "surname" | "like";
|
|
3
3
|
export declare const NAME_LEVELS: readonly NameLevel[];
|
|
4
4
|
export declare const finer: (a: NameLevel, b: NameLevel) => NameLevel;
|
|
5
5
|
export declare function nameLevel(q: PersonName, c: PersonName): NameLevel | null;
|
package/dist/types/dancers.d.ts
CHANGED
|
@@ -52,7 +52,9 @@ export interface DancerCandidate {
|
|
|
52
52
|
school: SchoolEvidence;
|
|
53
53
|
population: PopulationEvidence;
|
|
54
54
|
region: RegionEvidence;
|
|
55
|
+
form?: string[];
|
|
55
56
|
};
|
|
57
|
+
widened?: "birth-conflict";
|
|
56
58
|
prints: {
|
|
57
59
|
print: string;
|
|
58
60
|
rows: number;
|
|
@@ -82,13 +84,19 @@ export interface DancerRegion {
|
|
|
82
84
|
}
|
|
83
85
|
export interface ExcludedCandidate {
|
|
84
86
|
candidate: DancerCandidate;
|
|
85
|
-
why: "age" | "population" | "region" | "school";
|
|
87
|
+
why: "age" | "population" | "region" | "school" | "given" | "name-form";
|
|
86
88
|
}
|
|
87
89
|
export interface InitialsRefuted {
|
|
88
90
|
dancer_id: number;
|
|
89
|
-
why: "school" | "age" | "population" | "region";
|
|
91
|
+
why: "school" | "age" | "population" | "region" | "given" | "name-form";
|
|
90
92
|
fact: string;
|
|
91
93
|
}
|
|
94
|
+
export interface Narrowing {
|
|
95
|
+
open: number[];
|
|
96
|
+
heldByDanceUp: number[];
|
|
97
|
+
refuted: InitialsRefuted[];
|
|
98
|
+
year: number;
|
|
99
|
+
}
|
|
92
100
|
export interface DancerAnswer {
|
|
93
101
|
tag: string;
|
|
94
102
|
asked: DancerQuery;
|
|
@@ -128,12 +136,9 @@ export interface DancerAnswer {
|
|
|
128
136
|
lineage?: string[];
|
|
129
137
|
};
|
|
130
138
|
refused?: string;
|
|
131
|
-
initials?:
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
refuted: InitialsRefuted[];
|
|
135
|
-
year: number;
|
|
136
|
-
};
|
|
139
|
+
initials?: Narrowing;
|
|
140
|
+
fullName?: Narrowing;
|
|
141
|
+
widened?: "birth-conflict" | "name-form";
|
|
137
142
|
}
|
|
138
143
|
export interface DancerSearchQuery extends Omit<DancerQuery, "name"> {
|
|
139
144
|
name?: string;
|
|
@@ -216,6 +221,7 @@ export declare class DancerResolver {
|
|
|
216
221
|
years: DancerYear[];
|
|
217
222
|
}>;
|
|
218
223
|
resolve(q: DancerQuery): Promise<DancerAnswer>;
|
|
224
|
+
private formsOf;
|
|
219
225
|
search(q: DancerSearchQuery): Promise<DancerAnswer>;
|
|
220
226
|
private capped;
|
|
221
227
|
get(dancerId: number): Promise<DancerRecord | null>;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { type AssetPlan, DATABASES, type DatabaseName, type LandedFile, type Receipt, type ReleaseManifest, planAsset, } from "./assets.js";
|
|
2
2
|
export { sha256File, unzstdTo } from "./bytes.js";
|
|
3
|
-
export { type AgeAsked, type AgeEvidence, type DancerAnswer, type DancerBulkRecord, type DancerCandidate, type DancerQuery, type DancerRecord, DancerResolver, type DancerRegion, type DancerSchool, type DancerSearchQuery, type DancerYear, type ExcludedCandidate, FEIS_LOCAL_ID_FLOOR, type InitialsRefuted, initialsOnly, type OireachtasAsked, type PopulationEvidence, type RegionEvidence, type SchoolEvidence, readPopulation, } from "./dancers.js";
|
|
3
|
+
export { type AgeAsked, type AgeEvidence, type DancerAnswer, type DancerBulkRecord, type DancerCandidate, type DancerQuery, type DancerRecord, DancerResolver, type DancerRegion, type DancerSchool, type DancerSearchQuery, type DancerYear, type ExcludedCandidate, FEIS_LOCAL_ID_FLOOR, type InitialsRefuted, type Narrowing, initialsOnly, type OireachtasAsked, type PopulationEvidence, type RegionEvidence, type SchoolEvidence, readPopulation, } from "./dancers.js";
|
|
4
4
|
export { NAME_LEVELS, type NameLevel, nameLevel } from "./dancers-names.js";
|
|
5
5
|
export { type Comp, type CompAnswer, type CompDance, type CompKind, type CompQuery, CompResolver, type CompSource, type FeisPlace, type SyllabusAnswer, type SyllabusForAnswer, type SyllabusSource, type TitleCheck, canonicalOf, } from "./comps.js";
|
|
6
6
|
export { type ClientOptions, cacheRoot, repoOf } from "./config.js";
|
package/dist/types/schools.d.ts
CHANGED
|
@@ -10,6 +10,10 @@ export interface SchoolCandidate {
|
|
|
10
10
|
prints: string[];
|
|
11
11
|
regions: string[];
|
|
12
12
|
places: string[];
|
|
13
|
+
years?: {
|
|
14
|
+
lo: number | null;
|
|
15
|
+
hi: number | null;
|
|
16
|
+
};
|
|
13
17
|
}
|
|
14
18
|
export interface SchoolAnswer {
|
|
15
19
|
tag: string;
|
|
@@ -20,6 +24,10 @@ export interface SchoolAnswer {
|
|
|
20
24
|
asked: string;
|
|
21
25
|
narrowed: boolean;
|
|
22
26
|
};
|
|
27
|
+
year?: {
|
|
28
|
+
asked: number;
|
|
29
|
+
narrowed: boolean;
|
|
30
|
+
};
|
|
23
31
|
redirected?: {
|
|
24
32
|
from: string;
|
|
25
33
|
to: string;
|
|
@@ -28,6 +36,7 @@ export interface SchoolAnswer {
|
|
|
28
36
|
}
|
|
29
37
|
export interface SchoolQuery {
|
|
30
38
|
region?: string;
|
|
39
|
+
year?: number;
|
|
31
40
|
}
|
|
32
41
|
export interface SchoolReaderChoice {
|
|
33
42
|
id: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@finbheara/archive-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
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,7 +44,7 @@
|
|
|
44
44
|
"prepublishOnly": "bun scripts/build.ts && bun ../../tools/checks/archive-client-tarball.ts"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@finbheara/domain": "0.
|
|
47
|
+
"@finbheara/domain": "0.53.0",
|
|
48
48
|
"@finbheara/names": "0.25.0",
|
|
49
49
|
"hyparquet": "1.31.2"
|
|
50
50
|
},
|