linked-rolls 0.5.0 → 0.5.1

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 (41) hide show
  1. package/lib/Agent.d.ts +59 -0
  2. package/lib/Agent.js +1 -0
  3. package/lib/Assumption.d.ts +19 -1
  4. package/lib/Collation.d.ts +19 -0
  5. package/lib/Collation.js +25 -1
  6. package/lib/Edit.d.ts +1 -8
  7. package/lib/Edition.d.ts +4 -77
  8. package/lib/Edition.js +1 -1
  9. package/lib/EditionView.d.ts +0 -7
  10. package/lib/EditionView.js +0 -50
  11. package/lib/ReproducingSystem.d.ts +23 -1
  12. package/lib/RollCopy.d.ts +2 -68
  13. package/lib/RollCopy.js +2 -303
  14. package/lib/TrackerBar.d.ts +16 -14
  15. package/lib/TrackerBar.js +1 -56
  16. package/lib/alignment.d.ts +21 -0
  17. package/lib/alignment.js +117 -0
  18. package/lib/constraints.d.ts +27 -0
  19. package/lib/constraints.js +61 -0
  20. package/lib/editionOps.js +7 -10
  21. package/lib/index.d.ts +18 -13
  22. package/lib/index.js +18 -13
  23. package/lib/migrate.js +2 -1
  24. package/lib/readers/spencerMidi.d.ts +26 -0
  25. package/lib/readers/spencerMidi.js +58 -0
  26. package/lib/readers/stanfordAton.d.ts +18 -0
  27. package/lib/readers/stanfordAton.js +158 -0
  28. package/lib/systems/welteT100/bar.d.ts +14 -0
  29. package/lib/systems/welteT100/bar.js +56 -0
  30. package/lib/systems/{welteT100.d.ts → welteT100/system.d.ts} +1 -1
  31. package/lib/systems/{welteT100.js → welteT100/system.js} +1 -1
  32. package/lib/utils.d.ts +0 -8
  33. package/lib/validate.d.ts +0 -27
  34. package/lib/validate.js +0 -61
  35. package/package.json +3 -3
  36. package/lib/alignFeatures.d.ts +0 -12
  37. package/lib/alignFeatures.js +0 -55
  38. /package/lib/{aton → readers}/AtonParser.d.ts +0 -0
  39. /package/lib/{aton → readers}/AtonParser.js +0 -0
  40. /package/lib/{asMIDISpans.d.ts → readers/midiSpans.d.ts} +0 -0
  41. /package/lib/{asMIDISpans.js → readers/midiSpans.js} +0 -0
package/lib/Agent.d.ts ADDED
@@ -0,0 +1,59 @@
1
+ import { WithId } from "./utils";
2
+ /**
3
+ * Something with a name and, where one exists, an authority record.
4
+ */
5
+ export interface Named {
6
+ /**
7
+ * The name, e.g. "Grünfeld, Alfred", "Wien", "M. Welte & Söhne".
8
+ * @see rdfs:label
9
+ */
10
+ name: string;
11
+ /**
12
+ * Authority records for the same thing: GND, Wikidata,
13
+ * geonames or similar.
14
+ * @see owl:sameAs
15
+ * @example "https://d-nb.info/gnd/116888652"
16
+ */
17
+ sameAs: string[];
18
+ }
19
+ export declare const agentRoles: readonly ["pianist", "editor", "publisher"];
20
+ /**
21
+ * The role an agent plays in the context of the edition.
22
+ */
23
+ export type AgentRole = typeof agentRoles[number];
24
+ /**
25
+ * A person or a group: a pianist, an editor, a publisher,
26
+ * a manufacturer, a library.
27
+ * @see crm:E39 Actor
28
+ */
29
+ export interface Agent extends Named, Partial<WithId> {
30
+ /**
31
+ * The role of the agent in the context of the edition.
32
+ * @see crm:P2 has type
33
+ */
34
+ role?: AgentRole;
35
+ }
36
+ /**
37
+ * An agent that is a person.
38
+ */
39
+ export type Person = Agent;
40
+ export type WithActor = {
41
+ /**
42
+ * The person who carried out this activity.
43
+ * @see crm:P14 carried out by
44
+ */
45
+ actor?: Person;
46
+ };
47
+ /**
48
+ * A place, e.g. a recording location, publishing location, etc.
49
+ * @see crm:E53 Place
50
+ */
51
+ export interface Place extends Named {
52
+ }
53
+ /**
54
+ * A term from a vocabulary, such as a roll system or a kind of
55
+ * paper. A term the type vocabulary knows carries its IRI as `id`.
56
+ * @see crm:E55 Type
57
+ */
58
+ export interface Concept extends Named, Partial<WithId> {
59
+ }
package/lib/Agent.js ADDED
@@ -0,0 +1 @@
1
+ export const agentRoles = ['pianist', 'editor', 'publisher'];
@@ -1,4 +1,5 @@
1
- import { WithActor, WithNote, WithId } from "./utils";
1
+ import { WithNote, WithId } from "./utils";
2
+ import { Person, WithActor } from "./Agent";
2
3
  export declare const certainties: readonly ["true", "likely", "possible", "unlikely", "false"];
3
4
  /**
4
5
  * Certainty levels for beliefs, ranging from 'true' to 'false'
@@ -120,6 +121,23 @@ export type ReferenceAssumption = Assumption & WithId;
120
121
  * may be uncertain.
121
122
  */
122
123
  export type ObjectAssumption<O extends object> = Assumption & O;
124
+ /**
125
+ * An actor assignment associates a person with an action.
126
+ * It is an object assumption so that the attribution can be
127
+ * annotated with a belief about its certainty.
128
+ */
129
+ export type ActorAssignment = ObjectAssumption<Person>;
130
+ /**
131
+ * A date value wrapped as an assumption, so that the date
132
+ * can be annotated with a belief about its certainty and source.
133
+ */
134
+ export type DateAssignment = ValueAssumption<Date> & {
135
+ /**
136
+ * The datatype of the value. Written on export so that
137
+ * RDF reads the value as a date rather than a string.
138
+ */
139
+ '@type'?: 'xsd:date';
140
+ };
123
141
  export declare function valueOf<ValueT>(assumption: ValueAssumption<ValueT>): ValueT;
124
142
  export declare function valuesOf<ValueT>(assumptions: ValueAssumption<ValueT>[]): ValueT[];
125
143
  export declare function idOf(assumption: ReferenceAssumption): string;
@@ -1,3 +1,5 @@
1
+ import { HorizontalSpan } from "./Feature";
2
+ import { AnySymbol } from "./Symbol";
1
3
  /**
2
4
  * Tolerance used in collation of roll copies.
3
5
  * The start and end tolerances define the acceptable
@@ -13,3 +15,20 @@ export interface CollationTolerance {
13
15
  */
14
16
  toleranceEnd: number;
15
17
  }
18
+ export declare const defaultCollationTolerance: CollationTolerance;
19
+ /** Where a symbol lies along the roll, as its carriers put it, or nothing for a symbol without a place. */
20
+ export type Locate = (symbol: AnySymbol) => Readonly<{
21
+ horizontal: HorizontalSpan;
22
+ }> | undefined;
23
+ /**
24
+ * Two symbols collate when they are of one kind, say the same thing
25
+ * (pitch, or expression type and scope), and lie at about the same
26
+ * place along the roll.
27
+ */
28
+ export declare const isCollatable: (a: AnySymbol, b: AnySymbol, locate: Locate, tolerance?: CollationTolerance) => boolean;
29
+ export type Collation = {
30
+ symbol: Readonly<AnySymbol>;
31
+ counterpart: Readonly<AnySymbol>;
32
+ };
33
+ /** Each of the own symbols with every inherited symbol it collates with. */
34
+ export declare const collationsOf: (own: readonly Readonly<AnySymbol>[], inherited: readonly Readonly<AnySymbol>[], locate: Locate, tolerance?: CollationTolerance) => Collation[];
package/lib/Collation.js CHANGED
@@ -1 +1,25 @@
1
- export {};
1
+ export const defaultCollationTolerance = { toleranceStart: 5, toleranceEnd: 5 };
2
+ /**
3
+ * Two symbols collate when they are of one kind, say the same thing
4
+ * (pitch, or expression type and scope), and lie at about the same
5
+ * place along the roll.
6
+ */
7
+ export const isCollatable = (a, b, locate, tolerance = defaultCollationTolerance) => {
8
+ if (a.type !== b.type)
9
+ return false;
10
+ if (a.type === 'note' && b.type === 'note' && a.pitch !== b.pitch)
11
+ return false;
12
+ if (a.type === 'expression' && b.type === 'expression'
13
+ && (a.expressionType !== b.expressionType || a.scope !== b.scope))
14
+ return false;
15
+ const here = locate(a)?.horizontal;
16
+ const there = locate(b)?.horizontal;
17
+ if (!here || !there)
18
+ return false;
19
+ return Math.abs(here.from - there.from) <= tolerance.toleranceStart
20
+ && Math.abs(here.to - there.to) <= tolerance.toleranceEnd;
21
+ };
22
+ /** Each of the own symbols with every inherited symbol it collates with. */
23
+ export const collationsOf = (own, inherited, locate, tolerance = defaultCollationTolerance) => own.flatMap(symbol => inherited
24
+ .filter(candidate => isCollatable(symbol, candidate, locate, tolerance))
25
+ .map(counterpart => ({ symbol, counterpart })));
package/lib/Edit.d.ts CHANGED
@@ -1,5 +1,4 @@
1
- import { Assumption, ObjectAssumption } from "./Assumption";
2
- import { Person } from "./Edition";
1
+ import { Assumption } from "./Assumption";
3
2
  import { AnySymbol } from "./Symbol";
4
3
  import { WithId } from "./utils";
5
4
  export declare const editTypes: readonly ["short-dynamic-differentation", "additional-accent", "add-redundancy", "remove-redundancy", "replace-with-equivalent", "shift", "correct-error", "shorten", "prolong"];
@@ -9,12 +8,6 @@ export declare const editTypes: readonly ["short-dynamic-differentation", "addit
9
8
  * adds an accent, shifts a note, or shortens/prolongs a perforation.
10
9
  */
11
10
  export type EditType = typeof editTypes[number];
12
- /**
13
- * An actor assignment associates a person with an action.
14
- * It is an object assumption so that the attribution can be
15
- * annotated with a belief about its certainty.
16
- */
17
- export type ActorAssignment = ObjectAssumption<Person>;
18
11
  /**
19
12
  * A set of edits transforms a version of a roll into another version.
20
13
  * Edits insert or delete symbols, or both (= replace).
package/lib/Edition.d.ts CHANGED
@@ -1,59 +1,9 @@
1
- import { WithId } from "./utils";
2
- import { DateAssignment, RollCopy } from "./RollCopy";
1
+ import { RollCopy } from "./RollCopy";
3
2
  import { Version } from "./Version";
4
3
  import { CollationTolerance } from "./Collation";
5
- import { ObjectAssumption } from "./Assumption";
6
- /**
7
- * Something with a name and, where one exists, an authority record.
8
- */
9
- export interface Named {
10
- /**
11
- * The name, e.g. "Grünfeld, Alfred", "Wien", "M. Welte & Söhne".
12
- * @see rdfs:label
13
- */
14
- name: string;
15
- /**
16
- * Authority records for the same thing: GND, Wikidata,
17
- * geonames or similar.
18
- * @see owl:sameAs
19
- * @example "https://d-nb.info/gnd/116888652"
20
- */
21
- sameAs: string[];
22
- }
23
- export declare const agentRoles: readonly ["pianist", "editor", "publisher"];
24
- /**
25
- * The role an agent plays in the context of the edition.
26
- */
27
- export type AgentRole = typeof agentRoles[number];
28
- /**
29
- * A person or a group: a pianist, an editor, a publisher,
30
- * a manufacturer, a library.
31
- * @see crm:E39 Actor
32
- */
33
- export interface Agent extends Named, Partial<WithId> {
34
- /**
35
- * The role of the agent in the context of the edition.
36
- * @see crm:P2 has type
37
- */
38
- role?: AgentRole;
39
- }
40
- /**
41
- * An agent that is a person.
42
- */
43
- export type Person = Agent;
44
- /**
45
- * A place, e.g. a recording location, publishing location, etc.
46
- * @see crm:E53 Place
47
- */
48
- export interface Place extends Named {
49
- }
50
- /**
51
- * A term from a vocabulary, such as a roll system or a kind of
52
- * paper. A term the type vocabulary knows carries its IRI as `id`.
53
- * @see crm:E55 Type
54
- */
55
- export interface Concept extends Named, Partial<WithId> {
56
- }
4
+ import { DateAssignment, ObjectAssumption } from "./Assumption";
5
+ import { Concept, Person, Place } from "./Agent";
6
+ import { RollTempo } from "./ReproducingSystem";
57
7
  /**
58
8
  * This type describes the creation of an edition,
59
9
  * i.e. the editor, publisher, and publication date.
@@ -147,29 +97,6 @@ export interface Roll {
147
97
  */
148
98
  recordingEvent: RecordingEvent;
149
99
  }
150
- /**
151
- * The playback tempo of the roll, specified as a starting
152
- * and ending speed. The tempo may change over the course
153
- * of the roll due to acceleration effects.
154
- * @see crm:E54 Dimension
155
- */
156
- export interface RollTempo {
157
- /**
158
- * The tempo at the beginning of the roll.
159
- * @see reo:from
160
- */
161
- startsWith: number;
162
- /**
163
- * The tempo at the end of the roll.
164
- * @see reo:to
165
- */
166
- endsWith: number;
167
- /**
168
- * The unit of the tempo measurement (e.g. 'ft/min', 'm/min').
169
- * @see crm:P91 has unit
170
- */
171
- unit: string;
172
- }
173
100
  /**
174
101
  * Describes the specific digital edition of a piano roll.
175
102
  * @see lrmoo:F2 Expression
package/lib/Edition.js CHANGED
@@ -1 +1 @@
1
- export const agentRoles = ['pianist', 'editor', 'publisher'];
1
+ export {};
@@ -1,4 +1,3 @@
1
- import { CollationTolerance } from "./Collation";
2
1
  import { Edition } from "./Edition";
3
2
  import { HorizontalSpan, VerticalSpan, AnyFeature } from "./Feature";
4
3
  import { AnySymbol, Expression, Note } from "./Symbol";
@@ -20,11 +19,6 @@ export declare class EditionView {
20
19
  * Map from id to paths where it is referenced
21
20
  */
22
21
  private readonly links;
23
- /**
24
- * Dimensions cache: one frequent operation is to find the average
25
- * dimensions of a symbol based on its carriers. This cache stores
26
- * the computed dimensions for reuse.
27
- */
28
22
  constructor(edition: Edition);
29
23
  atPath<T>(path: Path): T | null;
30
24
  indexObjects(): void;
@@ -40,7 +34,6 @@ export declare class EditionView {
40
34
  vertical: VerticalSpan;
41
35
  }> | undefined;
42
36
  snapshot(versionId: string): readonly Readonly<AnySymbol>[];
43
- isCollatable(symbolA: AnySymbol, symbolB: AnySymbol, tolerance?: CollationTolerance): boolean;
44
37
  /**
45
38
  * Assigns a generation (depth) to every node.
46
39
  */
@@ -14,12 +14,6 @@ const referenceKeys = new Set([
14
14
  'motivation'
15
15
  ]);
16
16
  export class EditionView {
17
- /**
18
- * Dimensions cache: one frequent operation is to find the average
19
- * dimensions of a symbol based on its carriers. This cache stores
20
- * the computed dimensions for reuse.
21
- */
22
- //private readonly dimensionsCache: Map<string, { horizontal: HorizontalSpan, vertical: VerticalSpan }> = new Map()
23
17
  constructor(edition) {
24
18
  Object.defineProperty(this, "edition", {
25
19
  enumerable: true,
@@ -56,18 +50,7 @@ export class EditionView {
56
50
  });
57
51
  this.edition = edition;
58
52
  this.indexObjects();
59
- //this.buildDimensionsCache()
60
53
  }
61
- // private buildDimensionsCache() {
62
- // for (const version of this.edition.versions) {
63
- // for (const symbol of version.edits.flatMap(edit => edit.insert || [])) {
64
- // const dim = this.dimensionOf(symbol)
65
- // if (dim) {
66
- // this.dimensionsCache.set(symbol.id, dim)
67
- // }
68
- // }
69
- // }
70
- // }
71
54
  atPath(path) {
72
55
  const node = getAt(path, this.edition);
73
56
  return node || null;
@@ -163,9 +146,6 @@ export class EditionView {
163
146
  return this.get(idOf(v.basedOn));
164
147
  }
165
148
  dimensionOf(symbol) {
166
- // if (this.dimensionsCache.has(symbol.id)) {
167
- // return this.dimensionsCache.get(symbol.id);
168
- // }
169
149
  const carriers = this.getAll(idsOf(symbol.carriers));
170
150
  if (carriers.length === 0) {
171
151
  return;
@@ -211,36 +191,6 @@ export class EditionView {
211
191
  return (aDimension?.horizontal.from || 0) - (bDimension?.horizontal.from || 0);
212
192
  });
213
193
  }
214
- isCollatable(symbolA, symbolB, tolerance = {
215
- toleranceEnd: 5,
216
- toleranceStart: 5
217
- }) {
218
- // two symbols are collatible if they share the same
219
- // symbol characteristics (pitch, expression type etc.)
220
- // and occur in the same horizontal position.
221
- if (symbolA.type === 'note' && symbolB.type === 'note') {
222
- if (symbolA.pitch !== symbolB.pitch)
223
- return false;
224
- }
225
- else if (symbolA.type === 'expression' && symbolB.type === 'expression') {
226
- if (symbolA.expressionType !== symbolB.expressionType)
227
- return false;
228
- if (symbolA.scope !== symbolB.scope)
229
- return false;
230
- }
231
- const dimensionA = this.dimensionOf(symbolA);
232
- const dimensionB = this.dimensionOf(symbolB);
233
- if (!dimensionA || !dimensionB)
234
- return false;
235
- const distanceStart = Math.abs(dimensionA.horizontal.from - dimensionB.horizontal.from);
236
- const distanceEnd = Math.abs(dimensionA.horizontal.to - dimensionB.horizontal.to);
237
- if (distanceStart > tolerance.toleranceStart
238
- || distanceEnd > tolerance.toleranceEnd) {
239
- // the symbols are too far apart to be collated
240
- return false;
241
- }
242
- return true;
243
- }
244
194
  /**
245
195
  * Assigns a generation (depth) to every node.
246
196
  */
@@ -1,7 +1,29 @@
1
- import { RollTempo } from "./Edition";
2
1
  import { Hole } from "./Feature";
3
2
  import { Expression, Note } from "./Symbol";
4
3
  import { TrackerBar } from "./TrackerBar";
4
+ /**
5
+ * The playback tempo of the roll, specified as a starting
6
+ * and ending speed. The tempo may change over the course
7
+ * of the roll due to acceleration effects.
8
+ * @see crm:E54 Dimension
9
+ */
10
+ export interface RollTempo {
11
+ /**
12
+ * The tempo at the beginning of the roll.
13
+ * @see reo:from
14
+ */
15
+ startsWith: number;
16
+ /**
17
+ * The tempo at the end of the roll.
18
+ * @see reo:to
19
+ */
20
+ endsWith: number;
21
+ /**
22
+ * The unit of the tempo measurement (e.g. 'ft/min', 'm/min').
23
+ * @see crm:P91 has unit
24
+ */
25
+ unit: string;
26
+ }
5
27
  /**
6
28
  * A note or expression of a version with the dimensions of its carriers
7
29
  * averaged in and the editorial assumptions applied, which is all a
package/lib/RollCopy.d.ts CHANGED
@@ -3,10 +3,9 @@ import { AnySymbol } from "./Symbol";
3
3
  import { TrackerBar } from "./TrackerBar";
4
4
  import { TrackCalibration } from "./TrackCalibration";
5
5
  import { AnyFeature } from "./Feature";
6
- import { ObjectAssumption, ValueAssumption } from "./Assumption";
6
+ import { ActorAssignment, DateAssignment, ObjectAssumption } from "./Assumption";
7
7
  import { WithId, WithType } from "./utils";
8
- import { ActorAssignment } from "./Edit";
9
- import { Agent, Concept } from "./Edition";
8
+ import { Agent, Concept } from "./Agent";
10
9
  /**
11
10
  * This condition state is used to describe the roll's
12
11
  * paper shrinkage or stretching. It might be calculated
@@ -49,23 +48,6 @@ export interface Shift {
49
48
  */
50
49
  vertical: number;
51
50
  }
52
- export declare const applyShift: (shift: Shift, copy: RollCopy) => void;
53
- export declare const applyStretch: (paperStretch: ObjectAssumption<PaperStretch>, copy: RollCopy) => void;
54
- /** Takes the shift off the copy's features again, as far as one was applied. */
55
- export declare const revertShift: (copy: RollCopy) => void;
56
- /** Takes the stretch off the copy's features again, as far as one was applied. */
57
- export declare const revertStretch: (copy: RollCopy) => void;
58
- /**
59
- * A date value wrapped as an assumption, so that the date
60
- * can be annotated with a belief about its certainty and source.
61
- */
62
- export type DateAssignment = ValueAssumption<Date> & {
63
- /**
64
- * The datatype of the value. Written on export so that
65
- * RDF reads the value as a date rather than a string.
66
- */
67
- '@type'?: 'xsd:date';
68
- };
69
51
  /**
70
52
  * Describes the production of a roll copy: the manufacturer,
71
53
  * the paper used, and the date.
@@ -312,51 +294,3 @@ export declare function unreadTracks(features: AnyFeature[], bar?: TrackerBar):
312
294
  * calibration was written down; anything read since carries its own.
313
295
  */
314
296
  export declare const calibrationOf: (copy: RollCopy) => TrackCalibration | undefined;
315
- export interface StanfordAtonOptions {
316
- /**
317
- * Added to the scanning software's hole numbering to reach the
318
- * tracker bar. Left out, it is inferred by putting the rewind
319
- * perforation on the bar's rewind track.
320
- */
321
- trackShift?: number;
322
- bar?: TrackerBar;
323
- /**
324
- * Where the scan the analysis was made from can be seen. Stanford's
325
- * files name their scan by DRUID, so this is only needed for an
326
- * analysis of a scan hosted elsewhere.
327
- */
328
- scan?: string;
329
- }
330
- export declare function readFromStanfordAton(atonString: string, { trackShift, bar, scan }?: StanfordAtonOptions): RollCopy;
331
- /**
332
- * How a MIDI key number in one of Spencer Chase's roll files names a
333
- * tracker bar track.
334
- *
335
- * The note block follows the obvious rule, `pitch - 13`, which puts
336
- * track 11 on MIDI 24 as the T100 compass requires. The bass expression
337
- * block does not: it reads two tracks high, and subtracting two is what
338
- * has made these files come out right so far.
339
- *
340
- * The boundary between the two rules is unresolved. Taken literally the
341
- * rules leave tracks 8 and 9 unreachable and jump from track 7 to track 10,
342
- * which no lateral offset can produce, so at least one of them is
343
- * approximate. Settling it needs a Spencer file whose expression holes
344
- * can be checked against the roll, hence the option to override.
345
- */
346
- export declare const spencerTrackOf: (pitch: number) => number;
347
- /**
348
- * Spencer Chase's rolls seem to be scanned at a roll speed of
349
- * 83 (=8.3 feet per minute). A scanner feeds the paper at one
350
- * speed, so time in his files is proportional to place.
351
- */
352
- export declare const SPENCER_FEET_PER_MINUTE = 8.3;
353
- /** Place on the roll in mm after `seconds` at a constant `feetPerMinute`. */
354
- export declare const atConstantSpeed: (feetPerMinute: number) => (seconds: number) => number;
355
- export declare function readFromSpencerMIDI(midiBuffer: ArrayBuffer, placeAt?: (seconds: number) => number, trackOf?: (pitch: number) => number): RollCopy;
356
- /**
357
- * Moves features across the tracker bar. What the new position means is
358
- * left to the tracker bar to say, since meaning belongs to the symbols
359
- * read off a copy rather than to the holes themselves.
360
- */
361
- export declare function shiftVertically(features: AnyFeature[], amount: number): void;
362
- export declare const findCopiesCarrying: (sources: RollCopy[], symbol: AnySymbol) => Set<string>;