@finbheara/archive-client 0.19.0 → 0.20.2
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 +44 -0
- package/dist/chunks/{index-gpaf165j.js → index-6028k52f.js} +84 -1
- package/dist/cli.js +1 -1
- package/dist/index.js +3 -1
- package/dist/types/dancer-level.d.ts +24 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/results.d.ts +2 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -80,6 +80,7 @@ c.features; // [{ feature: "dancers", state: "full" | "missing", missing: [...
|
|
|
80
80
|
| feature | the calls | from cut |
|
|
81
81
|
| --- | --- | --- |
|
|
82
82
|
| `results.level` | `results.query`, `majors.results` | 215 |
|
|
83
|
+
| `results.dancer-level` | `results.dancerLevel` | 270 |
|
|
83
84
|
| `dancers` | `dancers.resolve`, `search`, `get` | 260 |
|
|
84
85
|
| `schools` | `schools.resolve`, a dancer question with a school | 260 |
|
|
85
86
|
| `staff` | `staff.teacher`, `staff.adjudicator` | 260 |
|
|
@@ -451,6 +452,49 @@ A row carries the prints and the ids that stand for them: the address, the compe
|
|
|
451
452
|
and age, the place, the name and school as printed with the dancer and school ids. The majors are
|
|
452
453
|
read from `majors.sqlite`, fetched on first use.
|
|
453
454
|
|
|
455
|
+
### What level a dancer dances
|
|
456
|
+
|
|
457
|
+
```ts
|
|
458
|
+
await rel.results.dancerLevel({ dancer_id: 1001, year: 2025 });
|
|
459
|
+
// { level: 200, grades: { advancement_range: { lo: 300, hi: 400 },
|
|
460
|
+
// level_range: { lo: 200, hi: 400 }, oireachtas_level: true } }
|
|
461
|
+
await rel.results.dancerLevel({ dancer_id: 1002 }); // its latest year: { level: 600 }
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
No single number is a grades dancer's level. Grades are won PER DANCE: a dancer can be Novice in
|
|
465
|
+
the reel and Prizewinner in the slip jig at once. Only a championship (600 preliminary, 700 open)
|
|
466
|
+
is a level of the dancer. A competition's `feis_level` is the competition's rung. A set, a set
|
|
467
|
+
dance, a treble reel or a special prints a rung that its entrants need not hold. So the answer
|
|
468
|
+
reads:
|
|
469
|
+
|
|
470
|
+
- **the year**: the competition's calendar year. When it is omitted, the latest year in which the
|
|
471
|
+
dancer has a rated feis row.
|
|
472
|
+
- **a rated row**: a feis row (tier `T4`, a platform's) of the dancer, on the floor (no printed
|
|
473
|
+
absence, no `DNT`), whose competition publishes a `feis_level`.
|
|
474
|
+
- **a championship row**: a rated row at 600 or 700. A 700 whose title or level field also names
|
|
475
|
+
the preliminary (`PC and OC`, `Prelim and Champ`) joins the two, and it reads 600 here.
|
|
476
|
+
- **a graded row**: a rated row at 100 to 500 whose `dance` is one of the six graded dances (reel,
|
|
477
|
+
light jig, single jig, slip jig, treble jig, hornpipe) and whose title, level or dance field names
|
|
478
|
+
no special (`special`, `spcl`, `trophy`). Sets, set dances, treble reels and specials are never
|
|
479
|
+
read.
|
|
480
|
+
|
|
481
|
+
| field | meaning |
|
|
482
|
+
| --- | --- |
|
|
483
|
+
| `level` | for a championship dancer (any championship row that year), the LOWEST championship rung danced that year. Otherwise the lowest graded rung danced that year. Null where the year holds neither |
|
|
484
|
+
| `grades` | present only for a grades dancer: no championship row that year, and at least one graded row |
|
|
485
|
+
| `grades.advancement_range` | `{ lo, hi }`, the lowest and highest rung over the reel, slip jig, treble jig and hornpipe, the dances a dancer advances in. Null where none of them was danced |
|
|
486
|
+
| `grades.level_range` | `{ lo, hi }` over all six graded dances |
|
|
487
|
+
| `grades.oireachtas_level` | `true` where the dancer danced a championship solo at a regional Oireachtas that year: a row on the floor at a tier `T3` event, the same calendar year, whose competition's `category` is `Solo`. A grade championship that the release files as `Solo` counts as well (one regional, in one year, prints ten) |
|
|
488
|
+
|
|
489
|
+
Only feis rows set the level. A dancer with majors rows and no feis row in the year (tier `T4`) gets `level` null, whatever they danced at the majors.
|
|
490
|
+
|
|
491
|
+
A dance that was not danced that year takes no part: each range covers what was danced. An adult
|
|
492
|
+
grade row is read like any other, since the adult ladder also grades per dance. A release older
|
|
493
|
+
than the published `dance` column is refused by name (`results.dancer-level`).
|
|
494
|
+
|
|
495
|
+
Each call reads the dancer's rows once. The release does not index the dancer id, so one call
|
|
496
|
+
scans the results table, as `results.query` does (about half a second on a full release).
|
|
497
|
+
|
|
454
498
|
## Every row, streamed
|
|
455
499
|
|
|
456
500
|
```ts
|
|
@@ -377,6 +377,69 @@ function notOnTheFloor(placePrinted, atts, withdrawn) {
|
|
|
377
377
|
return withdrawn !== null && DID_NOT_TABULATE.has(withdrawn);
|
|
378
378
|
}
|
|
379
379
|
|
|
380
|
+
import { GRADE_DANCES } from "@finbheara/domain/dance-types";
|
|
381
|
+
var ADVANCEMENT_DANCES2 = Object.freeze([
|
|
382
|
+
"reel",
|
|
383
|
+
"slip-jig",
|
|
384
|
+
"treble-jig",
|
|
385
|
+
"hornpipe"
|
|
386
|
+
]);
|
|
387
|
+
var SPECIAL_WORDS = Object.freeze(["special", "spcl", "trophy"]);
|
|
388
|
+
var JOINED_WORDS = Object.freeze([
|
|
389
|
+
"prelim",
|
|
390
|
+
"pc and oc",
|
|
391
|
+
"pc/oc",
|
|
392
|
+
"pc & oc",
|
|
393
|
+
"pc-oc",
|
|
394
|
+
"pc/c",
|
|
395
|
+
"pr\xEDomh",
|
|
396
|
+
"priomh"
|
|
397
|
+
]);
|
|
398
|
+
var MAJORS_SOURCES = new Set(["transcript", "manifested"]);
|
|
399
|
+
var has = (t, words) => words.some((w) => t.includes(w));
|
|
400
|
+
function range(levels) {
|
|
401
|
+
if (levels.length === 0)
|
|
402
|
+
return null;
|
|
403
|
+
return { lo: Math.min(...levels), hi: Math.max(...levels) };
|
|
404
|
+
}
|
|
405
|
+
var isRated = (r) => r.tier === "T4" && !MAJORS_SOURCES.has(r.source) && r.feis_level !== null;
|
|
406
|
+
function dancerLevelOf(db, tag, q) {
|
|
407
|
+
const all = db.query(`SELECT c.year AS year, c.tier AS tier, c.source AS source, c.feis_level AS feis_level,
|
|
408
|
+
c.dance AS dance, c.category AS category,
|
|
409
|
+
lower(coalesce(c.title, '') || ' | ' || coalesce(c.level_printed, '') || ' | ' ||
|
|
410
|
+
coalesce(c.dance_printed, '')) AS t,
|
|
411
|
+
r.place_printed AS place_printed, r.atts AS atts, r.withdrawn AS withdrawn
|
|
412
|
+
FROM results r JOIN competitions c ON c.file = r.file AND c.line = r.competition_line
|
|
413
|
+
WHERE r.dancer_id = ? AND c.tier IN ('T3', 'T4')`).all(q.dancer_id).filter((r) => !notOnTheFloor(r.place_printed, r.atts, r.withdrawn));
|
|
414
|
+
let year = q.year ?? null;
|
|
415
|
+
if (year === null) {
|
|
416
|
+
for (const r of all)
|
|
417
|
+
if (isRated(r) && r.year !== null && (year === null || r.year > year))
|
|
418
|
+
year = r.year;
|
|
419
|
+
}
|
|
420
|
+
const answer = { tag, asked: q, dancer_id: q.dancer_id, year, level: null };
|
|
421
|
+
if (year === null)
|
|
422
|
+
return answer;
|
|
423
|
+
const rows = all.filter((r) => r.year === year);
|
|
424
|
+
const rated = rows.filter(isRated);
|
|
425
|
+
const champs = rated.filter((r) => r.feis_level >= 600).map((r) => r.feis_level === 700 && has(r.t, JOINED_WORDS) ? 600 : r.feis_level);
|
|
426
|
+
if (champs.length > 0)
|
|
427
|
+
return { ...answer, level: Math.min(...champs) };
|
|
428
|
+
const graded = rated.filter((r) => r.feis_level >= 100 && r.feis_level <= 500 && r.dance !== null && GRADE_DANCES.includes(r.dance) && !has(r.t, SPECIAL_WORDS));
|
|
429
|
+
const levelRange = range(graded.map((r) => r.feis_level));
|
|
430
|
+
if (levelRange === null)
|
|
431
|
+
return answer;
|
|
432
|
+
return {
|
|
433
|
+
...answer,
|
|
434
|
+
level: levelRange.lo,
|
|
435
|
+
grades: {
|
|
436
|
+
advancement_range: range(graded.filter((r) => ADVANCEMENT_DANCES2.includes(r.dance)).map((r) => r.feis_level)),
|
|
437
|
+
level_range: levelRange,
|
|
438
|
+
oireachtas_level: rows.some((r) => r.tier === "T3" && r.category === "Solo")
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
|
|
380
443
|
var ENTRY_RANK = new Map([
|
|
381
444
|
["final", 0],
|
|
382
445
|
["", 1],
|
|
@@ -576,6 +639,11 @@ class ResultFinder2 {
|
|
|
576
639
|
await this.rel.require("results.level");
|
|
577
640
|
return queryResults(this.rel, "results", q);
|
|
578
641
|
}
|
|
642
|
+
async dancerLevel(q) {
|
|
643
|
+
await this.rel.fetch("results");
|
|
644
|
+
await this.rel.require("results.dancer-level");
|
|
645
|
+
return dancerLevelOf(this.rel.db("results"), this.rel.tag, q);
|
|
646
|
+
}
|
|
579
647
|
async streamDb(q) {
|
|
580
648
|
const db = scopeDb(q.scope);
|
|
581
649
|
await this.rel.fetch(db);
|
|
@@ -3088,6 +3156,21 @@ var FEATURES2 = [
|
|
|
3088
3156
|
since: 215,
|
|
3089
3157
|
calls: "results.query, majors.results"
|
|
3090
3158
|
},
|
|
3159
|
+
{
|
|
3160
|
+
feature: "results.dancer-level",
|
|
3161
|
+
needs: [
|
|
3162
|
+
"results:competitions.feis_level",
|
|
3163
|
+
"results:competitions.dance",
|
|
3164
|
+
"results:competitions.level_printed",
|
|
3165
|
+
"results:competitions.dance_printed",
|
|
3166
|
+
"results:competitions.category",
|
|
3167
|
+
"results:results.place_printed",
|
|
3168
|
+
"results:results.atts",
|
|
3169
|
+
"results:results.withdrawn"
|
|
3170
|
+
],
|
|
3171
|
+
since: 270,
|
|
3172
|
+
calls: "results.dancerLevel"
|
|
3173
|
+
},
|
|
3091
3174
|
{
|
|
3092
3175
|
feature: "majors.order",
|
|
3093
3176
|
needs: ["majors:competitions.seq"],
|
|
@@ -3854,4 +3937,4 @@ function releases2(opts = {}) {
|
|
|
3854
3937
|
return new ReleaseManager2(opts);
|
|
3855
3938
|
}
|
|
3856
3939
|
|
|
3857
|
-
export { DATABASES2, planAsset2, sha256File2, unzstdTo2, NAME_LEVELS2, nameLevel2, NO_CALENDAR2, FeisFinder2, entryRank2, FEIS_LOCAL_ID_FLOOR2, ResultFinder2, MajorsFinder2, LINEAGE_FILE2, linksOfLineage2, releaseSchoolGraph2, readsSpanishNames2, SchoolResolver2, initialsOnly2, nameOrderOf, DancerResolver2, readPopulation2, syllabusSourceOf2, canonicalOf2, CompResolver2, StaffFinder2, 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 };
|
|
3940
|
+
export { DATABASES2, planAsset2, sha256File2, unzstdTo2, NAME_LEVELS2, nameLevel2, NO_CALENDAR2, FeisFinder2, ADVANCEMENT_DANCES2, entryRank2, FEIS_LOCAL_ID_FLOOR2, ResultFinder2, MajorsFinder2, LINEAGE_FILE2, linksOfLineage2, releaseSchoolGraph2, readsSpanishNames2, SchoolResolver2, initialsOnly2, nameOrderOf, DancerResolver2, readPopulation2, syllabusSourceOf2, canonicalOf2, CompResolver2, StaffFinder2, 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
package/dist/index.js
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
nameLevel2,
|
|
9
9
|
NO_CALENDAR2,
|
|
10
10
|
FeisFinder2,
|
|
11
|
+
ADVANCEMENT_DANCES2,
|
|
11
12
|
entryRank2,
|
|
12
13
|
FEIS_LOCAL_ID_FLOOR2,
|
|
13
14
|
ResultFinder2,
|
|
@@ -51,7 +52,7 @@ import {
|
|
|
51
52
|
openCached2,
|
|
52
53
|
ReleaseManager2,
|
|
53
54
|
releases2
|
|
54
|
-
} from "./chunks/index-
|
|
55
|
+
} from "./chunks/index-6028k52f.js";
|
|
55
56
|
import {
|
|
56
57
|
cacheRoot2,
|
|
57
58
|
repoOf2
|
|
@@ -66,6 +67,7 @@ import {
|
|
|
66
67
|
pickTag2
|
|
67
68
|
} from "./chunks/index-hghdy980.js";
|
|
68
69
|
export {
|
|
70
|
+
ADVANCEMENT_DANCES2 as ADVANCEMENT_DANCES,
|
|
69
71
|
ARCHIVE_TAG2 as ARCHIVE_TAG,
|
|
70
72
|
CompResolver2 as CompResolver,
|
|
71
73
|
DATABASES2 as DATABASES,
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Database } from "bun:sqlite";
|
|
2
|
+
export declare const ADVANCEMENT_DANCES: readonly string[];
|
|
3
|
+
export interface DancerLevelQuery {
|
|
4
|
+
dancer_id: number;
|
|
5
|
+
year?: number;
|
|
6
|
+
}
|
|
7
|
+
export interface LevelRange {
|
|
8
|
+
lo: number;
|
|
9
|
+
hi: number;
|
|
10
|
+
}
|
|
11
|
+
export interface DancerGrades {
|
|
12
|
+
advancement_range: LevelRange | null;
|
|
13
|
+
level_range: LevelRange;
|
|
14
|
+
oireachtas_level: boolean;
|
|
15
|
+
}
|
|
16
|
+
export interface DancerLevelAnswer {
|
|
17
|
+
tag: string;
|
|
18
|
+
asked: DancerLevelQuery;
|
|
19
|
+
dancer_id: number;
|
|
20
|
+
year: number | null;
|
|
21
|
+
level: number | null;
|
|
22
|
+
grades?: DancerGrades;
|
|
23
|
+
}
|
|
24
|
+
export declare function dancerLevelOf(db: Database, tag: string, q: DancerLevelQuery): DancerLevelAnswer;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export { type AssetPlan, DATABASES, type DatabaseName, type LandedFile, type Rec
|
|
|
2
2
|
export { sha256File, unzstdTo } from "./bytes.js";
|
|
3
3
|
export { type AgeAsked, type AgeEvidence, type DancerAnswer, type DancerBulkRecord, type DancerCandidate, type DancerQuery, type DancerRecord, DancerResolver, type DancerRegion, type DancerSchool, type DancerSearchQuery, type DancerYear, type ExcludedCandidate, FEIS_LOCAL_ID_FLOOR, type InitialsRefuted, type Narrowing, initialsOnly, type OireachtasAsked, type PopulationEvidence, type RegionEvidence, type SchoolEvidence, readPopulation, } from "./dancers.js";
|
|
4
4
|
export { NAME_LEVELS, type NameLevel, nameLevel } from "./dancers-names.js";
|
|
5
|
+
export { ADVANCEMENT_DANCES, type DancerGrades, type DancerLevelAnswer, type DancerLevelQuery, type LevelRange, } from "./dancer-level.js";
|
|
5
6
|
export { type Comp, type CompAnswer, type CompDance, type CompKind, type CompQuery, CompResolver, type CompSource, type FeisPlace, type SyllabusAnswer, type SyllabusForAnswer, type SyllabusSource, type TitleCheck, canonicalOf, syllabusSourceOf, } from "./comps.js";
|
|
6
7
|
export { type ClientOptions, cacheRoot, repoOf } from "./config.js";
|
|
7
8
|
export { type Feis, type FeisAnswer, FeisFinder, type FeisQuery, NO_CALENDAR, type Series, type SeriesAnswer, type SeriesInstance, type SeriesNext, } from "./feises.js";
|
package/dist/types/results.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type DancerLevelAnswer, type DancerLevelQuery } from "./dancer-level.js";
|
|
1
2
|
import type { Release } from "./release.js";
|
|
2
3
|
import { type EntryRow, type StreamQuery, type StreamRow } from "./stream.js";
|
|
3
4
|
export declare const FEIS_LOCAL_ID_FLOOR = 17179869184;
|
|
@@ -44,6 +45,7 @@ export declare class ResultFinder {
|
|
|
44
45
|
private readonly rel;
|
|
45
46
|
constructor(rel: Release);
|
|
46
47
|
query(q: ResultQuery): Promise<ResultAnswer>;
|
|
48
|
+
dancerLevel(q: DancerLevelQuery): Promise<DancerLevelAnswer>;
|
|
47
49
|
private streamDb;
|
|
48
50
|
stream(q: StreamQuery): AsyncGenerator<StreamRow>;
|
|
49
51
|
entries(q: StreamQuery): AsyncGenerator<EntryRow>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@finbheara/archive-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.2",
|
|
4
4
|
"description": "Open a versioned release of an Irish dance results archive: download, verify, decompress and cache it by tag, keep the cache, and resolve feises and schools against it",
|
|
5
5
|
"keywords": ["irish-dance", "results", "release", "cache", "sqlite"],
|
|
6
6
|
"license": "MIT",
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
"prepublishOnly": "bun scripts/build.ts && bun ../../tools/checks/archive-client-tarball.ts"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@finbheara/domain": "0.
|
|
48
|
-
"@finbheara/names": "0.
|
|
47
|
+
"@finbheara/domain": "0.57.2",
|
|
48
|
+
"@finbheara/names": "0.30.0",
|
|
49
49
|
"hyparquet": "1.31.2"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|