linked-rolls 0.0.1 → 0.1.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.
Files changed (67) hide show
  1. package/README.md +48 -1
  2. package/lib/Assumption.d.ts +124 -0
  3. package/lib/Assumption.js +34 -0
  4. package/lib/Collation.d.ts +11 -0
  5. package/lib/ConditionState.d.ts +8 -3
  6. package/lib/ConditionState.js +0 -5
  7. package/lib/Edit.d.ts +44 -14
  8. package/lib/Edit.js +2 -95
  9. package/lib/Edition.d.ts +144 -4
  10. package/lib/EditionView.d.ts +51 -0
  11. package/lib/EditionView.js +294 -0
  12. package/lib/Emulation.d.ts +21 -68
  13. package/lib/Emulation.js +94 -386
  14. package/lib/Feature.d.ts +137 -16
  15. package/lib/Feature.js +9 -1
  16. package/lib/Plan.d.ts +190 -0
  17. package/lib/Plan.js +555 -0
  18. package/lib/ReproducingSystem.d.ts +80 -0
  19. package/lib/RollCopy.d.ts +259 -24
  20. package/lib/RollCopy.js +232 -215
  21. package/lib/Symbol.d.ts +70 -37
  22. package/lib/Symbol.js +2 -27
  23. package/lib/TrackCalibration.d.ts +33 -0
  24. package/lib/TrackCalibration.js +14 -0
  25. package/lib/TrackerBar.d.ts +52 -5
  26. package/lib/TrackerBar.js +70 -49
  27. package/lib/Version.d.ts +32 -33
  28. package/lib/Version.js +3 -209
  29. package/lib/alignFeatures.d.ts +3 -2
  30. package/lib/alignFeatures.js +5 -4
  31. package/lib/asJsonLd.d.ts +1 -1
  32. package/lib/asJsonLd.js +13 -26
  33. package/lib/importJsonLd.d.ts +0 -1
  34. package/lib/importJsonLd.js +9 -72
  35. package/lib/index.d.ts +7 -3
  36. package/lib/index.js +7 -3
  37. package/lib/schema.json +1739 -0
  38. package/lib/spec/context.json +125 -144
  39. package/lib/systems/welteT100.d.ts +55 -0
  40. package/lib/systems/welteT100.js +191 -0
  41. package/lib/utils.d.ts +29 -0
  42. package/lib/validate.d.ts +3 -0
  43. package/lib/validate.js +10 -0
  44. package/package.json +41 -8
  45. package/lib/Condition.d.ts +0 -10
  46. package/lib/EditorialAssumption.d.ts +0 -67
  47. package/lib/EditorialAssumption.js +0 -26
  48. package/lib/Measurement.d.ts +0 -9
  49. package/lib/PlaceTimeConversion.d.ts +0 -65
  50. package/lib/PlaceTimeConversion.js +0 -175
  51. package/lib/RollEvent.d.ts +0 -76
  52. package/lib/RollEvent.js +0 -3
  53. package/lib/Stage.d.ts +0 -37
  54. package/lib/Stage.js +0 -165
  55. package/lib/Transcription.d.ts +0 -7
  56. package/lib/Transcription.js +0 -9
  57. package/lib/WithId.d.ts +0 -3
  58. package/lib/WithId.js +0 -1
  59. package/lib/alignRolls.d.ts +0 -7
  60. package/lib/alignRolls.js +0 -49
  61. package/lib/alignSymbols.d.ts +0 -7
  62. package/lib/alignSymbols.js +0 -49
  63. package/lib/aton/AtonParser.test.d.ts +0 -1
  64. package/lib/aton/AtonParser.test.js +0 -16
  65. package/lib/build-schema.cjs +0 -113
  66. /package/lib/{Condition.js → ReproducingSystem.js} +0 -0
  67. /package/lib/{Measurement.js → utils.js} +0 -0
package/lib/Stage.js DELETED
@@ -1,165 +0,0 @@
1
- import { v4 } from "uuid";
2
- import { flat } from "./EditorialAssumption";
3
- import { dimensionOf } from "./Symbol";
4
- const versionType = [
5
- /**
6
- * The roll is in a state where it is used as
7
- * the master roll for several new reproductions.
8
- */
9
- 'edition',
10
- /**
11
- * This denotes a stage which is specific to (early)
12
- * Welte-Mignon piano rolls, where rolls inteded to
13
- * be pulished are revised by a controller first. These
14
- * rolls typically carry a "controlliert" stamp. The
15
- * revision is done on the same date as the perforation
16
- * and the date is written on the roll towards its end.
17
- */
18
- 'authorised-revision',
19
- /**
20
- * Unauthorised revisions are those, which cannot be linked
21
- * to a specific controller and are likely done by
22
- * a later, anonymous hand.
23
- */
24
- 'unauthorised-revision',
25
- /**
26
- * In the case of Welte Mignon rolls, glosses are
27
- * typically comments about the roll's condition, added
28
- * e.g. by the collector.
29
- */
30
- 'gloss'
31
- ];
32
- export const traverseStages = (stage, callback) => {
33
- callback(stage);
34
- if (stage.basedOn) {
35
- traverseStages(flat(stage.basedOn), callback);
36
- }
37
- };
38
- export const getSnapshot = (stage) => {
39
- const snapshot = [];
40
- const toDelete = [];
41
- traverseStages(stage, s => {
42
- snapshot.push(...s.edits.flatMap(edit => edit.insert || []));
43
- // as we travel further up, remove symbols that are
44
- // deleted in the stages further down
45
- const deleted = [];
46
- for (const toRemove of toDelete) {
47
- const index = snapshot.findIndex(s => s === toRemove);
48
- if (index !== -1) {
49
- snapshot.splice(index, 1);
50
- deleted.push(toRemove);
51
- }
52
- }
53
- for (const del of deleted) {
54
- toDelete.splice(toDelete.indexOf(del), 1);
55
- }
56
- // collect symbols that are deleted in the current stage
57
- toDelete.push(...s.edits.flatMap(edit => edit.delete || []));
58
- });
59
- return snapshot.sort((a, b) => {
60
- const aDimension = dimensionOf(a);
61
- const bDimension = dimensionOf(b);
62
- return aDimension.horizontal.from - bDimension.horizontal.from;
63
- });
64
- };
65
- const isCollatable = (symbolA, symbolB) => {
66
- // two symbols are collatible if they share the same
67
- // symbol characteristics (pitch, expression type etc.)
68
- // and occur in the same horizontal position.
69
- if (symbolA.type === 'note' && symbolB.type === 'note') {
70
- if (symbolA.pitch !== symbolB.pitch)
71
- return false;
72
- }
73
- else if (symbolA.type === 'expression' && symbolB.type === 'expression') {
74
- if (symbolA.expressionType !== symbolB.expressionType)
75
- return false;
76
- if (symbolA.scope !== symbolB.scope)
77
- return false;
78
- }
79
- const dimensionA = dimensionOf(symbolA);
80
- const dimensionB = dimensionOf(symbolB);
81
- const distanceStart = Math.abs(dimensionA.horizontal.from - dimensionB.horizontal.from);
82
- const distanceEnd = Math.abs(dimensionA.horizontal.to - dimensionB.horizontal.to);
83
- if (distanceStart > 5 || distanceEnd > 5) {
84
- // the symbols are too far apart to be collated
85
- return false;
86
- }
87
- return true;
88
- };
89
- const overlaps = (a, b) => {
90
- const overlapsDimension = (a, b) => (a.from ?? 0) < (b.to ?? Infinity) && (b.from ?? 0) < (a.to ?? Infinity);
91
- return overlapsDimension(a.horizontal, b.horizontal) && overlapsDimension(a.vertical, b.vertical);
92
- };
93
- /**
94
- * Walks through the stages. If it finds a symbol that is still
95
- * part of the tradition (i.e. it is included in the current snapshot)
96
- * and is equivalent with the given symbol, it will add the feature
97
- * carrying the symbol to the collated symbol. Otherwise, the
98
- * given symbol will be added to the current stage's insertions.
99
- *
100
- * All symbols of the tradition that are not included in the given
101
- * symbols are considered to be deleted.
102
- *
103
- * @param creation
104
- * @param symbols
105
- * @returns
106
- */
107
- export function fillEdits(currentStage, symbols) {
108
- const snapshot = getSnapshot(currentStage);
109
- const treatedSymbols = [];
110
- // can it be collated with any of the symbols of
111
- // included in the current snapshot?
112
- const insertions = [...symbols];
113
- for (const symbol of symbols) {
114
- snapshot
115
- .filter(toCompare => isCollatable(symbol, toCompare))
116
- .forEach(corresp => {
117
- corresp.carriers.push(...symbol.carriers);
118
- insertions.splice(insertions.indexOf(symbol), 1);
119
- treatedSymbols.push(corresp);
120
- });
121
- }
122
- // special treatment for covers
123
- const covers = insertions.filter(symbol => symbol.type === 'cover');
124
- for (const cover of covers) {
125
- // find perforations in the snapshot that
126
- // overlap with the cover
127
- snapshot
128
- .filter(symbol => symbol.type === 'note' || symbol.type === 'expression')
129
- .map(dimensionOf)
130
- .filter(dimension => overlaps(dimension, dimensionOf(cover)))
131
- .forEach(dimension => {
132
- const coverDimension = dimensionOf(cover);
133
- // check if the cover partially covers the beginning
134
- if (dimension.horizontal.from >= coverDimension.horizontal.from &&
135
- dimension.horizontal.from <= coverDimension.horizontal.to) {
136
- // the note starts where the cover ends
137
- dimension.horizontal.from = coverDimension.horizontal.to;
138
- }
139
- // check if the cover partially covers the ending
140
- if (dimension.horizontal.to >= coverDimension.horizontal.from &&
141
- dimension.horizontal.to <= coverDimension.horizontal.to) {
142
- // the note ends where the cover starts
143
- dimension.horizontal.to = coverDimension.horizontal.from;
144
- }
145
- });
146
- insertions.splice(insertions.indexOf(cover), 1);
147
- }
148
- currentStage.edits.push(...insertions.map((symbol) => {
149
- return {
150
- insert: [symbol],
151
- delete: [],
152
- id: v4(),
153
- };
154
- }));
155
- const deletions = snapshot.filter(sym => {
156
- return !treatedSymbols.includes(sym);
157
- });
158
- for (const symbol of deletions) {
159
- currentStage.edits.push({
160
- insert: [],
161
- delete: [symbol],
162
- id: v4(),
163
- });
164
- }
165
- }
@@ -1,7 +0,0 @@
1
- import { Observation } from "./EditorialAssumption";
2
- /**
3
- * Every transcription is an I1 Argumentation.
4
- */
5
- export interface Transcription extends Observation {
6
- software?: string;
7
- }
@@ -1,9 +0,0 @@
1
- export {};
2
- // Example:
3
- // Edit -> carried out by -> "Anonym"
4
- // Edit -> concluded by -> Observation: der äußeren Erscheinung nach eine spätere Hinzufügung von unbekanntere Hand
5
- // Edit -> insert -> Symbol
6
- // Symbol -> is carried by -> Roll Feature -> condition -> damaged
7
- // Symbol -> concludedBy -> Transcription -> Die Perforationen wurden nicht präzise an die richtige Stelle gesetzt.
8
- // Wir gehen davon aus, dass sie jeweils auf der darüberliegenden Linie
9
- // platziert werden sollten.
package/lib/WithId.d.ts DELETED
@@ -1,3 +0,0 @@
1
- export interface WithId {
2
- 'id': string;
3
- }
package/lib/WithId.js DELETED
@@ -1 +0,0 @@
1
- export {};
@@ -1,7 +0,0 @@
1
- import { AnySymbol } from "./Symbol";
2
- type AlignmentResult = {
3
- shift: number;
4
- stretch: number;
5
- };
6
- export declare function alignSymbols(rollA: AnySymbol[], rollB: AnySymbol[]): AlignmentResult;
7
- export {};
package/lib/alignRolls.js DELETED
@@ -1,49 +0,0 @@
1
- import { dimensionOf } from "./Symbol";
2
- export function alignSymbols(rollA, rollB) {
3
- // 1. Only musical-note anchors
4
- const XA = rollA.filter(e => e.type === 'note').map(e => dimensionOf(e).horizontal.from);
5
- const YB = rollB.filter(e => e.type === 'note').map(e => dimensionOf(e).horizontal.from);
6
- // 2. Initial LSQ fit for x2 = A*x + B
7
- let { A, B } = fitAffine(XA, YB);
8
- let stretch = A, shift = B / A;
9
- // 3. Refinement
10
- for (let i = 0; i < 10; i++) {
11
- const transformed = XA.map(x => stretch * (x + shift));
12
- const pairs = [];
13
- for (let tx of transformed) {
14
- const nearest = findClosest(tx, YB);
15
- if (Math.abs(tx - nearest) <= 3) {
16
- pairs.push([(tx / stretch) - shift, nearest]);
17
- }
18
- }
19
- if (pairs.length < 2)
20
- break;
21
- const [Xin, Yin] = unzip(pairs);
22
- const { A: A2, B: B2 } = fitAffine(Xin, Yin);
23
- const b2 = B2 / A2;
24
- if (Math.abs(A2 - A) < 1e-6 && Math.abs(b2 - shift) < 1e-3)
25
- break;
26
- A = A2;
27
- B = B2;
28
- stretch = A;
29
- shift = b2;
30
- }
31
- return { stretch: stretch, shift: shift };
32
- }
33
- const mean = (arr) => arr.reduce((acc, val) => acc + val, 0) / arr.length;
34
- function fitAffine(X, Y) {
35
- const mx = mean(X), my = mean(Y);
36
- let num = 0, den = 0;
37
- X.forEach((x, i) => { num += (x - mx) * (Y[i] - my); den += (x - mx) ** 2; });
38
- const A = den === 0 ? 1 : num / den;
39
- const B = my - A * mx;
40
- return { A, B };
41
- }
42
- function findClosest(val, arr) {
43
- return arr.reduce((best, curr) => Math.abs(curr - val) < Math.abs(best - val) ? curr : best);
44
- }
45
- function unzip(p) {
46
- const X = [], Y = [];
47
- p.forEach(([x, y]) => { X.push(x); Y.push(y); });
48
- return [X, Y];
49
- }
@@ -1,7 +0,0 @@
1
- import { AnySymbol } from "./Symbol";
2
- type AlignmentResult = {
3
- shift: number;
4
- stretch: number;
5
- };
6
- export declare function alignSymbols(rollA: AnySymbol[], rollB: AnySymbol[]): AlignmentResult;
7
- export {};
@@ -1,49 +0,0 @@
1
- import { dimensionOf } from "./Symbol";
2
- export function alignSymbols(rollA, rollB) {
3
- // 1. Only musical-note anchors
4
- const XA = rollA.filter(e => e.type === 'note').map(e => dimensionOf(e).horizontal.from);
5
- const YB = rollB.filter(e => e.type === 'note').map(e => dimensionOf(e).horizontal.from);
6
- // 2. Initial LSQ fit for x2 = A*x + B
7
- let { A, B } = fitAffine(XA, YB);
8
- let stretch = A, shift = B / A;
9
- // 3. Refinement
10
- for (let i = 0; i < 10; i++) {
11
- const transformed = XA.map(x => stretch * (x + shift));
12
- const pairs = [];
13
- for (let tx of transformed) {
14
- const nearest = findClosest(tx, YB);
15
- if (Math.abs(tx - nearest) <= 3) {
16
- pairs.push([(tx / stretch) - shift, nearest]);
17
- }
18
- }
19
- if (pairs.length < 2)
20
- break;
21
- const [Xin, Yin] = unzip(pairs);
22
- const { A: A2, B: B2 } = fitAffine(Xin, Yin);
23
- const b2 = B2 / A2;
24
- if (Math.abs(A2 - A) < 1e-6 && Math.abs(b2 - shift) < 1e-3)
25
- break;
26
- A = A2;
27
- B = B2;
28
- stretch = A;
29
- shift = b2;
30
- }
31
- return { stretch: stretch, shift: shift };
32
- }
33
- const mean = (arr) => arr.reduce((acc, val) => acc + val, 0) / arr.length;
34
- function fitAffine(X, Y) {
35
- const mx = mean(X), my = mean(Y);
36
- let num = 0, den = 0;
37
- X.forEach((x, i) => { num += (x - mx) * (Y[i] - my); den += (x - mx) ** 2; });
38
- const A = den === 0 ? 1 : num / den;
39
- const B = my - A * mx;
40
- return { A, B };
41
- }
42
- function findClosest(val, arr) {
43
- return arr.reduce((best, curr) => Math.abs(curr - val) < Math.abs(best - val) ? curr : best);
44
- }
45
- function unzip(p) {
46
- const X = [], Y = [];
47
- p.forEach(([x, y]) => { X.push(x); Y.push(y); });
48
- return [X, Y];
49
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,16 +0,0 @@
1
- import { expect, test } from 'vitest';
2
- import { AtonParser } from './AtonParser';
3
- test('it import ATON files correctly', () => {
4
- const parser = new AtonParser();
5
- const result = parser.parse(`
6
- @key1: value1
7
- @@START: key2
8
- @key2a: value2a
9
- @key2b: value2b
10
- @key2c: value2c
11
- @@END: key2
12
- @key3: value3`);
13
- expect(result.key1).toBe('value1');
14
- expect(result.key2.key2a).toBe('value2a');
15
- expect(result.key3).toBe('value3');
16
- });
@@ -1,113 +0,0 @@
1
- "use strict";
2
- var __assign = (this && this.__assign) || function () {
3
- __assign = Object.assign || function(t) {
4
- for (var s, i = 1, n = arguments.length; i < n; i++) {
5
- s = arguments[i];
6
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
- t[p] = s[p];
8
- }
9
- return t;
10
- };
11
- return __assign.apply(this, arguments);
12
- };
13
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
- if (k2 === undefined) k2 = k;
15
- var desc = Object.getOwnPropertyDescriptor(m, k);
16
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
- desc = { enumerable: true, get: function() { return m[k]; } };
18
- }
19
- Object.defineProperty(o, k2, desc);
20
- }) : (function(o, m, k, k2) {
21
- if (k2 === undefined) k2 = k;
22
- o[k2] = m[k];
23
- }));
24
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
- Object.defineProperty(o, "default", { enumerable: true, value: v });
26
- }) : function(o, v) {
27
- o["default"] = v;
28
- });
29
- var __importStar = (this && this.__importStar) || (function () {
30
- var ownKeys = function(o) {
31
- ownKeys = Object.getOwnPropertyNames || function (o) {
32
- var ar = [];
33
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
34
- return ar;
35
- };
36
- return ownKeys(o);
37
- };
38
- return function (mod) {
39
- if (mod && mod.__esModule) return mod;
40
- var result = {};
41
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
42
- __setModuleDefault(result, mod);
43
- return result;
44
- };
45
- })();
46
- Object.defineProperty(exports, "__esModule", { value: true });
47
- // build-schema.ts
48
- var ts_json_schema_generator_1 = require("ts-json-schema-generator");
49
- var fs = __importStar(require("fs"));
50
- /** Safely check if a referenced type is an ObjectType with a string `id` property. */
51
- function refTargetsRefableObject(ref, fmt) {
52
- var _a;
53
- var target = ref.getType();
54
- // console.log('target', target, target instanceof ObjectType)
55
- // if (!(target instanceof ObjectType)) return false;
56
- // Ask the default formatter for the *object's* definition and inspect its properties.
57
- // This is safe because 'target' isn't a ReferenceType, so the built-ins will produce
58
- // the object schema (possibly via $ref creation behind the scenes).
59
- var def = fmt.getDefinition(target);
60
- console.log('def=', def);
61
- var idSchema = (_a = def === null || def === void 0 ? void 0 : def.properties) === null || _a === void 0 ? void 0 : _a.id;
62
- if (!idSchema)
63
- return false;
64
- // Accept plain string or unions that contain string
65
- return idSchema.type === "string" ||
66
- (Array.isArray(idSchema.anyOf) && idSchema.anyOf.some(function (s) { return (s === null || s === void 0 ? void 0 : s.type) === "string"; }));
67
- }
68
- /** Wrap only ReferenceType occurrences to ref-able objects as oneOf($ref, "#id"). */
69
- var RefableReferenceWrapper = /** @class */ (function () {
70
- function RefableReferenceWrapper(child) {
71
- this.child = child;
72
- }
73
- // Only intercept ReferenceType; let built-ins handle everything else.
74
- RefableReferenceWrapper.prototype.supportsType = function (type) {
75
- return type instanceof ts_json_schema_generator_1.ReferenceType;
76
- };
77
- RefableReferenceWrapper.prototype.getDefinition = function (type) {
78
- console.log('ref type', type);
79
- var isRefable = type.getType().type.type.properties.findIndex(function (p) { return p.name === 'id'; }) !== -1;
80
- // Let the built-in ReferenceTypeFormatter do its thing first ($ref, etc.)
81
- var original = this.child.getDefinition(type);
82
- // If the reference points to an object with string `id`, allow "#id" as alternative.
83
- if (isRefable) {
84
- console.log('is refable', type);
85
- // Avoid double-wrapping if something upstream already produced oneOf.
86
- if (original && original.oneOf)
87
- return original;
88
- return original;
89
- //return {
90
- // oneOf: [
91
- // original, // usually { "$ref": "#/definitions/..." }
92
- // { type: "string", pattern: "^#.+$" }, // your "#<id>" form; tighten regex if needed
93
- // ],
94
- // };
95
- }
96
- return original;
97
- };
98
- RefableReferenceWrapper.prototype.getChildren = function (type) {
99
- // Always delegate. Do NOT call .getType() here—let the chain manage traversal.
100
- return this.child.getChildren(type);
101
- };
102
- return RefableReferenceWrapper;
103
- }());
104
- // ——— Wire up the generator ———
105
- var config = __assign(__assign({}, ts_json_schema_generator_1.DEFAULT_CONFIG), { path: "../src/**/*.ts", tsconfig: "tsconfig.json", type: "Edition" });
106
- var formatter = (0, ts_json_schema_generator_1.createFormatter)(config, function (fmt, circular) {
107
- fmt.addTypeFormatter(new RefableReferenceWrapper(circular));
108
- });
109
- var program = (0, ts_json_schema_generator_1.createProgram)(config);
110
- var parser = (0, ts_json_schema_generator_1.createParser)(program, config);
111
- var generator = new ts_json_schema_generator_1.SchemaGenerator(program, parser, formatter, config);
112
- var schema = generator.createSchema(config.type);
113
- fs.writeFileSync("./context.json", JSON.stringify(schema, null, 2));
File without changes
File without changes