linked-rolls 0.43.0 → 0.45.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.
Files changed (80) hide show
  1. package/README.md +94 -2
  2. package/lib/Agent.d.ts +1 -1
  3. package/lib/Assumption.d.ts +2 -2
  4. package/lib/Collation.d.ts +84 -7
  5. package/lib/Collation.js +63 -16
  6. package/lib/ConditionState.d.ts +1 -1
  7. package/lib/Edit.d.ts +3 -3
  8. package/lib/Edition.d.ts +14 -8
  9. package/lib/EditionView.d.ts +8 -8
  10. package/lib/EditionView.js +6 -6
  11. package/lib/Emulation.d.ts +4 -4
  12. package/lib/Emulation.js +3 -3
  13. package/lib/Feature.d.ts +5 -5
  14. package/lib/FeatureSource.d.ts +4 -4
  15. package/lib/ReproducingSystem.d.ts +4 -4
  16. package/lib/RollCopy.d.ts +10 -10
  17. package/lib/RollCopy.js +4 -4
  18. package/lib/Symbol.d.ts +2 -2
  19. package/lib/Symbol.js +1 -1
  20. package/lib/TrackCalibration.d.ts +1 -1
  21. package/lib/TrackCalibration.js +1 -1
  22. package/lib/TrackerBar.d.ts +3 -3
  23. package/lib/TrackerBar.js +1 -1
  24. package/lib/Version.d.ts +13 -15
  25. package/lib/Version.js +2 -2
  26. package/lib/alignment.d.ts +4 -4
  27. package/lib/alignment.js +3 -3
  28. package/lib/asJsonLd.d.ts +1 -1
  29. package/lib/asJsonLd.js +3 -3
  30. package/lib/constraints.d.ts +1 -1
  31. package/lib/constraints.js +5 -5
  32. package/lib/context.js +4 -4
  33. package/lib/editionOps.d.ts +42 -10
  34. package/lib/editionOps.js +132 -19
  35. package/lib/importJsonLd.d.ts +1 -1
  36. package/lib/importJsonLd.js +3 -3
  37. package/lib/index.d.ts +42 -40
  38. package/lib/index.js +42 -40
  39. package/lib/migrate.js +18 -7
  40. package/lib/procedures.d.ts +1 -1
  41. package/lib/readers/phillipsEroll.d.ts +19 -4
  42. package/lib/readers/phillipsEroll.js +21 -6
  43. package/lib/readers/spencerBar.d.ts +2 -2
  44. package/lib/readers/spencerBar.js +3 -3
  45. package/lib/readers/stanfordAton.d.ts +3 -3
  46. package/lib/readers/stanfordAton.js +4 -4
  47. package/lib/reservations.d.ts +3 -3
  48. package/lib/reservations.js +4 -4
  49. package/lib/scatter.d.ts +225 -0
  50. package/lib/scatter.js +231 -0
  51. package/lib/schema.json +60 -12
  52. package/lib/sigla.d.ts +1 -1
  53. package/lib/sigla.js +4 -4
  54. package/lib/statistics.d.ts +71 -0
  55. package/lib/statistics.js +121 -0
  56. package/lib/substitution.d.ts +5 -5
  57. package/lib/substitution.js +2 -2
  58. package/lib/systems/index.d.ts +2 -2
  59. package/lib/systems/index.js +4 -4
  60. package/lib/systems/welteLicensee/bar.d.ts +1 -1
  61. package/lib/systems/welteLicensee/bar.js +2 -2
  62. package/lib/systems/welteLicensee/system.d.ts +2 -2
  63. package/lib/systems/welteLicensee/system.js +3 -3
  64. package/lib/systems/welteT100/bar.d.ts +1 -1
  65. package/lib/systems/welteT100/bar.js +2 -2
  66. package/lib/systems/welteT100/system.d.ts +4 -4
  67. package/lib/systems/welteT100/system.js +4 -4
  68. package/lib/systems/welteT98/bar.d.ts +1 -1
  69. package/lib/systems/welteT98/bar.js +2 -2
  70. package/lib/systems/welteT98/system.d.ts +4 -4
  71. package/lib/systems/welteT98/system.js +4 -4
  72. package/lib/utils.d.ts +2 -0
  73. package/lib/utils.js +10 -0
  74. package/lib/validate.d.ts +1 -1
  75. package/lib/validate.js +1 -1
  76. package/lib/vocabulary.d.ts +1 -1
  77. package/lib/vocabulary.js +3 -3
  78. package/lib/witnesses.d.ts +2 -2
  79. package/lib/witnesses.js +2 -2
  80. package/package.json +1 -1
package/lib/schema.json CHANGED
@@ -204,15 +204,23 @@
204
204
  "type": "string"
205
205
  },
206
206
  "CollationTolerance": {
207
- "description": "Tolerance used in collation of roll copies: the acceptable deviation at either end when aligning features across copies.",
207
+ "description": "The window two readings of one feature must fall in to be collated: how far apart they may lie at either end, and where that window is centred.\n\nThe centre is worth stating. Two copies of one roll differ by a systematic offset as well as by scatter, and a window centred on nothing has to be widened by the whole of that offset before it admits what the offset alone displaces. Naming the offset lets the tolerance stand for the scatter only. A window that names none is centred on nothing, which is what every window written before the offset was held here means.",
208
208
  "properties": {
209
+ "offsetEnd": {
210
+ "$ref": "#/definitions/Millimeters",
211
+ "description": "The same at the end of a feature, in the same direction."
212
+ },
213
+ "offsetStart": {
214
+ "$ref": "#/definitions/Millimeters",
215
+ "description": "How much later the derived version puts the start of a feature than the version it is read against, where the two differ systematically. Nothing where they do not.\n\nThe direction is the one a collation measures in, the child less the parent, and it is not symmetric: stored the other way round the window sits on the wrong side of the readings and merges what it should separate. A measurement taken over the parent's copies gives the negative of this, which is what `toleranceAcross` asks the side for."
216
+ },
209
217
  "toleranceEnd": {
210
218
  "$ref": "#/definitions/Millimeters",
211
- "description": "Tolerance at the end position of a feature."
219
+ "description": "How far they may lie apart at the end, measured from `offsetEnd`."
212
220
  },
213
221
  "toleranceStart": {
214
222
  "$ref": "#/definitions/Millimeters",
215
- "description": "Tolerance at the start position of a feature."
223
+ "description": "How far the two readings may lie apart at the start of a feature, measured from `offsetStart`."
216
224
  }
217
225
  },
218
226
  "required": [
@@ -414,8 +422,8 @@
414
422
  "type": "object"
415
423
  },
416
424
  "collationTolerance": {
417
- "$ref": "#/definitions/CollationTolerance",
418
- "description": "The tolerance at which the derived version was collated against the one it is based on. A derivation written before the tolerance was held here states none. Not exported to RDF."
425
+ "$ref": "#/definitions/ObjectAssumption%3CCollationTolerance%3E",
426
+ "description": "The tolerance at which the derived version was collated against the one it is based on. A derivation written before the tolerance was held here states none. Not exported to RDF.\n\nIt is an object assumption, so that a tolerance calculated from the scatter of the readings can carry the inference it was drawn by. It is the one quantity in the edition that decides what counts as a reading at all, and a number arrived at by a method should say so."
419
427
  },
420
428
  "@id": {
421
429
  "description": "A unique identifier for this object.",
@@ -576,7 +584,8 @@
576
584
  "properties": {
577
585
  "collationTolerance": {
578
586
  "$ref": "#/definitions/CollationTolerance",
579
- "description": "The tolerance parameters used when collating (aligning) the different roll copies for this edition. Not exported to RDF."
587
+ "deprecated": true,
588
+ "description": "The tolerance every version of the edition was collated at, before each derivation stated its own. How precisely two copies place a symbol depends on which two they are, so the tolerance belongs to the derivation, `Derivation.collationTolerance`, and migration writes this one onto every derivation that gives none. Nothing else reads it. A window's offset is the displacement between two particular copies and so can never be stated here. Not exported to RDF."
580
589
  },
581
590
  "editors": {
582
591
  "description": "The persons who prepared the edition, each with the part they took in the editorial work. An edition written before this field existed carries none.",
@@ -1899,6 +1908,51 @@
1899
1908
  ],
1900
1909
  "type": "object"
1901
1910
  },
1911
+ "ObjectAssumption<CollationTolerance>": {
1912
+ "description": "An object assumption wraps a complex object with an optional annotation. Used for structured values (e.g. persons, conditions) whose properties may be uncertain.",
1913
+ "properties": {
1914
+ "@annotation": {
1915
+ "description": "An optional annotation expressing a belief about this assumption. Uses the JSON-LD-star `@annotation` mechanism to attach epistemic metadata (certainty and reasons) to any triple.",
1916
+ "properties": {
1917
+ "belief": {
1918
+ "$ref": "#/definitions/Belief",
1919
+ "description": "The belief held about the annotated statement.",
1920
+ "ontology": "crminf:J4i is subject of"
1921
+ },
1922
+ "@id": {
1923
+ "description": "A unique identifier for this object.",
1924
+ "type": "string"
1925
+ }
1926
+ },
1927
+ "required": [
1928
+ "belief",
1929
+ "@id"
1930
+ ],
1931
+ "type": "object"
1932
+ },
1933
+ "offsetEnd": {
1934
+ "$ref": "#/definitions/Millimeters",
1935
+ "description": "The same at the end of a feature, in the same direction."
1936
+ },
1937
+ "offsetStart": {
1938
+ "$ref": "#/definitions/Millimeters",
1939
+ "description": "How much later the derived version puts the start of a feature than the version it is read against, where the two differ systematically. Nothing where they do not.\n\nThe direction is the one a collation measures in, the child less the parent, and it is not symmetric: stored the other way round the window sits on the wrong side of the readings and merges what it should separate. A measurement taken over the parent's copies gives the negative of this, which is what `toleranceAcross` asks the side for."
1940
+ },
1941
+ "toleranceEnd": {
1942
+ "$ref": "#/definitions/Millimeters",
1943
+ "description": "How far they may lie apart at the end, measured from `offsetEnd`."
1944
+ },
1945
+ "toleranceStart": {
1946
+ "$ref": "#/definitions/Millimeters",
1947
+ "description": "How far the two readings may lie apart at the start of a feature, measured from `offsetStart`."
1948
+ }
1949
+ },
1950
+ "required": [
1951
+ "toleranceEnd",
1952
+ "toleranceStart"
1953
+ ],
1954
+ "type": "object"
1955
+ },
1902
1956
  "ObjectAssumption<ConditionState<\"general\">>": {
1903
1957
  "description": "An object assumption wraps a complex object with an optional annotation. Used for structured values (e.g. persons, conditions) whose properties may be uncertain.",
1904
1958
  "properties": {
@@ -3043,12 +3097,6 @@
3043
3097
  },
3044
3098
  "type": "array"
3045
3099
  },
3046
- "siglum": {
3047
- "deprecated": true,
3048
- "description": "A label a document carries from before the sigla were computed. Nothing should write one here and nothing should show one: what a version is called comes from `siglaOf`.",
3049
- "type": "string",
3050
- "ontology": "reo:siglum"
3051
- },
3052
3100
  "system": {
3053
3101
  "$ref": "#/definitions/Concept",
3054
3102
  "description": "The reproducing system this version is coded for. One roll was often issued for several of them, and a version is a reading in one system's words: its expression types are that system's vocabulary and its notes sit on that bar's positions. A system the type vocabulary knows carries the IRI of its concept as `id`, from which the export takes the system's own context.",
package/lib/sigla.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Edition } from './Edition';
1
+ import { Edition } from './Edition.js';
2
2
  /**
3
3
  * The siglum of every version, as the stemma stands. The letter names the
4
4
  * reproducing system a version is coded for, the number counts the
package/lib/sigla.js CHANGED
@@ -1,7 +1,7 @@
1
- import { idOf } from './Assumption';
2
- import { systemIdOf } from './TrackerBar';
3
- import { trackerBarOf } from './systems';
4
- import { principalDerivationOf } from './Version';
1
+ import { idOf } from './Assumption.js';
2
+ import { systemIdOf } from './TrackerBar.js';
3
+ import { trackerBarOf } from './systems/index.js';
4
+ import { principalDerivationOf } from './Version.js';
5
5
  /** The letter the versions of a system are labelled with. */
6
6
  const letters = new Map([
7
7
  ['welte-t100', 'R'],
@@ -0,0 +1,71 @@
1
+ import { Quantity } from "./Quantity.js";
2
+ /**
3
+ * The statistics a sample of measurements is described with.
4
+ *
5
+ * The centre and the scatter are taken from the median rather than from
6
+ * the mean, because the departures a measurement over an edition looks
7
+ * for are in the sample it is taken over. A mean and a standard
8
+ * deviation would grow towards those departures until they no longer
9
+ * stood out; a median and a median absolute deviation leave them out of
10
+ * account.
11
+ */
12
+ /** The middle of a sample, the mean of the two middle values where it has an even number of them. */
13
+ export declare const medianOf: <U extends string>(values: readonly Quantity<U>[]) => Quantity<U> | undefined;
14
+ /** Where a sample sits and how far it scatters. */
15
+ export interface Spread<U extends string> {
16
+ /** How many measurements it was taken over. */
17
+ n: number;
18
+ /** The middle measurement. */
19
+ median: Quantity<U>;
20
+ /**
21
+ * The scatter about the median, as the median absolute deviation
22
+ * scaled to the standard deviation a normal sample of that scatter
23
+ * would have. It is zero where more than half the sample sits at
24
+ * one value, and no scatter can be read off such a sample.
25
+ */
26
+ sigma: Quantity<U>;
27
+ }
28
+ /** Where the sample sits and how far it scatters, or nothing for an empty sample. */
29
+ export declare const spreadOf: <U extends string>(values: readonly Quantity<U>[]) => Spread<U> | undefined;
30
+ /** How far the value lies from the centre of the spread, in units of its scatter. */
31
+ export declare const standardise: <U extends string>(value: Quantity<U>, spread: Spread<U>) => number;
32
+ /** The share of a normal sample lying below `z` standard deviations. */
33
+ export declare const normalBelow: (z: number) => number;
34
+ /** The share of a normal sample lying further than `z` standard deviations from its centre, on either side. */
35
+ export declare const normalBeyond: (z: number) => number;
36
+ /**
37
+ * How many standard deviations out the given share of a normal sample
38
+ * lies below, after Acklam's rational approximation, whose relative
39
+ * error stays below 1.15e-9. The inverse of `normalBelow`.
40
+ */
41
+ export declare const normalQuantile: (share: number) => number;
42
+ /**
43
+ * How much heavier the tails of a standardised sample are than a normal
44
+ * sample's. Zero for a normal shape, positive where more of the sample
45
+ * lies far out than the curve allows.
46
+ */
47
+ export declare const excessKurtosisOf: (standardised: readonly number[]) => number;
48
+ /** How much of a sample lies beyond a given distance from its centre, against how much would under a normal curve. */
49
+ export interface Tail {
50
+ /** The distance from the centre, in standard deviations. */
51
+ beyond: number;
52
+ /** How many of the sample lie further out than that. */
53
+ observed: number;
54
+ /** How many a normal sample of the same size would put there. */
55
+ expected: number;
56
+ }
57
+ /** What the sample puts beyond the given distance, against what a normal sample would. */
58
+ export declare const tailOf: (standardised: readonly number[], beyond: number) => Tail;
59
+ /** A sample counted into bins of one width. */
60
+ export interface Histogram<U extends string> {
61
+ /** The bounds of the bins, in order, one more of them than there are counts. */
62
+ edges: Quantity<U>[];
63
+ /** How many of the sample fall in each bin. */
64
+ counts: number[];
65
+ }
66
+ /**
67
+ * The sample counted into bins of the given width, laid out on
68
+ * multiples of that width so that two histograms of one width share
69
+ * their bounds. Nothing for an empty sample or a width of nothing.
70
+ */
71
+ export declare const histogramOf: <U extends string>(values: readonly Quantity<U>[], binWidth: Quantity<U>) => Histogram<U> | undefined;
@@ -0,0 +1,121 @@
1
+ import { quantity } from "./Quantity.js";
2
+ /**
3
+ * The statistics a sample of measurements is described with.
4
+ *
5
+ * The centre and the scatter are taken from the median rather than from
6
+ * the mean, because the departures a measurement over an edition looks
7
+ * for are in the sample it is taken over. A mean and a standard
8
+ * deviation would grow towards those departures until they no longer
9
+ * stood out; a median and a median absolute deviation leave them out of
10
+ * account.
11
+ */
12
+ /** The middle of a sample, the mean of the two middle values where it has an even number of them. */
13
+ export const medianOf = (values) => {
14
+ if (values.length === 0)
15
+ return undefined;
16
+ const sorted = [...values].sort((a, b) => a - b);
17
+ const middle = Math.floor(sorted.length / 2);
18
+ return sorted.length % 2 === 1
19
+ ? sorted[middle]
20
+ : quantity((sorted[middle - 1] + sorted[middle]) / 2);
21
+ };
22
+ /** What the median absolute deviation must be multiplied by to estimate the standard deviation of a normal sample. */
23
+ const MAD_TO_SIGMA = 1.4826;
24
+ /** Where the sample sits and how far it scatters, or nothing for an empty sample. */
25
+ export const spreadOf = (values) => {
26
+ const median = medianOf(values);
27
+ if (median === undefined)
28
+ return undefined;
29
+ const deviations = values.map(value => quantity(Math.abs(value - median)));
30
+ return {
31
+ n: values.length,
32
+ median,
33
+ sigma: quantity(MAD_TO_SIGMA * (medianOf(deviations) ?? 0))
34
+ };
35
+ };
36
+ /** How far the value lies from the centre of the spread, in units of its scatter. */
37
+ export const standardise = (value, spread) => (value - spread.median) / spread.sigma;
38
+ /** The complementary error function, after Press et al., whose fractional error stays below 1.2e-7. */
39
+ const erfc = (x) => {
40
+ const z = Math.abs(x);
41
+ const t = 1 / (1 + z / 2);
42
+ const tail = t * Math.exp(-z * z - 1.26551223 + t * (1.00002368 + t * (0.37409196 + t * (0.09678418 +
43
+ t * (-0.18628806 + t * (0.27886807 + t * (-1.13520398 + t * (1.48851587 +
44
+ t * (-0.82215223 + t * 0.17087277)))))))));
45
+ return x >= 0 ? tail : 2 - tail;
46
+ };
47
+ /** The share of a normal sample lying below `z` standard deviations. */
48
+ export const normalBelow = (z) => erfc(-z / Math.SQRT2) / 2;
49
+ /** The share of a normal sample lying further than `z` standard deviations from its centre, on either side. */
50
+ export const normalBeyond = (z) => erfc(z / Math.SQRT2);
51
+ const horner = (coefficients, x) => coefficients.reduce((total, coefficient) => total * x + coefficient, 0);
52
+ const CENTRAL_NUMERATOR = [
53
+ -3.969683028665376e+01, 2.209460984245205e+02, -2.759285104469687e+02,
54
+ 1.383577518672690e+02, -3.066479806614716e+01, 2.506628277459239e+00
55
+ ];
56
+ const CENTRAL_DENOMINATOR = [
57
+ -5.447609879822406e+01, 1.615858368580409e+02, -1.556989798598866e+02,
58
+ 6.680131188771972e+01, -1.328068155288572e+01
59
+ ];
60
+ const TAIL_NUMERATOR = [
61
+ -7.784894002430293e-03, -3.223964580411365e-01, -2.400758277161838e+00,
62
+ -2.549732539343734e+00, 4.374664141464968e+00, 2.938163982698783e+00
63
+ ];
64
+ const TAIL_DENOMINATOR = [
65
+ 7.784695709041462e-03, 3.224671290700398e-01, 2.445134137142996e+00, 3.754408661907416e+00
66
+ ];
67
+ /** Outside this share the tail approximation is used in place of the central one. */
68
+ const CENTRAL_SHARE = 0.02425;
69
+ const tailQuantile = (share) => {
70
+ const q = Math.sqrt(-2 * Math.log(share));
71
+ return horner(TAIL_NUMERATOR, q) / (horner(TAIL_DENOMINATOR, q) * q + 1);
72
+ };
73
+ /**
74
+ * How many standard deviations out the given share of a normal sample
75
+ * lies below, after Acklam's rational approximation, whose relative
76
+ * error stays below 1.15e-9. The inverse of `normalBelow`.
77
+ */
78
+ export const normalQuantile = (share) => {
79
+ if (share <= 0)
80
+ return -Infinity;
81
+ if (share >= 1)
82
+ return Infinity;
83
+ if (share < CENTRAL_SHARE)
84
+ return tailQuantile(share);
85
+ if (share > 1 - CENTRAL_SHARE)
86
+ return -tailQuantile(1 - share);
87
+ const q = share - 0.5;
88
+ const r = q * q;
89
+ return horner(CENTRAL_NUMERATOR, r) * q / (horner(CENTRAL_DENOMINATOR, r) * r + 1);
90
+ };
91
+ /**
92
+ * How much heavier the tails of a standardised sample are than a normal
93
+ * sample's. Zero for a normal shape, positive where more of the sample
94
+ * lies far out than the curve allows.
95
+ */
96
+ export const excessKurtosisOf = (standardised) => standardised.reduce((total, z) => total + z ** 4, 0) / standardised.length - 3;
97
+ /** What the sample puts beyond the given distance, against what a normal sample would. */
98
+ export const tailOf = (standardised, beyond) => ({
99
+ beyond,
100
+ observed: standardised.filter(z => Math.abs(z) > beyond).length,
101
+ expected: standardised.length * normalBeyond(beyond)
102
+ });
103
+ /**
104
+ * The sample counted into bins of the given width, laid out on
105
+ * multiples of that width so that two histograms of one width share
106
+ * their bounds. Nothing for an empty sample or a width of nothing.
107
+ */
108
+ export const histogramOf = (values, binWidth) => {
109
+ if (values.length === 0 || binWidth <= 0)
110
+ return undefined;
111
+ const first = Math.floor(Math.min(...values) / binWidth) * binWidth;
112
+ const last = Math.ceil(Math.max(...values) / binWidth) * binWidth;
113
+ const bins = Math.max(1, Math.round((last - first) / binWidth));
114
+ return {
115
+ edges: Array.from({ length: bins + 1 }, (_, i) => quantity(first + i * binWidth)),
116
+ counts: values.reduce((tally, value) => {
117
+ tally[Math.min(bins - 1, Math.floor((value - first) / binWidth))] += 1;
118
+ return tally;
119
+ }, new Array(bins).fill(0))
120
+ };
121
+ };
@@ -1,7 +1,7 @@
1
- import { CollationTolerance, Locate } from "./Collation";
2
- import { AnySymbol, Expression } from "./Symbol";
3
- import { Millimeters, Track } from "./Quantity";
4
- import { TrackerBar } from "./TrackerBar";
1
+ import { CollationTolerance, Locate } from "./Collation.js";
2
+ import { AnySymbol, Expression } from "./Symbol.js";
3
+ import { Millimeters, Track } from "./Quantity.js";
4
+ import { TrackerBar } from "./TrackerBar.js";
5
5
  /**
6
6
  * How a scale words a function: as a command that turns it on, one that
7
7
  * cancels it, or one that holds it for as long as it lasts.
@@ -46,7 +46,7 @@ export interface Substitution {
46
46
  * 2.66 mm grid with bridges of about a millimetre, so a scan read hole
47
47
  * by hole shows a run where the paper shows one command.
48
48
  */
49
- export declare const defaultChainGap: import("./Quantity").Quantity<"mm">;
49
+ export declare const defaultChainGap: import("./Quantity.js").Quantity<"mm">;
50
50
  /**
51
51
  * The position a bar reads its own command for the same function on,
52
52
  * where it has no word for this one.
@@ -1,5 +1,5 @@
1
- import { defaultCollationTolerance } from "./Collation";
2
- import { distance, mm, track } from "./Quantity";
1
+ import { defaultCollationTolerance } from "./Collation.js";
2
+ import { distance, mm, track } from "./Quantity.js";
3
3
  /**
4
4
  * What each Welte expression type operates.
5
5
  *
@@ -1,5 +1,5 @@
1
- import { Concept } from "../Agent";
2
- import { TrackerBar } from "../TrackerBar";
1
+ import { Concept } from "../Agent.js";
2
+ import { TrackerBar } from "../TrackerBar.js";
3
3
  /** The tracker bars the library knows, the T-100 first as the usual one. */
4
4
  export declare const trackerBars: readonly TrackerBar[];
5
5
  /** The bar of a system the type vocabulary knows, from its concept. */
@@ -1,7 +1,7 @@
1
- import { systemIdOf } from "../TrackerBar";
2
- import { welteT100 } from "./welteT100/bar";
3
- import { welteLicensee } from "./welteLicensee/bar";
4
- import { welteT98 } from "./welteT98/bar";
1
+ import { systemIdOf } from "../TrackerBar.js";
2
+ import { welteT100 } from "./welteT100/bar.js";
3
+ import { welteLicensee } from "./welteLicensee/bar.js";
4
+ import { welteT98 } from "./welteT98/bar.js";
5
5
  /** The tracker bars the library knows, the T-100 first as the usual one. */
6
6
  export const trackerBars = [welteT100, welteLicensee, welteT98];
7
7
  /** The bar of a system the type vocabulary knows, from its concept. */
@@ -1,4 +1,4 @@
1
- import { TrackerBar } from "../../TrackerBar";
1
+ import { TrackerBar } from "../../TrackerBar.js";
2
2
  /**
3
3
  * Welte-Mignon (Licensee), the American re-cut of the T-100 rolls on
4
4
  * a roll 11¼ inches wide with 98 positions at nine to the inch, cf.
@@ -1,5 +1,5 @@
1
- import { describeTrackerBar } from "../../TrackerBar";
2
- import { mm } from "../../Quantity";
1
+ import { describeTrackerBar } from "../../TrackerBar.js";
2
+ import { mm } from "../../Quantity.js";
3
3
  /**
4
4
  * Welte-Mignon (Licensee), the American re-cut of the T-100 rolls on
5
5
  * a roll 11¼ inches wide with 98 positions at nine to the inch, cf.
@@ -1,5 +1,5 @@
1
- import { ReproducingSystem } from "../../ReproducingSystem";
2
- import { type WelteT100Options } from "../welteT100/system";
1
+ import { ReproducingSystem } from "../../ReproducingSystem.js";
2
+ import { type WelteT100Options } from "../welteT100/system.js";
3
3
  export type WelteLicenseeOptions = WelteT100Options;
4
4
  /**
5
5
  * The one instrument on offer, and it is not a Licensee instrument.
@@ -1,7 +1,7 @@
1
1
  import { CONSENSUS } from "welte-mignon-emulator/t100";
2
- import { track } from "../../Quantity";
3
- import { welteLicensee } from "./bar";
4
- import { defaultWelteT100Options, instrumentNameOf, nuanceOf, performAs } from "../welteT100/system";
2
+ import { track } from "../../Quantity.js";
3
+ import { welteLicensee } from "./bar.js";
4
+ import { defaultWelteT100Options, instrumentNameOf, nuanceOf, performAs } from "../welteT100/system.js";
5
5
  /**
6
6
  * The one instrument on offer, and it is not a Licensee instrument.
7
7
  *
@@ -1,4 +1,4 @@
1
- import { TrackerBar } from "../../TrackerBar";
1
+ import { TrackerBar } from "../../TrackerBar.js";
2
2
  /**
3
3
  * The commands of the Welte-Mignon T-100, as its tracker bar reads them.
4
4
  */
@@ -1,5 +1,5 @@
1
- import { describeTrackerBar } from "../../TrackerBar";
2
- import { metersPerMinute, mm } from "../../Quantity";
1
+ import { describeTrackerBar } from "../../TrackerBar.js";
2
+ import { metersPerMinute, mm } from "../../Quantity.js";
3
3
  /**
4
4
  * The commands of the Welte-Mignon T-100, as its tracker bar reads them.
5
5
  */
@@ -1,9 +1,9 @@
1
1
  import { Half, Parameters, PedalMode, Spool } from "welte-mignon-emulator";
2
2
  import { Instrument, RollNumber } from "welte-mignon-emulator/t100";
3
- import { NegotiatedEvent, Performance, ReproducingSystem, RollProperties } from "../../ReproducingSystem";
4
- import { Millimeters, Seconds, Track } from "../../Quantity";
5
- import { type VelocityMap } from "../velocity";
6
- export type { VelocityMap } from "../velocity";
3
+ import { NegotiatedEvent, Performance, ReproducingSystem, RollProperties } from "../../ReproducingSystem.js";
4
+ import { Millimeters, Seconds, Track } from "../../Quantity.js";
5
+ import { type VelocityMap } from "../velocity.js";
6
+ export type { VelocityMap } from "../velocity.js";
7
7
  export type { Instrument } from "welte-mignon-emulator/t100";
8
8
  export type InstrumentName = 'consensus' | RollNumber;
9
9
  /**
@@ -1,9 +1,9 @@
1
1
  import { DEFAULT_PUNCH_MM, geometryInMm, Grid, levelChanges, paperSeconds, pedalBrushing, pedalDefaults, ROWS_PER_MM, TRACKER_BORE_MM, WELTE_SPOOL, } from "welte-mignon-emulator";
2
2
  import { aperturePorts, CONSENSUS, mezzoforteTravel, pneumaticModel, PRESETS, runPedals, travelBetweenRails, } from "welte-mignon-emulator/t100";
3
- import { welteT100 } from "./bar";
4
- import { inCentimeters, mm, seconds, track } from "../../Quantity";
5
- import { partitionPoint } from "../../sorted";
6
- import { defaultVelocityMap, velocityOf } from "../velocity";
3
+ import { welteT100 } from "./bar.js";
4
+ import { inCentimeters, mm, seconds, track } from "../../Quantity.js";
5
+ import { partitionPoint } from "../../sorted.js";
6
+ import { defaultVelocityMap, velocityOf } from "../velocity.js";
7
7
  /**
8
8
  * The instruments the emulator was fitted as: the consensus over the six
9
9
  * rolls with drawn nuance lines, and the setting that drew each of them,
@@ -1,4 +1,4 @@
1
- import { TrackerBar } from "../../TrackerBar";
1
+ import { TrackerBar } from "../../TrackerBar.js";
2
2
  /**
3
3
  * The commands of the Welte-Mignon T-98, as its tracker bar reads them.
4
4
  *
@@ -1,5 +1,5 @@
1
- import { describeTrackerBar } from "../../TrackerBar";
2
- import { metersPerMinute, mm } from "../../Quantity";
1
+ import { describeTrackerBar } from "../../TrackerBar.js";
2
+ import { metersPerMinute, mm } from "../../Quantity.js";
3
3
  /**
4
4
  * The commands of the Welte-Mignon T-98, as its tracker bar reads them.
5
5
  *
@@ -1,9 +1,9 @@
1
1
  import { Half, Parameters, PedalMode, Spool } from "welte-mignon-emulator";
2
2
  import { instrumentT98Of, labelOf, nuanceOf, WelteT98InstrumentName } from "welte-mignon-emulator/t98";
3
- import { ReproducingSystem } from "../../ReproducingSystem";
4
- import { Millimeters, Seconds, Track } from "../../Quantity";
5
- import { type VelocityMap } from "../velocity";
6
- export type { VelocityMap } from "../velocity";
3
+ import { ReproducingSystem } from "../../ReproducingSystem.js";
4
+ import { Millimeters, Seconds, Track } from "../../Quantity.js";
5
+ import { type VelocityMap } from "../velocity.js";
6
+ export type { VelocityMap } from "../velocity.js";
7
7
  export type { WelteT98Instrument, WelteT98InstrumentName } from "welte-mignon-emulator/t98";
8
8
  /**
9
9
  * The instruments the emulator offers for the green Welte, in three groups that
@@ -1,9 +1,9 @@
1
1
  import { geometryInMm, Grid, levelChanges, mezzoforteTravel, paperSeconds, pedalBrushing, pedalDefaults, ROWS_PER_MM, travelBetweenRails, WELTE_T98_SPOOL, } from "welte-mignon-emulator";
2
2
  import { aperturePorts, CHAIN_GAP_MM, DERIVED, GENUINE, instrumentT98Of, labelOf, nuanceOf, PUNCH_T98_MM, pneumaticT98Model, rewindAt, runPedals, sforzandoPianoLift, STARTING_VALUES, TRACKER_BORE_T98_MM, } from "welte-mignon-emulator/t98";
3
- import { welteT98 } from "./bar";
4
- import { inCentimeters, mm, seconds, track } from "../../Quantity";
5
- import { partitionPoint } from "../../sorted";
6
- import { defaultVelocityMap, velocityOf } from "../velocity";
3
+ import { welteT98 } from "./bar.js";
4
+ import { inCentimeters, mm, seconds, track } from "../../Quantity.js";
5
+ import { partitionPoint } from "../../sorted.js";
6
+ import { defaultVelocityMap, velocityOf } from "../velocity.js";
7
7
  /**
8
8
  * The instruments the emulator offers for the green Welte, in three groups that
9
9
  * answer three different questions and must not be listed as one.
package/lib/utils.d.ts CHANGED
@@ -14,6 +14,8 @@ export type WithId = {
14
14
  };
15
15
  /** Whether a value is a date as the format writes one, `YYYY-MM-DD`. */
16
16
  export declare const isDateString: (value: unknown) => value is string;
17
+ /** The items by the key each of them gives, every group in the order its first item came in. */
18
+ export declare const groupBy: <T>(items: readonly T[], keyOf: (item: T) => string) => Map<string, T[]>;
17
19
  export type WithNote = {
18
20
  /**
19
21
  * A free-text note providing additional context.
package/lib/utils.js CHANGED
@@ -1,2 +1,12 @@
1
1
  /** Whether a value is a date as the format writes one, `YYYY-MM-DD`. */
2
2
  export const isDateString = (value) => typeof value === 'string' && /^\d{4}-\d{1,2}-\d{1,2}$/.test(value);
3
+ /** The items by the key each of them gives, every group in the order its first item came in. */
4
+ export const groupBy = (items, keyOf) => items.reduce((groups, item) => {
5
+ const key = keyOf(item);
6
+ const group = groups.get(key);
7
+ if (group)
8
+ group.push(item);
9
+ else
10
+ groups.set(key, [item]);
11
+ return groups;
12
+ }, new Map());
package/lib/validate.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { type ErrorObject } from "ajv";
2
- import { Edition } from "./Edition";
2
+ import { Edition } from "./Edition.js";
3
3
  /**
4
4
  * Holds a document against the edition schema. `errors` says what the
5
5
  * last call found wrong, and is empty where it found nothing.
package/lib/validate.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import Ajv from "ajv";
2
- import * as schema from "./schema.json";
2
+ import * as schema from "./schema.json" with { type: 'json' };
3
3
  const compileEditionSchema = () => new Ajv({ strict: false, formats: { "date": true } }).compile(schema);
4
4
  /**
5
5
  * Compiling costs enough that a consumer which never validates should not
@@ -1,4 +1,4 @@
1
- import { Concept } from "./Agent";
1
+ import { Concept } from "./Agent.js";
2
2
  /**
3
3
  * The concepts the type vocabulary declares, whatever kind they are:
4
4
  * the reproducing systems and the procedures. An edition names one of
package/lib/vocabulary.js CHANGED
@@ -1,6 +1,6 @@
1
- import { procedures } from "./procedures";
2
- import { systemOf } from "./TrackerBar";
3
- import { trackerBars } from "./systems";
1
+ import { procedures } from "./procedures.js";
2
+ import { systemOf } from "./TrackerBar.js";
3
+ import { trackerBars } from "./systems/index.js";
4
4
  /**
5
5
  * The concepts the type vocabulary declares, whatever kind they are:
6
6
  * the reproducing systems and the procedures. An edition names one of
@@ -1,5 +1,5 @@
1
- import { Belief, Certainty } from "./Assumption";
2
- import { EditionView } from "./EditionView";
1
+ import { Belief, Certainty } from "./Assumption.js";
2
+ import { EditionView } from "./EditionView.js";
3
3
  export type WitnessBy = 'carriers' | 'statement';
4
4
  /** A copy that bears witness to a version, and how. */
5
5
  export interface Witness {
package/lib/witnesses.js CHANGED
@@ -1,5 +1,5 @@
1
- import { certaintyOf, idOf, idsOf } from "./Assumption";
2
- import { insertedBy } from "./Version";
1
+ import { certaintyOf, idOf, idsOf } from "./Assumption.js";
2
+ import { insertedBy } from "./Version.js";
3
3
  /** The copies whose features carry any of the symbols. */
4
4
  const copiesCarrying = (view, symbols) => new Set(symbols
5
5
  .flatMap(symbol => idsOf(symbol.carriers))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "linked-rolls",
3
- "version": "0.43.0",
3
+ "version": "0.45.0",
4
4
  "description": "Digital editions of piano rolls: import, collation, editorial assumptions, JSON-LD export, and emulation through a reproducing system",
5
5
  "license": "MIT",
6
6
  "repository": {