@finbheara/domain 0.47.0 → 0.48.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
@@ -302,6 +302,12 @@ canOverlap(u12, Age.from("U14", { year: 2026 }), dancer); // tru
302
302
  Age.from("13 & Over", { year: 2026 }).interval(); // { lo: 13, hi: Infinity }, as "Over 13"
303
303
  ```
304
304
 
305
+ A range is another way of writing the `Under` band at its top: `11-13` reads as `U13`, and its
306
+ low number bounds nothing, since a youth ladder's range names the rung and not every age in it.
307
+ A range printed from 18 up is an age bracket, and its low number is its floor:
308
+ `Age.from("24-30", { year: 2026 })` is ages 24 to 29, born 1996 to 2001. A range that prints no
309
+ floor of 18 or more, on a ladder that offered the adult rung, floors at 18.
310
+
305
311
  A competition title usually carries its age group in its words. `Age.fromTitle` finds the
306
312
  phrase, reads it as `Age.from` would, and says where it was. A title that names no age group
307
313
  is empty, not refused. Competition numbers are never read as ages.
@@ -341,7 +347,7 @@ youth band stands.
341
347
 
342
348
  An adult word beside an and-over from 18 or a range from 18 reads both as well: `adult o40` and
343
349
  `adult 18-29` are adult (`isAdult()`), and their `kind`, interval and birth years are the ones the
344
- band alone reads on the same ladder, a range floored at 18 where no rung sits below it. So
350
+ band alone reads on the same ladder. So
345
351
  `Age.from("adult o40", { year: 2026 })` is born 1985 or earlier, as `o40` is. An and-over under
346
352
  18 or a range opening under 18 (`Teen & Adult 13 & Over`) admits youth, and the band stands. TIDA's
347
353
  `Senior Adult` beside an and-over is its oldest youth championship, an open championship that
package/dist/age.js CHANGED
@@ -39,7 +39,7 @@ import {
39
39
  youngFloor2,
40
40
  tooYoungForMajor2,
41
41
  tooYoungForFeis2
42
- } from "./chunks/place-mpeps8tn.js";
42
+ } from "./chunks/place-kmh59zkw.js";
43
43
  export {
44
44
  ADULT_FLOOR2 as ADULT_FLOOR,
45
45
  AVERAGE_AGE_DECIMALS2 as AVERAGE_AGE_DECIMALS,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  Age2,
3
3
  ageRelation2
4
- } from "./place-mpeps8tn.js";
4
+ } from "./place-kmh59zkw.js";
5
5
  import {
6
6
  validity
7
7
  } from "./place-q9kwsmzd.js";
@@ -242,12 +242,14 @@ function readRange(a, b, ladder) {
242
242
  clauses: ["range-overlapping"],
243
243
  parts: [a, b]
244
244
  };
245
- const below = maxWhere(ladder.caps, (c) => c < b);
245
+ const capBelow = maxWhere(ladder.caps, (c) => c < b);
246
+ const printedFloor = a >= ADULT_FLOOR2 && (capBelow === undefined || capBelow <= a);
247
+ const below = printedFloor ? a : capBelow;
246
248
  const adultFloor = below === undefined && ladder.adult === true && b > ADULT_FLOOR2;
247
249
  const meetsOver = ladder.overs.includes(b + 1) && !ladder.caps.some((c) => c > b);
248
250
  const clauses = [
249
251
  "range-as-under",
250
- below !== undefined ? "under-floored-on-rung" : adultFloor ? "range-adult-floor" : "youngest-absorbs"
252
+ printedFloor ? "range-printed-floor" : below !== undefined ? "under-floored-on-rung" : adultFloor ? "range-adult-floor" : "youngest-absorbs"
251
253
  ];
252
254
  if (meetsOver)
253
255
  clauses.push("range-top-meets-over");
@@ -429,7 +431,7 @@ function fromPrint(print, context = {}) {
429
431
  throw new Error(`Age.from(${JSON.stringify(print)}): birthYears needs a competition year`);
430
432
  return birthYearsOfInterval2(iv, at);
431
433
  },
432
- floorObserved: () => reading.kind !== "under" && reading.kind !== "range" || iv === null ? null : reading.clauses.includes("under-floored-on-rung") || reading.clauses.includes("range-adult-floor") || reading.clauses.includes("under-stride")
434
+ floorObserved: () => reading.kind !== "under" && reading.kind !== "range" || iv === null ? null : reading.clauses.includes("under-floored-on-rung") || reading.clauses.includes("range-adult-floor") || reading.clauses.includes("range-printed-floor") || reading.clauses.includes("under-stride")
433
435
  });
434
436
  }
435
437
  function fromYOB(from, to = from, context = {}) {
@@ -484,7 +486,7 @@ function sourceOf(r) {
484
486
  switch (r.kind) {
485
487
  case "range":
486
488
  case "under":
487
- if (r.clauses.includes("under-stride"))
489
+ if (r.clauses.includes("under-stride") || r.clauses.includes("range-printed-floor"))
488
490
  return "printed-band";
489
491
  return iv.lo > YOUNGEST_FLOOR2 ? "sibling-narrowed" : "printed-band";
490
492
  case "over":
package/dist/schedule.js CHANGED
@@ -1,8 +1,8 @@
1
- import"./chunks/place-mpeps8tn.js";
1
+ import"./chunks/place-kmh59zkw.js";
2
2
  import {
3
3
  compTitle2,
4
4
  matchTitle2
5
- } from "./chunks/place-y66f4138.js";
5
+ } from "./chunks/place-cdghn4v2.js";
6
6
 
7
7
  function hallKey(hall) {
8
8
  return hall.normalize("NFKD").replace(/\p{M}/gu, "").toLowerCase().replace(/[^a-z0-9]+/g, " ").trim();
package/dist/title.js CHANGED
@@ -6,8 +6,8 @@ import {
6
6
  titleRelation2,
7
7
  ladderOf2,
8
8
  matchTitle2
9
- } from "./chunks/place-y66f4138.js";
10
- import"./chunks/place-mpeps8tn.js";
9
+ } from "./chunks/place-cdghn4v2.js";
10
+ import"./chunks/place-kmh59zkw.js";
11
11
  export {
12
12
  compTitle2 as compTitle,
13
13
  ladderOf2 as ladderOf,
@@ -25,7 +25,7 @@ export type AgeArm = "band" | "yob" | "open" | "empty";
25
25
  export type AgeKind = "under" | "over" | "range" | "adult" | "senior" | "yob";
26
26
  export type AgeRefusal = "not-a-band" | "backwards-range" | "overlapping-ranges" | "senior-without-ladder" | "below-youngest-band" | "above-oldest-band" | "year-out-of-range";
27
27
  export type AgeSource = "sibling-narrowed" | "printed-band" | "printed-range" | "printed-yob" | "open";
28
- export type AgeClause = "under-floored-on-rung" | "under-stride" | "youngest-absorbs" | "over-ceiling-from-next-over" | "over-ceiling-refused-gap" | "and-over-no-ceiling" | "adult-under-ceiling" | "adult-band" | "range-overlapping" | "range-as-under" | "range-top-meets-over" | "range-adult-floor";
28
+ export type AgeClause = "under-floored-on-rung" | "under-stride" | "youngest-absorbs" | "over-ceiling-from-next-over" | "over-ceiling-refused-gap" | "and-over-no-ceiling" | "adult-under-ceiling" | "adult-band" | "range-overlapping" | "range-as-under" | "range-top-meets-over" | "range-adult-floor" | "range-printed-floor";
29
29
  export type AgeRelation = "same" | "contains" | "overlaps" | "disjoint" | "silent";
30
30
  export type AgeRelationReason = "equal" | "a-contains-b" | "b-contains-a" | "partial" | "a-older" | "a-younger" | "a-not-a-band" | "b-not-a-band";
31
31
  export interface AgeComparison {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@finbheara/domain",
3
- "version": "0.47.0",
3
+ "version": "0.48.0",
4
4
  "description": "Places, CLRG regions, school names, ages, dances, competition titles and schedules, and a person's print in its role, as they are printed: read, compared and told apart",
5
5
  "keywords": [
6
6
  "places",