@finbheara/domain 0.10.0 → 0.11.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
@@ -43,6 +43,7 @@ ESM, Node ≥ 22 or Bun ≥ 1.4.2. MIT. Not affiliated with or endorsed by any d
43
43
  | `@finbheara/domain/noun-index` | `createIndex`, `indexSchema`, `personEncoder`, and the `SqlHandle`/`NounEncoder` types: a database-backed name map (below) |
44
44
  | `@finbheara/domain/dance-types` | `danceTypes()`, `DANCE_TYPES`, `rhythmOfTime`, and the shared `DanceMatch`/`DanceRelation`/`SetRhythm`/`TimeSignature` types |
45
45
  | `@finbheara/domain/promotion` | `samePromotedRow`, `samePromotedSchool`, `samePromotedHeir`, `samePromotedName`, `questionMarksRead`, `foldCharSynonyms`: is a row the same row after a promotion (below) |
46
+ | `@finbheara/domain/person` | `seatName`, `dancerName`, `teacherName`, `roleName`, `roleSentinelOf`, the role lists and `SHARED_ROW_SENTINELS`: a person's print read in its role (below) |
46
47
 
47
48
  The library does no I/O and installs nothing process-wide. Every reader has a default and a
48
49
  factory: build your own with options when the default is not what you want.
@@ -457,6 +458,31 @@ Anything else is another row: a different surname or given name, one letter prin
457
458
  another, a `?` over an ASCII letter, a school that differs anywhere but a trailing `: location`.
458
459
  The caller pairs the card; nothing here reads an address.
459
460
 
461
+ ## Read a person's print in its role
462
+
463
+ A person is printed in a role: an adjudicator's seat on a panel sheet, a dancer's name cell, a
464
+ teacher in a school's listing. Each role prints its own sentinels where no one is named, and a
465
+ person-name reader cannot anticipate them. Each role here has its own not-a-name list, asked
466
+ FIRST; a print on no list is handed to `@finbheara/names` unchanged.
467
+
468
+ ```ts
469
+ import { dancerName, seatName, teacherName } from "@finbheara/domain/person";
470
+
471
+ seatName("Withdrawn Adjudicator").isPerson(); // false: the seat's own sentinel
472
+ dancerName("Withdrawn Adjudicator").isPerson(); // true: no dancer list holds it
473
+ dancerName("Test Dancer", "given-first").isPerson(); // false: the dancer's own sentinel
474
+ teacherName("N/A").printsNoName(); // true: a shared row sentinel
475
+ seatName("Aoife Mhaolvarna").nn2; // "Mhaolvarna<<Aoife": names' own parse
476
+ ```
477
+
478
+ - **A refused print is still a `PersonName`**: `isPerson()` is false, `printsNoName()` is true,
479
+ `refusal.rule` is `"placeholder"`, the print levels keep the print, and every level from NN2
480
+ down is names' refused value. Ask the type, never the string.
481
+ - **One shared list** (`SHARED_ROW_SENTINELS`: `N/A`, `TBA`, `Unknown`) opens every role's list
482
+ and the school cell's (`SCHOOL_CELL_SENTINELS` on `/school`, asked by the school reader before
483
+ its own register), so a sentinel a whole row prints has one definition.
484
+ - Each row is the folded print (`foldNameKey`), what it stands for, and where it was seen.
485
+
460
486
  ## Known gaps
461
487
 
462
488
  - `place()` reads `"Derry in Ireland"` and `"Calgary in Western Canada"` as `unread`: it does
@@ -0,0 +1,30 @@
1
+ import { foldNameKey } from "@finbheara/names/normalize";
2
+ var SHARED_ROW_SENTINELS2 = [
3
+ {
4
+ print: "n a",
5
+ authority: "`#N/A`, a spreadsheet's missing-value mark: 66 name cells and 66 school cells of one transcribed sheet set"
6
+ },
7
+ {
8
+ print: "tba",
9
+ authority: "`TBA`: 1 name cell and 1 school cell"
10
+ },
11
+ {
12
+ print: "unknown",
13
+ authority: "`Unknown`, `unknown`, `*Unknown*`: 4 name cells and 186 school cells"
14
+ }
15
+ ];
16
+ function sentinelIn2(list) {
17
+ const exact = new Map;
18
+ for (const row of list)
19
+ if (row.match === undefined && !exact.has(row.print))
20
+ exact.set(row.print, row);
21
+ const prefix = list.filter((row) => row.match === "prefix");
22
+ return (print) => {
23
+ const folded = foldNameKey(print);
24
+ if (folded === "")
25
+ return;
26
+ return exact.get(folded) ?? prefix.find((row) => folded === row.print || folded.startsWith(`${row.print} `));
27
+ };
28
+ }
29
+
30
+ export { SHARED_ROW_SENTINELS2, sentinelIn2 };
package/dist/person.js ADDED
@@ -0,0 +1,128 @@
1
+ import {
2
+ SHARED_ROW_SENTINELS2,
3
+ sentinelIn2
4
+ } from "./chunks/place-tcgfvemw.js";
5
+
6
+ import {
7
+ NAME_REFUSED,
8
+ personName
9
+ } from "@finbheara/names/normalize";
10
+ var ADJUDICATOR_SENTINELS = [
11
+ {
12
+ print: "withdrawn adjudicator",
13
+ authority: "`Withdrawn Adjudicator`: 180 seat cells, one panel sheet's empty seat"
14
+ },
15
+ {
16
+ print: "no school judge",
17
+ authority: "`No School Judge`: an entry form's option for an adjudicator's entry"
18
+ }
19
+ ];
20
+ var DANCER_SENTINELS = [
21
+ {
22
+ print: "name withheld",
23
+ authority: "`Name Withheld`: 136 name cells, the entry platform printed that the name was withheld"
24
+ },
25
+ {
26
+ print: "test dancer",
27
+ authority: "`Test Dancer`: 7 name cells, an entry platform's test entry"
28
+ },
29
+ {
30
+ print: "none none",
31
+ authority: "`none none`: 4 name cells, the sentinel `none` typed into both name fields"
32
+ },
33
+ {
34
+ print: "not known",
35
+ authority: "`Not known`: 1 name cell"
36
+ },
37
+ {
38
+ print: "don t know",
39
+ authority: "`Don't Know`: 1 name cell"
40
+ }
41
+ ];
42
+ var TEACHER_SENTINELS = [];
43
+ var ROLE_SENTINELS = {
44
+ adjudicator: [...SHARED_ROW_SENTINELS2, ...ADJUDICATOR_SENTINELS],
45
+ dancer: [...SHARED_ROW_SENTINELS2, ...DANCER_SENTINELS],
46
+ teacher: [...SHARED_ROW_SENTINELS2, ...TEACHER_SENTINELS]
47
+ };
48
+ var MATCHERS = {
49
+ adjudicator: sentinelIn2(ROLE_SENTINELS.adjudicator),
50
+ dancer: sentinelIn2(ROLE_SENTINELS.dancer),
51
+ teacher: sentinelIn2(ROLE_SENTINELS.teacher)
52
+ };
53
+ function roleSentinelOf(role, print) {
54
+ return MATCHERS[role](print);
55
+ }
56
+ var NO_PART = Object.freeze({ particles: [], base: "", parts: [], tradition: null });
57
+
58
+ class RoleRefusedName {
59
+ [Symbol.toStringTag] = "PersonName";
60
+ nn0;
61
+ nn1;
62
+ nn2 = NAME_REFUSED;
63
+ nn3 = NAME_REFUSED;
64
+ nn4 = NAME_REFUSED;
65
+ surname = NO_PART;
66
+ given = [];
67
+ suffixes = [];
68
+ refusal;
69
+ verdict;
70
+ role;
71
+ sentinel;
72
+ constructor(read, role, sentinel) {
73
+ this.role = role;
74
+ this.sentinel = sentinel;
75
+ this.nn0 = read.nn0;
76
+ this.nn1 = read.nn1;
77
+ this.refusal = { rule: "placeholder", printed: read.nn0, value: NAME_REFUSED };
78
+ this.verdict = { kind: "refused", refusal: this.refusal, rules: read.verdict.rules };
79
+ }
80
+ toString() {
81
+ return this.nn2;
82
+ }
83
+ get length() {
84
+ return this.nn2.length;
85
+ }
86
+ surnameKey() {
87
+ return "";
88
+ }
89
+ givenFields() {
90
+ return [];
91
+ }
92
+ givenName() {
93
+ return "";
94
+ }
95
+ isTeam() {
96
+ return false;
97
+ }
98
+ isPerson() {
99
+ return false;
100
+ }
101
+ isEmpty() {
102
+ return false;
103
+ }
104
+ printsNoName() {
105
+ return true;
106
+ }
107
+ }
108
+ function roleName(role, print, order) {
109
+ const read = personName(print, order);
110
+ const sentinel = MATCHERS[role](print);
111
+ return sentinel === undefined ? read : new RoleRefusedName(read, role, sentinel);
112
+ }
113
+ var seatName = (print) => roleName("adjudicator", print, "given-first");
114
+ var dancerName = (print, order) => roleName("dancer", print, order);
115
+ var teacherName = (print, order) => roleName("teacher", print, order);
116
+ export {
117
+ ADJUDICATOR_SENTINELS,
118
+ DANCER_SENTINELS,
119
+ ROLE_SENTINELS,
120
+ SHARED_ROW_SENTINELS2 as SHARED_ROW_SENTINELS,
121
+ TEACHER_SENTINELS,
122
+ dancerName,
123
+ roleName,
124
+ roleSentinelOf,
125
+ seatName,
126
+ sentinelIn2 as sentinelIn,
127
+ teacherName
128
+ };
package/dist/school.js CHANGED
@@ -9,6 +9,10 @@ import {
9
9
  placeRelation2,
10
10
  sameReading2
11
11
  } from "./chunks/place-tv86hmps.js";
12
+ import {
13
+ SHARED_ROW_SENTINELS2,
14
+ sentinelIn2
15
+ } from "./chunks/place-tcgfvemw.js";
12
16
  import {
13
17
  validity
14
18
  } from "./chunks/place-q9kwsmzd.js";
@@ -18,6 +22,27 @@ import { SURNAME_SEPARATOR, lexiconKey, titleCaseNamePart } from "@finbheara/nam
18
22
  import { personName } from "@finbheara/names/normalize";
19
23
 
20
24
  import { placeholderOf } from "@finbheara/names/normalize";
25
+
26
+ var SCHOOL_CELL_OWN_SENTINELS = [
27
+ {
28
+ print: "no school",
29
+ authority: "`No School`: 76 school cells, the dancer entered with no school"
30
+ },
31
+ {
32
+ print: "independent",
33
+ authority: "`Independent`, `independent`, `Independent?`: 5 school cells, no school by the dancer's own description"
34
+ },
35
+ {
36
+ print: "independent dancer",
37
+ authority: "`Independent Dancer`, `Independent dancer`, `Independent Dancer?`: 8 school cells"
38
+ }
39
+ ];
40
+ var SCHOOL_CELL_SENTINELS = [
41
+ ...SHARED_ROW_SENTINELS2,
42
+ ...SCHOOL_CELL_OWN_SENTINELS
43
+ ];
44
+ var schoolCellSentinelOf = sentinelIn2(SCHOOL_CELL_SENTINELS);
45
+
21
46
  var SCHOOL_NAME_EXCEPTIONS = [
22
47
  {
23
48
  phrase: "the academy",
@@ -257,7 +282,7 @@ function notASchoolIn(rows) {
257
282
  const text = normalizeForRefusal(print);
258
283
  if (text === "")
259
284
  return;
260
- const placeholder = placeholderOf(text);
285
+ const placeholder = schoolCellSentinelOf(text) ?? placeholderOf(text);
261
286
  if (placeholder !== undefined)
262
287
  return placeholderRow(placeholder);
263
288
  for (const row of rows) {
@@ -2137,8 +2162,11 @@ export {
2137
2162
  DEFAULT_SCHOOL_NAME_CAPACITY,
2138
2163
  DEFAULT_SCHOOL_NAME_READER,
2139
2164
  NOT_A_SCHOOL,
2165
+ SCHOOL_CELL_OWN_SENTINELS,
2166
+ SCHOOL_CELL_SENTINELS,
2140
2167
  SCHOOL_LEVEL_COLUMNS,
2141
2168
  SCHOOL_NAME_EXCEPTIONS,
2169
+ SHARED_ROW_SENTINELS2 as SHARED_ROW_SENTINELS,
2142
2170
  compareSchoolNames,
2143
2171
  compareSchools,
2144
2172
  createSchoolNameReader,
@@ -2152,6 +2180,7 @@ export {
2152
2180
  realWords,
2153
2181
  realWordsInPrintOrder,
2154
2182
  sameInEveryPart,
2183
+ schoolCellSentinelOf,
2155
2184
  schoolColumns,
2156
2185
  schoolCompare,
2157
2186
  schoolEncoder,
@@ -0,0 +1,14 @@
1
+ import { type ParseOrder, type PersonName } from "@finbheara/names/normalize";
2
+ import { type RowSentinel } from "./row-sentinels.ts";
3
+ export { SHARED_ROW_SENTINELS, sentinelIn } from "./row-sentinels.ts";
4
+ export type { RowSentinel } from "./row-sentinels.ts";
5
+ export type PersonRole = "adjudicator" | "dancer" | "teacher";
6
+ export declare const ADJUDICATOR_SENTINELS: readonly RowSentinel[];
7
+ export declare const DANCER_SENTINELS: readonly RowSentinel[];
8
+ export declare const TEACHER_SENTINELS: readonly RowSentinel[];
9
+ export declare const ROLE_SENTINELS: Readonly<Record<PersonRole, readonly RowSentinel[]>>;
10
+ export declare function roleSentinelOf(role: PersonRole, print: string): RowSentinel | undefined;
11
+ export declare function roleName(role: PersonRole, print: string, order?: ParseOrder): PersonName;
12
+ export declare const seatName: (print: string) => PersonName;
13
+ export declare const dancerName: (print: string, order?: ParseOrder) => PersonName;
14
+ export declare const teacherName: (print: string, order?: ParseOrder) => PersonName;
@@ -0,0 +1,4 @@
1
+ import { type NamePlaceholder } from "@finbheara/names/normalize";
2
+ export type RowSentinel = NamePlaceholder;
3
+ export declare const SHARED_ROW_SENTINELS: readonly RowSentinel[];
4
+ export declare function sentinelIn(list: readonly RowSentinel[]): (print: string) => RowSentinel | undefined;
@@ -0,0 +1,4 @@
1
+ import { type RowSentinel } from "./row-sentinels.ts";
2
+ export declare const SCHOOL_CELL_OWN_SENTINELS: readonly RowSentinel[];
3
+ export declare const SCHOOL_CELL_SENTINELS: readonly RowSentinel[];
4
+ export declare const schoolCellSentinelOf: (print: string) => RowSentinel | undefined;
@@ -8,5 +8,8 @@ export { compareSchoolNames, compareSchools } from "./school-identity.ts";
8
8
  export type { IdentityResult, IdentityVerdict } from "./school-identity.ts";
9
9
  export { foldSchoolName, hasSpecificToken, schoolKeyTokens } from "./school-match-key.ts";
10
10
  export { NOT_A_SCHOOL, SCHOOL_NAME_EXCEPTIONS, } from "./school-exception-vocabulary.ts";
11
+ export { SCHOOL_CELL_OWN_SENTINELS, SCHOOL_CELL_SENTINELS, schoolCellSentinelOf, } from "./school-cell-sentinels.ts";
12
+ export { SHARED_ROW_SENTINELS } from "./row-sentinels.ts";
13
+ export type { RowSentinel } from "./row-sentinels.ts";
11
14
  export type { EmptyReason, Validated } from "./validated.ts";
12
15
  export type { NotASchool, RefusalReason, SchoolNameException, } from "./school-exception-vocabulary.ts";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@finbheara/domain",
3
- "version": "0.10.0",
4
- "description": "Places, CLRG regions, school names, ages and dances as they are printed: read, compared and told apart",
3
+ "version": "0.11.0",
4
+ "description": "Places, CLRG regions, school names, ages, dances and a person's print in its role, as they are printed: read, compared and told apart",
5
5
  "keywords": [
6
6
  "places",
7
7
  "regions",
@@ -57,6 +57,10 @@
57
57
  "types": "./dist/types/promotion.d.ts",
58
58
  "default": "./dist/promotion.js"
59
59
  },
60
+ "./person": {
61
+ "types": "./dist/types/person.d.ts",
62
+ "default": "./dist/person.js"
63
+ },
60
64
  "./package.json": "./package.json"
61
65
  },
62
66
  "files": ["dist/*.js", "dist/chunks/*.js", "dist/types/**/*.d.ts", "README.md", "LICENSE"],