@finbheara/archive-client 0.4.0 → 0.6.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 +78 -6
- package/dist/chunks/{index-v8e0qe9f.js → index-gy5xye67.js} +308 -16
- package/dist/cli.js +136 -3
- package/dist/index.js +3 -1
- package/dist/types/cli.d.ts +3 -1
- package/dist/types/dancers.d.ts +33 -0
- package/dist/types/feises.d.ts +8 -0
- package/dist/types/index.d.ts +2 -1
- package/dist/types/results.d.ts +11 -0
- package/dist/types/stream.d.ts +73 -0
- package/dist/types/teams.d.ts +7 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ type declarations (`.d.ts`), so a TypeScript project needs Bun's types (`"types"
|
|
|
20
20
|
`bunx idq <verb>`.
|
|
21
21
|
|
|
22
22
|
The version is 0.x while the API settles: a minor bump may break, so pin a minor
|
|
23
|
-
(`"@finbheara/archive-client": "0.
|
|
23
|
+
(`"@finbheara/archive-client": "0.6.x"`).
|
|
24
24
|
|
|
25
25
|
## Configuration
|
|
26
26
|
|
|
@@ -85,7 +85,13 @@ c.features; // [{ feature: "dancers", state: "full" | "missing", missing: [...
|
|
|
85
85
|
| `staff` | `staff.teacher`, `staff.adjudicator` | 260 |
|
|
86
86
|
| `majors.order` | `majors.competitions` | 260 |
|
|
87
87
|
| `feises`, `comps` | `feises.find`, `feises.series`, `comps.*`, `registrations.resolve` | 265 |
|
|
88
|
+
| `results.stream`, `majors.stream` | `results.stream`, `results.entries` | 255 |
|
|
89
|
+
| `feises.dates` | `feises.dates` | 245 |
|
|
90
|
+
| `dancers.records` | `dancers.records` | 215 |
|
|
91
|
+
| `dancers.years` | `dancers.years` | 245 |
|
|
92
|
+
| `majors.tabs` | `majors.tabulated` | 215 |
|
|
88
93
|
| `teams` | `teams.results`, `teams.rosters`, `teams.resultRosters` | 260 |
|
|
94
|
+
| `teams.fields` | the fields `teams.results` (`age`, `gender`, `printed_status`) and `teams.rosters` (`dance`, `school_printed_as_of`, a member's `gender`) carry; absent, never refused, without it | 266 |
|
|
89
95
|
| `events` | `events.years` | 260 |
|
|
90
96
|
|
|
91
97
|
A spec is `pinned` (the default: the user-local pin, else the latest), `latest`, a cut number
|
|
@@ -276,15 +282,60 @@ A row carries the prints and the ids that stand for them: the address, the compe
|
|
|
276
282
|
and age, the place, the name and school as printed with the dancer and school ids. The majors are
|
|
277
283
|
read from `majors.sqlite`, fetched on first use.
|
|
278
284
|
|
|
285
|
+
## Every row, streamed
|
|
286
|
+
|
|
287
|
+
```ts
|
|
288
|
+
for await (const row of rel.results.stream({ scope: "majors" })) { ... }
|
|
289
|
+
for await (const row of rel.results.stream({
|
|
290
|
+
scope: "platform", // "majors" | "transcribed" | "platform" | "all"
|
|
291
|
+
primary: true, // only rows no other source stands in for
|
|
292
|
+
year: [2015, 2024], // a year or an inclusive range
|
|
293
|
+
feis_level: [600, 700], // also: event (one or several), tier, category, dancer_id, school_id
|
|
294
|
+
})) { ... }
|
|
295
|
+
for await (const entry of rel.results.entries({ scope: "all", event: "<event>" })) { ... }
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
A stream yields one row at a time and never holds the table in memory. A row carries its
|
|
299
|
+
competition beside its own fields: `competition`, `event`, `year`, `tier`, `comp_no`, `title`,
|
|
300
|
+
`category`, `age`, `age_printed`, `gender`, `competitors`, `feis_level`, `level_printed`,
|
|
301
|
+
`date_printed`, `source`, `round`, and at a feis its `feis_id`, `feis_date_lo` and
|
|
302
|
+
`feis_date_hi`. Its own: `address`, `section`, `card`, `place`, `place_printed`, `tie`,
|
|
303
|
+
`relative_place`, `atts`, `withdrawn`, `qualifier`, `name_printed`, `name`, `school_printed`,
|
|
304
|
+
`school_loc`, `school_id`, `dancer_id`, `dancer_scope`, `yob`, `yob_printed`, `points_printed`,
|
|
305
|
+
`platform_dancer_id`, `primary_source`, and its key in the release, `file` and `line` (one
|
|
306
|
+
`(file, line)` is one row, where an `address` may carry one row per section). Rows come in the
|
|
307
|
+
release's own order, a competition's rows together.
|
|
308
|
+
|
|
309
|
+
The scopes: `majors` reads the majors (tiers T1 to T3), `transcribed` the transcribed rows of
|
|
310
|
+
every tier, `platform` every row a results platform published, `all` every row.
|
|
311
|
+
|
|
312
|
+
AN ENTRY is one row per address, the row the card stands for: a card printed in several sections
|
|
313
|
+
(a recall order, the final, a single round's solo placing, a qualifying heat) keeps the final's
|
|
314
|
+
row, then the sectionless page's, the recall order's, the standings', the unplaced row, a heat's
|
|
315
|
+
and last a solo round's (`entryRank`), and two rows of one rank keep the later. `recall_place` is
|
|
316
|
+
the place the address's recall row carries.
|
|
317
|
+
|
|
318
|
+
## Bulk reads
|
|
319
|
+
|
|
320
|
+
```ts
|
|
321
|
+
await rel.dancers.records(); // every dancer: display, appearances, birth_lo, birth_hi,
|
|
322
|
+
// birth_source, birth_conflict, genders, scope
|
|
323
|
+
await rel.dancers.records({ ids: [1001] });
|
|
324
|
+
await rel.dancers.years({ ids: [1001], year: 2025 }); // region, region_source, nationals, geohash
|
|
325
|
+
await rel.feises.dates(); // every feis id with its first and last day
|
|
326
|
+
await rel.majors.tabulated({ min_true_round: 3 }); // the majors addresses marked to round 3 or later
|
|
327
|
+
```
|
|
328
|
+
|
|
279
329
|
## Teams and event-years
|
|
280
330
|
|
|
281
331
|
```ts
|
|
282
332
|
const r = await rel.teams.results({ event: "<event>", year: 2024 });
|
|
283
|
-
r.results; // [{ address, competition, event, year, comp_no, title, category, hands,
|
|
284
|
-
// school_printed, school_id, place, place_printed,
|
|
333
|
+
r.results; // [{ address, competition, event, year, comp_no, title, category, hands, age, gender,
|
|
334
|
+
// letter, label, school_printed, school_id, place, place_printed, printed_status, tie,
|
|
335
|
+
// competitors, atts, ... }]
|
|
285
336
|
const t = await rel.teams.rosters({ event: "<event>", year: 2024 });
|
|
286
337
|
t.teams; // [{ team, kind, event, year, comp_no, title, team_index, seq, school_id, school_printed,
|
|
287
|
-
// members: [{ seq, name_printed, name, yob, dancer_id, dancer_scope }] }]
|
|
338
|
+
// school_printed_as_of, dance, members: [{ seq, name_printed, name, yob, gender, dancer_id, dancer_scope }] }]
|
|
288
339
|
const j = await rel.teams.resultRosters({ event: "<event>", year: 2024 });
|
|
289
340
|
j.joins; // [{ team, result_address, join_kind, via_split, roster_index, result_letter, ... }]
|
|
290
341
|
const e = await rel.events.years({ event: "<event>" });
|
|
@@ -299,7 +350,21 @@ roster team met the results (`exact`, `card`, `branch`) or why it did not (`no-r
|
|
|
299
350
|
`no-school`, `no-roster`, `multi-team-unjoined`), and `result_address` is null where none joined.
|
|
300
351
|
An event-year's dates are a window (`date_lo`, `date_hi`) with how fine it is (`resolution`:
|
|
301
352
|
`day`, `month`, `calendar`) and what it is read from (`source`), and `place` is a place-tree node
|
|
302
|
-
where the release knows one. A
|
|
353
|
+
where the release knows one. A team result's `age` and `gender` are the competition's band and sex
|
|
354
|
+
as the release reads them, `printed_status` the row's printed status cell verbatim. A roster
|
|
355
|
+
team's `school_id` is its members' own school that year. Its `school_printed` is the school a
|
|
356
|
+
registration system held for it on `school_printed_as_of`, often years later, so a rename or a move
|
|
357
|
+
since shows there and it says nothing about the school that year. Its `dance` is the dance it was
|
|
358
|
+
entered for, and a member's `gender` is printed only as `M`:
|
|
359
|
+
the source withholds every other print, so null says nothing about a dancer's sex. A field the
|
|
360
|
+
source left empty is null.
|
|
361
|
+
|
|
362
|
+
THOSE NEWER FIELDS ARE ABSENT, NEVER NULL, ON A RELEASE THAT DOES NOT CARRY THEM: a team result's
|
|
363
|
+
`age`, `gender`, `printed_status`, a roster team's `school_printed_as_of`, `dance` and a member's
|
|
364
|
+
`gender` (feature `teams.fields`, see the table above). Absent means "this release does not carry it", null
|
|
365
|
+
means the release carries the field and has no value. `teams.results` and `teams.rosters` answer on
|
|
366
|
+
every release the `teams` feature names, and `(await rel.capability("teams.fields")).state` says which shape
|
|
367
|
+
a release has. The rows are read once per
|
|
303
368
|
release into the `teams` and `events` indexes.
|
|
304
369
|
|
|
305
370
|
## Teachers and adjudicators
|
|
@@ -426,6 +491,13 @@ and the competitions still resolve.
|
|
|
426
491
|
[--population girls|boys] [--rows]
|
|
427
492
|
idq results [--release <spec>] [--dancer <id>] [--feis <id>] [--comp <c>] [--school <s>] [--year <y>] [--limit <n>]
|
|
428
493
|
idq majors [--release <spec>] [--event <e>] [--year <y>] [--comp <c>] [--dancer <id>] [--rows]
|
|
494
|
+
idq stream [--release <spec>] --scope majors|transcribed|platform|all [--entries] [--event <e,...>]
|
|
495
|
+
[--year <y> | --year <from>..<to>] [--tier <t,...>] [--category <c,...>]
|
|
496
|
+
[--level <n,...>] [--dancer <id,...>] [--school <school_id>] [--primary]
|
|
497
|
+
idq records [--release <spec>] [--dancer <id,...>]
|
|
498
|
+
idq records --years [--release <spec>] [--dancer <id,...>] [--year <y>]
|
|
499
|
+
idq feis-dates [--release <spec>]
|
|
500
|
+
idq tabulated [--release <spec>] [--min-round <n>]
|
|
429
501
|
idq teams [--release <spec>] [--event <e>] [--year <y>] [--rosters | --joins]
|
|
430
502
|
idq events [--release <spec>] [--event <e>] [--year <y>]
|
|
431
503
|
idq teacher [--release <spec>] <name|TD number>
|
|
@@ -437,7 +509,7 @@ and the competitions still resolve.
|
|
|
437
509
|
idq resolve dancer [<name>] [--school s] [--comp <feis>/<code> | --yob y | --band b --year y]
|
|
438
510
|
idq resolve registrations
|
|
439
511
|
|
|
440
|
-
`dancer` prints the results of the one dancer where the answer is unique (every candidate's with
|
|
512
|
+
`stream` prints one JSON line per row (or entry), as it reads them. `dancer` prints the results of the one dancer where the answer is unique (every candidate's with
|
|
441
513
|
`--rows`). `--json` prints the call's answer as it is. `--cache` and `--repo` override the defaults.
|
|
442
514
|
|
|
443
515
|
`resolve` speaks JSON lines: one answer per line out, and with no positional question the
|
|
@@ -106,8 +106,149 @@ function nameLevel2(q, c) {
|
|
|
106
106
|
return null;
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
var ENTRY_RANK = new Map([
|
|
110
|
+
["final", 0],
|
|
111
|
+
["", 1],
|
|
112
|
+
["recall", 2],
|
|
113
|
+
["standings", 3],
|
|
114
|
+
["unplaced", 4],
|
|
115
|
+
["qual", 5],
|
|
116
|
+
["qual-a", 5],
|
|
117
|
+
["qual-b", 5]
|
|
118
|
+
]);
|
|
119
|
+
function entryRank2(section) {
|
|
120
|
+
const known = ENTRY_RANK.get(section);
|
|
121
|
+
if (known !== undefined)
|
|
122
|
+
return known;
|
|
123
|
+
if (/^solo(?:-r\d+)?$/.test(section))
|
|
124
|
+
return 6;
|
|
125
|
+
return 9;
|
|
126
|
+
}
|
|
127
|
+
var COLUMNS = `r.address AS address, r.competition AS competition, c.event AS event,
|
|
128
|
+
c.year AS year, c.tier AS tier, c.comp_no AS comp_no, c.title AS title, c.category AS category,
|
|
129
|
+
c.age AS age, c.age_printed AS age_printed, c.gender AS gender, c.competitors AS competitors,
|
|
130
|
+
c.feis_level AS feis_level, c.level_printed AS level_printed, c.date_printed AS date_printed,
|
|
131
|
+
c.source AS source, c.round AS round, r.section AS section, r.card AS card, r.place AS place,
|
|
132
|
+
r.place_printed AS place_printed, r.tie AS tie, r.relative_place AS relative_place,
|
|
133
|
+
r.atts AS atts, r.withdrawn AS withdrawn, r.qualifier AS qualifier,
|
|
134
|
+
r.name_printed AS name_printed, r.name AS name, r.school_printed AS school_printed,
|
|
135
|
+
r.school_loc AS school_loc, r.school_id AS school_id, r.dancer_id AS dancer_id, r.yob AS yob,
|
|
136
|
+
r.yob_printed AS yob_printed, r.points_printed AS points_printed,
|
|
137
|
+
r.platform_dancer_id AS platform_dancer_id, r.primary_source AS primary_source,
|
|
138
|
+
r.file AS file, r.line AS line`;
|
|
139
|
+
var TRANSCRIBED = "('transcript', 'manifested')";
|
|
140
|
+
var scopeDb = (s) => s === "majors" ? "majors" : "results";
|
|
141
|
+
function streamSql(q) {
|
|
142
|
+
const where = [];
|
|
143
|
+
const args = [];
|
|
144
|
+
const list = (col, v, nocase = false) => {
|
|
145
|
+
if (v.length === 0) {
|
|
146
|
+
where.push("0");
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
where.push(`${col}${nocase ? " COLLATE NOCASE" : ""} IN (${v.map(() => "?").join(", ")})`);
|
|
150
|
+
args.push(...v);
|
|
151
|
+
};
|
|
152
|
+
if (q.scope === "transcribed")
|
|
153
|
+
where.push(`r.source IN ${TRANSCRIBED}`);
|
|
154
|
+
else if (q.scope === "platform")
|
|
155
|
+
where.push(`r.source NOT IN ${TRANSCRIBED}`);
|
|
156
|
+
else if (q.scope !== "majors" && q.scope !== "all")
|
|
157
|
+
throw new Error(`archive-client: no stream scope "${String(q.scope)}"`);
|
|
158
|
+
if (q.event !== undefined)
|
|
159
|
+
list("c.event", typeof q.event === "string" ? [q.event] : q.event, true);
|
|
160
|
+
if (typeof q.year === "number") {
|
|
161
|
+
where.push("c.year = ?");
|
|
162
|
+
args.push(q.year);
|
|
163
|
+
} else if (Array.isArray(q.year)) {
|
|
164
|
+
where.push("c.year BETWEEN ? AND ?");
|
|
165
|
+
args.push(q.year[0], q.year[1]);
|
|
166
|
+
}
|
|
167
|
+
if (q.tier !== undefined)
|
|
168
|
+
list("c.tier", q.tier);
|
|
169
|
+
if (q.category !== undefined)
|
|
170
|
+
list("c.category", q.category);
|
|
171
|
+
if (q.feis_level !== undefined)
|
|
172
|
+
list("c.feis_level", q.feis_level);
|
|
173
|
+
if (q.dancer_id !== undefined)
|
|
174
|
+
list("r.dancer_id", q.dancer_id);
|
|
175
|
+
if (q.school_id !== undefined) {
|
|
176
|
+
where.push("r.school_id = ?");
|
|
177
|
+
args.push(q.school_id);
|
|
178
|
+
}
|
|
179
|
+
if (q.primary === true)
|
|
180
|
+
where.push("(r.primary_source IS NULL OR r.primary_source = '')");
|
|
181
|
+
return {
|
|
182
|
+
sql: `SELECT ${COLUMNS} 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`,
|
|
183
|
+
args
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
function feisDates(db) {
|
|
187
|
+
const out = new Map;
|
|
188
|
+
for (const f of db.query("SELECT feis_id, min(date_lo) AS lo, max(date_hi) AS hi FROM feises GROUP BY feis_id").all())
|
|
189
|
+
out.set(f.feis_id, { lo: f.lo, hi: f.hi });
|
|
190
|
+
return out;
|
|
191
|
+
}
|
|
192
|
+
var text = (v) => v === null || v === "" ? null : v;
|
|
193
|
+
function rowOf(r, dates) {
|
|
194
|
+
const { atts, withdrawn, ...rest } = r;
|
|
195
|
+
const d = dates.get(r.event);
|
|
196
|
+
return {
|
|
197
|
+
...rest,
|
|
198
|
+
feis_id: d === undefined ? null : r.event,
|
|
199
|
+
feis_date_lo: d?.lo ?? null,
|
|
200
|
+
feis_date_hi: d?.hi ?? null,
|
|
201
|
+
atts: atts === "" ? [] : atts.split(","),
|
|
202
|
+
withdrawn: text(withdrawn),
|
|
203
|
+
qualifier: text(rest.qualifier),
|
|
204
|
+
primary_source: text(rest.primary_source),
|
|
205
|
+
dancer_scope: r.dancer_id === null ? null : r.dancer_id >= FEIS_LOCAL_ID_FLOOR2 ? "per-release" : "stable"
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
async function* streamRows(db, q) {
|
|
209
|
+
const dates = feisDates(db);
|
|
210
|
+
const { sql, args } = streamSql(q);
|
|
211
|
+
const stmt = db.prepare(sql);
|
|
212
|
+
try {
|
|
213
|
+
for (const r of stmt.iterate(...args))
|
|
214
|
+
yield rowOf(r, dates);
|
|
215
|
+
} finally {
|
|
216
|
+
stmt.finalize();
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
async function* entryRows(db, q) {
|
|
220
|
+
const dates = feisDates(db);
|
|
221
|
+
const { sql, args } = streamSql(q);
|
|
222
|
+
const stmt = db.prepare(sql);
|
|
223
|
+
let file = null;
|
|
224
|
+
let held = new Map;
|
|
225
|
+
const flush = function* () {
|
|
226
|
+
for (const h of held.values())
|
|
227
|
+
yield { ...rowOf(h.raw, dates), recall_place: h.recall };
|
|
228
|
+
held = new Map;
|
|
229
|
+
};
|
|
230
|
+
try {
|
|
231
|
+
for (const r of stmt.iterate(...args)) {
|
|
232
|
+
if (r.file !== file) {
|
|
233
|
+
yield* flush();
|
|
234
|
+
file = r.file;
|
|
235
|
+
}
|
|
236
|
+
const rank = entryRank2(r.section);
|
|
237
|
+
const h = held.get(r.address);
|
|
238
|
+
const recall = r.section === "recall" ? r.place : h?.recall ?? null;
|
|
239
|
+
if (h === undefined || rank <= h.rank)
|
|
240
|
+
held.set(r.address, { raw: r, rank, recall });
|
|
241
|
+
else
|
|
242
|
+
h.recall = recall;
|
|
243
|
+
}
|
|
244
|
+
yield* flush();
|
|
245
|
+
} finally {
|
|
246
|
+
stmt.finalize();
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
109
250
|
var FEIS_LOCAL_ID_FLOOR2 = 17179869184;
|
|
110
|
-
var
|
|
251
|
+
var COLUMNS2 = `r.address AS address, r.competition AS competition, c.event AS event, c.year AS year,
|
|
111
252
|
c.tier AS tier, c.title AS title, c.age AS age, c.category AS category, c.gender AS gender,
|
|
112
253
|
c.feis_level AS feis_level, c.comp_no AS comp_no, r.place AS place,
|
|
113
254
|
r.place_printed AS place_printed, c.competitors AS competitors, r.name_printed AS name_printed,
|
|
@@ -139,7 +280,7 @@ function queryResults(rel, db, q) {
|
|
|
139
280
|
args.push(q.year);
|
|
140
281
|
}
|
|
141
282
|
const limit = q.limit ?? 500;
|
|
142
|
-
const all = rel.db(db).query(`SELECT ${
|
|
283
|
+
const all = rel.db(db).query(`SELECT ${COLUMNS2} FROM results r JOIN competitions c ON c.file = r.file AND c.line = r.competition_line
|
|
143
284
|
WHERE ${where.join(" AND ")}
|
|
144
285
|
ORDER BY c.year, c.event, r.competition, r.place IS NULL, r.place, r.address`).all(...args);
|
|
145
286
|
return {
|
|
@@ -164,6 +305,18 @@ class ResultFinder2 {
|
|
|
164
305
|
await this.rel.require("results.level");
|
|
165
306
|
return queryResults(this.rel, "results", q);
|
|
166
307
|
}
|
|
308
|
+
async streamDb(q) {
|
|
309
|
+
const db = scopeDb(q.scope);
|
|
310
|
+
await this.rel.fetch(db);
|
|
311
|
+
await this.rel.require(db === "majors" ? "majors.stream" : "results.stream");
|
|
312
|
+
return this.rel.db(db);
|
|
313
|
+
}
|
|
314
|
+
async* stream(q) {
|
|
315
|
+
yield* streamRows(await this.streamDb(q), q);
|
|
316
|
+
}
|
|
317
|
+
async* entries(q) {
|
|
318
|
+
yield* entryRows(await this.streamDb(q), q);
|
|
319
|
+
}
|
|
167
320
|
}
|
|
168
321
|
|
|
169
322
|
class MajorsFinder2 {
|
|
@@ -208,6 +361,13 @@ class MajorsFinder2 {
|
|
|
208
361
|
ORDER BY c.year, c.seq, c.competition`).all(...args).map((c) => ({ ...c, rows: rows.get(c.competition) ?? 0 }));
|
|
209
362
|
return { tag: this.rel.tag, competitions };
|
|
210
363
|
}
|
|
364
|
+
async tabulated(q = {}) {
|
|
365
|
+
const db = await this.db();
|
|
366
|
+
await this.rel.require("majors.tabs");
|
|
367
|
+
const min = q.min_true_round ?? 3;
|
|
368
|
+
const addresses = db.query("SELECT DISTINCT address FROM tabs WHERE true_round >= ? ORDER BY address").all(min).map((r) => r.address);
|
|
369
|
+
return { tag: this.rel.tag, min_true_round: min, addresses };
|
|
370
|
+
}
|
|
211
371
|
async results(q) {
|
|
212
372
|
await this.db();
|
|
213
373
|
await this.rel.require("results.level");
|
|
@@ -365,6 +525,12 @@ var SCHOOL_WEIGHT = {
|
|
|
365
525
|
unresolved: 0,
|
|
366
526
|
unasked: 0
|
|
367
527
|
};
|
|
528
|
+
function idChunks(ids) {
|
|
529
|
+
const out = [];
|
|
530
|
+
for (let i = 0;i < ids.length; i += 500)
|
|
531
|
+
out.push(ids.slice(i, i + 500));
|
|
532
|
+
return out;
|
|
533
|
+
}
|
|
368
534
|
|
|
369
535
|
class DancerResolver2 {
|
|
370
536
|
rel;
|
|
@@ -372,6 +538,34 @@ class DancerResolver2 {
|
|
|
372
538
|
constructor(rel) {
|
|
373
539
|
this.rel = rel;
|
|
374
540
|
}
|
|
541
|
+
async records(q = {}) {
|
|
542
|
+
await this.rel.fetch("results");
|
|
543
|
+
await this.rel.require("dancers.records");
|
|
544
|
+
const db = this.rel.db("results");
|
|
545
|
+
const sql = "SELECT dancer_id, display, appearances, birth_lo, birth_hi, birth_source, birth_conflict, genders FROM dancers";
|
|
546
|
+
const rows = q.ids === undefined ? db.query(`${sql} ORDER BY dancer_id`).all() : idChunks(q.ids).flatMap((c) => db.query(`${sql} WHERE dancer_id IN (${c.map(() => "?").join(",")})`).all(...c));
|
|
547
|
+
rows.sort((a, b) => a.dancer_id - b.dancer_id);
|
|
548
|
+
return {
|
|
549
|
+
tag: this.rel.tag,
|
|
550
|
+
records: rows.map((r) => ({
|
|
551
|
+
...r,
|
|
552
|
+
scope: r.dancer_id >= FEIS_LOCAL_ID_FLOOR2 ? "per-release" : "stable",
|
|
553
|
+
birth_conflict: r.birth_conflict === 1,
|
|
554
|
+
genders: r.genders === "" ? [] : r.genders.split(",")
|
|
555
|
+
}))
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
async years(q = {}) {
|
|
559
|
+
await this.rel.fetch("results");
|
|
560
|
+
await this.rel.require("dancers.years");
|
|
561
|
+
const db = this.rel.db("results");
|
|
562
|
+
const sql = "SELECT dancer_id, year, region, region_source, nationals, nationals_source, geohash FROM dancer_years";
|
|
563
|
+
const yearSql = q.year === undefined ? "" : " AND year = ?";
|
|
564
|
+
const yearArgs = q.year === undefined ? [] : [q.year];
|
|
565
|
+
const rows = q.ids === undefined ? db.query(`${sql} WHERE 1${yearSql} ORDER BY dancer_id, year`).all(...yearArgs) : idChunks(q.ids).flatMap((c) => db.query(`${sql} WHERE dancer_id IN (${c.map(() => "?").join(",")})${yearSql}`).all(...c, ...yearArgs));
|
|
566
|
+
rows.sort((a, b) => a.dancer_id - b.dancer_id || a.year - b.year);
|
|
567
|
+
return { tag: this.rel.tag, years: rows };
|
|
568
|
+
}
|
|
375
569
|
async resolve(q) {
|
|
376
570
|
const db = await this.rel.indexDb("dancers");
|
|
377
571
|
const asked = dancerName(q.name, q.order === "unknown" ? undefined : q.order);
|
|
@@ -1067,6 +1261,12 @@ class FeisFinder2 {
|
|
|
1067
1261
|
constructor(rel) {
|
|
1068
1262
|
this.rel = rel;
|
|
1069
1263
|
}
|
|
1264
|
+
async dates() {
|
|
1265
|
+
await this.rel.fetch("results");
|
|
1266
|
+
await this.rel.require("feises.dates");
|
|
1267
|
+
const dates = this.rel.db("results").query("SELECT feis_id, min(date_lo) AS date_lo, max(date_hi) AS date_hi FROM feises GROUP BY feis_id ORDER BY feis_id").all();
|
|
1268
|
+
return { tag: this.rel.tag, dates };
|
|
1269
|
+
}
|
|
1070
1270
|
async find(q) {
|
|
1071
1271
|
const db = await this.rel.indexDb("feises");
|
|
1072
1272
|
const where = [];
|
|
@@ -1634,12 +1834,13 @@ CREATE TABLE event_year(event_year TEXT PRIMARY KEY, event TEXT NOT NULL, year I
|
|
|
1634
1834
|
CREATE TABLE result(address TEXT PRIMARY KEY, competition TEXT, event TEXT, year INTEGER,
|
|
1635
1835
|
card TEXT, comp_no TEXT, title TEXT, category TEXT, hands INTEGER, letter TEXT, label TEXT,
|
|
1636
1836
|
name_printed TEXT, school_printed TEXT, school_loc TEXT, school_id TEXT, place INTEGER,
|
|
1637
|
-
place_printed TEXT, tie INTEGER, competitors INTEGER, atts TEXT,
|
|
1837
|
+
place_printed TEXT, tie INTEGER, competitors INTEGER, atts TEXT, age TEXT, gender TEXT,
|
|
1838
|
+
printed_status TEXT, ord INTEGER);
|
|
1638
1839
|
CREATE TABLE roster_team(team TEXT PRIMARY KEY, kind TEXT, event TEXT, year INTEGER,
|
|
1639
1840
|
comp_no TEXT, title TEXT, team_index TEXT, seq INTEGER, school_id TEXT, school_printed TEXT,
|
|
1640
|
-
ord INTEGER);
|
|
1841
|
+
dance TEXT, school_printed_as_of TEXT, ord INTEGER);
|
|
1641
1842
|
CREATE TABLE roster_member(team TEXT, seq INTEGER, name_printed TEXT, name TEXT, yob INTEGER,
|
|
1642
|
-
dancer_id INTEGER, ord INTEGER);
|
|
1843
|
+
dancer_id INTEGER, gender TEXT, ord INTEGER);
|
|
1643
1844
|
CREATE TABLE result_roster(team TEXT, event TEXT, year INTEGER, comp_no TEXT, school_id TEXT,
|
|
1644
1845
|
result_address TEXT, join_kind TEXT, via_split INTEGER, roster_teams INTEGER,
|
|
1645
1846
|
result_teams INTEGER, roster_index TEXT, result_letter TEXT, ord INTEGER);
|
|
@@ -1663,7 +1864,7 @@ async function readTables(rel, tables) {
|
|
|
1663
1864
|
}
|
|
1664
1865
|
var teamsIndex = {
|
|
1665
1866
|
name: "teams",
|
|
1666
|
-
version: "
|
|
1867
|
+
version: "2",
|
|
1667
1868
|
inputs: TEAM_TABLES.map(tableAsset),
|
|
1668
1869
|
says: "the team results, the roster teams with their members, and how they join, by event-year",
|
|
1669
1870
|
load: (rel) => readTables(rel, TEAM_TABLES),
|
|
@@ -1681,18 +1882,18 @@ var teamsIndex = {
|
|
|
1681
1882
|
ey.set(k, { event, year });
|
|
1682
1883
|
putEy.run(k, event, year);
|
|
1683
1884
|
}
|
|
1684
|
-
const putR = out.prepare("INSERT OR IGNORE INTO result VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
1885
|
+
const putR = out.prepare("INSERT OR IGNORE INTO result VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
1685
1886
|
let ord = 0;
|
|
1686
1887
|
for (const r of t.team_results)
|
|
1687
|
-
putR.run(str(r.address), str(r.slug), str(r.event), num(r.year), str(r.card), str(r.comp_no), str(r.title), str(r.category), num(r.hands), str(r.letter), str(r.label), str(r.name_printed), str(r.school_printed), str(r.school_loc), str(r.school_id), num(r.place), str(r.place_printed), num(r.tie), num(r.competitors), JSON.stringify(strs(r.atts)), ord++);
|
|
1688
|
-
const putT = out.prepare("INSERT OR IGNORE INTO roster_team VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
1888
|
+
putR.run(str(r.address), str(r.slug), str(r.event), num(r.year), str(r.card), str(r.comp_no), str(r.title), str(r.category), num(r.hands), str(r.letter), str(r.label), str(r.name_printed), str(r.school_printed), str(r.school_loc), str(r.school_id), num(r.place), str(r.place_printed), num(r.tie), num(r.competitors), JSON.stringify(strs(r.atts)), str(r.age), str(r.gender), JSON.stringify(strs(r.printed_status)), ord++);
|
|
1889
|
+
const putT = out.prepare("INSERT OR IGNORE INTO roster_team VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
1689
1890
|
for (const r of t.roster_teams) {
|
|
1690
1891
|
const e = ey.get(str(r.event_year) ?? "");
|
|
1691
|
-
putT.run(str(r.team), str(r.kind), e?.event ?? null, num(r.year) ?? e?.year ?? null, str(r.comp_no), str(r.title), str(r.team_index), num(r.seq), str(r.school_id), str(r.school_print_materialized), ord++);
|
|
1892
|
+
putT.run(str(r.team), str(r.kind), e?.event ?? null, num(r.year) ?? e?.year ?? null, str(r.comp_no), str(r.title), str(r.team_index), num(r.seq), str(r.school_id), str(r.school_print_materialized), str(r.dance), str(r.school_print_as_of), ord++);
|
|
1692
1893
|
}
|
|
1693
|
-
const putM = out.prepare("INSERT INTO roster_member VALUES (?, ?, ?, ?, ?, ?, ?)");
|
|
1894
|
+
const putM = out.prepare("INSERT INTO roster_member VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
|
|
1694
1895
|
for (const r of t.roster_members)
|
|
1695
|
-
putM.run(str(r.team), num(r.seq), typeof r.name_printed === "string" ? r.name_printed : "", str(r.name), num(r.yob), num(r.dancer_id), ord++);
|
|
1896
|
+
putM.run(str(r.team), num(r.seq), typeof r.name_printed === "string" ? r.name_printed : "", str(r.name), num(r.yob), num(r.dancer_id), str(r.gender), ord++);
|
|
1696
1897
|
const putJ = out.prepare("INSERT INTO result_roster VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
1697
1898
|
for (const r of t.team_result_rosters) {
|
|
1698
1899
|
const e = ey.get(str(r.event_year) ?? "");
|
|
@@ -1747,27 +1948,37 @@ class TeamFinder2 {
|
|
|
1747
1948
|
db() {
|
|
1748
1949
|
return this.rel.indexDb("teams");
|
|
1749
1950
|
}
|
|
1951
|
+
async hasFields() {
|
|
1952
|
+
return (await this.rel.capability("teams.fields")).state === "full";
|
|
1953
|
+
}
|
|
1750
1954
|
async results(q = {}) {
|
|
1751
1955
|
const db = await this.db();
|
|
1956
|
+
const fields = await this.hasFields();
|
|
1752
1957
|
const w = whereOf(q);
|
|
1753
1958
|
const rows = db.query(`SELECT address, competition, event, year, card, comp_no, title, category, hands, letter,
|
|
1754
1959
|
label, name_printed, school_printed, school_loc, school_id, place, place_printed, tie,
|
|
1755
|
-
competitors, atts
|
|
1960
|
+
competitors, atts${fields ? ", age, gender, printed_status" : ""}
|
|
1756
1961
|
FROM result${w.sql} ORDER BY year, event, competition, place IS NULL, place, ord`).all(...w.args);
|
|
1757
1962
|
return {
|
|
1758
1963
|
tag: this.rel.tag,
|
|
1759
1964
|
asked: q,
|
|
1760
|
-
results: rows.map((
|
|
1965
|
+
results: rows.map(({ printed_status, ...r }) => ({
|
|
1966
|
+
...r,
|
|
1967
|
+
atts: JSON.parse(r.atts),
|
|
1968
|
+
...printed_status === undefined ? {} : { printed_status: JSON.parse(printed_status ?? "[]") }
|
|
1969
|
+
}))
|
|
1761
1970
|
};
|
|
1762
1971
|
}
|
|
1763
1972
|
async rosters(q = {}) {
|
|
1764
1973
|
const db = await this.db();
|
|
1974
|
+
const fields = await this.hasFields();
|
|
1765
1975
|
const w = whereOf(q, "t.");
|
|
1766
1976
|
const teams = db.query(`SELECT team, kind, event, year, comp_no, title, team_index, seq, school_id, school_printed
|
|
1977
|
+
${fields ? ", school_printed_as_of, dance" : ""}
|
|
1767
1978
|
FROM roster_team t${w.sql} ORDER BY year, event, ord`).all(...w.args);
|
|
1768
1979
|
const members = new Map;
|
|
1769
1980
|
for (const m of db.query(`SELECT m.team AS team, m.seq AS seq, m.name_printed AS name_printed, m.name AS name,
|
|
1770
|
-
m.yob AS yob, m.dancer_id AS dancer_id
|
|
1981
|
+
m.yob AS yob, m.dancer_id AS dancer_id${fields ? ", m.gender AS gender" : ""}
|
|
1771
1982
|
FROM roster_member m JOIN roster_team t ON t.team = m.team${w.sql}
|
|
1772
1983
|
ORDER BY m.team, m.seq, m.ord`).all(...w.args)) {
|
|
1773
1984
|
const { team, ...rest } = m;
|
|
@@ -2298,6 +2509,74 @@ var FEATURES2 = [
|
|
|
2298
2509
|
since: 265,
|
|
2299
2510
|
calls: "comps.resolve, comps.syllabus, comps.syllabusFor, registrations.resolve (the comps index)"
|
|
2300
2511
|
},
|
|
2512
|
+
{
|
|
2513
|
+
feature: "results.stream",
|
|
2514
|
+
needs: [
|
|
2515
|
+
"results:competitions.round",
|
|
2516
|
+
"results:competitions.feis_level",
|
|
2517
|
+
"results:competitions.level_printed",
|
|
2518
|
+
"results:competitions.age_printed",
|
|
2519
|
+
"results:results.yob_printed",
|
|
2520
|
+
"results:results.primary_source",
|
|
2521
|
+
"results:results.platform_dancer_id",
|
|
2522
|
+
"results:results.relative_place",
|
|
2523
|
+
"results:feises.date_lo",
|
|
2524
|
+
"results:feises.date_hi"
|
|
2525
|
+
],
|
|
2526
|
+
since: 255,
|
|
2527
|
+
calls: "results.stream, results.entries (scopes transcribed, platform, all)"
|
|
2528
|
+
},
|
|
2529
|
+
{
|
|
2530
|
+
feature: "majors.stream",
|
|
2531
|
+
needs: [
|
|
2532
|
+
"majors:competitions.round",
|
|
2533
|
+
"majors:competitions.feis_level",
|
|
2534
|
+
"majors:results.yob_printed",
|
|
2535
|
+
"majors:results.primary_source",
|
|
2536
|
+
"majors:results.relative_place",
|
|
2537
|
+
"majors:feises.date_lo"
|
|
2538
|
+
],
|
|
2539
|
+
since: 255,
|
|
2540
|
+
calls: "results.stream, results.entries (scope majors)"
|
|
2541
|
+
},
|
|
2542
|
+
{
|
|
2543
|
+
feature: "majors.tabs",
|
|
2544
|
+
needs: ["majors:tabs.address", "majors:tabs.true_round"],
|
|
2545
|
+
since: 215,
|
|
2546
|
+
calls: "majors.tabulated"
|
|
2547
|
+
},
|
|
2548
|
+
{
|
|
2549
|
+
feature: "feises.dates",
|
|
2550
|
+
needs: ["results:feises.feis_id", "results:feises.date_lo", "results:feises.date_hi"],
|
|
2551
|
+
since: 245,
|
|
2552
|
+
calls: "feises.dates"
|
|
2553
|
+
},
|
|
2554
|
+
{
|
|
2555
|
+
feature: "dancers.records",
|
|
2556
|
+
needs: [
|
|
2557
|
+
"results:dancers.display",
|
|
2558
|
+
"results:dancers.appearances",
|
|
2559
|
+
"results:dancers.birth_lo",
|
|
2560
|
+
"results:dancers.birth_hi",
|
|
2561
|
+
"results:dancers.birth_source",
|
|
2562
|
+
"results:dancers.birth_conflict",
|
|
2563
|
+
"results:dancers.genders"
|
|
2564
|
+
],
|
|
2565
|
+
since: 215,
|
|
2566
|
+
calls: "dancers.records"
|
|
2567
|
+
},
|
|
2568
|
+
{
|
|
2569
|
+
feature: "dancers.years",
|
|
2570
|
+
needs: [
|
|
2571
|
+
"results:dancer_years.region",
|
|
2572
|
+
"results:dancer_years.region_source",
|
|
2573
|
+
"results:dancer_years.nationals",
|
|
2574
|
+
"results:dancer_years.nationals_source",
|
|
2575
|
+
"results:dancer_years.geohash"
|
|
2576
|
+
],
|
|
2577
|
+
since: 245,
|
|
2578
|
+
calls: "dancers.years"
|
|
2579
|
+
},
|
|
2301
2580
|
{
|
|
2302
2581
|
feature: "teams",
|
|
2303
2582
|
needs: [
|
|
@@ -2356,6 +2635,19 @@ var FEATURES2 = [
|
|
|
2356
2635
|
since: 260,
|
|
2357
2636
|
calls: "teams.results, teams.rosters, teams.resultRosters (the teams index)"
|
|
2358
2637
|
},
|
|
2638
|
+
{
|
|
2639
|
+
feature: "teams.fields",
|
|
2640
|
+
needs: [
|
|
2641
|
+
"table:team_results.age",
|
|
2642
|
+
"table:team_results.gender",
|
|
2643
|
+
"table:team_results.printed_status",
|
|
2644
|
+
"table:roster_teams.dance",
|
|
2645
|
+
"table:roster_teams.school_print_as_of",
|
|
2646
|
+
"table:roster_members.gender"
|
|
2647
|
+
],
|
|
2648
|
+
since: 266,
|
|
2649
|
+
calls: "the fields teams.results (age, gender, printed_status) and teams.rosters (dance, school_printed_as_of, a member's gender) carry where present: absent, never refused, on a release without them"
|
|
2650
|
+
},
|
|
2359
2651
|
{
|
|
2360
2652
|
feature: "events",
|
|
2361
2653
|
needs: [
|
|
@@ -2929,4 +3221,4 @@ function releases2(opts = {}) {
|
|
|
2929
3221
|
return new ReleaseManager2(opts);
|
|
2930
3222
|
}
|
|
2931
3223
|
|
|
2932
|
-
export { DATABASES2, planAsset2, sha256File2, unzstdTo2, NAME_LEVELS2, nameLevel2, FEIS_LOCAL_ID_FLOOR2, ResultFinder2, MajorsFinder2, nameOrderOf, DancerResolver2, readPopulation2, canonicalOf2, CompResolver2, NO_CALENDAR2, FeisFinder2, StaffFinder2, SchoolResolver2, TeamFinder2, EventFinder2, defaultBuilders2, indexPath2, indexKey2, isCurrent2, buildIndex2, ensureIndex2, listIndexes2, readPin2, youngest2, dancerResolverOf2, RegistrationResolver2, ghRemote2, httpsRemote2, fallbackRemote2, setRemote2, columnsOf2, FEATURES2, capabilityOf2, needsRelease2, resolveTag2, Release2, openRelease2, openCached2, ReleaseManager2, releases2 };
|
|
3224
|
+
export { DATABASES2, planAsset2, sha256File2, unzstdTo2, NAME_LEVELS2, nameLevel2, entryRank2, FEIS_LOCAL_ID_FLOOR2, ResultFinder2, MajorsFinder2, nameOrderOf, DancerResolver2, readPopulation2, canonicalOf2, CompResolver2, NO_CALENDAR2, FeisFinder2, StaffFinder2, SchoolResolver2, TeamFinder2, EventFinder2, defaultBuilders2, indexPath2, indexKey2, isCurrent2, buildIndex2, ensureIndex2, listIndexes2, readPin2, youngest2, dancerResolverOf2, RegistrationResolver2, ghRemote2, httpsRemote2, fallbackRemote2, setRemote2, columnsOf2, FEATURES2, capabilityOf2, needsRelease2, resolveTag2, Release2, openRelease2, openCached2, ReleaseManager2, releases2 };
|
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-gy5xye67.js";
|
|
8
8
|
import"./chunks/index-hne1wadw.js";
|
|
9
9
|
import"./chunks/index-hghdy980.js";
|
|
10
10
|
|
|
@@ -50,6 +50,21 @@ var USAGE = `usage: idq <verb> [--cache <dir>] [--repo <owner/name>] [--json]
|
|
|
50
50
|
majors [--release <spec>] [--event <e>] [--year <y>] [--comp <competition>] [--dancer <id>]
|
|
51
51
|
the majors: every event and its years; an event's
|
|
52
52
|
competitions; a competition's, an event's or a dancer's rows
|
|
53
|
+
stream [--release <spec>] --scope majors|transcribed|platform|all [--entries] [--event <e,...>]
|
|
54
|
+
[--year <y> | --year <from>..<to>] [--tier <t,...>] [--category <c,...>]
|
|
55
|
+
[--level <feis_level,...>] [--dancer <id,...>] [--school <school_id>] [--primary]
|
|
56
|
+
every row a scope holds, one JSON line each, never the
|
|
57
|
+
whole table in memory; --entries one per address (the row
|
|
58
|
+
it stands for, with its recall order)
|
|
59
|
+
records [--release <spec>] [--dancer <id,...>]
|
|
60
|
+
every dancer's record: display, appearances, birth window,
|
|
61
|
+
populations
|
|
62
|
+
records --years [--release <spec>] [--dancer <id,...>] [--year <y>]
|
|
63
|
+
each dancer's region, nationals and place per year
|
|
64
|
+
feis-dates [--release <spec>] every feis's first and last day
|
|
65
|
+
tabulated [--release <spec>] [--min-round <n>]
|
|
66
|
+
the majors addresses the marks sheets tabulate to round n
|
|
67
|
+
or later (default 3)
|
|
53
68
|
teams [--release <spec>] [--event <e>] [--year <y>] [--rosters | --joins]
|
|
54
69
|
the team result rows of an event-year; with --rosters its
|
|
55
70
|
roster teams and their dancers; with --joins how each roster
|
|
@@ -107,7 +122,12 @@ var VALUE = new Set([
|
|
|
107
122
|
"--limit",
|
|
108
123
|
"--event",
|
|
109
124
|
"--title",
|
|
110
|
-
"--for"
|
|
125
|
+
"--for",
|
|
126
|
+
"--scope",
|
|
127
|
+
"--tier",
|
|
128
|
+
"--category",
|
|
129
|
+
"--level",
|
|
130
|
+
"--min-round"
|
|
111
131
|
]);
|
|
112
132
|
function parseArgs(argv) {
|
|
113
133
|
const positional = [];
|
|
@@ -319,6 +339,45 @@ async function resolveVerb(rel, what, args, p, say, stdin) {
|
|
|
319
339
|
throw new Error("resolve comp|dancer|registrations");
|
|
320
340
|
}
|
|
321
341
|
}
|
|
342
|
+
var SCOPES = ["majors", "transcribed", "platform", "all"];
|
|
343
|
+
var listOf = (v) => v.split(",").map((x) => x.trim()).filter((x) => x !== "");
|
|
344
|
+
var idsOf = (v) => v === undefined ? undefined : listOf(v).map(Number);
|
|
345
|
+
function streamQueryOf(p) {
|
|
346
|
+
const scope = p.flags.get("--scope");
|
|
347
|
+
if (scope === undefined || !SCOPES.includes(scope))
|
|
348
|
+
throw new Error(`stream takes --scope ${SCOPES.join("|")}`);
|
|
349
|
+
const q = { scope };
|
|
350
|
+
const event = p.flags.get("--event");
|
|
351
|
+
if (event !== undefined)
|
|
352
|
+
q.event = listOf(event);
|
|
353
|
+
const year = p.flags.get("--year");
|
|
354
|
+
if (year !== undefined) {
|
|
355
|
+
const m = /^(\d{4})\.\.(\d{4})$/.exec(year);
|
|
356
|
+
q.year = m === null ? Number(year) : [Number(m[1]), Number(m[2])];
|
|
357
|
+
if (typeof q.year === "number" && !Number.isInteger(q.year))
|
|
358
|
+
throw new Error(`--year takes a year or <from>..<to>, not "${year}"`);
|
|
359
|
+
}
|
|
360
|
+
for (const [flag, key] of [
|
|
361
|
+
["--tier", "tier"],
|
|
362
|
+
["--category", "category"]
|
|
363
|
+
]) {
|
|
364
|
+
const v = p.flags.get(flag);
|
|
365
|
+
if (v !== undefined)
|
|
366
|
+
q[key] = listOf(v);
|
|
367
|
+
}
|
|
368
|
+
const level = p.flags.get("--level");
|
|
369
|
+
if (level !== undefined)
|
|
370
|
+
q.feis_level = listOf(level).map(Number);
|
|
371
|
+
const dancers = idsOf(p.flags.get("--dancer"));
|
|
372
|
+
if (dancers !== undefined)
|
|
373
|
+
q.dancer_id = dancers;
|
|
374
|
+
const school = p.flags.get("--school");
|
|
375
|
+
if (school !== undefined)
|
|
376
|
+
q.school_id = school;
|
|
377
|
+
if (p.bools.has("--primary"))
|
|
378
|
+
q.primary = true;
|
|
379
|
+
return q;
|
|
380
|
+
}
|
|
322
381
|
function eventYearOf(p) {
|
|
323
382
|
const event = p.flags.get("--event");
|
|
324
383
|
const year = p.flags.get("--year");
|
|
@@ -644,6 +703,79 @@ async function main(argv, io = {}) {
|
|
|
644
703
|
rel.close();
|
|
645
704
|
}
|
|
646
705
|
}
|
|
706
|
+
case "stream": {
|
|
707
|
+
const q = streamQueryOf(p);
|
|
708
|
+
const rel = await openRelease2(spec, { ...opts, assets: [] });
|
|
709
|
+
try {
|
|
710
|
+
let n = 0;
|
|
711
|
+
const rows = p.bools.has("--entries") ? rel.results.entries(q) : rel.results.stream(q);
|
|
712
|
+
for await (const r of rows) {
|
|
713
|
+
say(JSON.stringify(r));
|
|
714
|
+
n++;
|
|
715
|
+
}
|
|
716
|
+
log(`${n} ${p.bools.has("--entries") ? "entries" : "rows"} in ${rel.tag}`);
|
|
717
|
+
return n === 0 ? 1 : 0;
|
|
718
|
+
} finally {
|
|
719
|
+
rel.close();
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
case "records": {
|
|
723
|
+
const rel = await openRelease2(spec, { ...opts, assets: [] });
|
|
724
|
+
try {
|
|
725
|
+
const ids = idsOf(p.flags.get("--dancer"));
|
|
726
|
+
if (p.bools.has("--years")) {
|
|
727
|
+
const year = p.flags.get("--year");
|
|
728
|
+
const a = await rel.dancers.years({
|
|
729
|
+
...ids !== undefined ? { ids } : {},
|
|
730
|
+
...year !== undefined ? { year: Number(year) } : {}
|
|
731
|
+
});
|
|
732
|
+
out(a, () => {
|
|
733
|
+
for (const y of a.years)
|
|
734
|
+
say(` ${y.dancer_id} ${y.year} ${y.region ?? "-"} (${y.region_source ?? "-"}) nationals ${y.nationals ?? "-"} ${y.geohash ?? "-"}`);
|
|
735
|
+
say(`${a.years.length} dancer-year(s) in ${a.tag}`);
|
|
736
|
+
});
|
|
737
|
+
return a.years.length === 0 ? 1 : 0;
|
|
738
|
+
}
|
|
739
|
+
const a = await rel.dancers.records(ids !== undefined ? { ids } : {});
|
|
740
|
+
out(a, () => {
|
|
741
|
+
for (const r of a.records)
|
|
742
|
+
say(` ${r.dancer_id} ${r.display} ${r.appearances} entries born ${r.birth_lo ?? "?"}..${r.birth_hi ?? "?"} (${r.birth_source}${r.birth_conflict ? ", conflict" : ""}) ${r.genders.join(",") || "-"}`);
|
|
743
|
+
say(`${a.records.length} dancer(s) in ${a.tag}`);
|
|
744
|
+
});
|
|
745
|
+
return a.records.length === 0 ? 1 : 0;
|
|
746
|
+
} finally {
|
|
747
|
+
rel.close();
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
case "feis-dates": {
|
|
751
|
+
const rel = await openRelease2(spec, { ...opts, assets: [] });
|
|
752
|
+
try {
|
|
753
|
+
const a = await rel.feises.dates();
|
|
754
|
+
out(a, () => {
|
|
755
|
+
for (const d of a.dates)
|
|
756
|
+
say(` ${d.feis_id} ${d.date_lo ?? "?"}..${d.date_hi ?? "?"}`);
|
|
757
|
+
say(`${a.dates.length} feis(es) in ${a.tag}`);
|
|
758
|
+
});
|
|
759
|
+
return a.dates.length === 0 ? 1 : 0;
|
|
760
|
+
} finally {
|
|
761
|
+
rel.close();
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
case "tabulated": {
|
|
765
|
+
const rel = await openRelease2(spec, { ...opts, assets: [] });
|
|
766
|
+
try {
|
|
767
|
+
const min = p.flags.get("--min-round");
|
|
768
|
+
const a = await rel.majors.tabulated(min !== undefined ? { min_true_round: Number(min) } : {});
|
|
769
|
+
out(a, () => {
|
|
770
|
+
for (const x of a.addresses)
|
|
771
|
+
say(` ${x}`);
|
|
772
|
+
say(`${a.addresses.length} address(es) tabulated to round ${a.min_true_round} or later in ${a.tag}`);
|
|
773
|
+
});
|
|
774
|
+
return a.addresses.length === 0 ? 1 : 0;
|
|
775
|
+
} finally {
|
|
776
|
+
rel.close();
|
|
777
|
+
}
|
|
778
|
+
}
|
|
647
779
|
case "teams": {
|
|
648
780
|
const rel = await openRelease2(spec, { ...opts, assets: [] });
|
|
649
781
|
try {
|
|
@@ -783,5 +915,6 @@ export {
|
|
|
783
915
|
USAGE,
|
|
784
916
|
jsonLines,
|
|
785
917
|
main,
|
|
786
|
-
parseArgs
|
|
918
|
+
parseArgs,
|
|
919
|
+
streamQueryOf
|
|
787
920
|
};
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
unzstdTo2,
|
|
7
7
|
NAME_LEVELS2,
|
|
8
8
|
nameLevel2,
|
|
9
|
+
entryRank2,
|
|
9
10
|
FEIS_LOCAL_ID_FLOOR2,
|
|
10
11
|
ResultFinder2,
|
|
11
12
|
MajorsFinder2,
|
|
@@ -44,7 +45,7 @@ import {
|
|
|
44
45
|
openCached2,
|
|
45
46
|
ReleaseManager2,
|
|
46
47
|
releases2
|
|
47
|
-
} from "./chunks/index-
|
|
48
|
+
} from "./chunks/index-gy5xye67.js";
|
|
48
49
|
import {
|
|
49
50
|
cacheRoot2,
|
|
50
51
|
repoOf2
|
|
@@ -87,6 +88,7 @@ export {
|
|
|
87
88
|
dancerResolverOf2 as dancerResolverOf,
|
|
88
89
|
defaultBuilders2 as defaultBuilders,
|
|
89
90
|
ensureIndex2 as ensureIndex,
|
|
91
|
+
entryRank2 as entryRank,
|
|
90
92
|
fallbackRemote2 as fallbackRemote,
|
|
91
93
|
ghRemote2 as ghRemote,
|
|
92
94
|
httpsRemote2 as httpsRemote,
|
package/dist/types/cli.d.ts
CHANGED
|
@@ -1,6 +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] [--rows]\n the dancers a name reaches, each with its evidence\n (name level, age, school, population) and the arm; 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 (or the prior year's)\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 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?}, a registration: {name, school?, codes[], feis,\n year?, population?})\n\n <spec>: pinned (the default) | latest | a cut (42, 42.1) | a tag (archive-YYYY.MM.DD-N)";
|
|
4
5
|
export interface Parsed {
|
|
5
6
|
positional: string[];
|
|
6
7
|
flags: Map<string, string>;
|
|
@@ -15,6 +16,7 @@ type Line<T> = {
|
|
|
15
16
|
error: string;
|
|
16
17
|
};
|
|
17
18
|
export declare function jsonLines<T>(text: string, check: (v: T) => string | null): Line<T>[];
|
|
19
|
+
export declare function streamQueryOf(p: Parsed): StreamQuery;
|
|
18
20
|
export declare function main(argv: readonly string[], io?: {
|
|
19
21
|
say?: (s: string) => void;
|
|
20
22
|
log?: (s: string) => void;
|
package/dist/types/dancers.d.ts
CHANGED
|
@@ -140,10 +140,43 @@ export interface DancerRecord {
|
|
|
140
140
|
export declare const PACKAGE_KEY_PARTS: readonly string[];
|
|
141
141
|
export declare const dancersIndex: IndexBuilder;
|
|
142
142
|
export declare function yearOf(asOf: string | undefined): number | null;
|
|
143
|
+
export interface DancerBulkRecord {
|
|
144
|
+
dancer_id: number;
|
|
145
|
+
display: string;
|
|
146
|
+
scope: "per-release" | "stable";
|
|
147
|
+
appearances: number;
|
|
148
|
+
birth_lo: number | null;
|
|
149
|
+
birth_hi: number | null;
|
|
150
|
+
birth_source: string;
|
|
151
|
+
birth_conflict: boolean;
|
|
152
|
+
genders: string[];
|
|
153
|
+
}
|
|
154
|
+
export interface DancerYear {
|
|
155
|
+
dancer_id: number;
|
|
156
|
+
year: number;
|
|
157
|
+
region: string | null;
|
|
158
|
+
region_source: string | null;
|
|
159
|
+
nationals: string | null;
|
|
160
|
+
nationals_source: string | null;
|
|
161
|
+
geohash: string | null;
|
|
162
|
+
}
|
|
143
163
|
export declare class DancerResolver {
|
|
144
164
|
private readonly rel;
|
|
145
165
|
private readonly printIds;
|
|
146
166
|
constructor(rel: Release);
|
|
167
|
+
records(q?: {
|
|
168
|
+
ids?: readonly number[];
|
|
169
|
+
}): Promise<{
|
|
170
|
+
tag: string;
|
|
171
|
+
records: DancerBulkRecord[];
|
|
172
|
+
}>;
|
|
173
|
+
years(q?: {
|
|
174
|
+
ids?: readonly number[];
|
|
175
|
+
year?: number;
|
|
176
|
+
}): Promise<{
|
|
177
|
+
tag: string;
|
|
178
|
+
years: DancerYear[];
|
|
179
|
+
}>;
|
|
147
180
|
resolve(q: DancerQuery): Promise<DancerAnswer>;
|
|
148
181
|
search(q: DancerSearchQuery): Promise<DancerAnswer>;
|
|
149
182
|
private capped;
|
package/dist/types/feises.d.ts
CHANGED
|
@@ -77,6 +77,14 @@ export declare const NO_CALENDAR = "the release holds a feis-year once its resul
|
|
|
77
77
|
export declare class FeisFinder {
|
|
78
78
|
private readonly rel;
|
|
79
79
|
constructor(rel: Release);
|
|
80
|
+
dates(): Promise<{
|
|
81
|
+
tag: string;
|
|
82
|
+
dates: {
|
|
83
|
+
feis_id: string;
|
|
84
|
+
date_lo: string | null;
|
|
85
|
+
date_hi: string | null;
|
|
86
|
+
}[];
|
|
87
|
+
}>;
|
|
80
88
|
find(q: FeisQuery): Promise<FeisAnswer>;
|
|
81
89
|
codeStem(token: string, stem: string): Promise<string[]>;
|
|
82
90
|
seriesOf(brand: string): Promise<Series>;
|
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 DancerCandidate, type DancerQuery, type DancerRecord, DancerResolver, type DancerSchool, type DancerSearchQuery, type ExcludedCandidate, FEIS_LOCAL_ID_FLOOR, type PopulationEvidence, type SchoolEvidence, readPopulation, } from "./dancers.js";
|
|
3
|
+
export { type AgeAsked, type AgeEvidence, type DancerAnswer, type DancerBulkRecord, type DancerCandidate, type DancerQuery, type DancerRecord, DancerResolver, type DancerSchool, type DancerSearchQuery, type DancerYear, type ExcludedCandidate, FEIS_LOCAL_ID_FLOOR, type PopulationEvidence, 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 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";
|
|
@@ -15,5 +15,6 @@ export { type MajorCompetition, type MajorEvent, MajorsFinder, type ResultAnswer
|
|
|
15
15
|
export { type DancerAnswerLike, type DancerQueryLike, type DancerResolverLike, type DancerUnavailable, type RegistrationRow, type ResolvedDancer, RegistrationResolver, type ResolvedRegistration, dancerResolverOf, youngest, } from "./registrations.js";
|
|
16
16
|
export { type SchoolAnswer, type SchoolCandidate, type SchoolQuery, SchoolResolver, type SchoolRung, } from "./schools.js";
|
|
17
17
|
export { type Capability, FEATURES, type Feature, type SchemaProbe, capabilityOf, columnsOf, needsRelease, } from "./schema.js";
|
|
18
|
+
export { type EntryRow, type StreamQuery, type StreamRow, type StreamScope, entryRank, } from "./stream.js";
|
|
18
19
|
export { EventFinder, type EventYear, type EventYearQuery, type ResultRoster, type RosterMember, type RosterTeam, TeamFinder, type TeamResult, } from "./teams.js";
|
|
19
20
|
export { ARCHIVE_TAG, type ArchiveTag, type ReleaseSpec, compareTagsNewestFirst, cutOf, parseArchiveTag, parseReleaseSpec, pickTag, renderArchiveTag, } from "./tag.js";
|
package/dist/types/results.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Release } from "./release.js";
|
|
2
|
+
import { type EntryRow, type StreamQuery, type StreamRow } from "./stream.js";
|
|
2
3
|
export declare const FEIS_LOCAL_ID_FLOOR = 17179869184;
|
|
3
4
|
export interface ResultQuery {
|
|
4
5
|
dancer_id?: number;
|
|
@@ -43,6 +44,9 @@ export declare class ResultFinder {
|
|
|
43
44
|
private readonly rel;
|
|
44
45
|
constructor(rel: Release);
|
|
45
46
|
query(q: ResultQuery): Promise<ResultAnswer>;
|
|
47
|
+
private streamDb;
|
|
48
|
+
stream(q: StreamQuery): AsyncGenerator<StreamRow>;
|
|
49
|
+
entries(q: StreamQuery): AsyncGenerator<EntryRow>;
|
|
46
50
|
}
|
|
47
51
|
export interface MajorEvent {
|
|
48
52
|
event: string;
|
|
@@ -78,5 +82,12 @@ export declare class MajorsFinder {
|
|
|
78
82
|
tag: string;
|
|
79
83
|
competitions: MajorCompetition[];
|
|
80
84
|
}>;
|
|
85
|
+
tabulated(q?: {
|
|
86
|
+
min_true_round?: number;
|
|
87
|
+
}): Promise<{
|
|
88
|
+
tag: string;
|
|
89
|
+
min_true_round: number;
|
|
90
|
+
addresses: string[];
|
|
91
|
+
}>;
|
|
81
92
|
results(q: ResultQuery): Promise<ResultAnswer>;
|
|
82
93
|
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { Database } from "bun:sqlite";
|
|
2
|
+
export type StreamScope = "majors" | "transcribed" | "platform" | "all";
|
|
3
|
+
export interface StreamQuery {
|
|
4
|
+
scope: StreamScope;
|
|
5
|
+
event?: string | string[];
|
|
6
|
+
year?: number | [number, number];
|
|
7
|
+
tier?: string[];
|
|
8
|
+
category?: string[];
|
|
9
|
+
feis_level?: number[];
|
|
10
|
+
dancer_id?: number[];
|
|
11
|
+
school_id?: string;
|
|
12
|
+
primary?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface StreamRow {
|
|
15
|
+
address: string;
|
|
16
|
+
competition: string;
|
|
17
|
+
event: string;
|
|
18
|
+
year: number | null;
|
|
19
|
+
tier: string;
|
|
20
|
+
comp_no: string | null;
|
|
21
|
+
title: string | null;
|
|
22
|
+
category: string | null;
|
|
23
|
+
age: string | null;
|
|
24
|
+
age_printed: string | null;
|
|
25
|
+
gender: string | null;
|
|
26
|
+
competitors: number | null;
|
|
27
|
+
feis_level: number | null;
|
|
28
|
+
level_printed: string | null;
|
|
29
|
+
date_printed: string | null;
|
|
30
|
+
source: string;
|
|
31
|
+
round: string | null;
|
|
32
|
+
feis_id: string | null;
|
|
33
|
+
feis_date_lo: string | null;
|
|
34
|
+
feis_date_hi: string | null;
|
|
35
|
+
section: string;
|
|
36
|
+
card: string;
|
|
37
|
+
place: number | null;
|
|
38
|
+
place_printed: string;
|
|
39
|
+
tie: number;
|
|
40
|
+
relative_place: number | null;
|
|
41
|
+
atts: string[];
|
|
42
|
+
withdrawn: string | null;
|
|
43
|
+
qualifier: string | null;
|
|
44
|
+
name_printed: string;
|
|
45
|
+
name: string | null;
|
|
46
|
+
school_printed: string;
|
|
47
|
+
school_loc: string;
|
|
48
|
+
school_id: string | null;
|
|
49
|
+
dancer_id: number | null;
|
|
50
|
+
dancer_scope: "per-release" | "stable" | null;
|
|
51
|
+
yob: number | null;
|
|
52
|
+
yob_printed: string | null;
|
|
53
|
+
points_printed: string | null;
|
|
54
|
+
platform_dancer_id: string | null;
|
|
55
|
+
primary_source: string | null;
|
|
56
|
+
file: string;
|
|
57
|
+
line: number;
|
|
58
|
+
}
|
|
59
|
+
export interface EntryRow extends StreamRow {
|
|
60
|
+
recall_place: number | null;
|
|
61
|
+
}
|
|
62
|
+
export declare function entryRank(section: string): number;
|
|
63
|
+
export declare const scopeDb: (s: StreamScope) => "majors" | "results";
|
|
64
|
+
export declare function streamSql(q: StreamQuery): {
|
|
65
|
+
sql: string;
|
|
66
|
+
args: (string | number)[];
|
|
67
|
+
};
|
|
68
|
+
export declare function feisDates(db: Database): Map<string, {
|
|
69
|
+
lo: string | null;
|
|
70
|
+
hi: string | null;
|
|
71
|
+
}>;
|
|
72
|
+
export declare function streamRows(db: Database, q: StreamQuery): AsyncGenerator<StreamRow>;
|
|
73
|
+
export declare function entryRows(db: Database, q: StreamQuery): AsyncGenerator<EntryRow>;
|
package/dist/types/teams.d.ts
CHANGED
|
@@ -25,6 +25,9 @@ export interface TeamResult {
|
|
|
25
25
|
tie: number | null;
|
|
26
26
|
competitors: number | null;
|
|
27
27
|
atts: string[];
|
|
28
|
+
age?: string | null;
|
|
29
|
+
gender?: string | null;
|
|
30
|
+
printed_status?: string[];
|
|
28
31
|
}
|
|
29
32
|
export interface RosterMember {
|
|
30
33
|
seq: number;
|
|
@@ -33,6 +36,7 @@ export interface RosterMember {
|
|
|
33
36
|
yob: number | null;
|
|
34
37
|
dancer_id: number | null;
|
|
35
38
|
dancer_scope: "per-release" | "stable" | null;
|
|
39
|
+
gender?: string | null;
|
|
36
40
|
}
|
|
37
41
|
export interface RosterTeam {
|
|
38
42
|
team: string;
|
|
@@ -45,6 +49,8 @@ export interface RosterTeam {
|
|
|
45
49
|
seq: number | null;
|
|
46
50
|
school_id: string | null;
|
|
47
51
|
school_printed: string | null;
|
|
52
|
+
school_printed_as_of?: string | null;
|
|
53
|
+
dance?: string | null;
|
|
48
54
|
members: RosterMember[];
|
|
49
55
|
}
|
|
50
56
|
export interface ResultRoster {
|
|
@@ -78,6 +84,7 @@ export declare class TeamFinder {
|
|
|
78
84
|
private readonly rel;
|
|
79
85
|
constructor(rel: Release);
|
|
80
86
|
private db;
|
|
87
|
+
private hasFields;
|
|
81
88
|
results(q?: EventYearQuery): Promise<{
|
|
82
89
|
tag: string;
|
|
83
90
|
asked: EventYearQuery;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@finbheara/archive-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.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",
|