linked-rolls 0.64.0 → 0.66.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 +8 -0
- package/lib/analysis/constraints.js +31 -28
- package/lib/analysis/paper.d.ts +17 -0
- package/lib/analysis/paper.js +38 -1
- package/lib/analysis/reservations.js +2 -2
- package/lib/analysis/witnesses.js +6 -3
- package/lib/collation/alignment.js +55 -20
- package/lib/collation/scatter.d.ts +2 -2
- package/lib/io/asJsonLd.js +33 -38
- package/lib/io/migrate.js +73 -26
- package/lib/model/Agent.d.ts +17 -0
- package/lib/model/Assumption.d.ts +53 -8
- package/lib/model/Edition.d.ts +0 -13
- package/lib/model/FeatureSource.d.ts +2 -17
- package/lib/model/RollCopy.d.ts +36 -47
- package/lib/model/RollCopy.js +10 -0
- package/lib/model/Version.d.ts +30 -0
- package/lib/ops/collation.js +13 -9
- package/lib/ops/copies.js +11 -3
- package/lib/ops/immutable.d.ts +7 -1
- package/lib/ops/immutable.js +22 -8
- package/lib/readers/phillipsEroll.js +1 -8
- package/lib/readers/stanfordAton.js +20 -19
- package/lib/schema.json +297 -141
- package/lib/spec/context.json +12 -8
- package/lib/systems/welte.d.ts +21 -1
- package/lib/systems/welte.js +22 -4
- package/lib/systems/welteT100/system.d.ts +1 -16
- package/lib/systems/welteT100/system.js +3 -17
- package/lib/systems/welteT98/system.d.ts +1 -12
- package/lib/systems/welteT98/system.js +3 -13
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { WithNote, WithId } from "../shared/utils.js";
|
|
2
|
-
import { Person, WithActor } from "./Agent.js";
|
|
2
|
+
import { Concept, Person, Software, WithActor } from "./Agent.js";
|
|
3
3
|
export declare const certainties: readonly ['true', 'likely', 'possible', 'unlikely', 'false'];
|
|
4
4
|
/**
|
|
5
5
|
* Certainty levels for beliefs, ranging from 'true' to 'false'
|
|
@@ -102,6 +102,11 @@ export interface BeliefAdoption extends Argumentation<'beliefAdoption'> {
|
|
|
102
102
|
* premises. CRMinf counts observations, and a measurement is one, among
|
|
103
103
|
* the ways a belief comes about, so the value does not have to be
|
|
104
104
|
* passed off as an inference.
|
|
105
|
+
*
|
|
106
|
+
* A measurement a program took names the program and its version, so
|
|
107
|
+
* that the value can be taken again and a value taken by a program
|
|
108
|
+
* later found wanting can be told from the rest. Naming software makes
|
|
109
|
+
* it a digital measurement event in the sense of CRMdig.
|
|
105
110
|
* @see crmsci:S21 Measurement
|
|
106
111
|
*/
|
|
107
112
|
export interface Measurement extends Argumentation<'measurement'> {
|
|
@@ -111,6 +116,24 @@ export interface Measurement extends Argumentation<'measurement'> {
|
|
|
111
116
|
* @see crm:P16 used specific object
|
|
112
117
|
*/
|
|
113
118
|
used?: string[];
|
|
119
|
+
/**
|
|
120
|
+
* The method followed, where it has a name apart from the program
|
|
121
|
+
* that carries it out, such as a line of Theil and Sen through the
|
|
122
|
+
* matched notes of two copies.
|
|
123
|
+
* @see crm:P33 used specific technique
|
|
124
|
+
*/
|
|
125
|
+
procedure?: Concept;
|
|
126
|
+
/**
|
|
127
|
+
* The programs that took the measurement, each with its version.
|
|
128
|
+
* @see crmdig:L23 used software or firmware
|
|
129
|
+
*/
|
|
130
|
+
software?: Software[];
|
|
131
|
+
/**
|
|
132
|
+
* When the measurement was taken. It is part of the reason and
|
|
133
|
+
* carries no belief of its own.
|
|
134
|
+
* @see crm:P4 has time-span
|
|
135
|
+
*/
|
|
136
|
+
date?: TimeSpan;
|
|
114
137
|
}
|
|
115
138
|
/**
|
|
116
139
|
* An argumentation can be either a plain argumentation, a
|
|
@@ -185,7 +208,6 @@ export type ObjectAssumption<O extends object> = Assumption & O;
|
|
|
185
208
|
* annotated with a belief about its certainty.
|
|
186
209
|
*/
|
|
187
210
|
export type ActorAssignment = ObjectAssumption<Person>;
|
|
188
|
-
/** The day an event falls within. */
|
|
189
211
|
interface DateWithin {
|
|
190
212
|
/**
|
|
191
213
|
* The day the event falls within.
|
|
@@ -194,8 +216,7 @@ interface DateWithin {
|
|
|
194
216
|
*/
|
|
195
217
|
within: Date;
|
|
196
218
|
}
|
|
197
|
-
|
|
198
|
-
interface DateBounds {
|
|
219
|
+
interface DateAfter {
|
|
199
220
|
/**
|
|
200
221
|
* The earliest day the event can have happened on: it did not
|
|
201
222
|
* happen before it.
|
|
@@ -203,6 +224,22 @@ interface DateBounds {
|
|
|
203
224
|
* @see crm:P82a begin of the begin
|
|
204
225
|
*/
|
|
205
226
|
after: Date;
|
|
227
|
+
/**
|
|
228
|
+
* The latest day the event can have happened on: it did not
|
|
229
|
+
* happen after it.
|
|
230
|
+
* @format date
|
|
231
|
+
* @see crm:P82b end of the end
|
|
232
|
+
*/
|
|
233
|
+
before?: Date;
|
|
234
|
+
}
|
|
235
|
+
interface DateBefore {
|
|
236
|
+
/**
|
|
237
|
+
* The earliest day the event can have happened on: it did not
|
|
238
|
+
* happen before it.
|
|
239
|
+
* @format date
|
|
240
|
+
* @see crm:P82a begin of the begin
|
|
241
|
+
*/
|
|
242
|
+
after?: Date;
|
|
206
243
|
/**
|
|
207
244
|
* The latest day the event can have happened on: it did not
|
|
208
245
|
* happen after it.
|
|
@@ -212,12 +249,20 @@ interface DateBounds {
|
|
|
212
249
|
before: Date;
|
|
213
250
|
}
|
|
214
251
|
/**
|
|
215
|
-
* When something happened
|
|
216
|
-
*
|
|
217
|
-
*
|
|
252
|
+
* When something happened: the day it falls `within`, or the bounds it
|
|
253
|
+
* lies between. A bound nobody can give is left out, so `after` alone
|
|
254
|
+
* says "not before".
|
|
255
|
+
* @see crm:E52 Time-Span
|
|
256
|
+
*/
|
|
257
|
+
export type TimeSpan = DateWithin | DateAfter | DateBefore;
|
|
258
|
+
/**
|
|
259
|
+
* When something happened, as far as the edition can state it, and as
|
|
260
|
+
* an assumption, so that a dating can carry the belief it rests on: the
|
|
261
|
+
* day it falls `within`, or the bounds it lies between. A bound nobody
|
|
262
|
+
* can give is left out, so `after` alone says "not before".
|
|
218
263
|
* @see crm:E52 Time-Span
|
|
219
264
|
*/
|
|
220
|
-
export type DateAssignment = Assumption &
|
|
265
|
+
export type DateAssignment = Assumption & TimeSpan;
|
|
221
266
|
export declare function valueOf<ValueT>(assumption: ValueAssumption<ValueT>): ValueT;
|
|
222
267
|
export declare function valuesOf<ValueT>(assumptions: ValueAssumption<ValueT>[]): ValueT[];
|
|
223
268
|
export declare function idOf(assumption: ReferenceAssumption): string;
|
package/lib/model/Edition.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { RollCopy } from "./RollCopy.js";
|
|
2
2
|
import { Version } from "./Version.js";
|
|
3
|
-
import { CollationTolerance } from "../collation/Collation.js";
|
|
4
3
|
import { DateAssignment, ObjectAssumption } from "./Assumption.js";
|
|
5
4
|
import { Editor, Person, Place } from "./Agent.js";
|
|
6
5
|
import { RollTempo } from "../systems/ReproducingSystem.js";
|
|
@@ -28,18 +27,6 @@ export interface EditionCreation {
|
|
|
28
27
|
* @see dcterms:date
|
|
29
28
|
*/
|
|
30
29
|
publicationDate: Date;
|
|
31
|
-
/**
|
|
32
|
-
* The tolerance every version of the edition was collated at,
|
|
33
|
-
* before each derivation stated its own. How precisely two copies
|
|
34
|
-
* place a symbol depends on which two they are, so the tolerance
|
|
35
|
-
* belongs to the derivation, `Derivation.collationTolerance`, and
|
|
36
|
-
* migration writes this one onto every derivation that gives none.
|
|
37
|
-
* Nothing else reads it. A window's offset is the displacement
|
|
38
|
-
* between two particular copies and so can never be stated here.
|
|
39
|
-
* Not exported to RDF.
|
|
40
|
-
* @deprecated
|
|
41
|
-
*/
|
|
42
|
-
collationTolerance?: CollationTolerance;
|
|
43
30
|
}
|
|
44
31
|
/**
|
|
45
32
|
* Describes the event of recording and documents
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ActorAssignment, DateAssignment, ObjectAssumption } from "./Assumption.js";
|
|
2
|
-
import { Concept, Named } from "./Agent.js";
|
|
2
|
+
import { Concept, Named, Software } from "./Agent.js";
|
|
3
3
|
import { ConditionState } from "./ConditionState.js";
|
|
4
4
|
import { WithNote } from "../shared/utils.js";
|
|
5
5
|
/**
|
|
@@ -25,22 +25,7 @@ export declare const isMeasured: (kind: SourceKind) => boolean;
|
|
|
25
25
|
* be observed on the roll and on an image of it, and on nothing else.
|
|
26
26
|
*/
|
|
27
27
|
export declare const bearsPhysicalEvidence: (kind: SourceKind) => boolean;
|
|
28
|
-
|
|
29
|
-
* Software a capture ran, such as the transcriber that read a recording
|
|
30
|
-
* into notes or the emulator that wrote a MIDI file.
|
|
31
|
-
* @see crmdig:D14 Software
|
|
32
|
-
*/
|
|
33
|
-
export interface Software {
|
|
34
|
-
/**
|
|
35
|
-
* @see rdfs:label
|
|
36
|
-
*/
|
|
37
|
-
name: string;
|
|
38
|
-
/**
|
|
39
|
-
* The release, or the model checkpoint of a transcriber.
|
|
40
|
-
* @see owl:versionInfo
|
|
41
|
-
*/
|
|
42
|
-
version?: string;
|
|
43
|
-
}
|
|
28
|
+
export type { Software } from "./Agent.js";
|
|
44
29
|
/**
|
|
45
30
|
* An instrument a copy was played on to be recorded. How it was
|
|
46
31
|
* regulated, where that is known, is its condition.
|
package/lib/model/RollCopy.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { TrackCalibration } from "./TrackCalibration.js";
|
|
|
5
5
|
import { AnyFeature, FeatureOrPatch, HorizontalSpan, Patch } from "./Feature.js";
|
|
6
6
|
import { ActorAssignment, DateAssignment, ObjectAssumption, ReferenceAssumption } from "./Assumption.js";
|
|
7
7
|
import { WithId, WithType } from "../shared/utils.js";
|
|
8
|
-
import { Agent, Concept } from "./Agent.js";
|
|
8
|
+
import { Agent, Concept, Software } from "./Agent.js";
|
|
9
9
|
import { FeatureSource } from "./FeatureSource.js";
|
|
10
10
|
import { Measure, Millimeters, Percent, Quantity, Track } from "./Quantity.js";
|
|
11
11
|
import { Perforator } from "./Perforator.js";
|
|
@@ -161,6 +161,28 @@ export interface Alignment {
|
|
|
161
161
|
date: Date;
|
|
162
162
|
};
|
|
163
163
|
}
|
|
164
|
+
/**
|
|
165
|
+
* The width and length of a roll copy's paper, as they were measured on
|
|
166
|
+
* it or on its scan.
|
|
167
|
+
* @see crm:E54 Dimension
|
|
168
|
+
*/
|
|
169
|
+
export interface RollDimensions {
|
|
170
|
+
/**
|
|
171
|
+
* The width of the roll.
|
|
172
|
+
* @see reo:width
|
|
173
|
+
*/
|
|
174
|
+
width: Millimeters;
|
|
175
|
+
/**
|
|
176
|
+
* The total height (length) of the roll.
|
|
177
|
+
* @see reo:height
|
|
178
|
+
*/
|
|
179
|
+
height: Millimeters;
|
|
180
|
+
/**
|
|
181
|
+
* The unit of measurement.
|
|
182
|
+
* @see crm:P91 has unit
|
|
183
|
+
*/
|
|
184
|
+
unit: 'mm';
|
|
185
|
+
}
|
|
164
186
|
/** The margins on the treble and bass sides of the roll, in the unit the scan was measured in. */
|
|
165
187
|
export interface Margins<U extends 'px' | 'mm'> {
|
|
166
188
|
treble: Quantity<U>;
|
|
@@ -307,11 +329,14 @@ export type Modification = Partial<{
|
|
|
307
329
|
*/
|
|
308
330
|
export interface RollCopy extends WithType<'RollCopy'>, WithId {
|
|
309
331
|
/**
|
|
310
|
-
* Physical measurements of this roll copy,
|
|
311
|
-
*
|
|
312
|
-
* edition's axis
|
|
313
|
-
*
|
|
314
|
-
*
|
|
332
|
+
* Physical measurements of this roll copy: its dimensions, hole
|
|
333
|
+
* separation and margins, the resolution of its scan, and how it
|
|
334
|
+
* lies on the edition's axis. What the perforations tell about the
|
|
335
|
+
* machine that cut them is stated with the production.
|
|
336
|
+
*
|
|
337
|
+
* A value the edition exports is an object assumption, so that it
|
|
338
|
+
* can say what took it: a measurement naming the program and its
|
|
339
|
+
* version, the scan or analysis it was taken on, and the day.
|
|
315
340
|
* @see crm:P39i was measured by
|
|
316
341
|
*/
|
|
317
342
|
measurements: Partial<{
|
|
@@ -319,23 +344,7 @@ export interface RollCopy extends WithType<'RollCopy'>, WithId {
|
|
|
319
344
|
* The physical dimensions of the roll.
|
|
320
345
|
* @see reo:dimensions
|
|
321
346
|
*/
|
|
322
|
-
dimensions:
|
|
323
|
-
/**
|
|
324
|
-
* The width of the roll.
|
|
325
|
-
* @see reo:width
|
|
326
|
-
*/
|
|
327
|
-
width: Millimeters;
|
|
328
|
-
/**
|
|
329
|
-
* The total height (length) of the roll.
|
|
330
|
-
* @see reo:height
|
|
331
|
-
*/
|
|
332
|
-
height: Millimeters;
|
|
333
|
-
/**
|
|
334
|
-
* The unit of measurement.
|
|
335
|
-
* @see crm:P91 has unit
|
|
336
|
-
*/
|
|
337
|
-
unit: 'mm';
|
|
338
|
-
};
|
|
347
|
+
dimensions: ObjectAssumption<RollDimensions>;
|
|
339
348
|
/**
|
|
340
349
|
* The distance across the roll from the centre of one track to
|
|
341
350
|
* the next, the track pitch or Teilung, in the unit the scan was
|
|
@@ -344,7 +353,7 @@ export interface RollCopy extends WithType<'RollCopy'>, WithId {
|
|
|
344
353
|
* along the roll.
|
|
345
354
|
* @see reo:holeSeparation
|
|
346
355
|
*/
|
|
347
|
-
holeSeparation: Measure<'px'> | Measure<'mm'
|
|
356
|
+
holeSeparation: ObjectAssumption<Measure<'px'> | Measure<'mm'>>;
|
|
348
357
|
/**
|
|
349
358
|
* The margins on the treble and bass sides of the roll.
|
|
350
359
|
* Not exported to RDF.
|
|
@@ -389,35 +398,13 @@ export interface RollCopy extends WithType<'RollCopy'>, WithId {
|
|
|
389
398
|
* files do not state.
|
|
390
399
|
* @see reo:scanResolution
|
|
391
400
|
*/
|
|
392
|
-
scanResolution: Measure<'px/in'
|
|
401
|
+
scanResolution: ObjectAssumption<Measure<'px/in'>>;
|
|
393
402
|
/**
|
|
394
403
|
* Relates this copy's scan to the tracker bar: how the scanning
|
|
395
404
|
* software's hole numbering was shifted onto the bar, and where
|
|
396
405
|
* the track grid sits in the image. Not exported to RDF.
|
|
397
406
|
*/
|
|
398
407
|
trackCalibration: TrackCalibration;
|
|
399
|
-
/**
|
|
400
|
-
* Information about the software used to take the measurements.
|
|
401
|
-
* @see crmdig:L23 used software or firmware
|
|
402
|
-
*/
|
|
403
|
-
measuredBy: {
|
|
404
|
-
/**
|
|
405
|
-
* The name of the measurement software.
|
|
406
|
-
* @see rdfs:label
|
|
407
|
-
*/
|
|
408
|
-
software: string;
|
|
409
|
-
/**
|
|
410
|
-
* The version of the measurement software.
|
|
411
|
-
* @see owl:versionInfo
|
|
412
|
-
*/
|
|
413
|
-
version: string;
|
|
414
|
-
/**
|
|
415
|
-
* The date on which the measurements were taken.
|
|
416
|
-
* @format date
|
|
417
|
-
* @see dcterms:date
|
|
418
|
-
*/
|
|
419
|
-
date: Date;
|
|
420
|
-
};
|
|
421
408
|
}>;
|
|
422
409
|
/**
|
|
423
410
|
* The production event that created this roll copy.
|
|
@@ -496,6 +483,8 @@ export declare const statesNothing: (modification: Modification) => boolean;
|
|
|
496
483
|
export declare const featuresByAct: (copy: Pick<RollCopy, 'production' | 'modifications'>) => FeatureOrPatch[][];
|
|
497
484
|
/** Every feature the copy states at a place of its own, whichever act made it. */
|
|
498
485
|
export declare const featuresOf: (copy: Pick<RollCopy, 'production' | 'modifications'>) => FeatureOrPatch[];
|
|
486
|
+
/** The programs the measurements of a copy name as having taken them, each once, as far as they name any. */
|
|
487
|
+
export declare const measuringSoftwareOf: (copy: Pick<RollCopy, 'measurements'>) => Software[];
|
|
499
488
|
/** Whether the condition is the stretch or shrinkage of the paper, as measured on the copy. */
|
|
500
489
|
export declare const isPaperStretch: (condition: RollConditionAssignment) => condition is ObjectAssumption<PaperStretch>;
|
|
501
490
|
/** What the copy's paper was measured to have done, where anything was measured. */
|
package/lib/model/RollCopy.js
CHANGED
|
@@ -35,6 +35,16 @@ export const statesNothing = (modification) => modification.type === 'Removal' ?
|
|
|
35
35
|
export const featuresByAct = (copy) => [copy.production?.produced ?? [], ...copy.modifications.map(featuresMadeBy)];
|
|
36
36
|
/** Every feature the copy states at a place of its own, whichever act made it. */
|
|
37
37
|
export const featuresOf = (copy) => featuresByAct(copy).flat();
|
|
38
|
+
/** The measurements of a copy the edition exports, each of which can say what took it. */
|
|
39
|
+
const exportedMeasurementsOf = (copy) => [copy.measurements.dimensions, copy.measurements.holeSeparation, copy.measurements.scanResolution]
|
|
40
|
+
.filter(value => value !== undefined);
|
|
41
|
+
/** The programs the measurements of a copy name as having taken them, each once, as far as they name any. */
|
|
42
|
+
export const measuringSoftwareOf = (copy) => {
|
|
43
|
+
const named = exportedMeasurementsOf(copy)
|
|
44
|
+
.flatMap(value => value['@annotation']?.belief.reasons ?? [])
|
|
45
|
+
.flatMap(reason => reason.type === 'measurement' ? reason.software ?? [] : []);
|
|
46
|
+
return [...new Map(named.map(software => [`${software.name}\u0000${software.version ?? ''}`, software])).values()];
|
|
47
|
+
};
|
|
38
48
|
/** Whether the condition is the stretch or shrinkage of the paper, as measured on the copy. */
|
|
39
49
|
export const isPaperStretch = (condition) => condition.conditionType === 'paper-stretch';
|
|
40
50
|
/** What the copy's paper was measured to have done, where anything was measured. */
|
package/lib/model/Version.d.ts
CHANGED
|
@@ -33,6 +33,23 @@ export type Derivation = ReferenceAssumption & {
|
|
|
33
33
|
};
|
|
34
34
|
/** The tolerance the derivation was collated at, or the default where it states none. */
|
|
35
35
|
export declare const collationToleranceOf: (derivation: Readonly<Derivation>) => CollationTolerance;
|
|
36
|
+
/**
|
|
37
|
+
* How long a version's paper runs for a length of the paper of the
|
|
38
|
+
* version it derives from: about 0.77 for a Licensee or green re-cut of
|
|
39
|
+
* a red roll, cut for a slower paper speed.
|
|
40
|
+
* @see crm:E54 Dimension
|
|
41
|
+
*/
|
|
42
|
+
export interface LengthRatio {
|
|
43
|
+
/**
|
|
44
|
+
* @see crm:P90 has value
|
|
45
|
+
*/
|
|
46
|
+
value: number;
|
|
47
|
+
/**
|
|
48
|
+
* The standard uncertainty of the value, one standard deviation.
|
|
49
|
+
* @see reo:uncertainty
|
|
50
|
+
*/
|
|
51
|
+
uncertainty?: number;
|
|
52
|
+
}
|
|
36
53
|
/**
|
|
37
54
|
* How a version was made, where that is known and worth stating.
|
|
38
55
|
*
|
|
@@ -63,6 +80,19 @@ export interface VersionCreation {
|
|
|
63
80
|
* @see crm:P33 used specific technique
|
|
64
81
|
*/
|
|
65
82
|
procedure?: Concept;
|
|
83
|
+
/**
|
|
84
|
+
* How long the act made the version's paper for a length of the
|
|
85
|
+
* paper of the version it derives from. A re-cut for a system whose
|
|
86
|
+
* paper runs slower comes out shorter by the ratio of the speeds,
|
|
87
|
+
* and the alignments of the copies measure that ratio more closely
|
|
88
|
+
* than any label states a speed (`lengthRatioOf`). It is stated
|
|
89
|
+
* where the edition holds to it, as a measurement naming the copies
|
|
90
|
+
* it used and the program that found it, so that it can serve as a
|
|
91
|
+
* premise. A speed follows from it only together with a premise
|
|
92
|
+
* about the speed of the other version.
|
|
93
|
+
* @see reo:lengthRatio
|
|
94
|
+
*/
|
|
95
|
+
lengthRatio?: ObjectAssumption<LengthRatio>;
|
|
66
96
|
}
|
|
67
97
|
/**
|
|
68
98
|
* A version is defined by the sum of edits applied to the version it is
|
package/lib/ops/collation.js
CHANGED
|
@@ -5,7 +5,7 @@ import { collationToleranceOf, derivesFrom, editsOf, insertedBy, principalDeriva
|
|
|
5
5
|
import { substitutionsBetween } from "../collation/substitution.js";
|
|
6
6
|
import { trackerBarOf } from "../systems/index.js";
|
|
7
7
|
import { assignReference, idOf } from "../model/Assumption.js";
|
|
8
|
-
import { noChange, onVersion,
|
|
8
|
+
import { noChange, onVersion, insertion, deletion, asUnchecked, declaring, dropInsertions, reading } from "./draft.js";
|
|
9
9
|
import { hypothesesBeside } from "./versions.js";
|
|
10
10
|
import { placeOf, snapshotOf } from "../analysis/text.js";
|
|
11
11
|
import { copyOfFeature, versionIn } from "../lookup/lookup.js";
|
|
@@ -114,14 +114,18 @@ export const connectVersions = (childId, parentId, tolerance = defaultCollationT
|
|
|
114
114
|
.filter(symbol => !matched.has(symbol.id) && !paired.has(symbol.id))
|
|
115
115
|
.map(symbol => asUnchecked(deletion(symbol.id)))
|
|
116
116
|
];
|
|
117
|
-
|
|
117
|
+
// Read off the child as it stands, since once its edits are written a
|
|
118
|
+
// reading of it would copy them all.
|
|
119
|
+
const motivations = declaring(child?.motivations ?? [], edits);
|
|
120
|
+
const basedOn = [
|
|
121
|
+
{ ...assignReference(parentId), collationTolerance: tolerance },
|
|
122
|
+
...(child ? hypothesesBeside(child, parentId) : [])
|
|
123
|
+
];
|
|
124
|
+
return onVersion(childId, (version, draft) => {
|
|
118
125
|
handOverCarriers(edition, draft, collations);
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
{ ...assignReference(parentId), collationTolerance: tolerance },
|
|
123
|
-
...hypothesesBeside(stateOf(child), parentId)
|
|
124
|
-
];
|
|
126
|
+
version.edits = edits;
|
|
127
|
+
version.motivations = motivations;
|
|
128
|
+
version.basedOn = basedOn;
|
|
125
129
|
});
|
|
126
130
|
});
|
|
127
131
|
/**
|
|
@@ -135,7 +139,7 @@ export const collateSymbols = (versionId, symbolIds, tolerance) => reading(editi
|
|
|
135
139
|
if (!version || !principal)
|
|
136
140
|
return noChange;
|
|
137
141
|
const chosen = new Set(symbolIds);
|
|
138
|
-
const own =
|
|
142
|
+
const own = insertedBy(version).filter(symbol => chosen.has(symbol.id));
|
|
139
143
|
const collations = collationsOf(own, snapshotOf(edition, idOf(principal)), symbol => placeOf(edition, symbol), tolerance ?? collationToleranceOf(principal));
|
|
140
144
|
const collated = new Set(collations.map(({ symbol }) => symbol.id));
|
|
141
145
|
return onVersion(versionId, (version, draft) => {
|
package/lib/ops/copies.js
CHANGED
|
@@ -83,9 +83,17 @@ export const alignCopies = (date = new Date()) => draft => {
|
|
|
83
83
|
const own = draft.copies.find(c => c.id === reference.id);
|
|
84
84
|
if (own)
|
|
85
85
|
revertAlignment(own);
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
86
|
+
// Aligning a copy moves neither the reference copy nor any other,
|
|
87
|
+
// so every copy is aligned from the one state. Read afresh after
|
|
88
|
+
// each, the draft would be copied with every copy aligned so far.
|
|
89
|
+
const state = stateOf(draft);
|
|
90
|
+
state.copies.forEach((copy, i) => {
|
|
91
|
+
if (copy.id === reference.id || featuresOf(copy).length === 0)
|
|
92
|
+
return;
|
|
93
|
+
const alignment = alignmentFor(state, copy, date);
|
|
94
|
+
if (alignment)
|
|
95
|
+
applyAlignment(alignment, draft.copies[i]);
|
|
96
|
+
});
|
|
89
97
|
};
|
|
90
98
|
/**
|
|
91
99
|
* Makes the copy the one whose millimetres are the edition's axis, and
|
package/lib/ops/immutable.d.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
/** Rewritings that return the very object they were given wherever they change nothing, so that an immer draft is left untouched there. */
|
|
2
2
|
/** The items that do not match, or the very same array when none does, so that a draft stays untouched. */
|
|
3
3
|
export declare const without: <T>(items: T[], matches: (item: T) => boolean) => T[];
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* The items each changed, or the very same array when the change left
|
|
6
|
+
* every one as it was. The array is copied at the first item that
|
|
7
|
+
* changes, so that one left as it was costs no copy.
|
|
8
|
+
*/
|
|
5
9
|
export declare const mapped: <T>(items: T[], change: (item: T) => T) => T[];
|
|
6
10
|
/** The items each changed, less those the change emptied; the very same array where it changed none. */
|
|
7
11
|
export declare const pruned: <T>(items: T[], change: (item: T) => T, emptied: (item: T) => boolean) => T[];
|
|
@@ -10,6 +14,8 @@ export declare const replacing: <T extends object, K extends keyof T>(record: T,
|
|
|
10
14
|
/** A record of the edition, as the walk over it sees one. */
|
|
11
15
|
export type Node = Record<string, unknown>;
|
|
12
16
|
export declare const isRecord: (value: unknown) => value is Node;
|
|
17
|
+
/** The record's values each changed, or the very same record where the change left every one as it was, copied as `mapped` copies. */
|
|
18
|
+
export declare const withValues: (record: Node, change: (value: unknown) => unknown) => Node;
|
|
13
19
|
/** The value with the change applied to every record within it and then to itself, innermost first. */
|
|
14
20
|
export declare const deeply: (change: (record: object) => object) => (value: unknown) => unknown;
|
|
15
21
|
/** Writes onto the draft what the rewriting changed, as deep as the change reaches. */
|
package/lib/ops/immutable.js
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
/** Rewritings that return the very object they were given wherever they change nothing, so that an immer draft is left untouched there. */
|
|
2
2
|
/** The items that do not match, or the very same array when none does, so that a draft stays untouched. */
|
|
3
3
|
export const without = (items, matches) => items.some(matches) ? items.filter(item => !matches(item)) : items;
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* The items each changed, or the very same array when the change left
|
|
6
|
+
* every one as it was. The array is copied at the first item that
|
|
7
|
+
* changes, so that one left as it was costs no copy.
|
|
8
|
+
*/
|
|
5
9
|
export const mapped = (items, change) => {
|
|
6
|
-
|
|
7
|
-
|
|
10
|
+
let changed;
|
|
11
|
+
items.forEach((item, i) => {
|
|
12
|
+
const after = change(item);
|
|
13
|
+
if (after !== item)
|
|
14
|
+
(changed ?? (changed = items.slice()))[i] = after;
|
|
15
|
+
});
|
|
16
|
+
return changed ?? items;
|
|
8
17
|
};
|
|
9
18
|
/** The items each changed, less those the change emptied; the very same array where it changed none. */
|
|
10
19
|
export const pruned = (items, change, emptied) => {
|
|
@@ -14,11 +23,16 @@ export const pruned = (items, change, emptied) => {
|
|
|
14
23
|
/** The record with the field replaced, or the very same record where that is what stood there. */
|
|
15
24
|
export const replacing = (record, key, value) => record[key] === value ? record : { ...record, [key]: value };
|
|
16
25
|
export const isRecord = (value) => typeof value === 'object' && value !== null;
|
|
17
|
-
/** The record's values each changed, or the very same record where the change left every one as it was. */
|
|
18
|
-
const withValues = (record, change) => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
26
|
+
/** The record's values each changed, or the very same record where the change left every one as it was, copied as `mapped` copies. */
|
|
27
|
+
export const withValues = (record, change) => {
|
|
28
|
+
let changed;
|
|
29
|
+
Object.keys(record).forEach(key => {
|
|
30
|
+
const value = record[key];
|
|
31
|
+
const after = change(value);
|
|
32
|
+
if (after !== value)
|
|
33
|
+
(changed ?? (changed = { ...record }))[key] = after;
|
|
34
|
+
});
|
|
35
|
+
return changed ?? record;
|
|
22
36
|
};
|
|
23
37
|
/** The value with the change applied to every record within it and then to itself, innermost first. */
|
|
24
38
|
export const deeply = (change) => {
|
|
@@ -129,12 +129,6 @@ const controlOffsetOf = (system, given) => {
|
|
|
129
129
|
}
|
|
130
130
|
return measured;
|
|
131
131
|
};
|
|
132
|
-
/** The position each note of the bar sounds from. */
|
|
133
|
-
const positionsByPitch = (bar) => new Map(Array.from({ length: bar.trackCount }, (_, index) => track(index + 1))
|
|
134
|
-
.flatMap((position) => {
|
|
135
|
-
const meaning = bar.meaningOf(position);
|
|
136
|
-
return meaning?.type === 'note' ? [[meaning.pitch, position]] : [];
|
|
137
|
-
}));
|
|
138
132
|
/**
|
|
139
133
|
* Reads one of his e-roll files as a copy of the roll, in millimetres
|
|
140
134
|
* of paper, on the bar it was cut for and in that bar's numbering. A
|
|
@@ -146,8 +140,7 @@ export function readFromPhillipsEroll(buffer, { system = welteT100, controlOffse
|
|
|
146
140
|
const elapsedAt = clockOf(temposIn(timed), file.header.ticksPerBeat);
|
|
147
141
|
const place = placeAt ?? atStatedSpeed(system);
|
|
148
142
|
const offset = controlOffsetOf(system, controlOffset);
|
|
149
|
-
const
|
|
150
|
-
const positionOf = (number) => notePositions.get(number) ?? track(number - offset);
|
|
143
|
+
const positionOf = (number) => system.positionOf({ type: 'note', pitch: number }) ?? track(number - offset);
|
|
151
144
|
const features = notesIn(timed).flatMap((note) => {
|
|
152
145
|
const position = positionOf(note.pitch);
|
|
153
146
|
if (!system.meaningOf(position))
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { v4 } from "uuid";
|
|
2
2
|
import { AtonParser } from "./AtonParser.js";
|
|
3
|
+
import { assignDate } from "../model/Assumption.js";
|
|
3
4
|
import { systemOf } from "../systems/TrackerBar.js";
|
|
4
5
|
import { welteT100 } from "../systems/welteT100/bar.js";
|
|
5
6
|
import { inMillimeters, mean, mm, pixelsPerInch, px, subtract, track } from "../model/Quantity.js";
|
|
7
|
+
import { medianOf } from "../collation/statistics.js";
|
|
6
8
|
/** Values in these files carry their unit as a suffix, e.g. "37.7646px". */
|
|
7
9
|
const readPx = (value) => px(parseFloat(value));
|
|
8
10
|
/** The parser writes one record as an object and several as an array. */
|
|
@@ -20,11 +22,6 @@ const chainedBadHoles = (holes, calibration) => holes
|
|
|
20
22
|
...hole,
|
|
21
23
|
TRACKER_HOLE: `${Math.round((readPx(hole.CENTROID_COL) - calibration.offset) / calibration.separation)}`
|
|
22
24
|
}));
|
|
23
|
-
const median = (values) => {
|
|
24
|
-
const sorted = [...values].sort((a, b) => a - b);
|
|
25
|
-
const middle = Math.floor(sorted.length / 2);
|
|
26
|
-
return sorted.length % 2 ? sorted[middle] : (sorted[middle - 1] + sorted[middle]) / 2;
|
|
27
|
-
};
|
|
28
25
|
const mostFrequent = (values) => {
|
|
29
26
|
const counts = values.reduce((acc, value) => acc.set(value, (acc.get(value) || 0) + 1), new Map());
|
|
30
27
|
return [...counts].sort(([, a], [, b]) => b - a)[0]?.[0];
|
|
@@ -76,7 +73,7 @@ const calibrationShiftIn = (holes, bar) => {
|
|
|
76
73
|
const gridOffsetOf = (holes, separation, stated) => {
|
|
77
74
|
if (stated !== undefined)
|
|
78
75
|
return readPx(stated);
|
|
79
|
-
return
|
|
76
|
+
return medianOf(holes.map(hole => px(readPx(hole.CENTROID_COL) - +hole.TRACKER_HOLE * separation))) ?? px(0);
|
|
80
77
|
};
|
|
81
78
|
const chainsAmong = (holes) => holes
|
|
82
79
|
.filter(hole => hole.NOTE_ATTACK && hole.OFF_TIME)
|
|
@@ -124,19 +121,24 @@ const tearsIn = (tears, dpi, depictionOf) => {
|
|
|
124
121
|
.sort((a, b) => a.horizontal.from - b.horizontal.from);
|
|
125
122
|
};
|
|
126
123
|
/**
|
|
127
|
-
* The software behind an analysis and
|
|
128
|
-
* analysis file states them
|
|
124
|
+
* The software behind an analysis and the day it was run, as the
|
|
125
|
+
* analysis file states them: the measurement the dimensions and the
|
|
126
|
+
* hole separation it gives rest on.
|
|
129
127
|
*/
|
|
130
|
-
const
|
|
128
|
+
const measurementOf = (rollinfo) => {
|
|
131
129
|
const date = new Date(rollinfo.ANALYSIS_DATE);
|
|
132
130
|
if (!rollinfo.HOLE_SOFTWARE || isNaN(date.getTime()))
|
|
133
131
|
return undefined;
|
|
134
132
|
return {
|
|
135
|
-
|
|
136
|
-
version: rollinfo.SOFTWARE_DATE
|
|
137
|
-
date
|
|
133
|
+
type: 'measurement',
|
|
134
|
+
software: [{ name: rollinfo.HOLE_SOFTWARE, ...(rollinfo.SOFTWARE_DATE && { version: rollinfo.SOFTWARE_DATE }) }],
|
|
135
|
+
date: assignDate(new Date(date.getFullYear(), date.getMonth(), date.getDate()))
|
|
138
136
|
};
|
|
139
137
|
};
|
|
138
|
+
/** The value held on the strength of the measurement, where the file names one, and plainly where it does not. */
|
|
139
|
+
const takenBy = (measurement) => (value) => measurement
|
|
140
|
+
? { ...value, '@annotation': { id: v4(), belief: { type: 'belief', id: v4(), certainty: 'true', reasons: [measurement] } } }
|
|
141
|
+
: value;
|
|
140
142
|
export function readFromStanfordAton(atonString, { trackShift, system = welteT100, scan } = {}) {
|
|
141
143
|
const parser = new AtonParser();
|
|
142
144
|
const json = parser.parse(atonString);
|
|
@@ -145,7 +147,7 @@ export function readFromStanfordAton(atonString, { trackShift, system = welteT10
|
|
|
145
147
|
const stanford = druid ? stanfordScan(druid) : undefined;
|
|
146
148
|
const separation = readPx(json.ROLLINFO.HOLE_SEPARATION);
|
|
147
149
|
const dpi = parseFloat(json.ROLLINFO.LENGTH_DPI);
|
|
148
|
-
const
|
|
150
|
+
const measured = takenBy(measurementOf(json.ROLLINFO));
|
|
149
151
|
const shift = trackShift ?? calibrationShiftIn(holes, system);
|
|
150
152
|
const calibration = {
|
|
151
153
|
unit: 'px',
|
|
@@ -200,15 +202,15 @@ export function readFromStanfordAton(atonString, { trackShift, system = welteT10
|
|
|
200
202
|
modifications: [],
|
|
201
203
|
...((scan ?? stanford) && { scan: scan ?? stanford?.scan }),
|
|
202
204
|
measurements: {
|
|
203
|
-
dimensions: {
|
|
205
|
+
dimensions: measured({
|
|
204
206
|
width: inMillimeters(readPx(json.ROLLINFO.ROLL_WIDTH), dpi),
|
|
205
207
|
height: inMillimeters(readPx(json.ROLLINFO.IMAGE_LENGTH), dpi),
|
|
206
208
|
unit: 'mm'
|
|
207
|
-
},
|
|
208
|
-
holeSeparation: {
|
|
209
|
+
}),
|
|
210
|
+
holeSeparation: measured({
|
|
209
211
|
value: separation,
|
|
210
212
|
unit: 'px'
|
|
211
|
-
},
|
|
213
|
+
}),
|
|
212
214
|
margins: {
|
|
213
215
|
treble: readPx(json.ROLLINFO.HARD_MARGIN_TREBLE),
|
|
214
216
|
bass: readPx(json.ROLLINFO.HARD_MARGIN_BASS),
|
|
@@ -217,8 +219,7 @@ export function readFromStanfordAton(atonString, { trackShift, system = welteT10
|
|
|
217
219
|
...(Number.isFinite(dpi) && {
|
|
218
220
|
scanResolution: { value: pixelsPerInch(dpi), unit: 'px/in' }
|
|
219
221
|
}),
|
|
220
|
-
trackCalibration: calibration
|
|
221
|
-
...(measuredBy && { measuredBy })
|
|
222
|
+
trackCalibration: calibration
|
|
222
223
|
}
|
|
223
224
|
};
|
|
224
225
|
}
|