linked-rolls 0.70.0 → 0.72.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 +106 -5
- package/lib/analysis/constraints.d.ts +7 -0
- package/lib/analysis/constraints.js +1 -0
- package/lib/analysis/ownPaper.d.ts +5 -1
- package/lib/analysis/ownPaper.js +5 -1
- package/lib/analysis/paper.d.ts +22 -4
- package/lib/analysis/paper.js +6 -0
- package/lib/analysis/reservations.d.ts +24 -1
- package/lib/analysis/reservations.js +15 -1
- package/lib/analysis/sigla.d.ts +6 -1
- package/lib/analysis/sigla.js +5 -1
- package/lib/analysis/stemma.d.ts +6 -1
- package/lib/analysis/stemma.js +6 -1
- package/lib/analysis/text.d.ts +16 -2
- package/lib/analysis/text.js +16 -2
- package/lib/analysis/witnesses.d.ts +20 -1
- package/lib/analysis/witnesses.js +4 -0
- package/lib/collation/Collation.d.ts +47 -8
- package/lib/collation/Collation.js +29 -5
- package/lib/collation/alignment.d.ts +16 -3
- package/lib/collation/alignment.js +15 -3
- package/lib/collation/scatter.d.ts +50 -9
- package/lib/collation/scatter.js +11 -1
- package/lib/collation/statistics.d.ts +39 -9
- package/lib/collation/statistics.js +27 -6
- package/lib/collation/substitution.d.ts +5 -0
- package/lib/collation/substitution.js +4 -0
- package/lib/emulation/Emulation.d.ts +16 -1
- package/lib/emulation/Emulation.js +10 -0
- package/lib/emulation/negotiation.d.ts +1 -0
- package/lib/emulation/negotiation.js +1 -0
- package/lib/filiation/adoption.d.ts +47 -0
- package/lib/filiation/adoption.js +190 -0
- package/lib/filiation/changes.d.ts +33 -0
- package/lib/filiation/changes.js +38 -0
- package/lib/filiation/index.d.ts +12 -0
- package/lib/filiation/index.js +12 -0
- package/lib/filiation/presence.d.ts +50 -0
- package/lib/filiation/presence.js +122 -0
- package/lib/filiation/proposal.d.ts +132 -0
- package/lib/filiation/proposal.js +376 -0
- package/lib/filiation/readings.d.ts +108 -0
- package/lib/filiation/readings.js +281 -0
- package/lib/filiation/search.d.ts +113 -0
- package/lib/filiation/search.js +268 -0
- package/lib/filiation/systems.d.ts +21 -0
- package/lib/filiation/systems.js +39 -0
- package/lib/filiation/trees.d.ts +20 -0
- package/lib/filiation/trees.js +69 -0
- package/lib/index.d.ts +34 -2
- package/lib/index.js +3 -1
- package/lib/io/asJsonLd.d.ts +10 -0
- package/lib/io/asJsonLd.js +10 -0
- package/lib/io/context.d.ts +16 -2
- package/lib/io/context.js +16 -2
- package/lib/io/importJsonLd.d.ts +1 -0
- package/lib/io/importJsonLd.js +1 -0
- package/lib/io/migrate.d.ts +8 -0
- package/lib/io/migrate.js +8 -0
- package/lib/lookup/lookup.d.ts +29 -5
- package/lib/lookup/lookup.js +29 -5
- package/lib/lookup/paths.d.ts +23 -3
- package/lib/lookup/paths.js +17 -3
- package/lib/model/Agent.d.ts +28 -2
- package/lib/model/Agent.js +15 -1
- package/lib/model/Assumption.d.ts +96 -7
- package/lib/model/Assumption.js +65 -7
- package/lib/model/ConditionState.d.ts +1 -0
- package/lib/model/Edit.d.ts +10 -0
- package/lib/model/Edit.js +8 -0
- package/lib/model/Edition.d.ts +11 -0
- package/lib/model/Edition.js +1 -0
- package/lib/model/Feature.d.ts +74 -7
- package/lib/model/Feature.js +41 -3
- package/lib/model/FeatureSource.d.ts +14 -1
- package/lib/model/FeatureSource.js +7 -1
- package/lib/model/Perforator.d.ts +10 -0
- package/lib/model/Perforator.js +1 -0
- package/lib/model/Quantity.d.ts +160 -13
- package/lib/model/Quantity.js +110 -6
- package/lib/model/RollCopy.d.ts +74 -12
- package/lib/model/RollCopy.js +53 -10
- package/lib/model/Symbol.d.ts +38 -1
- package/lib/model/Symbol.js +16 -0
- package/lib/model/TrackCalibration.d.ts +10 -2
- package/lib/model/TrackCalibration.js +9 -2
- package/lib/model/Version.d.ts +24 -4
- package/lib/model/Version.js +19 -4
- package/lib/model/notes.d.ts +15 -2
- package/lib/model/notes.js +9 -2
- package/lib/model/procedures.d.ts +5 -1
- package/lib/model/procedures.js +5 -1
- package/lib/model/vocabulary.d.ts +6 -1
- package/lib/model/vocabulary.js +6 -1
- package/lib/ops/beliefs.d.ts +23 -1
- package/lib/ops/beliefs.js +23 -1
- package/lib/ops/collation.d.ts +3 -0
- package/lib/ops/collation.js +3 -0
- package/lib/ops/commands.d.ts +17 -2
- package/lib/ops/commands.js +17 -2
- package/lib/ops/copies.d.ts +37 -6
- package/lib/ops/copies.js +37 -6
- package/lib/ops/draft.d.ts +2 -0
- package/lib/ops/draft.js +1 -0
- package/lib/ops/edits.d.ts +5 -1
- package/lib/ops/edits.js +5 -1
- package/lib/ops/features.d.ts +12 -1
- package/lib/ops/features.js +7 -0
- package/lib/ops/versions.d.ts +15 -3
- package/lib/ops/versions.js +15 -3
- package/lib/readers/phillipsEroll.d.ts +12 -1
- package/lib/readers/phillipsEroll.js +6 -1
- package/lib/readers/spencerBar.d.ts +12 -1
- package/lib/readers/spencerBar.js +7 -1
- package/lib/readers/stanfordAton.d.ts +15 -0
- package/lib/readers/stanfordAton.js +9 -0
- package/lib/schema.json +10 -0
- package/lib/shared/utils.d.ts +12 -0
- package/lib/spec/context.json +4 -0
- package/lib/systems/ReproducingSystem.d.ts +46 -3
- package/lib/systems/TrackerBar.d.ts +45 -4
- package/lib/systems/TrackerBar.js +20 -3
- package/lib/systems/index.d.ts +9 -2
- package/lib/systems/index.js +9 -2
- package/lib/systems/velocity.d.ts +1 -0
- package/lib/systems/velocity.js +1 -0
- package/lib/systems/welte.d.ts +18 -3
- package/lib/systems/welte.js +9 -2
- package/lib/systems/welteLicensee/bar.d.ts +1 -0
- package/lib/systems/welteLicensee/bar.js +1 -0
- package/lib/systems/welteLicensee/system.d.ts +18 -0
- package/lib/systems/welteLicensee/system.js +17 -0
- package/lib/systems/welteT100/bar.d.ts +8 -0
- package/lib/systems/welteT100/bar.js +4 -0
- package/lib/systems/welteT100/system.d.ts +46 -5
- package/lib/systems/welteT100/system.js +29 -3
- package/lib/systems/welteT98/bar.d.ts +6 -0
- package/lib/systems/welteT98/bar.js +2 -0
- package/lib/systems/welteT98/system.d.ts +58 -5
- package/lib/systems/welteT98/system.js +42 -3
- package/lib/validate.d.ts +16 -0
- package/lib/validate.js +15 -0
- package/package.json +2 -1
|
@@ -9,7 +9,10 @@ import { quantity } from "../model/Quantity.js";
|
|
|
9
9
|
* stood out; a median and a median absolute deviation leave them out of
|
|
10
10
|
* account.
|
|
11
11
|
*/
|
|
12
|
-
/**
|
|
12
|
+
/**
|
|
13
|
+
* The middle of a sample, the mean of the two middle values where it has an even number of them.
|
|
14
|
+
* @internal
|
|
15
|
+
*/
|
|
13
16
|
export const medianOf = (values) => {
|
|
14
17
|
if (values.length === 0)
|
|
15
18
|
return undefined;
|
|
@@ -21,7 +24,10 @@ export const medianOf = (values) => {
|
|
|
21
24
|
};
|
|
22
25
|
/** What the median absolute deviation must be multiplied by to estimate the standard deviation of a normal sample. */
|
|
23
26
|
const MAD_TO_SIGMA = 1.4826;
|
|
24
|
-
/**
|
|
27
|
+
/**
|
|
28
|
+
* Where the sample sits and how far it scatters, or nothing for an empty sample.
|
|
29
|
+
* @internal
|
|
30
|
+
*/
|
|
25
31
|
export const spreadOf = (values) => {
|
|
26
32
|
const median = medianOf(values);
|
|
27
33
|
if (median === undefined)
|
|
@@ -33,7 +39,10 @@ export const spreadOf = (values) => {
|
|
|
33
39
|
sigma: quantity(MAD_TO_SIGMA * (medianOf(deviations) ?? 0))
|
|
34
40
|
};
|
|
35
41
|
};
|
|
36
|
-
/**
|
|
42
|
+
/**
|
|
43
|
+
* How far the value lies from the centre of the spread, in units of its scatter.
|
|
44
|
+
* @internal
|
|
45
|
+
*/
|
|
37
46
|
export const standardise = (value, spread) => (value - spread.median) / spread.sigma;
|
|
38
47
|
/** The complementary error function, after Press et al., whose fractional error stays below 1.2e-7. */
|
|
39
48
|
const erfc = (x) => {
|
|
@@ -44,9 +53,15 @@ const erfc = (x) => {
|
|
|
44
53
|
t * (-0.82215223 + t * 0.17087277)))))))));
|
|
45
54
|
return x >= 0 ? tail : 2 - tail;
|
|
46
55
|
};
|
|
47
|
-
/**
|
|
56
|
+
/**
|
|
57
|
+
* The share of a normal sample lying below `z` standard deviations.
|
|
58
|
+
* @internal
|
|
59
|
+
*/
|
|
48
60
|
export const normalBelow = (z) => erfc(-z / Math.SQRT2) / 2;
|
|
49
|
-
/**
|
|
61
|
+
/**
|
|
62
|
+
* The share of a normal sample lying further than `z` standard deviations from its centre, on either side.
|
|
63
|
+
* @internal
|
|
64
|
+
*/
|
|
50
65
|
export const normalBeyond = (z) => erfc(z / Math.SQRT2);
|
|
51
66
|
const horner = (coefficients, x) => coefficients.reduce((total, coefficient) => total * x + coefficient, 0);
|
|
52
67
|
const CENTRAL_NUMERATOR = [
|
|
@@ -74,6 +89,7 @@ const tailQuantile = (share) => {
|
|
|
74
89
|
* How many standard deviations out the given share of a normal sample
|
|
75
90
|
* lies below, after Acklam's rational approximation, whose relative
|
|
76
91
|
* error stays below 1.15e-9. The inverse of `normalBelow`.
|
|
92
|
+
* @internal
|
|
77
93
|
*/
|
|
78
94
|
export const normalQuantile = (share) => {
|
|
79
95
|
if (share <= 0)
|
|
@@ -92,9 +108,13 @@ export const normalQuantile = (share) => {
|
|
|
92
108
|
* How much heavier the tails of a standardised sample are than a normal
|
|
93
109
|
* sample's. Zero for a normal shape, positive where more of the sample
|
|
94
110
|
* lies far out than the curve allows.
|
|
111
|
+
* @internal
|
|
95
112
|
*/
|
|
96
113
|
export const excessKurtosisOf = (standardised) => standardised.reduce((total, z) => total + z ** 4, 0) / standardised.length - 3;
|
|
97
|
-
/**
|
|
114
|
+
/**
|
|
115
|
+
* What the sample puts beyond the given distance, against what a normal sample would.
|
|
116
|
+
* @internal
|
|
117
|
+
*/
|
|
98
118
|
export const tailOf = (standardised, beyond) => ({
|
|
99
119
|
beyond,
|
|
100
120
|
observed: standardised.filter(z => Math.abs(z) > beyond).length,
|
|
@@ -104,6 +124,7 @@ export const tailOf = (standardised, beyond) => ({
|
|
|
104
124
|
* The sample counted into bins of the given width, laid out on
|
|
105
125
|
* multiples of that width so that two histograms of one width share
|
|
106
126
|
* their bounds. Nothing for an empty sample or a width of nothing.
|
|
127
|
+
* @internal
|
|
107
128
|
*/
|
|
108
129
|
export const histogramOf = (values, binWidth) => {
|
|
109
130
|
if (values.length === 0 || binWidth <= 0)
|
|
@@ -8,11 +8,13 @@ export type { Operation, Spelling } from "../systems/TrackerBar.js";
|
|
|
8
8
|
* nothing for a word no bar here knows or one without a counterpart in
|
|
9
9
|
* another scale. The bars share their words where they share a scale,
|
|
10
10
|
* as the Licensee does the T-100's, so the first that reads it answers.
|
|
11
|
+
* @category Systems and emulation
|
|
11
12
|
*/
|
|
12
13
|
export declare const operationOf: (expressionType: string) => Operation | undefined;
|
|
13
14
|
/**
|
|
14
15
|
* A latched function of the older version and the held command of the
|
|
15
16
|
* newer one that stands for it.
|
|
17
|
+
* @category Collation and alignment
|
|
16
18
|
*/
|
|
17
19
|
export interface Substitution {
|
|
18
20
|
/** The command that turned the function on, and the one that cancelled it. */
|
|
@@ -30,6 +32,7 @@ export interface Substitution {
|
|
|
30
32
|
* command. The T-98 punches a hold as a chain of round holes on a
|
|
31
33
|
* 2.66 mm grid with bridges of about a millimetre, so a scan read hole
|
|
32
34
|
* by hole shows a run where the paper shows one command.
|
|
35
|
+
* @category Collation and alignment
|
|
33
36
|
*/
|
|
34
37
|
export declare const defaultChainGap: import("../index.js").Quantity<"mm">;
|
|
35
38
|
/**
|
|
@@ -42,6 +45,7 @@ export declare const defaultChainGap: import("../index.js").Quantity<"mm">;
|
|
|
42
45
|
* the green bar, so drawing it as a perforation is out of the question,
|
|
43
46
|
* but an edit still has to be shown somewhere, and the lane the green
|
|
44
47
|
* scale gives the same function is where it belongs.
|
|
48
|
+
* @internal
|
|
45
49
|
*/
|
|
46
50
|
export declare const positionOfSameFunction: (bar: TrackerBar, symbol: Expression) => Track | undefined;
|
|
47
51
|
/**
|
|
@@ -54,5 +58,6 @@ export declare const positionOfSameFunction: (bar: TrackerBar, symbol: Expressio
|
|
|
54
58
|
* reported and the editor is left to say what happened. Nothing is
|
|
55
59
|
* invented either: both sides are perforations somebody punched, and all
|
|
56
60
|
* this asserts is which stands for which.
|
|
61
|
+
* @category Collation and alignment
|
|
57
62
|
*/
|
|
58
63
|
export declare const substitutionsBetween: (own: readonly AnySymbol[], inherited: readonly AnySymbol[], locate: Locate, tolerance?: CollationTolerance, chainGap?: Millimeters) => Substitution[];
|
|
@@ -6,6 +6,7 @@ import { trackerBars } from "../systems/index.js";
|
|
|
6
6
|
* nothing for a word no bar here knows or one without a counterpart in
|
|
7
7
|
* another scale. The bars share their words where they share a scale,
|
|
8
8
|
* as the Licensee does the T-100's, so the first that reads it answers.
|
|
9
|
+
* @category Systems and emulation
|
|
9
10
|
*/
|
|
10
11
|
export const operationOf = (expressionType) => {
|
|
11
12
|
for (const bar of trackerBars) {
|
|
@@ -20,6 +21,7 @@ export const operationOf = (expressionType) => {
|
|
|
20
21
|
* command. The T-98 punches a hold as a chain of round holes on a
|
|
21
22
|
* 2.66 mm grid with bridges of about a millimetre, so a scan read hole
|
|
22
23
|
* by hole shows a run where the paper shows one command.
|
|
24
|
+
* @category Collation and alignment
|
|
23
25
|
*/
|
|
24
26
|
export const defaultChainGap = mm(3);
|
|
25
27
|
const isExpression = (symbol) => symbol.type === 'expression';
|
|
@@ -35,6 +37,7 @@ const functionKey = (symbol, operation) => operation.sided ? `${operation.operat
|
|
|
35
37
|
* the green bar, so drawing it as a perforation is out of the question,
|
|
36
38
|
* but an edit still has to be shown somewhere, and the lane the green
|
|
37
39
|
* scale gives the same function is where it belongs.
|
|
40
|
+
* @internal
|
|
38
41
|
*/
|
|
39
42
|
export const positionOfSameFunction = (bar, symbol) => {
|
|
40
43
|
const wanted = operationOf(symbol.expressionType);
|
|
@@ -132,6 +135,7 @@ const theOnly = (items) => items.length === 1 ? items[0] : undefined;
|
|
|
132
135
|
* reported and the editor is left to say what happened. Nothing is
|
|
133
136
|
* invented either: both sides are perforations somebody punched, and all
|
|
134
137
|
* this asserts is which stands for which.
|
|
138
|
+
* @category Collation and alignment
|
|
135
139
|
*/
|
|
136
140
|
export const substitutionsBetween = (own, inherited, locate, tolerance = defaultCollationTolerance, chainGap = defaultChainGap) => {
|
|
137
141
|
const latched = latchedIn(inherited, locate);
|
|
@@ -4,6 +4,10 @@ import { Version } from "../model/Version.js";
|
|
|
4
4
|
import { AnyPerformedRollFeature, EmulatedCurve, NegotiatedEvent, ReproducingSystem } from "../systems/ReproducingSystem.js";
|
|
5
5
|
import { Millimeters } from "../model/Quantity.js";
|
|
6
6
|
import { Edition } from "../model/Edition.js";
|
|
7
|
+
/**
|
|
8
|
+
* Which part of a version `emulate` plays, and where its clock starts.
|
|
9
|
+
* @category Systems and emulation
|
|
10
|
+
*/
|
|
7
11
|
export type EmulationScope = {
|
|
8
12
|
/** Only notes whose onset lies within this span of the roll are played. */
|
|
9
13
|
range?: [Millimeters, Millimeters];
|
|
@@ -15,15 +19,20 @@ export type EmulationScope = {
|
|
|
15
19
|
* left as they were. The edition supplies the copies, whose measurements
|
|
16
20
|
* decide how far before or after its reference a command goes, and a
|
|
17
21
|
* punch diameter, or a millimetre, where no copy agrees with a statement.
|
|
22
|
+
* @category Systems and emulation
|
|
18
23
|
*/
|
|
19
24
|
export declare const withPlacementsApplied: (edition: Edition, events: readonly NegotiatedEvent[]) => NegotiatedEvent[];
|
|
20
25
|
/**
|
|
21
26
|
* The commands of a version as the bar performs them, in order of place,
|
|
22
27
|
* within the scope and with the placements applied. A note plays only
|
|
23
28
|
* where its onset falls in the range; expressions play throughout.
|
|
29
|
+
* @category Systems and emulation
|
|
24
30
|
*/
|
|
25
31
|
export declare const negotiatedEventsOf: (edition: Edition, version: Readonly<Version>, bar: TrackerBar, { range }?: Pick<EmulationScope, 'range'>) => NegotiatedEvent[];
|
|
26
|
-
/**
|
|
32
|
+
/**
|
|
33
|
+
* A version performed: what was negotiated, and what the system made of it.
|
|
34
|
+
* @category Systems and emulation
|
|
35
|
+
*/
|
|
27
36
|
export interface Emulated {
|
|
28
37
|
/** The id of the version performed. */
|
|
29
38
|
readonly source: string;
|
|
@@ -35,18 +44,21 @@ export interface Emulated {
|
|
|
35
44
|
/**
|
|
36
45
|
* Performs a version on a reproducing system: the symbols are negotiated
|
|
37
46
|
* into placed events and the system plays them. Nothing given is changed.
|
|
47
|
+
* @category Systems and emulation
|
|
38
48
|
*/
|
|
39
49
|
export declare const emulate: <Options extends object>(system: ReproducingSystem<Options>, version: Readonly<Version>, edition: Edition, options?: Options, { range, skipToFirstNote }?: EmulationScope) => Emulated;
|
|
40
50
|
/**
|
|
41
51
|
* The performed events as a MIDI file, in which every note and pedal step
|
|
42
52
|
* is labelled with the symbol it performs. The file names the system, the
|
|
43
53
|
* version and the options it was played with.
|
|
54
|
+
* @category Systems and emulation
|
|
44
55
|
*/
|
|
45
56
|
export declare const midiOf: (events: readonly AnyPerformedRollFeature[], systemName: string, options: object, source?: string) => MidiFile;
|
|
46
57
|
/**
|
|
47
58
|
* A version of the edition, performed and kept: `emulate` and `midiOf`
|
|
48
59
|
* with the result held on the object between the two calls. Prefer the
|
|
49
60
|
* functions where nothing needs holding.
|
|
61
|
+
* @category Systems and emulation
|
|
50
62
|
*/
|
|
51
63
|
export declare class Emulation<Options extends object> {
|
|
52
64
|
readonly system: ReproducingSystem<Options>;
|
|
@@ -58,7 +70,10 @@ export declare class Emulation<Options extends object> {
|
|
|
58
70
|
constructor(system: ReproducingSystem<Options>, options?: Options);
|
|
59
71
|
/** Moves the negotiated events to where their statements put them; see `withPlacementsApplied`. */
|
|
60
72
|
applyConstraints(edition: Edition): void;
|
|
73
|
+
/** Performs the version, keeps what came of it, and returns the performed events; see `emulate`. */
|
|
61
74
|
emulateVersion(version: Version, edition: Edition, scope?: EmulationScope): AnyPerformedRollFeature[];
|
|
75
|
+
/** The performed events that sound or follow from the symbol with the id. */
|
|
62
76
|
findEventsPerforming(id: string): AnyPerformedRollFeature[];
|
|
77
|
+
/** The performed events as a MIDI file; see `midiOf`. */
|
|
63
78
|
asMIDI(): MidiFile;
|
|
64
79
|
}
|
|
@@ -151,6 +151,7 @@ const earliestOf = (times) => times.length === 0 ? seconds(0) : times.reduce((so
|
|
|
151
151
|
* left as they were. The edition supplies the copies, whose measurements
|
|
152
152
|
* decide how far before or after its reference a command goes, and a
|
|
153
153
|
* punch diameter, or a millimetre, where no copy agrees with a statement.
|
|
154
|
+
* @category Systems and emulation
|
|
154
155
|
*/
|
|
155
156
|
export const withPlacementsApplied = (edition, events) => {
|
|
156
157
|
const gap = meanPunchDiameterOf(edition) ?? mm(1);
|
|
@@ -168,6 +169,7 @@ export const withPlacementsApplied = (edition, events) => {
|
|
|
168
169
|
* The commands of a version as the bar performs them, in order of place,
|
|
169
170
|
* within the scope and with the placements applied. A note plays only
|
|
170
171
|
* where its onset falls in the range; expressions play throughout.
|
|
172
|
+
* @category Systems and emulation
|
|
171
173
|
*/
|
|
172
174
|
export const negotiatedEventsOf = (edition, version, bar, { range } = {}) => {
|
|
173
175
|
const inScope = (event) => !range || event.type !== 'note' || (event.horizontal.from > range[0] && event.horizontal.from < range[1]);
|
|
@@ -180,6 +182,7 @@ export const negotiatedEventsOf = (edition, version, bar, { range } = {}) => {
|
|
|
180
182
|
/**
|
|
181
183
|
* Performs a version on a reproducing system: the symbols are negotiated
|
|
182
184
|
* into placed events and the system plays them. Nothing given is changed.
|
|
185
|
+
* @category Systems and emulation
|
|
183
186
|
*/
|
|
184
187
|
export const emulate = (system, version, edition, options = system.defaultOptions, { range, skipToFirstNote = false } = {}) => {
|
|
185
188
|
const negotiated = negotiatedEventsOf(edition, version, system.trackerBar, { range });
|
|
@@ -202,6 +205,7 @@ export const emulate = (system, version, edition, options = system.defaultOption
|
|
|
202
205
|
* The performed events as a MIDI file, in which every note and pedal step
|
|
203
206
|
* is labelled with the symbol it performs. The file names the system, the
|
|
204
207
|
* version and the options it was played with.
|
|
208
|
+
* @category Systems and emulation
|
|
205
209
|
*/
|
|
206
210
|
export const midiOf = (events, systemName, options, source) => {
|
|
207
211
|
const TICKS_PER_SECOND = 1000;
|
|
@@ -262,6 +266,8 @@ export const midiOf = (events, systemName, options, source) => {
|
|
|
262
266
|
midi.push(controller(controllerOf(event), event.value, labelled ? deltaTime : 0));
|
|
263
267
|
}
|
|
264
268
|
}
|
|
269
|
+
// a standard MIDI file ends every track with this event
|
|
270
|
+
midi.push({ type: 'meta', subtype: 'endOfTrack', deltaTime: 0 });
|
|
265
271
|
return {
|
|
266
272
|
header: {
|
|
267
273
|
ticksPerBeat: TICKS_PER_SECOND,
|
|
@@ -275,6 +281,7 @@ export const midiOf = (events, systemName, options, source) => {
|
|
|
275
281
|
* A version of the edition, performed and kept: `emulate` and `midiOf`
|
|
276
282
|
* with the result held on the object between the two calls. Prefer the
|
|
277
283
|
* functions where nothing needs holding.
|
|
284
|
+
* @category Systems and emulation
|
|
278
285
|
*/
|
|
279
286
|
export class Emulation {
|
|
280
287
|
constructor(system, options = system.defaultOptions) {
|
|
@@ -322,6 +329,7 @@ export class Emulation {
|
|
|
322
329
|
applyConstraints(edition) {
|
|
323
330
|
this.negotiatedEvents = withPlacementsApplied(edition, this.negotiatedEvents);
|
|
324
331
|
}
|
|
332
|
+
/** Performs the version, keeps what came of it, and returns the performed events; see `emulate`. */
|
|
325
333
|
emulateVersion(version, edition, scope = {}) {
|
|
326
334
|
const emulated = emulate(this.system, version, edition, this.options, scope);
|
|
327
335
|
this.source = emulated.source;
|
|
@@ -330,9 +338,11 @@ export class Emulation {
|
|
|
330
338
|
this.midiEvents = [...emulated.events];
|
|
331
339
|
return this.midiEvents;
|
|
332
340
|
}
|
|
341
|
+
/** The performed events that sound or follow from the symbol with the id. */
|
|
333
342
|
findEventsPerforming(id) {
|
|
334
343
|
return this.midiEvents.filter(event => event.performs.id === id);
|
|
335
344
|
}
|
|
345
|
+
/** The performed events as a MIDI file; see `midiOf`. */
|
|
336
346
|
asMIDI() {
|
|
337
347
|
return midiOf(this.midiEvents, this.system.name, this.options, this.source);
|
|
338
348
|
}
|
|
@@ -10,5 +10,6 @@ import { Edition } from "../model/Edition.js";
|
|
|
10
10
|
* transfer between systems leaves behind: a red `ForzandoOn` a
|
|
11
11
|
* green version still inherits cannot be performed on a green
|
|
12
12
|
* machine, and an edit has yet to say what took its place.
|
|
13
|
+
* @category Systems and emulation
|
|
13
14
|
*/
|
|
14
15
|
export declare const negotiatedEventOf: (edition: Edition, symbol: Note | Expression, bar: TrackerBar) => NegotiatedEvent | null;
|
|
@@ -7,6 +7,7 @@ import { placeOf } from "../analysis/text.js";
|
|
|
7
7
|
* transfer between systems leaves behind: a red `ForzandoOn` a
|
|
8
8
|
* green version still inherits cannot be performed on a green
|
|
9
9
|
* machine, and an edit has yet to say what took its place.
|
|
10
|
+
* @category Systems and emulation
|
|
10
11
|
*/
|
|
11
12
|
export const negotiatedEventOf = (edition, symbol, bar) => {
|
|
12
13
|
const horizontal = placeOf(edition, symbol);
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Edition } from "../model/Edition.js";
|
|
2
|
+
import { Version } from "../model/Version.js";
|
|
3
|
+
import { EditionOp } from "../ops/draft.js";
|
|
4
|
+
import { StemmaProposal, Unpinned } from "./proposal.js";
|
|
5
|
+
/**
|
|
6
|
+
* What adopting a proposal makes of the stemma: the versions it puts in
|
|
7
|
+
* place of the edition's, and what of the edition it leaves out.
|
|
8
|
+
* @category Filiation
|
|
9
|
+
*/
|
|
10
|
+
export interface Adoption {
|
|
11
|
+
versions: Version[];
|
|
12
|
+
/** By version of the proposal, the id of the version it becomes. */
|
|
13
|
+
ids: Record<string, string>;
|
|
14
|
+
/** The versions of the edition the adoption leaves out. */
|
|
15
|
+
removed: string[];
|
|
16
|
+
/** The edits the editor wrote that the adoption leaves out, and why. */
|
|
17
|
+
dropped: Unpinned[];
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* What adopting the proposal makes of the edition's stemma, worked out
|
|
21
|
+
* without changing it, so that it can be looked at first.
|
|
22
|
+
*
|
|
23
|
+
* A version of the proposal that stands for a version of the edition
|
|
24
|
+
* keeps its id, system, creation and motivations, the derivation it
|
|
25
|
+
* states where it still derives from the same version, and its other
|
|
26
|
+
* derivations, the hypotheses, as long as they name a version that is
|
|
27
|
+
* still there and does not derive from it. Its edits are the proposal's:
|
|
28
|
+
* the edits the editor wrote that the proposal keeps, as they are, and
|
|
29
|
+
* one edit for each further reading it inserts or deletes, or for each
|
|
30
|
+
* recoding. An edit the version stated before over the very same
|
|
31
|
+
* readings is taken over with its id and what was written on it; the
|
|
32
|
+
* others are new and marked unchecked, as a collation marks its own.
|
|
33
|
+
*
|
|
34
|
+
* A reading that stands for a symbol of the edition keeps that symbol's
|
|
35
|
+
* id and whatever it states beside its carriers. A version of the edition
|
|
36
|
+
* nothing stands for goes, unless it states no edits and derives from a
|
|
37
|
+
* version that stays, as a version known only from a recording does.
|
|
38
|
+
* @category Filiation
|
|
39
|
+
*/
|
|
40
|
+
export declare const adoptionOf: (edition: Edition, proposal: StemmaProposal) => Adoption;
|
|
41
|
+
/**
|
|
42
|
+
* Puts the proposed stemma in place of the edition's, as `adoptionOf`
|
|
43
|
+
* describes, and takes back a copy's statement that it carries a version
|
|
44
|
+
* that goes. One operation, and so one undo step.
|
|
45
|
+
* @category Operations
|
|
46
|
+
*/
|
|
47
|
+
export declare const adoptStemma: (proposal: StemmaProposal) => EditionOp;
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/** Taking a proposed stemma into the edition, as one operation. */
|
|
2
|
+
import { v5 } from "uuid";
|
|
3
|
+
import { assignReference, idOf } from "../model/Assumption.js";
|
|
4
|
+
import { derivesFrom, editsOf, insertedBy, principalDerivationOf } from "../model/Version.js";
|
|
5
|
+
import { systemOf } from "../systems/TrackerBar.js";
|
|
6
|
+
import { unchecked } from "../collation/Collation.js";
|
|
7
|
+
import { versionIn } from "../lookup/lookup.js";
|
|
8
|
+
import { declaring, reading } from "../ops/draft.js";
|
|
9
|
+
import { dropStatements } from "../ops/copies.js";
|
|
10
|
+
import { barNamed } from "./systems.js";
|
|
11
|
+
/** The namespace the names of adopted versions and edits are minted in, so that adopting again gives them again. */
|
|
12
|
+
const ADOPTED = '6f1d2c8e-93a4-4f0b-b8a1-2f4c5d7e9a31';
|
|
13
|
+
const exchangeKey = (inserted, deleted) => `${[...inserted].sort().join(',')}/${[...deleted].sort().join(',')}`;
|
|
14
|
+
/** The carriers of the reading, keeping what the edition states of those it held already. */
|
|
15
|
+
const carriersOf = (reading, stated) => {
|
|
16
|
+
const known = new Map(stated.map(carrier => [idOf(carrier), carrier]));
|
|
17
|
+
return reading.carriers.map(id => known.get(id) ?? assignReference(id));
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* What adopting the proposal makes of the edition's stemma, worked out
|
|
21
|
+
* without changing it, so that it can be looked at first.
|
|
22
|
+
*
|
|
23
|
+
* A version of the proposal that stands for a version of the edition
|
|
24
|
+
* keeps its id, system, creation and motivations, the derivation it
|
|
25
|
+
* states where it still derives from the same version, and its other
|
|
26
|
+
* derivations, the hypotheses, as long as they name a version that is
|
|
27
|
+
* still there and does not derive from it. Its edits are the proposal's:
|
|
28
|
+
* the edits the editor wrote that the proposal keeps, as they are, and
|
|
29
|
+
* one edit for each further reading it inserts or deletes, or for each
|
|
30
|
+
* recoding. An edit the version stated before over the very same
|
|
31
|
+
* readings is taken over with its id and what was written on it; the
|
|
32
|
+
* others are new and marked unchecked, as a collation marks its own.
|
|
33
|
+
*
|
|
34
|
+
* A reading that stands for a symbol of the edition keeps that symbol's
|
|
35
|
+
* id and whatever it states beside its carriers. A version of the edition
|
|
36
|
+
* nothing stands for goes, unless it states no edits and derives from a
|
|
37
|
+
* version that stays, as a version known only from a recording does.
|
|
38
|
+
* @category Filiation
|
|
39
|
+
*/
|
|
40
|
+
export const adoptionOf = (edition, proposal) => {
|
|
41
|
+
const readingOf = new Map(proposal.collation.readings.map(reading => [reading.id, reading]));
|
|
42
|
+
const symbolIdOf = (reading) => proposal.symbols[reading] ?? reading;
|
|
43
|
+
const existing = new Map(edition.versions.flatMap(insertedBy).map(symbol => [symbol.id, symbol]));
|
|
44
|
+
// A reading the stemma lets arise more than once is one symbol for each time it arises, each
|
|
45
|
+
// carried by the copies below where it arose: the edition inserts a symbol in one version only.
|
|
46
|
+
const parentOf = new Map(proposal.versions.map(proposed => [proposed.id, proposed.parent]));
|
|
47
|
+
const copiesBelow = new Map(proposal.versions.map(proposed => [proposed.id, new Set()]));
|
|
48
|
+
for (const proposed of proposal.versions) {
|
|
49
|
+
for (let at = proposed.id; at !== undefined; at = parentOf.get(at)) {
|
|
50
|
+
if (proposed.copy)
|
|
51
|
+
copiesBelow.get(at).add(proposed.copy);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const arising = new Map();
|
|
55
|
+
for (const proposed of proposal.versions) {
|
|
56
|
+
for (const reading of proposed.inserts)
|
|
57
|
+
arising.set(reading, [...(arising.get(reading) ?? []), proposed.id]);
|
|
58
|
+
}
|
|
59
|
+
/** The symbol a reading is where it arose in the version given. */
|
|
60
|
+
const symbolIdAt = (reading, at) => {
|
|
61
|
+
const places = arising.get(reading) ?? [];
|
|
62
|
+
return places.indexOf(at) > 0 ? `symbol_${v5(`${reading}|${at}`, ADOPTED)}` : symbolIdOf(reading);
|
|
63
|
+
};
|
|
64
|
+
/** The symbol a version inherits of a reading: the one that arose nearest above it. */
|
|
65
|
+
const inheritedAt = (reading, at) => {
|
|
66
|
+
const places = arising.get(reading) ?? [];
|
|
67
|
+
for (let above = parentOf.get(at); above !== undefined; above = parentOf.get(above)) {
|
|
68
|
+
if (places.includes(above))
|
|
69
|
+
return symbolIdAt(reading, above);
|
|
70
|
+
}
|
|
71
|
+
return symbolIdOf(reading);
|
|
72
|
+
};
|
|
73
|
+
const symbolOf = (id, at) => {
|
|
74
|
+
const reading = readingOf.get(id);
|
|
75
|
+
const twice = (arising.get(id)?.length ?? 0) > 1;
|
|
76
|
+
const below = copiesBelow.get(at);
|
|
77
|
+
const own = twice
|
|
78
|
+
? { ...reading, carriers: reading.carriers.filter((_, index) => below.has(reading.copies[index])) }
|
|
79
|
+
: reading;
|
|
80
|
+
const symbol = symbolIdAt(id, at);
|
|
81
|
+
const stated = symbol === proposal.symbols[id] ? existing.get(symbol) : undefined;
|
|
82
|
+
const carriers = carriersOf(own, stated?.carriers ?? []);
|
|
83
|
+
if (stated)
|
|
84
|
+
return { ...stated, carriers };
|
|
85
|
+
return reading.meaning.type === 'note'
|
|
86
|
+
? { type: 'note', id: symbol, pitch: reading.meaning.pitch, carriers }
|
|
87
|
+
: { type: 'expression', id: symbol, expressionType: reading.meaning.expressionType, scope: reading.meaning.scope, carriers };
|
|
88
|
+
};
|
|
89
|
+
const standingFor = new Map(Object.entries(proposal.symbols).map(([reading, symbol]) => [symbol, reading]));
|
|
90
|
+
/** The symbol as an edit the editor wrote inserts it, with the carriers of the reading it stands for. */
|
|
91
|
+
const restated = (symbol) => {
|
|
92
|
+
const reading = standingFor.get(symbol.id);
|
|
93
|
+
return reading ? { ...symbol, carriers: carriersOf(readingOf.get(reading), symbol.carriers) } : symbol;
|
|
94
|
+
};
|
|
95
|
+
const idFor = (proposed) => proposed.version ?? v5(`version|${proposed.copy ?? ''}|${[...proposed.inserts].sort().join(',')}`, ADOPTED);
|
|
96
|
+
const ids = new Map(proposal.versions.map(proposed => [proposed.id, idFor(proposed)]));
|
|
97
|
+
const staying = new Set(ids.values());
|
|
98
|
+
const versions = proposal.versions.map((proposed) => {
|
|
99
|
+
const id = ids.get(proposed.id);
|
|
100
|
+
const before = proposed.version ? versionIn(edition, proposed.version) : undefined;
|
|
101
|
+
const pinned = new Set(proposed.pinned);
|
|
102
|
+
const stated = before ? editsOf(before) : [];
|
|
103
|
+
const kept = stated
|
|
104
|
+
.filter(edit => pinned.has(edit.id))
|
|
105
|
+
.map(edit => edit.insert ? { ...edit, insert: edit.insert.map(restated) } : edit);
|
|
106
|
+
const spoken = new Set(kept.flatMap(edit => [...(edit.insert ?? []).map(symbol => symbol.id), ...(edit.delete ?? [])]));
|
|
107
|
+
const statedBefore = new Map(stated.map(edit => [exchangeKey((edit.insert ?? []).map(symbol => symbol.id), edit.delete ?? []), edit]));
|
|
108
|
+
const made = (inserts, deletes, recoding) => {
|
|
109
|
+
const inserted = inserts.map(reading => symbolIdAt(reading, proposed.id));
|
|
110
|
+
const deleted = deletes.map(reading => inheritedAt(reading, proposed.id));
|
|
111
|
+
if ([...inserted, ...deleted].some(symbol => spoken.has(symbol)))
|
|
112
|
+
return undefined;
|
|
113
|
+
const key = exchangeKey(inserted, deleted);
|
|
114
|
+
const same = statedBefore.get(key);
|
|
115
|
+
const insert = inserts.map(reading => symbolOf(reading, proposed.id));
|
|
116
|
+
if (same)
|
|
117
|
+
return { ...same, ...(insert.length > 0 && { insert }), ...(deleted.length > 0 && { delete: deleted }) };
|
|
118
|
+
return {
|
|
119
|
+
type: 'edit',
|
|
120
|
+
id: v5(`edit|${id}|${key}`, ADOPTED),
|
|
121
|
+
...(recoding && { editType: 'recoding' }),
|
|
122
|
+
motivation: unchecked,
|
|
123
|
+
...(insert.length > 0 && { insert }),
|
|
124
|
+
...(deleted.length > 0 && { delete: deleted })
|
|
125
|
+
};
|
|
126
|
+
};
|
|
127
|
+
// A recoding an edit of the editor's cuts into is stated reading by reading.
|
|
128
|
+
const whole = proposed.recodings.filter(recoding => ![...recoding.by.map(reading => symbolIdAt(reading, proposed.id)), ...recoding.replaced.map(reading => inheritedAt(reading, proposed.id))]
|
|
129
|
+
.some(symbol => spoken.has(symbol)));
|
|
130
|
+
const recoded = new Set(whole.flatMap(recoding => [...recoding.by, ...recoding.replaced]));
|
|
131
|
+
const edits = [
|
|
132
|
+
...kept,
|
|
133
|
+
...whole.map(recoding => made(recoding.by, recoding.replaced, true)),
|
|
134
|
+
...proposed.inserts.filter(reading => !recoded.has(reading)).map(reading => made([reading], [], false)),
|
|
135
|
+
...proposed.deletes.filter(reading => !recoded.has(reading)).map(reading => made([], [reading], false))
|
|
136
|
+
].filter((edit) => edit !== undefined);
|
|
137
|
+
const parent = proposed.parent ? ids.get(proposed.parent) : undefined;
|
|
138
|
+
const principal = before && principalDerivationOf(before);
|
|
139
|
+
const derivation = parent === undefined
|
|
140
|
+
? undefined
|
|
141
|
+
: principal && idOf(principal) === parent ? principal : assignReference(parent);
|
|
142
|
+
const hypotheses = (before?.basedOn ?? [])
|
|
143
|
+
.filter(other => other !== principal && staying.has(idOf(other)) && idOf(other) !== parent);
|
|
144
|
+
const basedOn = [...(derivation ? [derivation] : []), ...hypotheses];
|
|
145
|
+
const copy = proposed.copy ? edition.copies.find(copy => copy.id === proposed.copy) : undefined;
|
|
146
|
+
const bar = barNamed(proposed.system);
|
|
147
|
+
const system = copy?.production?.system ?? before?.system ?? (bar ? systemOf(bar) : { id: proposed.system, name: proposed.system, sameAs: [] });
|
|
148
|
+
const { basedOn: _, edits: __, ...rest } = before ?? {};
|
|
149
|
+
return {
|
|
150
|
+
...rest,
|
|
151
|
+
id,
|
|
152
|
+
system,
|
|
153
|
+
...(basedOn.length > 0 && { basedOn }),
|
|
154
|
+
edits,
|
|
155
|
+
motivations: declaring(before?.motivations ?? [], edits)
|
|
156
|
+
};
|
|
157
|
+
});
|
|
158
|
+
// A hypothesis may not name a version that now derives from the one stating it.
|
|
159
|
+
const pruned = versions.map(version => ({
|
|
160
|
+
...version,
|
|
161
|
+
...(version.basedOn && {
|
|
162
|
+
basedOn: version.basedOn.filter((derivation, index) => index === 0 || !derivesFrom(versions, idOf(derivation), version.id))
|
|
163
|
+
})
|
|
164
|
+
}));
|
|
165
|
+
const statedOnly = edition.versions.filter(version => {
|
|
166
|
+
if (staying.has(version.id) || editsOf(version).length > 0)
|
|
167
|
+
return false;
|
|
168
|
+
const principal = principalDerivationOf(version);
|
|
169
|
+
return principal !== undefined && staying.has(idOf(principal));
|
|
170
|
+
});
|
|
171
|
+
const removed = edition.versions.filter(version => !staying.has(version.id) && !statedOnly.includes(version)).map(version => version.id);
|
|
172
|
+
// The edition's order where a version stays, the new ones after it.
|
|
173
|
+
const rank = new Map(edition.versions.map((version, index) => [version.id, index]));
|
|
174
|
+
const ordered = [...pruned, ...statedOnly].sort((a, b) => (rank.get(a.id) ?? Infinity) - (rank.get(b.id) ?? Infinity));
|
|
175
|
+
return { versions: ordered, ids: Object.fromEntries(ids), removed, dropped: proposal.unpinned };
|
|
176
|
+
};
|
|
177
|
+
/**
|
|
178
|
+
* Puts the proposed stemma in place of the edition's, as `adoptionOf`
|
|
179
|
+
* describes, and takes back a copy's statement that it carries a version
|
|
180
|
+
* that goes. One operation, and so one undo step.
|
|
181
|
+
* @category Operations
|
|
182
|
+
*/
|
|
183
|
+
export const adoptStemma = (proposal) => reading(edition => {
|
|
184
|
+
const { versions, removed } = adoptionOf(edition, proposal);
|
|
185
|
+
const gone = new Set(removed);
|
|
186
|
+
return draft => {
|
|
187
|
+
draft.versions = versions;
|
|
188
|
+
draft.copies.forEach(copy => dropStatements(copy, statement => gone.has(idOf(statement))));
|
|
189
|
+
};
|
|
190
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** What tells two states of a stemma apart, version by version. */
|
|
2
|
+
import { Edition } from "../model/Edition.js";
|
|
3
|
+
/**
|
|
4
|
+
* How a version differs between two states of the edition: whether it
|
|
5
|
+
* is in either, what it derives from in each, and which symbols it
|
|
6
|
+
* inserts and deletes in one and not the other.
|
|
7
|
+
* @category Filiation
|
|
8
|
+
*/
|
|
9
|
+
export interface VersionChange {
|
|
10
|
+
version: string;
|
|
11
|
+
/** The version it derives from in the state before, where it is in that state. */
|
|
12
|
+
parentBefore?: string | null;
|
|
13
|
+
/** The version it derives from in the state after, where it is in that state. */
|
|
14
|
+
parentAfter?: string | null;
|
|
15
|
+
inserted: {
|
|
16
|
+
kept: number;
|
|
17
|
+
gone: string[];
|
|
18
|
+
added: string[];
|
|
19
|
+
};
|
|
20
|
+
deleted: {
|
|
21
|
+
kept: number;
|
|
22
|
+
gone: string[];
|
|
23
|
+
added: string[];
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Version by version, how the stemma of one state of the edition differs
|
|
28
|
+
* from that of another, as when a proposed stemma is set against the one
|
|
29
|
+
* the edition holds. The versions of the state before come first, in
|
|
30
|
+
* their order, then those only the state after holds.
|
|
31
|
+
* @category Filiation
|
|
32
|
+
*/
|
|
33
|
+
export declare const stemmaChanges: (before: Pick<Edition, 'versions'>, after: Pick<Edition, 'versions'>) => VersionChange[];
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { idOf } from "../model/Assumption.js";
|
|
2
|
+
import { deletedBy, insertedBy, principalDerivationOf } from "../model/Version.js";
|
|
3
|
+
const compared = (before, after) => {
|
|
4
|
+
const was = new Set(before);
|
|
5
|
+
const is = new Set(after);
|
|
6
|
+
return {
|
|
7
|
+
kept: after.filter(id => was.has(id)).length,
|
|
8
|
+
gone: before.filter(id => !is.has(id)),
|
|
9
|
+
added: after.filter(id => !was.has(id))
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
const parentOf = (version) => {
|
|
13
|
+
const principal = principalDerivationOf(version);
|
|
14
|
+
return principal ? idOf(principal) : null;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Version by version, how the stemma of one state of the edition differs
|
|
18
|
+
* from that of another, as when a proposed stemma is set against the one
|
|
19
|
+
* the edition holds. The versions of the state before come first, in
|
|
20
|
+
* their order, then those only the state after holds.
|
|
21
|
+
* @category Filiation
|
|
22
|
+
*/
|
|
23
|
+
export const stemmaChanges = (before, after) => {
|
|
24
|
+
const was = new Map(before.versions.map(version => [version.id, version]));
|
|
25
|
+
const is = new Map(after.versions.map(version => [version.id, version]));
|
|
26
|
+
const ids = [...new Set([...was.keys(), ...is.keys()])];
|
|
27
|
+
return ids.map(id => {
|
|
28
|
+
const one = was.get(id);
|
|
29
|
+
const other = is.get(id);
|
|
30
|
+
return {
|
|
31
|
+
version: id,
|
|
32
|
+
...(one && { parentBefore: parentOf(one) }),
|
|
33
|
+
...(other && { parentAfter: parentOf(other) }),
|
|
34
|
+
inserted: compared(one ? insertedBy(one).map(symbol => symbol.id) : [], other ? insertedBy(other).map(symbol => symbol.id) : []),
|
|
35
|
+
deleted: compared(one ? deletedBy(one) : [], other ? deletedBy(other) : [])
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filiation: proposing a stemma from the copies alone, by the editorial
|
|
3
|
+
* principles the rules of an edition state, and taking it into the
|
|
4
|
+
* edition.
|
|
5
|
+
*/
|
|
6
|
+
export { collateCopies, readingsOfCopy, type CopyCollation, type CollatedReading, type CopyReading, type PairWindow, type Recoding } from "./readings.js";
|
|
7
|
+
export { presenceIn, ineffectiveAmong, defaultMargin, type Presence, type PresenceMatrix } from "./presence.js";
|
|
8
|
+
export { defaultCosts, type Costs, type Scored, type Support } from "./search.js";
|
|
9
|
+
export { transfersOf, systemAbove } from "./systems.js";
|
|
10
|
+
export { proposeStemma, defaultMovedWithin, type FiliationOptions, type ProposedVersion, type StemmaProposal, type Unpinned } from "./proposal.js";
|
|
11
|
+
export { adoptionOf, adoptStemma, type Adoption } from "./adoption.js";
|
|
12
|
+
export { stemmaChanges, type VersionChange } from "./changes.js";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filiation: proposing a stemma from the copies alone, by the editorial
|
|
3
|
+
* principles the rules of an edition state, and taking it into the
|
|
4
|
+
* edition.
|
|
5
|
+
*/
|
|
6
|
+
export { collateCopies, readingsOfCopy } from "./readings.js";
|
|
7
|
+
export { presenceIn, ineffectiveAmong, defaultMargin } from "./presence.js";
|
|
8
|
+
export { defaultCosts } from "./search.js";
|
|
9
|
+
export { transfersOf, systemAbove } from "./systems.js";
|
|
10
|
+
export { proposeStemma, defaultMovedWithin } from "./proposal.js";
|
|
11
|
+
export { adoptionOf, adoptStemma } from "./adoption.js";
|
|
12
|
+
export { stemmaChanges } from "./changes.js";
|