@finbheara/archive-client 0.34.0 → 0.35.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 +23 -0
- package/dist/chunks/{index-cwhyrcyx.js → index-gt7yxxp8.js} +62 -5
- package/dist/cli.js +19 -4
- package/dist/index.js +1 -1
- package/dist/types/calendar.d.ts +25 -0
- package/dist/types/index.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -101,6 +101,8 @@ c.features; // [{ feature: "dancers", state: "full" | "missing", missing: [...
|
|
|
101
101
|
| `upcoming.fields`, `upcoming.entrants` | `upcoming.fields`, `upcoming.entrants` (285 and 290 carry the tables empty) | 291 |
|
|
102
102
|
| `upcoming.fields.instance` | the `feis_instance_id` `upcoming.fields` carries; absent, never refused, without it | 320 |
|
|
103
103
|
| `calendar` | `calendar.get`, `calendar.list` | 320 |
|
|
104
|
+
| `calendar.expected` | each calendar stage's `expected`; absent, never refused, without it | 320 |
|
|
105
|
+
| `calendar.next` | `calendar.next` | 320 |
|
|
104
106
|
| `tabs`, `panels` | `tabs.query`, `tabs.stream`; `panels.query` | 184 |
|
|
105
107
|
| `feis-panels` | `feisPanels.query` | 260 |
|
|
106
108
|
| `staff.adjudicators` | `staff.adjudicators` | 230 |
|
|
@@ -762,8 +764,14 @@ g.via; // "instance" | "formerly" | "feis_id" | "occurrence_id" | null
|
|
|
762
764
|
g.entries; // [{ feis_instance_id, feis_brand_id, tier, name_printed, date_lo, date_hi, date_source,
|
|
763
765
|
// occurrence_ids, feis_ids, stages: { announced, syllabus, entrants, run, results },
|
|
764
766
|
// terminal, carried, formerly }]
|
|
767
|
+
g.entries[0].stages.results.expected;
|
|
768
|
+
// { date, basis, n, platform } or null: "announced" | "brand" | "platform" |
|
|
769
|
+
// "pooled" | "roster-window" | "unmeasured"
|
|
765
770
|
const l = await rel.calendar.list({ stage: "entrants", state: "observed", from: "2026-11-01" });
|
|
766
771
|
// brand, tier, from, to, stage, state, terminal ("none": still ahead)
|
|
772
|
+
const n = await rel.calendar.next({ brand: "plf" });
|
|
773
|
+
// [{ feis_brand_id, year, run_expected, run_expected_basis, run_expected_n,
|
|
774
|
+
// from_instance_id, from_date }]: a series' next edition no listing names yet
|
|
767
775
|
```
|
|
768
776
|
|
|
769
777
|
ONE ROW PER FEIS INSTANCE, on the id its results carry: a feis-series instance (`<brand>.<year>`),
|
|
@@ -780,6 +788,20 @@ order: only results after the run is a belief. `get` tries the instance id, then
|
|
|
780
788
|
a capture, then an occurrence id, and says which met (`via`). On a release without the table each
|
|
781
789
|
call refuses by name.
|
|
782
790
|
|
|
791
|
+
EXPECTED DAYS (`calendar.expected`): each stage carries `expected`, `{ date, basis, n, platform }`
|
|
792
|
+
or null. `announced` is the listing's own first day; `brand` the series' edition the year before
|
|
793
|
+
plus 364 days, `n` its held years; `platform` a platform's capture lag (the P90 of first results
|
|
794
|
+
capture less last day) or list lead (the median of first day less first list capture), measured
|
|
795
|
+
over the feiseanna run in the 180 days before the cut, `n` at least 10; `pooled` every platform's
|
|
796
|
+
results lags together, for a feis whose hosts have no capture form (`platform` `all`) and, NAMED, in
|
|
797
|
+
place of a platform measured on fewer than 10 (`platform` the host's); `roster-window` a majors event-year
|
|
798
|
+
no capture dates; `unmeasured` no day. A stage still ahead always carries one; an observed stage
|
|
799
|
+
carries the day its estimator gives it where one applies, so the misses can be read. The lags are
|
|
800
|
+
capture's own scrape cadence, re-measured every release. `next` lists each series with two or more
|
|
801
|
+
held years, the last the release's year or the one before, whose next edition is not on the
|
|
802
|
+
calendar: its year and expected first day. It is never an instance: an id is minted only once a
|
|
803
|
+
listing names the edition.
|
|
804
|
+
|
|
783
805
|
## Teachers and adjudicators
|
|
784
806
|
|
|
785
807
|
```ts
|
|
@@ -958,6 +980,7 @@ is passed to the dancer resolver as asked (`rel.dancers`, above).
|
|
|
958
980
|
idq calendar [--release <spec>] <instance|feis id|occurrence id>
|
|
959
981
|
idq calendar [--brand <series>] [--tier <t>] [--from <date>] [--to <date>] [--stage <s>] [--state <s>]
|
|
960
982
|
[--terminal results|withdrawn|passed-no-results|none]
|
|
983
|
+
idq calendar --next [--brand <series>]
|
|
961
984
|
idq teacher [--release <spec>] <name|TD number>
|
|
962
985
|
idq adjudicator [--release <spec>] <name|TD number>
|
|
963
986
|
idq comp [--release <spec>] <feis> <code> [--year y] [--title t]
|
|
@@ -722,6 +722,26 @@ var FEATURES2 = [
|
|
|
722
722
|
since: 320,
|
|
723
723
|
calls: "calendar.get, calendar.list"
|
|
724
724
|
},
|
|
725
|
+
{
|
|
726
|
+
feature: "calendar.expected",
|
|
727
|
+
needs: ["announced", "syllabus", "entrants", "run", "results"].flatMap((st) => ["", "_basis", "_n", "_platform"].map((x) => `results:feis_calendar.${st}_expected${x}`)),
|
|
728
|
+
since: 320,
|
|
729
|
+
calls: "each calendar stage's `expected` (absent, never refused, without it)"
|
|
730
|
+
},
|
|
731
|
+
{
|
|
732
|
+
feature: "calendar.next",
|
|
733
|
+
needs: [
|
|
734
|
+
"feis_brand_id",
|
|
735
|
+
"year",
|
|
736
|
+
"run_expected",
|
|
737
|
+
"run_expected_basis",
|
|
738
|
+
"run_expected_n",
|
|
739
|
+
"from_instance_id",
|
|
740
|
+
"from_date"
|
|
741
|
+
].map((c) => `results:feis_series_next.${c}`),
|
|
742
|
+
since: 320,
|
|
743
|
+
calls: "calendar.next"
|
|
744
|
+
},
|
|
725
745
|
{
|
|
726
746
|
feature: "upcoming.entrants",
|
|
727
747
|
needs: [
|
|
@@ -3877,13 +3897,26 @@ var CALENDAR_TERMINALS2 = [
|
|
|
3877
3897
|
"passed-no-results"
|
|
3878
3898
|
];
|
|
3879
3899
|
var json = (s, empty) => typeof s === "string" && s !== "" ? JSON.parse(s) : empty;
|
|
3880
|
-
function
|
|
3900
|
+
function expectedOf(r, s) {
|
|
3901
|
+
const basis = r[`${s}_expected_basis`];
|
|
3902
|
+
if (basis === null || basis === undefined)
|
|
3903
|
+
return null;
|
|
3904
|
+
const n = r[`${s}_expected_n`];
|
|
3905
|
+
return {
|
|
3906
|
+
date: r[`${s}_expected`] ?? null,
|
|
3907
|
+
basis,
|
|
3908
|
+
n: n === null || n === undefined ? null : Number(n),
|
|
3909
|
+
platform: r[`${s}_expected_platform`] ?? null
|
|
3910
|
+
};
|
|
3911
|
+
}
|
|
3912
|
+
function entryOf2(r, expected) {
|
|
3881
3913
|
const stages = Object.fromEntries(CALENDAR_STAGES2.map((s) => [
|
|
3882
3914
|
s,
|
|
3883
3915
|
{
|
|
3884
3916
|
state: r[`${s}_state`],
|
|
3885
3917
|
date: r[`${s}_date`] ?? null,
|
|
3886
|
-
cite: r[`${s}_cite`] ?? null
|
|
3918
|
+
cite: r[`${s}_cite`] ?? null,
|
|
3919
|
+
...expected ? { expected: expectedOf(r, s) } : {}
|
|
3887
3920
|
}
|
|
3888
3921
|
]));
|
|
3889
3922
|
return {
|
|
@@ -3914,6 +3947,27 @@ class CalendarFinder2 {
|
|
|
3914
3947
|
await this.rel.require("calendar");
|
|
3915
3948
|
return this.rel.db("results");
|
|
3916
3949
|
}
|
|
3950
|
+
async expected() {
|
|
3951
|
+
return (await this.rel.capability("calendar.expected")).state === "full";
|
|
3952
|
+
}
|
|
3953
|
+
async next(q = {}) {
|
|
3954
|
+
await this.rel.fetch("results");
|
|
3955
|
+
await this.rel.require("calendar.next");
|
|
3956
|
+
const db = this.rel.db("results");
|
|
3957
|
+
const rows = q.brand === undefined ? db.query("SELECT * FROM feis_series_next ORDER BY run_expected, feis_brand_id").all() : db.query("SELECT * FROM feis_series_next WHERE feis_brand_id = ? ORDER BY run_expected").all(q.brand);
|
|
3958
|
+
return {
|
|
3959
|
+
tag: this.rel.tag,
|
|
3960
|
+
next: rows.map((r) => ({
|
|
3961
|
+
feis_brand_id: r.feis_brand_id,
|
|
3962
|
+
year: Number(r.year),
|
|
3963
|
+
run_expected: r.run_expected,
|
|
3964
|
+
run_expected_basis: "brand",
|
|
3965
|
+
run_expected_n: Number(r.run_expected_n),
|
|
3966
|
+
from_instance_id: r.from_instance_id,
|
|
3967
|
+
from_date: r.from_date
|
|
3968
|
+
}))
|
|
3969
|
+
};
|
|
3970
|
+
}
|
|
3917
3971
|
async get(id) {
|
|
3918
3972
|
const db = await this.db();
|
|
3919
3973
|
const ways = [
|
|
@@ -3924,8 +3978,10 @@ class CalendarFinder2 {
|
|
|
3924
3978
|
];
|
|
3925
3979
|
for (const [via, where] of ways) {
|
|
3926
3980
|
const rows = db.query(`SELECT * FROM feis_calendar WHERE ${where} ORDER BY feis_instance_id`).all(id);
|
|
3927
|
-
if (rows.length > 0)
|
|
3928
|
-
|
|
3981
|
+
if (rows.length > 0) {
|
|
3982
|
+
const e = await this.expected();
|
|
3983
|
+
return { tag: this.rel.tag, asked: id, via, entries: rows.map((r) => entryOf2(r, e)) };
|
|
3984
|
+
}
|
|
3929
3985
|
}
|
|
3930
3986
|
return {
|
|
3931
3987
|
tag: this.rel.tag,
|
|
@@ -3967,7 +4023,8 @@ class CalendarFinder2 {
|
|
|
3967
4023
|
add("terminal = ?", q.terminal);
|
|
3968
4024
|
const sql = `SELECT * FROM feis_calendar${where.length > 0 ? ` WHERE ${where.join(" AND ")}` : ""} ORDER BY date_lo IS NULL, date_lo, feis_instance_id`;
|
|
3969
4025
|
const rows = db.query(sql).all(...args);
|
|
3970
|
-
|
|
4026
|
+
const e = await this.expected();
|
|
4027
|
+
return { tag: this.rel.tag, entries: rows.map((r) => entryOf2(r, e)) };
|
|
3971
4028
|
}
|
|
3972
4029
|
}
|
|
3973
4030
|
|
package/dist/cli.js
CHANGED
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
latestCheck2,
|
|
22
22
|
within,
|
|
23
23
|
staleWarning2
|
|
24
|
-
} from "./chunks/index-
|
|
24
|
+
} from "./chunks/index-gt7yxxp8.js";
|
|
25
25
|
import"./chunks/index-hghdy980.js";
|
|
26
26
|
|
|
27
27
|
var USAGE_HEADER = "usage: idq <verb> [--cache <dir>] [--repo <owner/name>] [--json] [--live]";
|
|
@@ -395,7 +395,7 @@ var VERBS = [
|
|
|
395
395
|
{
|
|
396
396
|
verb: "calendar",
|
|
397
397
|
value: ["--release", "--brand", "--tier", "--from", "--to", "--stage", "--state", "--terminal"],
|
|
398
|
-
bool: [],
|
|
398
|
+
bool: ["--next"],
|
|
399
399
|
usage: [
|
|
400
400
|
" calendar [--release <spec>] <instance|feis id|occurrence id>",
|
|
401
401
|
" one feis instance's stages: announced, syllabus, entrants,",
|
|
@@ -404,7 +404,11 @@ var VERBS = [
|
|
|
404
404
|
" calendar [--brand <series>] [--tier T1..T4] [--from <date>] [--to <date>]",
|
|
405
405
|
" [--stage announced|syllabus|entrants|run|results] [--state observed|pending|not-captured]",
|
|
406
406
|
" [--terminal results|withdrawn|passed-no-results|none]",
|
|
407
|
-
" the instances a query names, by first day"
|
|
407
|
+
" the instances a query names, by first day; each stage's",
|
|
408
|
+
" expected day with its basis and n where the release has them",
|
|
409
|
+
" calendar --next [--brand <series>]",
|
|
410
|
+
" each series' next edition no listing names yet: its year",
|
|
411
|
+
" and expected first day from the year before (basis brand)"
|
|
408
412
|
]
|
|
409
413
|
},
|
|
410
414
|
{
|
|
@@ -523,6 +527,7 @@ function parseArgs(argv) {
|
|
|
523
527
|
return { positional, flags, bools };
|
|
524
528
|
}
|
|
525
529
|
var mb = (n) => `${(n / 1e6).toFixed(1)} MB`;
|
|
530
|
+
var expectedText = (e) => e === null || e === undefined ? "" : ` expected ${e.date ?? "-"} (${e.basis}${e.platform !== null ? ` ${e.platform}` : ""}${e.n !== null ? `, n ${e.n}` : ""})`;
|
|
526
531
|
function printPlan(p, say) {
|
|
527
532
|
for (const k of p.keep)
|
|
528
533
|
say(`keep ${k.tag} (${k.why})`);
|
|
@@ -1553,13 +1558,23 @@ async function main(argv, io = {}) {
|
|
|
1553
1558
|
const rel = await open(spec, { ...opts, assets: [] });
|
|
1554
1559
|
try {
|
|
1555
1560
|
const line = (e) => ` ${e.date_lo ?? "?"} ${e.feis_instance_id} ${e.tier} ${["announced", "syllabus", "entrants", "run", "results"].map((s) => `${s}:${e.stages[s].state === "observed" ? e.stages[s].date ?? "seen" : e.stages[s].state}`).join(" ")} [${e.terminal ?? "ahead"}]${e.name_printed !== null ? ` "${e.name_printed}"` : ""}`;
|
|
1561
|
+
if (p.bools.has("--next")) {
|
|
1562
|
+
const brand = p.flags.get("--brand");
|
|
1563
|
+
const a = await rel.calendar.next(brand === undefined ? {} : { brand });
|
|
1564
|
+
out(a, () => {
|
|
1565
|
+
for (const n of a.next)
|
|
1566
|
+
say(` ${n.run_expected} ${n.feis_brand_id} ${n.year} brand n ${n.run_expected_n} from ${n.from_instance_id} (${n.from_date})`);
|
|
1567
|
+
say(`${a.next.length} next edition(s) in ${a.tag}`);
|
|
1568
|
+
});
|
|
1569
|
+
return a.next.length === 0 ? 1 : 0;
|
|
1570
|
+
}
|
|
1556
1571
|
if (rest.length > 0) {
|
|
1557
1572
|
const a = await rel.calendar.get(rest.join(" "));
|
|
1558
1573
|
out(a, () => {
|
|
1559
1574
|
for (const e of a.entries) {
|
|
1560
1575
|
say(line(e));
|
|
1561
1576
|
for (const s of ["announced", "syllabus", "entrants", "run", "results"])
|
|
1562
|
-
say(` ${s} ${e.stages[s].state} ${e.stages[s].date ?? "-"} ${e.stages[s].cite ?? "-"}${e.carried.includes(s) ? " (carried)" : ""}`);
|
|
1577
|
+
say(` ${s} ${e.stages[s].state} ${e.stages[s].date ?? "-"} ${e.stages[s].cite ?? "-"}${e.carried.includes(s) ? " (carried)" : ""}${expectedText(e.stages[s].expected)}`);
|
|
1563
1578
|
}
|
|
1564
1579
|
say(`${a.entries.length} instance(s) for "${a.asked}"${a.via !== null ? ` by ${a.via}` : ""}${a.why !== undefined ? ` (${a.why})` : ""} in ${a.tag}`);
|
|
1565
1580
|
});
|
package/dist/index.js
CHANGED
package/dist/types/calendar.d.ts
CHANGED
|
@@ -5,10 +5,18 @@ export type CalendarStageState = "observed" | "pending" | "not-captured";
|
|
|
5
5
|
export declare const CALENDAR_STAGE_STATES: readonly CalendarStageState[];
|
|
6
6
|
export type CalendarTerminal = "results" | "withdrawn" | "passed-no-results";
|
|
7
7
|
export declare const CALENDAR_TERMINALS: readonly CalendarTerminal[];
|
|
8
|
+
export type CalendarExpectedBasis = "announced" | "brand" | "platform" | "pooled" | "roster-window" | "unmeasured";
|
|
9
|
+
export interface CalendarExpected {
|
|
10
|
+
date: string | null;
|
|
11
|
+
basis: CalendarExpectedBasis;
|
|
12
|
+
n: number | null;
|
|
13
|
+
platform: string | null;
|
|
14
|
+
}
|
|
8
15
|
export interface CalendarStageValue {
|
|
9
16
|
state: CalendarStageState;
|
|
10
17
|
date: string | null;
|
|
11
18
|
cite: string | null;
|
|
19
|
+
expected?: CalendarExpected | null;
|
|
12
20
|
}
|
|
13
21
|
export interface CalendarEntry {
|
|
14
22
|
feis_instance_id: string;
|
|
@@ -38,6 +46,19 @@ export interface CalendarAnswer {
|
|
|
38
46
|
tag: string;
|
|
39
47
|
entries: CalendarEntry[];
|
|
40
48
|
}
|
|
49
|
+
export interface CalendarNext {
|
|
50
|
+
feis_brand_id: string;
|
|
51
|
+
year: number;
|
|
52
|
+
run_expected: string;
|
|
53
|
+
run_expected_basis: "brand";
|
|
54
|
+
run_expected_n: number;
|
|
55
|
+
from_instance_id: string;
|
|
56
|
+
from_date: string;
|
|
57
|
+
}
|
|
58
|
+
export interface CalendarNextAnswer {
|
|
59
|
+
tag: string;
|
|
60
|
+
next: CalendarNext[];
|
|
61
|
+
}
|
|
41
62
|
export interface CalendarGetAnswer {
|
|
42
63
|
tag: string;
|
|
43
64
|
asked: string;
|
|
@@ -49,6 +70,10 @@ export declare class CalendarFinder {
|
|
|
49
70
|
private readonly rel;
|
|
50
71
|
constructor(rel: Release);
|
|
51
72
|
private db;
|
|
73
|
+
private expected;
|
|
74
|
+
next(q?: {
|
|
75
|
+
brand?: string;
|
|
76
|
+
}): Promise<CalendarNextAnswer>;
|
|
52
77
|
get(id: string): Promise<CalendarGetAnswer>;
|
|
53
78
|
list(q?: CalendarQuery): Promise<CalendarAnswer>;
|
|
54
79
|
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -26,5 +26,5 @@ export { type EntryRow, type StreamCompetition, type StreamQuery, type StreamRow
|
|
|
26
26
|
export { type FeisPanelSeat, FeisPanelFinder, PanelFinder, type PanelSeat, type RegisterRow, type TabAnswer, TabFinder, type TabQuery, type TabRow, type TabStreamQuery, } from "./tabs.js";
|
|
27
27
|
export { EventFinder, type EventYear, type EventYearQuery, type ResultRoster, type RosterMember, type RosterTeam, TeamFinder, type TeamResult, } from "./teams.js";
|
|
28
28
|
export { type EntrantCandidate, FIELD_STATES, type FieldComp, DEPARTURE_REASONS, type DepartureReason, type FieldState, type HeldOut, type UpcomingDeparture, type UpcomingDepartureAnswer, type UpcomingDepartureQuery, type UpcomingEntrant, type UpcomingEntrantAnswer, type UpcomingEntrantQuery, type UpcomingFeis, type UpcomingFeisAnswer, type UpcomingFeisQuery, type UpcomingFeisState, type UpcomingField, type UpcomingFieldAnswer, type UpcomingFieldQuery, UpcomingFinder, type UpcomingHost, } from "./upcoming.js";
|
|
29
|
-
export { CALENDAR_STAGES, CALENDAR_STAGE_STATES, CALENDAR_TERMINALS, type CalendarAnswer, type CalendarEntry, CalendarFinder, type CalendarGetAnswer, type CalendarQuery, type CalendarStage, type CalendarStageState, type CalendarStageValue, type CalendarTerminal, } from "./calendar.js";
|
|
29
|
+
export { CALENDAR_STAGES, CALENDAR_STAGE_STATES, CALENDAR_TERMINALS, type CalendarAnswer, type CalendarEntry, type CalendarExpected, type CalendarExpectedBasis, type CalendarNext, type CalendarNextAnswer, CalendarFinder, type CalendarGetAnswer, type CalendarQuery, type CalendarStage, type CalendarStageState, type CalendarStageValue, type CalendarTerminal, } from "./calendar.js";
|
|
30
30
|
export { ARCHIVE_TAG, type ArchiveTag, type ReleaseSpec, compareTagsNewestFirst, cutOf, parseArchiveTag, parseReleaseSpec, pickTag, renderArchiveTag, } from "./tag.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@finbheara/archive-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.35.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",
|