linked-rolls 0.62.0 → 0.64.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 +26 -7
- package/lib/analysis/constraints.d.ts +2 -2
- package/lib/analysis/constraints.js +30 -21
- package/lib/analysis/ownPaper.d.ts +11 -16
- package/lib/analysis/ownPaper.js +13 -31
- package/lib/analysis/paper.d.ts +129 -0
- package/lib/analysis/paper.js +260 -0
- package/lib/analysis/reservations.d.ts +2 -2
- package/lib/analysis/reservations.js +6 -6
- package/lib/analysis/sigla.d.ts +4 -5
- package/lib/analysis/sigla.js +4 -4
- package/lib/analysis/stemma.d.ts +22 -0
- package/lib/analysis/stemma.js +38 -0
- package/lib/analysis/text.d.ts +31 -0
- package/lib/analysis/text.js +62 -0
- package/lib/analysis/witnesses.d.ts +5 -5
- package/lib/analysis/witnesses.js +22 -20
- package/lib/collation/alignment.d.ts +46 -8
- package/lib/collation/alignment.js +137 -47
- package/lib/collation/scatter.d.ts +4 -4
- package/lib/collation/scatter.js +15 -13
- package/lib/emulation/Emulation.d.ts +7 -7
- package/lib/emulation/Emulation.js +29 -27
- package/lib/emulation/negotiation.d.ts +2 -2
- package/lib/emulation/negotiation.js +3 -2
- package/lib/index.d.ts +6 -2
- package/lib/index.js +6 -2
- package/lib/io/asJsonLd.js +16 -1
- package/lib/io/importJsonLd.d.ts +5 -0
- package/lib/io/importJsonLd.js +18 -1
- package/lib/io/migrate.js +94 -2
- package/lib/lookup/lookup.d.ts +32 -0
- package/lib/lookup/lookup.js +40 -0
- package/lib/lookup/paths.d.ts +11 -0
- package/lib/lookup/paths.js +78 -0
- package/lib/lookup/perState.d.ts +32 -0
- package/lib/lookup/perState.js +63 -0
- package/lib/model/Assumption.d.ts +21 -9
- package/lib/model/Edit.d.ts +4 -0
- package/lib/model/Edition.d.ts +19 -0
- package/lib/model/Edition.js +9 -1
- package/lib/model/Quantity.d.ts +4 -1
- package/lib/model/Quantity.js +1 -0
- package/lib/model/RollCopy.d.ts +144 -48
- package/lib/model/RollCopy.js +9 -6
- package/lib/model/Version.d.ts +7 -1
- package/lib/ops/beliefs.d.ts +1 -1
- package/lib/ops/beliefs.js +1 -1
- package/lib/ops/collation.d.ts +3 -4
- package/lib/ops/collation.js +25 -23
- package/lib/ops/commands.d.ts +4 -5
- package/lib/ops/commands.js +10 -10
- package/lib/ops/copies.d.ts +47 -10
- package/lib/ops/copies.js +92 -26
- package/lib/ops/draft.d.ts +12 -12
- package/lib/ops/draft.js +11 -13
- package/lib/ops/edits.d.ts +1 -2
- package/lib/ops/edits.js +13 -10
- package/lib/ops/features.d.ts +2 -2
- package/lib/ops/features.js +3 -2
- package/lib/ops/index.d.ts +2 -2
- package/lib/ops/index.js +7 -1
- package/lib/ops/versions.d.ts +2 -3
- package/lib/ops/versions.js +6 -5
- package/lib/readers/stanfordAton.js +28 -1
- package/lib/schema.json +185 -26
- package/lib/spec/context.json +33 -1
- package/lib/systems/ReproducingSystem.d.ts +7 -6
- package/package.json +1 -1
- package/lib/view/EditionView.d.ts +0 -103
- package/lib/view/EditionView.js +0 -329
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { RollCopy } from "../model/RollCopy.js";
|
|
2
2
|
import { Version } from "../model/Version.js";
|
|
3
|
-
import {
|
|
3
|
+
import { Edition } from "../model/Edition.js";
|
|
4
4
|
export declare const reservationTypes: readonly ['source-not-stated', 'source-undocumented', 'software-not-named', 'instrument-not-named', 'features-interpreted', 'no-physical-evidence', 'measurement-undocumented', 'not-calibrated', 'system-unknown', 'keeper-unknown'];
|
|
5
5
|
export type ReservationType = typeof reservationTypes[number];
|
|
6
6
|
/**
|
|
@@ -27,4 +27,4 @@ export declare const reservationsAbout: (copy: RollCopy) => Reservation[];
|
|
|
27
27
|
export declare const versionReservationTypes: readonly ['text-not-stated', 'witnessed-by-statement-only', 'no-direct-witness'];
|
|
28
28
|
export type VersionReservationType = typeof versionReservationTypes[number];
|
|
29
29
|
/** What the edition cannot vouch for in a version, in the order the checks are listed. */
|
|
30
|
-
export declare const reservationsAboutVersion: (
|
|
30
|
+
export declare const reservationsAboutVersion: (edition: Edition, version: Readonly<Version>) => Reservation<VersionReservationType>[];
|
|
@@ -105,12 +105,12 @@ export const versionReservationTypes = [
|
|
|
105
105
|
'witnessed-by-statement-only',
|
|
106
106
|
'no-direct-witness'
|
|
107
107
|
];
|
|
108
|
-
const textStated = (
|
|
108
|
+
const textStated = (_edition, version) => version.edits ? undefined : {
|
|
109
109
|
type: 'text-not-stated',
|
|
110
110
|
note: 'The version does not state its edits, so it reads as the version it derives from.'
|
|
111
111
|
};
|
|
112
|
-
const witnessedByFeatures = (
|
|
113
|
-
const witnesses = witnessesOf(
|
|
112
|
+
const witnessedByFeatures = (edition, version) => {
|
|
113
|
+
const witnesses = witnessesOf(edition, version.id);
|
|
114
114
|
return witnesses.length > 0 && witnesses.every(({ by }) => by === 'statement') ? {
|
|
115
115
|
type: 'witnessed-by-statement-only',
|
|
116
116
|
note: 'No copy\'s features carry what the version inserts; only copies that state they carry it bear witness to it.'
|
|
@@ -121,8 +121,8 @@ const witnessedByFeatures = (view, version) => {
|
|
|
121
121
|
* Its text is a reconstruction from below, as a lost state's is, and
|
|
122
122
|
* nothing surviving shows it as it stood.
|
|
123
123
|
*/
|
|
124
|
-
const witnessedAtFirstHand = (
|
|
125
|
-
const carriers = witnessesOf(
|
|
124
|
+
const witnessedAtFirstHand = (edition, version) => {
|
|
125
|
+
const carriers = witnessesOf(edition, version.id).filter(({ by }) => by === 'carriers');
|
|
126
126
|
return carriers.length > 0 && carriers.every(({ through }) => through !== undefined) ? {
|
|
127
127
|
type: 'no-direct-witness',
|
|
128
128
|
note: 'No copy carries it at first hand; its text is a reconstruction from the versions derived from it.'
|
|
@@ -130,4 +130,4 @@ const witnessedAtFirstHand = (view, version) => {
|
|
|
130
130
|
};
|
|
131
131
|
const versionChecks = [textStated, witnessedByFeatures, witnessedAtFirstHand];
|
|
132
132
|
/** What the edition cannot vouch for in a version, in the order the checks are listed. */
|
|
133
|
-
export const reservationsAboutVersion = (
|
|
133
|
+
export const reservationsAboutVersion = (edition, version) => versionChecks.flatMap(check => check(edition, version) ?? []);
|
package/lib/analysis/sigla.d.ts
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { Edition } from '../model/Edition.js';
|
|
2
|
-
import { EditionView } from '../view/EditionView.js';
|
|
3
2
|
/**
|
|
4
|
-
* What the sigla are read off: the versions alone, or
|
|
5
|
-
*
|
|
3
|
+
* What the sigla are read off: the versions alone, or the edition, whose
|
|
4
|
+
* copies tell which versions a witness shows.
|
|
6
5
|
*/
|
|
7
|
-
export type Stemma = Pick<Edition, 'versions'> |
|
|
6
|
+
export type Stemma = Pick<Edition, 'versions'> | Edition;
|
|
8
7
|
/**
|
|
9
8
|
* The siglum of every version, as the stemma stands: where it sits
|
|
10
|
-
* (`alongTheStemma`) and, given
|
|
9
|
+
* (`alongTheStemma`) and, given the edition, whether any copy shows it.
|
|
11
10
|
*
|
|
12
11
|
* A version no copy's features carry at first hand is inferred, whether
|
|
13
12
|
* it is reached only through the versions derived from it or a copy does
|
package/lib/analysis/sigla.js
CHANGED
|
@@ -91,7 +91,7 @@ const alongTheStemma = (versions) => {
|
|
|
91
91
|
}
|
|
92
92
|
return sigla;
|
|
93
93
|
};
|
|
94
|
-
const
|
|
94
|
+
const holdsCopies = (stemma) => 'copies' in stemma;
|
|
95
95
|
/**
|
|
96
96
|
* The sigla with the inferred versions in lowercase, as editions mark a
|
|
97
97
|
* state nothing surviving shows. The letter still names the system and
|
|
@@ -100,7 +100,7 @@ const isView = (stemma) => !('versions' in stemma);
|
|
|
100
100
|
const marking = (sigla, attested) => new Map([...sigla].map(([id, siglum]) => [id, attested.has(id) ? siglum : siglum.toLowerCase()]));
|
|
101
101
|
/**
|
|
102
102
|
* The siglum of every version, as the stemma stands: where it sits
|
|
103
|
-
* (`alongTheStemma`) and, given
|
|
103
|
+
* (`alongTheStemma`) and, given the edition, whether any copy shows it.
|
|
104
104
|
*
|
|
105
105
|
* A version no copy's features carry at first hand is inferred, whether
|
|
106
106
|
* it is reached only through the versions derived from it or a copy does
|
|
@@ -112,8 +112,8 @@ const marking = (sigla, attested) => new Map([...sigla].map(([id, siglum]) => [i
|
|
|
112
112
|
* A siglum is computed anew when the stemma or the copies change, so
|
|
113
113
|
* nothing should cite one without saying which state it belongs to.
|
|
114
114
|
*/
|
|
115
|
-
export const siglaOf = (stemma) =>
|
|
116
|
-
? marking(alongTheStemma(stemma.
|
|
115
|
+
export const siglaOf = (stemma) => holdsCopies(stemma)
|
|
116
|
+
? marking(alongTheStemma(stemma.versions), attestedVersions(stemma))
|
|
117
117
|
: alongTheStemma(stemma.versions);
|
|
118
118
|
/** The siglum of one version as the stemma stands, or nothing where the edition holds no such version. */
|
|
119
119
|
export const siglumOf = (stemma, versionId) => siglaOf(stemma).get(versionId);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** Walking the stemma of an edition along the principal derivations. */
|
|
2
|
+
import { Edition } from "../model/Edition.js";
|
|
3
|
+
import { Version } from "../model/Version.js";
|
|
4
|
+
/**
|
|
5
|
+
* The version and its ancestors along the principal line, from the
|
|
6
|
+
* version up to the root. A stemma that loops back on itself is walked
|
|
7
|
+
* once round, so that an edition in that state can still be read and
|
|
8
|
+
* repaired.
|
|
9
|
+
*/
|
|
10
|
+
export declare const lineageOf: (edition: Pick<Edition, 'versions'>, versionId: string) => Readonly<Version>[];
|
|
11
|
+
/** The version the given one's text is read against, by its principal derivation. */
|
|
12
|
+
export declare const predecessorOf: (edition: Pick<Edition, 'versions'>, versionId: string) => Readonly<Version> | undefined;
|
|
13
|
+
/**
|
|
14
|
+
* Every version with its generation: how many principal derivations
|
|
15
|
+
* lie between it and the root. A version whose parent the edition does
|
|
16
|
+
* not hold counts as a root. In a stemma that loops, the loop is walked
|
|
17
|
+
* once round, as `lineageOf` walks it, so that the stemma of an edition
|
|
18
|
+
* in that state can still be drawn and repaired.
|
|
19
|
+
*/
|
|
20
|
+
export declare const withGenerations: (edition: Pick<Edition, 'versions'>) => Array<Version & {
|
|
21
|
+
generation: number;
|
|
22
|
+
}>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { principalDerivationOf } from "../model/Version.js";
|
|
2
|
+
import { idOf } from "../model/Assumption.js";
|
|
3
|
+
import { versionIn } from "../lookup/lookup.js";
|
|
4
|
+
/**
|
|
5
|
+
* The version and its ancestors along the principal line, from the
|
|
6
|
+
* version up to the root. A stemma that loops back on itself is walked
|
|
7
|
+
* once round, so that an edition in that state can still be read and
|
|
8
|
+
* repaired.
|
|
9
|
+
*/
|
|
10
|
+
export const lineageOf = (edition, versionId) => {
|
|
11
|
+
const lineage = [];
|
|
12
|
+
const visited = new Set();
|
|
13
|
+
let v = versionIn(edition, versionId);
|
|
14
|
+
while (v && !visited.has(v.id)) {
|
|
15
|
+
visited.add(v.id);
|
|
16
|
+
lineage.push(v);
|
|
17
|
+
const principal = principalDerivationOf(v);
|
|
18
|
+
v = principal && versionIn(edition, idOf(principal));
|
|
19
|
+
}
|
|
20
|
+
return lineage;
|
|
21
|
+
};
|
|
22
|
+
/** The version the given one's text is read against, by its principal derivation. */
|
|
23
|
+
export const predecessorOf = (edition, versionId) => {
|
|
24
|
+
const v = versionIn(edition, versionId);
|
|
25
|
+
const principal = v && principalDerivationOf(v);
|
|
26
|
+
return principal && versionIn(edition, idOf(principal));
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Every version with its generation: how many principal derivations
|
|
30
|
+
* lie between it and the root. A version whose parent the edition does
|
|
31
|
+
* not hold counts as a root. In a stemma that loops, the loop is walked
|
|
32
|
+
* once round, as `lineageOf` walks it, so that the stemma of an edition
|
|
33
|
+
* in that state can still be drawn and repaired.
|
|
34
|
+
*/
|
|
35
|
+
export const withGenerations = (edition) => edition.versions.map(version => ({
|
|
36
|
+
...version,
|
|
37
|
+
generation: lineageOf(edition, version.id).length - 1
|
|
38
|
+
}));
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** What a version shows, and where along the roll its symbols lie. */
|
|
2
|
+
import { Edition } from "../model/Edition.js";
|
|
3
|
+
import { FeatureOrPatch, HorizontalSpan, NestedFeature } from "../model/Feature.js";
|
|
4
|
+
import { AnySymbol } from "../model/Symbol.js";
|
|
5
|
+
import { Millimeters } from "../model/Quantity.js";
|
|
6
|
+
export declare const carriersOf: (edition: Pick<Edition, 'copies'>, symbol: AnySymbol) => Readonly<NestedFeature>[];
|
|
7
|
+
/** The carriers that state a place of their own, which a feature on a patch does not. */
|
|
8
|
+
export declare const placedCarriersOf: (edition: Pick<Edition, 'copies'>, symbol: AnySymbol) => Readonly<FeatureOrPatch>[];
|
|
9
|
+
/**
|
|
10
|
+
* Where along the roll the symbol lies, as its carriers put it, or
|
|
11
|
+
* nothing for a symbol no copy carries.
|
|
12
|
+
*
|
|
13
|
+
* Only the place is measured. Which track the symbol sits on is not
|
|
14
|
+
* a measurement but a question for a tracker bar, since a note of
|
|
15
|
+
* one pitch sits on exactly one position of a given bar: ask
|
|
16
|
+
* `bar.positionOf`. The carriers cannot answer it, because a copy
|
|
17
|
+
* cut for another system numbers its tracks differently, and one
|
|
18
|
+
* symbol may be carried by copies of both — averaging a red carrier
|
|
19
|
+
* on track 47 with a green one on 45 would give 46, a legal
|
|
20
|
+
* position a semitone away on either bar.
|
|
21
|
+
*/
|
|
22
|
+
export declare const placeOf: (edition: Pick<Edition, 'copies'>, symbol: AnySymbol) => Readonly<HorizontalSpan> | undefined;
|
|
23
|
+
/** Where the symbol begins, as the mean onset of its carriers, or nothing for a symbol without a place. */
|
|
24
|
+
export declare const onsetOf: (edition: Pick<Edition, 'copies'>, symbol: AnySymbol) => Millimeters | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* The symbols the version shows: what it and its ancestors insert,
|
|
27
|
+
* each version's deletions striking what it or its ancestors inserted.
|
|
28
|
+
* They are worked out once for each state of the edition, and the list
|
|
29
|
+
* is frozen, since everyone who asks is handed the same one.
|
|
30
|
+
*/
|
|
31
|
+
export declare const snapshotOf: (edition: Edition, versionId: string) => readonly Readonly<AnySymbol>[];
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { isPlaced } from "../model/Feature.js";
|
|
2
|
+
import { deletedBy, insertedBy } from "../model/Version.js";
|
|
3
|
+
import { idsOf } from "../model/Assumption.js";
|
|
4
|
+
import { mean } from "../model/Quantity.js";
|
|
5
|
+
import { featuresIn } from "../lookup/lookup.js";
|
|
6
|
+
import { perState } from "../lookup/perState.js";
|
|
7
|
+
import { lineageOf } from "./stemma.js";
|
|
8
|
+
export const carriersOf = (edition, symbol) => featuresIn(edition, idsOf(symbol.carriers));
|
|
9
|
+
/** The carriers that state a place of their own, which a feature on a patch does not. */
|
|
10
|
+
export const placedCarriersOf = (edition, symbol) => carriersOf(edition, symbol).filter(isPlaced);
|
|
11
|
+
/**
|
|
12
|
+
* Where along the roll the symbol lies, as its carriers put it, or
|
|
13
|
+
* nothing for a symbol no copy carries.
|
|
14
|
+
*
|
|
15
|
+
* Only the place is measured. Which track the symbol sits on is not
|
|
16
|
+
* a measurement but a question for a tracker bar, since a note of
|
|
17
|
+
* one pitch sits on exactly one position of a given bar: ask
|
|
18
|
+
* `bar.positionOf`. The carriers cannot answer it, because a copy
|
|
19
|
+
* cut for another system numbers its tracks differently, and one
|
|
20
|
+
* symbol may be carried by copies of both — averaging a red carrier
|
|
21
|
+
* on track 47 with a green one on 45 would give 46, a legal
|
|
22
|
+
* position a semitone away on either bar.
|
|
23
|
+
*/
|
|
24
|
+
export const placeOf = (edition, symbol) => {
|
|
25
|
+
const carriers = placedCarriersOf(edition, symbol);
|
|
26
|
+
if (carriers.length === 0)
|
|
27
|
+
return;
|
|
28
|
+
return {
|
|
29
|
+
unit: 'mm',
|
|
30
|
+
from: mean(carriers.map(carrier => carrier.horizontal.from)),
|
|
31
|
+
to: mean(carriers.map(carrier => carrier.horizontal.to))
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
/** Where the symbol begins, as the mean onset of its carriers, or nothing for a symbol without a place. */
|
|
35
|
+
export const onsetOf = (edition, symbol) => placeOf(edition, symbol)?.from;
|
|
36
|
+
/** The symbols by onset, those without a place first; symbols at one place keep their order. */
|
|
37
|
+
const inOrderOfPlace = (edition, symbols) => symbols
|
|
38
|
+
.map(symbol => ({ symbol, at: onsetOf(edition, symbol) || 0 }))
|
|
39
|
+
.sort((a, b) => a.at - b.at)
|
|
40
|
+
.map(({ symbol }) => symbol);
|
|
41
|
+
/** The snapshots of a state asked for so far, by version. */
|
|
42
|
+
const snapshotsIn = perState((_) => new Map());
|
|
43
|
+
/**
|
|
44
|
+
* The symbols the version shows: what it and its ancestors insert,
|
|
45
|
+
* each version's deletions striking what it or its ancestors inserted.
|
|
46
|
+
* They are worked out once for each state of the edition, and the list
|
|
47
|
+
* is frozen, since everyone who asks is handed the same one.
|
|
48
|
+
*/
|
|
49
|
+
export const snapshotOf = (edition, versionId) => {
|
|
50
|
+
const known = snapshotsIn(edition);
|
|
51
|
+
const kept = known.get(versionId);
|
|
52
|
+
if (kept)
|
|
53
|
+
return kept;
|
|
54
|
+
const deleted = new Set();
|
|
55
|
+
const symbols = lineageOf(edition, versionId).flatMap(version => {
|
|
56
|
+
deletedBy(version).forEach(id => deleted.add(id));
|
|
57
|
+
return insertedBy(version).filter(symbol => !deleted.has(symbol.id));
|
|
58
|
+
});
|
|
59
|
+
const snapshot = Object.freeze(inOrderOfPlace(edition, symbols));
|
|
60
|
+
known.set(versionId, snapshot);
|
|
61
|
+
return snapshot;
|
|
62
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Belief, Certainty } from "../model/Assumption.js";
|
|
2
|
-
import {
|
|
2
|
+
import { Edition } from "../model/Edition.js";
|
|
3
3
|
export type WitnessBy = 'carriers' | 'statement';
|
|
4
4
|
/** A copy that bears witness to a version, and how. */
|
|
5
5
|
export interface Witness {
|
|
@@ -25,7 +25,7 @@ export interface Witness {
|
|
|
25
25
|
* the versions derived from it, or is attested by statement alone, and
|
|
26
26
|
* its text is a reconstruction rather than a reading.
|
|
27
27
|
*/
|
|
28
|
-
export declare const attestedVersions: (
|
|
28
|
+
export declare const attestedVersions: (edition: Edition) => ReadonlySet<string>;
|
|
29
29
|
/**
|
|
30
30
|
* The copies that bear witness to the version: those whose features carry
|
|
31
31
|
* a symbol the version's own edits insert, and those that state they carry
|
|
@@ -44,12 +44,12 @@ export declare const attestedVersions: (view: EditionView) => ReadonlySet<string
|
|
|
44
44
|
* reported as it stands. A version whose edits are not stated inserts
|
|
45
45
|
* nothing and is witnessed by statement alone.
|
|
46
46
|
*/
|
|
47
|
-
export declare const witnessesOf: (
|
|
47
|
+
export declare const witnessesOf: (edition: Edition, versionId: string) => Witness[];
|
|
48
48
|
/**
|
|
49
49
|
* The versions the copy bears witness to, each with how, in the order the
|
|
50
50
|
* edition lists its versions.
|
|
51
51
|
*/
|
|
52
|
-
export declare const versionsWitnessedBy: (
|
|
52
|
+
export declare const versionsWitnessedBy: (edition: Edition, copyId: string) => (Witness & {
|
|
53
53
|
version: string;
|
|
54
54
|
})[];
|
|
55
55
|
export type CarriageProblem = {
|
|
@@ -62,4 +62,4 @@ export type CarriageProblem = {
|
|
|
62
62
|
* made although the copy's features carry symbols, which say by
|
|
63
63
|
* themselves what it carries, and one naming a version the edition lacks.
|
|
64
64
|
*/
|
|
65
|
-
export declare const carriageProblems: (
|
|
65
|
+
export declare const carriageProblems: (edition: Edition) => CarriageProblem[];
|
|
@@ -1,24 +1,26 @@
|
|
|
1
1
|
import { certaintyOf, idOf, idsOf } from "../model/Assumption.js";
|
|
2
2
|
import { insertedBy } from "../model/Version.js";
|
|
3
|
+
import { lineageOf } from "./stemma.js";
|
|
4
|
+
import { copyOfFeature, versionIn } from "../lookup/lookup.js";
|
|
3
5
|
/** The copies whose features carry any of the symbols. */
|
|
4
|
-
const copiesCarrying = (
|
|
6
|
+
const copiesCarrying = (edition, symbols) => new Set(symbols
|
|
5
7
|
.flatMap(symbol => idsOf(symbol.carriers))
|
|
6
8
|
.flatMap(id => {
|
|
7
|
-
const copy =
|
|
9
|
+
const copy = copyOfFeature(edition, id);
|
|
8
10
|
return copy ? [copy.id] : [];
|
|
9
11
|
}));
|
|
10
12
|
/** Every copy carrying what a version inserts, version by version, the copies in the order the edition lists them. */
|
|
11
|
-
const carriagesIn = (
|
|
12
|
-
const carrying = copiesCarrying(
|
|
13
|
-
const depth =
|
|
14
|
-
return
|
|
13
|
+
const carriagesIn = (edition) => edition.versions.flatMap(version => {
|
|
14
|
+
const carrying = copiesCarrying(edition, insertedBy(version));
|
|
15
|
+
const depth = lineageOf(edition, version.id).length;
|
|
16
|
+
return edition.copies
|
|
15
17
|
.filter(copy => carrying.has(copy.id))
|
|
16
18
|
.map((copy) => ({ copy: copy.id, version: version.id, depth }));
|
|
17
19
|
});
|
|
18
|
-
const carriersIn = (
|
|
19
|
-
const carriages = carriagesIn(
|
|
20
|
+
const carriersIn = (edition) => {
|
|
21
|
+
const carriages = carriagesIn(edition);
|
|
20
22
|
return {
|
|
21
|
-
copiesOf: new Map(
|
|
23
|
+
copiesOf: new Map(edition.versions.map(version => [
|
|
22
24
|
version.id,
|
|
23
25
|
carriages.filter(carriage => carriage.version === version.id).map(carriage => carriage.copy)
|
|
24
26
|
])),
|
|
@@ -34,15 +36,15 @@ const carriersIn = (view) => {
|
|
|
34
36
|
* the versions derived from it, or is attested by statement alone, and
|
|
35
37
|
* its text is a reconstruction rather than a reading.
|
|
36
38
|
*/
|
|
37
|
-
export const attestedVersions = (
|
|
38
|
-
const witnessesIn = (carriers,
|
|
39
|
+
export const attestedVersions = (edition) => new Set(carriersIn(edition).latestOf.values());
|
|
40
|
+
const witnessesIn = (carriers, edition, versionId) => {
|
|
39
41
|
const carrying = carriers.copiesOf.get(versionId) ?? [];
|
|
40
42
|
const byCarriers = carrying.map((copy) => {
|
|
41
43
|
const latest = carriers.latestOf.get(copy);
|
|
42
44
|
return { copy, by: 'carriers', ...(latest !== undefined && latest !== versionId && { through: latest }) };
|
|
43
45
|
});
|
|
44
46
|
const carryingIt = new Set(carrying);
|
|
45
|
-
const byStatement =
|
|
47
|
+
const byStatement = edition.copies
|
|
46
48
|
.filter(copy => !carryingIt.has(copy.id))
|
|
47
49
|
.flatMap(copy => (copy.carries ?? [])
|
|
48
50
|
.filter(statement => idOf(statement) === versionId)
|
|
@@ -70,14 +72,14 @@ const witnessesIn = (carriers, view, versionId) => {
|
|
|
70
72
|
* reported as it stands. A version whose edits are not stated inserts
|
|
71
73
|
* nothing and is witnessed by statement alone.
|
|
72
74
|
*/
|
|
73
|
-
export const witnessesOf = (
|
|
75
|
+
export const witnessesOf = (edition, versionId) => versionIn(edition, versionId) ? witnessesIn(carriersIn(edition), edition, versionId) : [];
|
|
74
76
|
/**
|
|
75
77
|
* The versions the copy bears witness to, each with how, in the order the
|
|
76
78
|
* edition lists its versions.
|
|
77
79
|
*/
|
|
78
|
-
export const versionsWitnessedBy = (
|
|
79
|
-
const carriers = carriersIn(
|
|
80
|
-
return
|
|
80
|
+
export const versionsWitnessedBy = (edition, copyId) => {
|
|
81
|
+
const carriers = carriersIn(edition);
|
|
82
|
+
return edition.versions.flatMap(version => witnessesIn(carriers, edition, version.id)
|
|
81
83
|
.filter(witness => witness.copy === copyId)
|
|
82
84
|
.map(witness => ({ ...witness, version: version.id })));
|
|
83
85
|
};
|
|
@@ -86,13 +88,13 @@ export const versionsWitnessedBy = (view, copyId) => {
|
|
|
86
88
|
* made although the copy's features carry symbols, which say by
|
|
87
89
|
* themselves what it carries, and one naming a version the edition lacks.
|
|
88
90
|
*/
|
|
89
|
-
export const carriageProblems = (
|
|
90
|
-
const carrying = copiesCarrying(
|
|
91
|
-
return
|
|
91
|
+
export const carriageProblems = (edition) => {
|
|
92
|
+
const carrying = copiesCarrying(edition, edition.versions.flatMap(insertedBy));
|
|
93
|
+
return edition.copies.flatMap(copy => (copy.carries ?? []).flatMap((statement) => {
|
|
92
94
|
const version = idOf(statement);
|
|
93
95
|
return [
|
|
94
96
|
...(carrying.has(copy.id) ? [{ copy: copy.id, version, problem: 'stated-beside-carriers' }] : []),
|
|
95
|
-
...(
|
|
97
|
+
...(versionIn(edition, version) ? [] : [{ copy: copy.id, version, problem: 'version-missing' }])
|
|
96
98
|
];
|
|
97
99
|
}));
|
|
98
100
|
};
|
|
@@ -1,14 +1,34 @@
|
|
|
1
1
|
import { FeatureOrPatch } from "../model/Feature.js";
|
|
2
|
-
import {
|
|
2
|
+
import { Alignment, RollCopy } from "../model/RollCopy.js";
|
|
3
3
|
import { TrackerBar } from "../systems/TrackerBar.js";
|
|
4
4
|
import { Millimeters } from "../model/Quantity.js";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
5
|
+
/** A place on the copy's own paper, on the edition's axis. */
|
|
6
|
+
export declare const toAxis: (alignment: Alignment | undefined) => (place: Millimeters) => Millimeters;
|
|
7
|
+
/** A place on the edition's axis, on the copy's own paper. */
|
|
8
|
+
export declare const fromAxis: (alignment: Alignment | undefined) => (place: Millimeters) => Millimeters;
|
|
9
|
+
/**
|
|
10
|
+
* Carries the copy's features and tears from its own places onto the
|
|
11
|
+
* axis, and records how, in place of any alignment it had: that one is
|
|
12
|
+
* taken off first.
|
|
13
|
+
*/
|
|
14
|
+
export declare const applyAlignment: (alignment: Alignment, copy: RollCopy) => void;
|
|
15
|
+
/** Takes the copy's features and tears back to its own places, as far as it was aligned. */
|
|
16
|
+
export declare const revertAlignment: (copy: RollCopy) => void;
|
|
17
|
+
/**
|
|
18
|
+
* The copy with its features and tears at its own places, as a document
|
|
19
|
+
* holds them, and its alignment kept to say how they go onto the axis.
|
|
20
|
+
* The copy given is left as it is. A copy that is not aligned is the
|
|
21
|
+
* very same copy.
|
|
22
|
+
*/
|
|
23
|
+
export declare const atOwnPlaces: (copy: RollCopy) => RollCopy;
|
|
24
|
+
/**
|
|
25
|
+
* Puts the features and tears of a copy read from a document, which
|
|
26
|
+
* holds them at the copy's own places, onto the axis. The copy given is
|
|
27
|
+
* changed.
|
|
28
|
+
*/
|
|
29
|
+
export declare const putOnAxis: (copy: RollCopy) => void;
|
|
30
|
+
/** The copy's features at its own places, as it was read, whatever alignment it has. */
|
|
31
|
+
export declare const ownFeaturesOf: (copy: RollCopy) => FeatureOrPatch[];
|
|
12
32
|
/**
|
|
13
33
|
* Takes the extension a pneumatic reader adds off the ends of the
|
|
14
34
|
* copy's chains of holes, and records how much was taken.
|
|
@@ -59,6 +79,16 @@ export declare const tooShortToShorten: (extension: Millimeters, copy: RollCopy,
|
|
|
59
79
|
export declare const shortenChains: (extension: Millimeters, copy: RollCopy, leaving?: ReadonlySet<string>) => void;
|
|
60
80
|
/** Puts the reader's extension back on the chains it was taken off, as far as one was taken off. */
|
|
61
81
|
export declare const revertShortening: (copy: RollCopy) => void;
|
|
82
|
+
/**
|
|
83
|
+
* The method `alignFeatures` follows, as an alignment records it. Its
|
|
84
|
+
* revision changes when the method does and at no other release, so
|
|
85
|
+
* that an alignment found by an earlier method can be told from one
|
|
86
|
+
* that would be found again as it stands.
|
|
87
|
+
*/
|
|
88
|
+
export declare const ALIGNMENT_METHOD: {
|
|
89
|
+
readonly software: 'linked-rolls alignFeatures';
|
|
90
|
+
readonly version: '1';
|
|
91
|
+
};
|
|
62
92
|
/**
|
|
63
93
|
* How a copy's places are carried onto another copy's:
|
|
64
94
|
* `x_other = (x + shift) · scale`.
|
|
@@ -71,6 +101,14 @@ export interface AlignmentResult {
|
|
|
71
101
|
matched: number;
|
|
72
102
|
/** How far the counterparts still lie apart, as a root mean square in the other copy's millimetres. */
|
|
73
103
|
residual: Millimeters;
|
|
104
|
+
/**
|
|
105
|
+
* The standard error of the scale, as for a line of least squares
|
|
106
|
+
* through the matches: the residual over the spread of the matched
|
|
107
|
+
* notes along the copy, and over the root of their number. The
|
|
108
|
+
* robust line is fitted otherwise, but on Welte 225 this comes
|
|
109
|
+
* within a few per cent of what resampling the matches gives.
|
|
110
|
+
*/
|
|
111
|
+
scaleError: number;
|
|
74
112
|
}
|
|
75
113
|
/**
|
|
76
114
|
* Finds the shift and scale that carry the places of `rollA` onto those
|