linked-rolls 0.13.0 → 0.14.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 +35 -0
- package/lib/FeatureSource.d.ts +65 -0
- package/lib/FeatureSource.js +35 -0
- package/lib/RollCopy.d.ts +8 -0
- package/lib/editionOps.d.ts +5 -0
- package/lib/editionOps.js +8 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +2 -0
- package/lib/reservations.d.ts +23 -0
- package/lib/reservations.js +53 -0
- package/lib/schema.json +48 -0
- package/lib/spec/context.json +16 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -33,6 +33,41 @@ the keeper and the production metadata are nodes with a name and
|
|
|
33
33
|
authority links, and the roll names its reproducing system. Exports
|
|
34
34
|
are always in the current format.
|
|
35
35
|
|
|
36
|
+
## Where a copy's features come from
|
|
37
|
+
|
|
38
|
+
`readFrom` states what a copy's features were read from: the roll
|
|
39
|
+
itself, a `scan` of it, an `analysis` somebody else measured on a
|
|
40
|
+
scan, an `emulation` in which the roll has already been read into
|
|
41
|
+
notes and commands, or a `recording` captured while the copy was
|
|
42
|
+
played. Beside the kind it holds who carried the capture out, on what
|
|
43
|
+
device, when, and a note. What is not known is left out.
|
|
44
|
+
|
|
45
|
+
This says where the numbers of the edition come from and nothing
|
|
46
|
+
about the state of the paper, which is a condition of the copy. In
|
|
47
|
+
RDF it is `reo:capture`, an activity typed by what it read from; the
|
|
48
|
+
file it produced is `crmdig:L11 had output`, the machine it ran on
|
|
49
|
+
`crmdig:L12 happened on device`.
|
|
50
|
+
|
|
51
|
+
Nothing records that a copy is doubtful. `reservationsAbout` works
|
|
52
|
+
out from what a copy states what the edition cannot vouch for in it:
|
|
53
|
+
that it names no source, that the making of its source is
|
|
54
|
+
undocumented, that its features are somebody else's reading, that its
|
|
55
|
+
source bears no physical evidence, that no measuring software is
|
|
56
|
+
recorded, that it is not calibrated. A reservation goes away when the
|
|
57
|
+
gap it names is filled.
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
import { reservationsAbout, stateSource } from 'linked-rolls'
|
|
61
|
+
|
|
62
|
+
const next = produce(edition, stateSource(copyId, {
|
|
63
|
+
kind: 'emulation',
|
|
64
|
+
output: 'https://example.org/wm225.mid',
|
|
65
|
+
note: 'MIDI from a third party; the emulator is not named.'
|
|
66
|
+
}))
|
|
67
|
+
|
|
68
|
+
reservationsAbout(next.copies[0]).map(reservation => reservation.note)
|
|
69
|
+
```
|
|
70
|
+
|
|
36
71
|
## Emulation
|
|
37
72
|
|
|
38
73
|
`Emulation` turns a version of the edition into MIDI. The core of the
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { ActorAssignment, DateAssignment } from "./Assumption";
|
|
2
|
+
import { Concept } from "./Agent";
|
|
3
|
+
import { WithNote } from "./utils";
|
|
4
|
+
/**
|
|
5
|
+
* What a copy's features were read from. The kinds run from the paper
|
|
6
|
+
* itself to a file in which the roll has already been read into notes
|
|
7
|
+
* and commands.
|
|
8
|
+
*/
|
|
9
|
+
export declare const sourceKinds: readonly ['roll', 'scan', 'analysis', 'emulation', 'recording'];
|
|
10
|
+
export type SourceKind = typeof sourceKinds[number];
|
|
11
|
+
/** How each kind of source is referred to in prose. */
|
|
12
|
+
export declare const sourceLabels: Record<SourceKind, string>;
|
|
13
|
+
/**
|
|
14
|
+
* Whether a source of this kind gives positions that were measured.
|
|
15
|
+
* An emulation and a recording give the reading somebody else made:
|
|
16
|
+
* the roll has been turned into notes and commands already, and
|
|
17
|
+
* turning those back into holes reconstructs them.
|
|
18
|
+
*/
|
|
19
|
+
export declare const isMeasured: (kind: SourceKind) => boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Whether a source of this kind bears witness to the paper. Punch
|
|
22
|
+
* diameter, hole separation, punching pattern, marks and writings can
|
|
23
|
+
* be observed on the roll and on an image of it, and on nothing else.
|
|
24
|
+
*/
|
|
25
|
+
export declare const bearsPhysicalEvidence: (kind: SourceKind) => boolean;
|
|
26
|
+
/**
|
|
27
|
+
* The capture by which a copy's features became data: what they were
|
|
28
|
+
* read from, who read them, on what device and when. It states where
|
|
29
|
+
* the numbers of the edition come from and says nothing about the
|
|
30
|
+
* state of the paper, which is a condition.
|
|
31
|
+
*
|
|
32
|
+
* What is not known is left out. A reader is told about the gap by
|
|
33
|
+
* `reservationsAbout`, which works out what a copy cannot vouch for
|
|
34
|
+
* from what it states here.
|
|
35
|
+
* @see crm:E7 Activity
|
|
36
|
+
*/
|
|
37
|
+
export interface FeatureSource extends WithNote {
|
|
38
|
+
/**
|
|
39
|
+
* What the features were read from.
|
|
40
|
+
* @see crm:P2 has type
|
|
41
|
+
*/
|
|
42
|
+
kind: SourceKind;
|
|
43
|
+
/**
|
|
44
|
+
* The file the capture produced, where it has an address.
|
|
45
|
+
* @see crmdig:L11 had output
|
|
46
|
+
*/
|
|
47
|
+
output?: string;
|
|
48
|
+
/**
|
|
49
|
+
* Who carried out the capture.
|
|
50
|
+
* @see crm:P14 carried out by
|
|
51
|
+
*/
|
|
52
|
+
actor?: ActorAssignment;
|
|
53
|
+
/**
|
|
54
|
+
* The make and model of the scanner, camera or player the capture
|
|
55
|
+
* ran on.
|
|
56
|
+
* @see crmdig:L12 happened on device
|
|
57
|
+
*/
|
|
58
|
+
device?: Concept;
|
|
59
|
+
/**
|
|
60
|
+
* When the capture took place.
|
|
61
|
+
* @format date
|
|
62
|
+
* @see dcterms:date
|
|
63
|
+
*/
|
|
64
|
+
date?: DateAssignment;
|
|
65
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a copy's features were read from. The kinds run from the paper
|
|
3
|
+
* itself to a file in which the roll has already been read into notes
|
|
4
|
+
* and commands.
|
|
5
|
+
*/
|
|
6
|
+
export const sourceKinds = [
|
|
7
|
+
'roll',
|
|
8
|
+
'scan',
|
|
9
|
+
'analysis',
|
|
10
|
+
'emulation',
|
|
11
|
+
'recording'
|
|
12
|
+
];
|
|
13
|
+
/** How each kind of source is referred to in prose. */
|
|
14
|
+
export const sourceLabels = {
|
|
15
|
+
roll: 'the roll itself',
|
|
16
|
+
scan: 'a scan of the roll',
|
|
17
|
+
analysis: 'a hole analysis of a scan',
|
|
18
|
+
emulation: 'an emulated MIDI file',
|
|
19
|
+
recording: 'a MIDI recording of the copy being played'
|
|
20
|
+
};
|
|
21
|
+
const measured = ['roll', 'scan', 'analysis'];
|
|
22
|
+
const physical = ['roll', 'scan'];
|
|
23
|
+
/**
|
|
24
|
+
* Whether a source of this kind gives positions that were measured.
|
|
25
|
+
* An emulation and a recording give the reading somebody else made:
|
|
26
|
+
* the roll has been turned into notes and commands already, and
|
|
27
|
+
* turning those back into holes reconstructs them.
|
|
28
|
+
*/
|
|
29
|
+
export const isMeasured = (kind) => measured.includes(kind);
|
|
30
|
+
/**
|
|
31
|
+
* Whether a source of this kind bears witness to the paper. Punch
|
|
32
|
+
* diameter, hole separation, punching pattern, marks and writings can
|
|
33
|
+
* be observed on the roll and on an image of it, and on nothing else.
|
|
34
|
+
*/
|
|
35
|
+
export const bearsPhysicalEvidence = (kind) => physical.includes(kind);
|
package/lib/RollCopy.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { AnyFeature } from "./Feature";
|
|
|
6
6
|
import { ActorAssignment, DateAssignment, ObjectAssumption } from "./Assumption";
|
|
7
7
|
import { WithId, WithType } from "./utils";
|
|
8
8
|
import { Agent, Concept } from "./Agent";
|
|
9
|
+
import { FeatureSource } from "./FeatureSource";
|
|
9
10
|
import { Measure, Millimeters, Quantity, Track } from "./Quantity";
|
|
10
11
|
/**
|
|
11
12
|
* This condition state is used to describe the roll's
|
|
@@ -282,6 +283,13 @@ export interface RollCopy extends WithType<'RollCopy'>, WithId {
|
|
|
282
283
|
* @see crm:P138i has representation
|
|
283
284
|
*/
|
|
284
285
|
scan?: string;
|
|
286
|
+
/**
|
|
287
|
+
* What this copy's features were read from. A copy that states no
|
|
288
|
+
* source is one whose features reached the edition by a way that
|
|
289
|
+
* was not written down.
|
|
290
|
+
* @see reo:capture
|
|
291
|
+
*/
|
|
292
|
+
readFrom?: FeatureSource;
|
|
285
293
|
}
|
|
286
294
|
/**
|
|
287
295
|
* Reads the features of a copy as the tracker bar would read them.
|
package/lib/editionOps.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { AnySymbol, PlacementRelation } from "./Symbol";
|
|
|
5
5
|
import { CollationTolerance } from "./Collation";
|
|
6
6
|
import { Edit } from "./Edit";
|
|
7
7
|
import { RollCopy, ScaleReading, Shift } from "./RollCopy";
|
|
8
|
+
import { FeatureSource } from "./FeatureSource";
|
|
8
9
|
import { AnyArgumentation, Certainty } from "./Assumption";
|
|
9
10
|
/**
|
|
10
11
|
* A change to an edition, written onto an immer draft of it. One
|
|
@@ -30,6 +31,10 @@ export declare const alignCopy: (copyId: string, shift: Shift, scale: number, re
|
|
|
30
31
|
* being a fact about the copy.
|
|
31
32
|
*/
|
|
32
33
|
export declare const unalignCopy: (copyId: string) => EditionOp;
|
|
34
|
+
/** States what the copy's features were read from, in place of any earlier statement. */
|
|
35
|
+
export declare const stateSource: (copyId: string, source: FeatureSource) => EditionOp;
|
|
36
|
+
/** Takes back the statement, leaving the copy silent about its source again. */
|
|
37
|
+
export declare const clearSource: (copyId: string) => EditionOp;
|
|
33
38
|
/** The symbols of the versions that no other copy carries. */
|
|
34
39
|
export declare const symbolsCarriedOnlyBy: (edition: Edition, copyId: string) => AnySymbol[];
|
|
35
40
|
/** Takes the features off the copy, and out of the versions with what only they carried. */
|
package/lib/editionOps.js
CHANGED
|
@@ -96,6 +96,14 @@ export const unalignCopy = (copyId) => onCopy(copyId, copy => {
|
|
|
96
96
|
revertShift(copy);
|
|
97
97
|
copy.conditions = without(copy.conditions, isPaperStretch);
|
|
98
98
|
});
|
|
99
|
+
/** States what the copy's features were read from, in place of any earlier statement. */
|
|
100
|
+
export const stateSource = (copyId, source) => onCopy(copyId, copy => {
|
|
101
|
+
copy.readFrom = source;
|
|
102
|
+
});
|
|
103
|
+
/** Takes back the statement, leaving the copy silent about its source again. */
|
|
104
|
+
export const clearSource = (copyId) => onCopy(copyId, copy => {
|
|
105
|
+
copy.readFrom = undefined;
|
|
106
|
+
});
|
|
99
107
|
const featureIdsOf = (copy) => new Set(copy.features.map(feature => feature.id));
|
|
100
108
|
/**
|
|
101
109
|
* A symbol every carrier of which lies among the features loses its
|
package/lib/index.d.ts
CHANGED
|
@@ -14,7 +14,9 @@ export * from './systems/welteT100/bar';
|
|
|
14
14
|
export * from './systems/welteLicensee/bar';
|
|
15
15
|
export * from './systems';
|
|
16
16
|
export * from './ReproducingSystem';
|
|
17
|
+
export * from './FeatureSource';
|
|
17
18
|
export * from './RollCopy';
|
|
19
|
+
export * from './reservations';
|
|
18
20
|
export * from './alignment';
|
|
19
21
|
export * from './Edition';
|
|
20
22
|
export * from './EditionView';
|
package/lib/index.js
CHANGED
|
@@ -14,7 +14,9 @@ export * from './systems/welteT100/bar';
|
|
|
14
14
|
export * from './systems/welteLicensee/bar';
|
|
15
15
|
export * from './systems';
|
|
16
16
|
export * from './ReproducingSystem';
|
|
17
|
+
export * from './FeatureSource';
|
|
17
18
|
export * from './RollCopy';
|
|
19
|
+
export * from './reservations';
|
|
18
20
|
export * from './alignment';
|
|
19
21
|
export * from './Edition';
|
|
20
22
|
export * from './EditionView';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { RollCopy } from "./RollCopy";
|
|
2
|
+
export declare const reservationTypes: readonly ['source-not-stated', 'source-undocumented', 'features-interpreted', 'no-physical-evidence', 'measurement-undocumented', 'not-calibrated'];
|
|
3
|
+
export type ReservationType = typeof reservationTypes[number];
|
|
4
|
+
/**
|
|
5
|
+
* Something an edition cannot vouch for in one of its copies.
|
|
6
|
+
*
|
|
7
|
+
* A reservation is worked out from what the copy states about itself
|
|
8
|
+
* and is never written into the edition: it says that knowledge of
|
|
9
|
+
* the copy is incomplete, so filling in what is missing makes it go
|
|
10
|
+
* away. Nothing here describes the state of the paper, which is a
|
|
11
|
+
* condition of the copy.
|
|
12
|
+
*/
|
|
13
|
+
export interface Reservation {
|
|
14
|
+
type: ReservationType;
|
|
15
|
+
/** What the reservation means for a reader, in one sentence. */
|
|
16
|
+
note: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* What the edition cannot vouch for in a copy, in the order the
|
|
20
|
+
* checks are listed: where its features came from first, then what
|
|
21
|
+
* the measurement leaves open.
|
|
22
|
+
*/
|
|
23
|
+
export declare const reservationsAbout: (copy: RollCopy) => Reservation[];
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { bearsPhysicalEvidence, isMeasured, sourceLabels } from "./FeatureSource";
|
|
2
|
+
import { calibrationOf } from "./RollCopy";
|
|
3
|
+
export const reservationTypes = [
|
|
4
|
+
'source-not-stated',
|
|
5
|
+
'source-undocumented',
|
|
6
|
+
'features-interpreted',
|
|
7
|
+
'no-physical-evidence',
|
|
8
|
+
'measurement-undocumented',
|
|
9
|
+
'not-calibrated'
|
|
10
|
+
];
|
|
11
|
+
const sourceStated = copy => copy.readFrom ? undefined : {
|
|
12
|
+
type: 'source-not-stated',
|
|
13
|
+
note: 'The copy does not state what its features were read from.'
|
|
14
|
+
};
|
|
15
|
+
const sourceDocumented = copy => {
|
|
16
|
+
const source = copy.readFrom;
|
|
17
|
+
if (!source || source.actor || source.device || source.date)
|
|
18
|
+
return undefined;
|
|
19
|
+
return {
|
|
20
|
+
type: 'source-undocumented',
|
|
21
|
+
note: `The copy names ${sourceLabels[source.kind]} as its source, but records nobody who made it, no device and no date.`
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
const featuresMeasured = copy => copy.readFrom && !isMeasured(copy.readFrom.kind) ? {
|
|
25
|
+
type: 'features-interpreted',
|
|
26
|
+
note: `The features come from ${sourceLabels[copy.readFrom.kind]}, in which the roll has already been read into notes and commands by somebody else.`
|
|
27
|
+
} : undefined;
|
|
28
|
+
const physicalEvidence = copy => copy.readFrom && !bearsPhysicalEvidence(copy.readFrom.kind) ? {
|
|
29
|
+
type: 'no-physical-evidence',
|
|
30
|
+
note: 'Punch diameter, hole separation, punching pattern, marks and writings cannot be observed on this source.'
|
|
31
|
+
} : undefined;
|
|
32
|
+
const measurementDocumented = copy => !copy.measurements.measuredBy && copy.readFrom?.kind !== 'roll' ? {
|
|
33
|
+
type: 'measurement-undocumented',
|
|
34
|
+
note: 'No measuring software is recorded for this copy.'
|
|
35
|
+
} : undefined;
|
|
36
|
+
const calibrated = copy => calibrationOf(copy) ? undefined : {
|
|
37
|
+
type: 'not-calibrated',
|
|
38
|
+
note: 'The copy is not calibrated against the tracker bar, so its track positions rest on the numbering its source used.'
|
|
39
|
+
};
|
|
40
|
+
const checks = [
|
|
41
|
+
sourceStated,
|
|
42
|
+
sourceDocumented,
|
|
43
|
+
featuresMeasured,
|
|
44
|
+
physicalEvidence,
|
|
45
|
+
measurementDocumented,
|
|
46
|
+
calibrated
|
|
47
|
+
];
|
|
48
|
+
/**
|
|
49
|
+
* What the edition cannot vouch for in a copy, in the order the
|
|
50
|
+
* checks are listed: where its features came from first, then what
|
|
51
|
+
* the measurement leaves open.
|
|
52
|
+
*/
|
|
53
|
+
export const reservationsAbout = (copy) => checks.flatMap(check => check(copy) ?? []);
|
package/lib/schema.json
CHANGED
|
@@ -543,6 +543,40 @@
|
|
|
543
543
|
],
|
|
544
544
|
"type": "string"
|
|
545
545
|
},
|
|
546
|
+
"FeatureSource": {
|
|
547
|
+
"description": "The capture by which a copy's features became data: what they were read from, who read them, on what device and when. It states where the numbers of the edition come from and says nothing about the state of the paper, which is a condition.\n\nWhat is not known is left out. A reader is told about the gap by `reservationsAbout`, which works out what a copy cannot vouch for from what it states here. [ontology: crm:E7 Activity]",
|
|
548
|
+
"properties": {
|
|
549
|
+
"actor": {
|
|
550
|
+
"$ref": "#/definitions/ActorAssignment",
|
|
551
|
+
"description": "Who carried out the capture. [ontology: crm:P14 carried out by]"
|
|
552
|
+
},
|
|
553
|
+
"date": {
|
|
554
|
+
"$ref": "#/definitions/DateAssignment",
|
|
555
|
+
"description": "When the capture took place. [ontology: dcterms:date]",
|
|
556
|
+
"format": "date"
|
|
557
|
+
},
|
|
558
|
+
"device": {
|
|
559
|
+
"$ref": "#/definitions/Concept",
|
|
560
|
+
"description": "The make and model of the scanner, camera or player the capture ran on. [ontology: crmdig:L12 happened on device]"
|
|
561
|
+
},
|
|
562
|
+
"kind": {
|
|
563
|
+
"$ref": "#/definitions/SourceKind",
|
|
564
|
+
"description": "What the features were read from. [ontology: crm:P2 has type]"
|
|
565
|
+
},
|
|
566
|
+
"note": {
|
|
567
|
+
"description": "A free-text note providing additional context. [ontology: crm:P3 has note]",
|
|
568
|
+
"type": "string"
|
|
569
|
+
},
|
|
570
|
+
"output": {
|
|
571
|
+
"description": "The file the capture produced, where it has an address. [ontology: crmdig:L11 had output]",
|
|
572
|
+
"type": "string"
|
|
573
|
+
}
|
|
574
|
+
},
|
|
575
|
+
"required": [
|
|
576
|
+
"kind"
|
|
577
|
+
],
|
|
578
|
+
"type": "object"
|
|
579
|
+
},
|
|
546
580
|
"GluedOn": {
|
|
547
581
|
"description": "A piece of material (paper or tape) glued onto the roll surface. Glued-on features are typically used to cover perforations (for corrections) or to reinforce damaged areas. They may themselves carry other features such as writings or additional holes. [ontology: crm:E22 Human-Made Object]",
|
|
548
582
|
"properties": {
|
|
@@ -1816,6 +1850,10 @@
|
|
|
1816
1850
|
"$ref": "#/definitions/ProductionEvent",
|
|
1817
1851
|
"description": "The production event that created this roll copy. [ontology: lrmoo:R28i was produced by]"
|
|
1818
1852
|
},
|
|
1853
|
+
"readFrom": {
|
|
1854
|
+
"$ref": "#/definitions/FeatureSource",
|
|
1855
|
+
"description": "What this copy's features were read from. A copy that states no source is one whose features reached the edition by a way that was not written down. [ontology: reo:capture]"
|
|
1856
|
+
},
|
|
1819
1857
|
"scan": {
|
|
1820
1858
|
"description": "The scan URL or IIIF URL of the roll. [ontology: crm:P138i has representation]",
|
|
1821
1859
|
"type": "string"
|
|
@@ -1861,6 +1899,16 @@
|
|
|
1861
1899
|
],
|
|
1862
1900
|
"type": "object"
|
|
1863
1901
|
},
|
|
1902
|
+
"SourceKind": {
|
|
1903
|
+
"enum": [
|
|
1904
|
+
"roll",
|
|
1905
|
+
"scan",
|
|
1906
|
+
"analysis",
|
|
1907
|
+
"emulation",
|
|
1908
|
+
"recording"
|
|
1909
|
+
],
|
|
1910
|
+
"type": "string"
|
|
1911
|
+
},
|
|
1864
1912
|
"Text": {
|
|
1865
1913
|
"description": "A textual symbol, e.g. a label or annotation found on the roll. [ontology: crm:E33 Linguistic Object]",
|
|
1866
1914
|
"properties": {
|
package/lib/spec/context.json
CHANGED
|
@@ -165,6 +165,22 @@
|
|
|
165
165
|
"@id": "crm:P138i_has_representation",
|
|
166
166
|
"@type": "@id"
|
|
167
167
|
},
|
|
168
|
+
"readFrom": {
|
|
169
|
+
"@id": "reo:capture",
|
|
170
|
+
"@context": {
|
|
171
|
+
"kind": {
|
|
172
|
+
"@id": "crm:P2_has_type",
|
|
173
|
+
"@type": "@vocab",
|
|
174
|
+
"@context": { "@vocab": "https://w3id.org/reo/type/" }
|
|
175
|
+
},
|
|
176
|
+
"output": {
|
|
177
|
+
"@id": "crmdig:L11_had_output",
|
|
178
|
+
"@type": "@id"
|
|
179
|
+
},
|
|
180
|
+
"device": "crmdig:L12_happened_on_device",
|
|
181
|
+
"note": "crm:P3_has_note"
|
|
182
|
+
}
|
|
183
|
+
},
|
|
168
184
|
"depiction": {
|
|
169
185
|
"@id": "crm:P138i_has_representation",
|
|
170
186
|
"@type": "@id"
|
package/package.json
CHANGED