@finbheara/archive-client 0.5.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 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.5.x"`).
23
+ (`"@finbheara/archive-client": "0.6.x"`).
24
24
 
25
25
  ## Configuration
26
26
 
@@ -91,6 +91,7 @@ c.features; // [{ feature: "dancers", state: "full" | "missing", missing: [...
91
91
  | `dancers.years` | `dancers.years` | 245 |
92
92
  | `majors.tabs` | `majors.tabulated` | 215 |
93
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 |
94
95
  | `events` | `events.years` | 260 |
95
96
 
96
97
  A spec is `pinned` (the default: the user-local pin, else the latest), `latest`, a cut number
@@ -301,8 +302,9 @@ competition beside its own fields: `competition`, `event`, `year`, `tier`, `comp
301
302
  `feis_date_hi`. Its own: `address`, `section`, `card`, `place`, `place_printed`, `tie`,
302
303
  `relative_place`, `atts`, `withdrawn`, `qualifier`, `name_printed`, `name`, `school_printed`,
303
304
  `school_loc`, `school_id`, `dancer_id`, `dancer_scope`, `yob`, `yob_printed`, `points_printed`,
304
- `platform_dancer_id`, `primary_source`. Rows come in the release's own order, a competition's
305
- rows together.
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.
306
308
 
307
309
  The scopes: `majors` reads the majors (tiers T1 to T3), `transcribed` the transcribed rows of
308
310
  every tier, `platform` every row a results platform published, `all` every row.
@@ -328,11 +330,12 @@ await rel.majors.tabulated({ min_true_round: 3 }); // the majors addresses m
328
330
 
329
331
  ```ts
330
332
  const r = await rel.teams.results({ event: "<event>", year: 2024 });
331
- r.results; // [{ address, competition, event, year, comp_no, title, category, hands, letter, label,
332
- // school_printed, school_id, place, place_printed, tie, competitors, atts, ... }]
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, ... }]
333
336
  const t = await rel.teams.rosters({ event: "<event>", year: 2024 });
334
337
  t.teams; // [{ team, kind, event, year, comp_no, title, team_index, seq, school_id, school_printed,
335
- // 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 }] }]
336
339
  const j = await rel.teams.resultRosters({ event: "<event>", year: 2024 });
337
340
  j.joins; // [{ team, result_address, join_kind, via_split, roster_index, result_letter, ... }]
338
341
  const e = await rel.events.years({ event: "<event>" });
@@ -347,7 +350,21 @@ roster team met the results (`exact`, `card`, `branch`) or why it did not (`no-r
347
350
  `no-school`, `no-roster`, `multi-team-unjoined`), and `result_address` is null where none joined.
348
351
  An event-year's dates are a window (`date_lo`, `date_hi`) with how fine it is (`resolution`:
349
352
  `day`, `month`, `calendar`) and what it is read from (`source`), and `place` is a place-tree node
350
- where the release knows one. A field the source left empty is null. The rows are read once per
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
351
368
  release into the `teams` and `events` indexes.
352
369
 
353
370
  ## Teachers and adjudicators
@@ -135,7 +135,7 @@ var COLUMNS = `r.address AS address, r.competition AS competition, c.event AS ev
135
135
  r.school_loc AS school_loc, r.school_id AS school_id, r.dancer_id AS dancer_id, r.yob AS yob,
136
136
  r.yob_printed AS yob_printed, r.points_printed AS points_printed,
137
137
  r.platform_dancer_id AS platform_dancer_id, r.primary_source AS primary_source,
138
- r.file AS file`;
138
+ r.file AS file, r.line AS line`;
139
139
  var TRANSCRIBED = "('transcript', 'manifested')";
140
140
  var scopeDb = (s) => s === "majors" ? "majors" : "results";
141
141
  function streamSql(q) {
@@ -191,7 +191,7 @@ function feisDates(db) {
191
191
  }
192
192
  var text = (v) => v === null || v === "" ? null : v;
193
193
  function rowOf(r, dates) {
194
- const { file: _file, atts, withdrawn, ...rest } = r;
194
+ const { atts, withdrawn, ...rest } = r;
195
195
  const d = dates.get(r.event);
196
196
  return {
197
197
  ...rest,
@@ -1834,12 +1834,13 @@ CREATE TABLE event_year(event_year TEXT PRIMARY KEY, event TEXT NOT NULL, year I
1834
1834
  CREATE TABLE result(address TEXT PRIMARY KEY, competition TEXT, event TEXT, year INTEGER,
1835
1835
  card TEXT, comp_no TEXT, title TEXT, category TEXT, hands INTEGER, letter TEXT, label TEXT,
1836
1836
  name_printed TEXT, school_printed TEXT, school_loc TEXT, school_id TEXT, place INTEGER,
1837
- place_printed TEXT, tie INTEGER, competitors INTEGER, atts TEXT, ord INTEGER);
1837
+ place_printed TEXT, tie INTEGER, competitors INTEGER, atts TEXT, age TEXT, gender TEXT,
1838
+ printed_status TEXT, ord INTEGER);
1838
1839
  CREATE TABLE roster_team(team TEXT PRIMARY KEY, kind TEXT, event TEXT, year INTEGER,
1839
1840
  comp_no TEXT, title TEXT, team_index TEXT, seq INTEGER, school_id TEXT, school_printed TEXT,
1840
- ord INTEGER);
1841
+ dance TEXT, school_printed_as_of TEXT, ord INTEGER);
1841
1842
  CREATE TABLE roster_member(team TEXT, seq INTEGER, name_printed TEXT, name TEXT, yob INTEGER,
1842
- dancer_id INTEGER, ord INTEGER);
1843
+ dancer_id INTEGER, gender TEXT, ord INTEGER);
1843
1844
  CREATE TABLE result_roster(team TEXT, event TEXT, year INTEGER, comp_no TEXT, school_id TEXT,
1844
1845
  result_address TEXT, join_kind TEXT, via_split INTEGER, roster_teams INTEGER,
1845
1846
  result_teams INTEGER, roster_index TEXT, result_letter TEXT, ord INTEGER);
@@ -1863,7 +1864,7 @@ async function readTables(rel, tables) {
1863
1864
  }
1864
1865
  var teamsIndex = {
1865
1866
  name: "teams",
1866
- version: "1",
1867
+ version: "2",
1867
1868
  inputs: TEAM_TABLES.map(tableAsset),
1868
1869
  says: "the team results, the roster teams with their members, and how they join, by event-year",
1869
1870
  load: (rel) => readTables(rel, TEAM_TABLES),
@@ -1881,18 +1882,18 @@ var teamsIndex = {
1881
1882
  ey.set(k, { event, year });
1882
1883
  putEy.run(k, event, year);
1883
1884
  }
1884
- const putR = out.prepare("INSERT OR IGNORE INTO result VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
1885
+ const putR = out.prepare("INSERT OR IGNORE INTO result VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
1885
1886
  let ord = 0;
1886
1887
  for (const r of t.team_results)
1887
- 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++);
1888
- 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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
1889
1890
  for (const r of t.roster_teams) {
1890
1891
  const e = ey.get(str(r.event_year) ?? "");
1891
- 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++);
1892
1893
  }
1893
- const putM = out.prepare("INSERT INTO roster_member VALUES (?, ?, ?, ?, ?, ?, ?)");
1894
+ const putM = out.prepare("INSERT INTO roster_member VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
1894
1895
  for (const r of t.roster_members)
1895
- 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++);
1896
1897
  const putJ = out.prepare("INSERT INTO result_roster VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
1897
1898
  for (const r of t.team_result_rosters) {
1898
1899
  const e = ey.get(str(r.event_year) ?? "");
@@ -1947,27 +1948,37 @@ class TeamFinder2 {
1947
1948
  db() {
1948
1949
  return this.rel.indexDb("teams");
1949
1950
  }
1951
+ async hasFields() {
1952
+ return (await this.rel.capability("teams.fields")).state === "full";
1953
+ }
1950
1954
  async results(q = {}) {
1951
1955
  const db = await this.db();
1956
+ const fields = await this.hasFields();
1952
1957
  const w = whereOf(q);
1953
1958
  const rows = db.query(`SELECT address, competition, event, year, card, comp_no, title, category, hands, letter,
1954
1959
  label, name_printed, school_printed, school_loc, school_id, place, place_printed, tie,
1955
- competitors, atts
1960
+ competitors, atts${fields ? ", age, gender, printed_status" : ""}
1956
1961
  FROM result${w.sql} ORDER BY year, event, competition, place IS NULL, place, ord`).all(...w.args);
1957
1962
  return {
1958
1963
  tag: this.rel.tag,
1959
1964
  asked: q,
1960
- results: rows.map((r) => ({ ...r, atts: JSON.parse(r.atts) }))
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
+ }))
1961
1970
  };
1962
1971
  }
1963
1972
  async rosters(q = {}) {
1964
1973
  const db = await this.db();
1974
+ const fields = await this.hasFields();
1965
1975
  const w = whereOf(q, "t.");
1966
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" : ""}
1967
1978
  FROM roster_team t${w.sql} ORDER BY year, event, ord`).all(...w.args);
1968
1979
  const members = new Map;
1969
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,
1970
- 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" : ""}
1971
1982
  FROM roster_member m JOIN roster_team t ON t.team = m.team${w.sql}
1972
1983
  ORDER BY m.team, m.seq, m.ord`).all(...w.args)) {
1973
1984
  const { team, ...rest } = m;
@@ -2624,6 +2635,19 @@ var FEATURES2 = [
2624
2635
  since: 260,
2625
2636
  calls: "teams.results, teams.rosters, teams.resultRosters (the teams index)"
2626
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
+ },
2627
2651
  {
2628
2652
  feature: "events",
2629
2653
  needs: [
package/dist/cli.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  nameOrderOf,
5
5
  openRelease2,
6
6
  releases2
7
- } from "./chunks/index-8gna56w2.js";
7
+ } from "./chunks/index-gy5xye67.js";
8
8
  import"./chunks/index-hne1wadw.js";
9
9
  import"./chunks/index-hghdy980.js";
10
10
 
package/dist/index.js CHANGED
@@ -45,7 +45,7 @@ import {
45
45
  openCached2,
46
46
  ReleaseManager2,
47
47
  releases2
48
- } from "./chunks/index-8gna56w2.js";
48
+ } from "./chunks/index-gy5xye67.js";
49
49
  import {
50
50
  cacheRoot2,
51
51
  repoOf2
@@ -53,6 +53,8 @@ export interface StreamRow {
53
53
  points_printed: string | null;
54
54
  platform_dancer_id: string | null;
55
55
  primary_source: string | null;
56
+ file: string;
57
+ line: number;
56
58
  }
57
59
  export interface EntryRow extends StreamRow {
58
60
  recall_place: number | null;
@@ -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.5.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",