@willcgage/module-schematic 0.13.2 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +68 -36
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +31 -1
- package/dist/index.d.ts +31 -1
- package/dist/index.js +66 -37
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
+
var FREEMO_ENDPLATE_WIDTH_MIN_INCHES = 12;
|
|
5
|
+
var FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES = 24;
|
|
6
|
+
function endplateWidthInches(ep) {
|
|
7
|
+
const w = ep?.widthInches;
|
|
8
|
+
return typeof w === "number" && w > 0 ? w : FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES;
|
|
9
|
+
}
|
|
4
10
|
function isLoopDoc(doc) {
|
|
5
11
|
return doc.loop === true || doc.endplates.length === 1;
|
|
6
12
|
}
|
|
@@ -32,6 +38,7 @@ function emptyEditorState(lengthInches) {
|
|
|
32
38
|
crossings: [],
|
|
33
39
|
branches: [],
|
|
34
40
|
poseOverrides: {},
|
|
41
|
+
endplateWidths: {},
|
|
35
42
|
controlPoints: []
|
|
36
43
|
};
|
|
37
44
|
}
|
|
@@ -41,7 +48,7 @@ function isTransitionTurnout(t) {
|
|
|
41
48
|
function main2Track(state) {
|
|
42
49
|
const bothDouble = state.configA === "double" && state.configB === "double";
|
|
43
50
|
const sw = state.turnouts.find(isTransitionTurnout);
|
|
44
|
-
if (bothDouble || !sw) {
|
|
51
|
+
if (bothDouble || !sw || sw.divergeTrack !== MAIN2_TRACK_ID) {
|
|
45
52
|
return { id: MAIN2_TRACK_ID, role: "main", lane: 1, from: "A", to: "B" };
|
|
46
53
|
}
|
|
47
54
|
return state.configA === "double" ? (
|
|
@@ -93,6 +100,12 @@ function withPoses(endplates, overrides) {
|
|
|
93
100
|
(e) => overrides[e.id] ? { ...e, pose: overrides[e.id] } : e
|
|
94
101
|
);
|
|
95
102
|
}
|
|
103
|
+
function withWidths(endplates, widths) {
|
|
104
|
+
return endplates.map((e) => {
|
|
105
|
+
const w = widths[e.id];
|
|
106
|
+
return typeof w === "number" && w > 0 ? { ...e, widthInches: w } : e;
|
|
107
|
+
});
|
|
108
|
+
}
|
|
96
109
|
function stateToDoc(state, recordNumber) {
|
|
97
110
|
return {
|
|
98
111
|
version: 1,
|
|
@@ -100,42 +113,45 @@ function stateToDoc(state, recordNumber) {
|
|
|
100
113
|
lengthInches: state.lengthInches,
|
|
101
114
|
...state.loop ? { loop: true } : {},
|
|
102
115
|
...state.loop && state.loopReturn === "main2" ? { loopReturn: "main2" } : {},
|
|
103
|
-
endplates:
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
) : [
|
|
114
|
-
{ id: "A", label: "West", tracks: [{ trackId: MAIN_TRACK_ID, lane: 0, config: state.configA }] },
|
|
115
|
-
// Non-loop modules always have a real B ("none" never applies).
|
|
116
|
-
{
|
|
117
|
-
id: "B",
|
|
118
|
-
label: "East",
|
|
119
|
-
tracks: [
|
|
120
|
-
{
|
|
121
|
-
trackId: MAIN_TRACK_ID,
|
|
122
|
-
lane: 0,
|
|
123
|
-
config: state.configB === "none" ? "single" : state.configB
|
|
124
|
-
}
|
|
116
|
+
endplates: withWidths(
|
|
117
|
+
withPoses(
|
|
118
|
+
[
|
|
119
|
+
...state.loop ? (
|
|
120
|
+
// Balloon loop: A is the entry. A standard endplate B on the balloon
|
|
121
|
+
// makes it an INTERCHANGE (second route connects at the loop, e.g.
|
|
122
|
+
// Seaford); configB "none" makes it a pure turnback.
|
|
123
|
+
[
|
|
124
|
+
{ id: "A", label: "Entry", tracks: [{ trackId: MAIN_TRACK_ID, lane: 0, config: state.configA }] },
|
|
125
|
+
...state.configB !== "none" ? [{ id: "B", label: "Interchange", tracks: [{ trackId: MAIN_TRACK_ID, lane: 0, config: state.configB }] }] : []
|
|
125
126
|
]
|
|
126
|
-
|
|
127
|
+
) : [
|
|
128
|
+
{ id: "A", label: "West", tracks: [{ trackId: MAIN_TRACK_ID, lane: 0, config: state.configA }] },
|
|
129
|
+
// Non-loop modules always have a real B ("none" never applies).
|
|
130
|
+
{
|
|
131
|
+
id: "B",
|
|
132
|
+
label: "East",
|
|
133
|
+
tracks: [
|
|
134
|
+
{
|
|
135
|
+
trackId: MAIN_TRACK_ID,
|
|
136
|
+
lane: 0,
|
|
137
|
+
config: state.configB === "none" ? "single" : state.configB
|
|
138
|
+
}
|
|
139
|
+
]
|
|
140
|
+
}
|
|
141
|
+
],
|
|
142
|
+
// Branch endplates C, D, … — junction connections at pos, off one side
|
|
143
|
+
// (#170). A set can carry several (e.g. a second railroad through).
|
|
144
|
+
...state.branches.map((b, i) => ({
|
|
145
|
+
id: String.fromCharCode(67 + i),
|
|
146
|
+
// C, D, E…
|
|
147
|
+
label: b.label || `Branch ${i + 1}`,
|
|
148
|
+
tracks: [{ trackId: MAIN_TRACK_ID, lane: 0, config: b.config }],
|
|
149
|
+
at: { pos: b.pos, side: b.side }
|
|
150
|
+
}))
|
|
127
151
|
],
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
id: String.fromCharCode(67 + i),
|
|
132
|
-
// C, D, E…
|
|
133
|
-
label: b.label || `Branch ${i + 1}`,
|
|
134
|
-
tracks: [{ trackId: MAIN_TRACK_ID, lane: 0, config: b.config }],
|
|
135
|
-
at: { pos: b.pos, side: b.side }
|
|
136
|
-
}))
|
|
137
|
-
],
|
|
138
|
-
state.poseOverrides
|
|
152
|
+
state.poseOverrides
|
|
153
|
+
),
|
|
154
|
+
state.endplateWidths
|
|
139
155
|
),
|
|
140
156
|
tracks: [
|
|
141
157
|
state.loop ? (
|
|
@@ -261,6 +277,11 @@ function docToState(doc, fallbackLength, moduleTracks = []) {
|
|
|
261
277
|
(e) => e.id !== "A" && e.id !== "B" && e.at
|
|
262
278
|
);
|
|
263
279
|
const poseOverrides = poseOverridesFromDoc(d);
|
|
280
|
+
const endplateWidths = {};
|
|
281
|
+
for (const e of d.endplates ?? []) {
|
|
282
|
+
if (typeof e.widthInches === "number" && e.widthInches > 0)
|
|
283
|
+
endplateWidths[e.id] = e.widthInches;
|
|
284
|
+
}
|
|
264
285
|
return {
|
|
265
286
|
lengthInches: len,
|
|
266
287
|
loop,
|
|
@@ -275,6 +296,7 @@ function docToState(doc, fallbackLength, moduleTracks = []) {
|
|
|
275
296
|
config: ep.tracks?.[0]?.config === "double" ? "double" : "single"
|
|
276
297
|
})),
|
|
277
298
|
poseOverrides,
|
|
299
|
+
endplateWidths,
|
|
278
300
|
crossings: (d.crossings ?? []).map((x) => ({
|
|
279
301
|
id: x.id,
|
|
280
302
|
name: x.name ?? "",
|
|
@@ -607,13 +629,20 @@ function moduleFeatures(doc) {
|
|
|
607
629
|
fromFrac: clampFrac(main2.fromPos ?? 0),
|
|
608
630
|
toFrac: clampFrac(main2.toPos ?? len)
|
|
609
631
|
};
|
|
610
|
-
} else if (main2 && transitionSw && !loop) {
|
|
632
|
+
} else if (main2 && transitionSw && transitionSw.divergeTrack === MAIN2_TRACK_ID && !loop) {
|
|
611
633
|
main2Extent = aDbl ? { fromFrac: 0, toFrac: clampFrac(transitionSw.pos) } : { fromFrac: clampFrac(transitionSw.pos), toFrac: 1 };
|
|
612
634
|
}
|
|
635
|
+
const transition = transitionSw && aDbl !== bDbl && !loop ? {
|
|
636
|
+
throughLane: trackLane.get(transitionSw.onTrack) ?? 0,
|
|
637
|
+
branchLane: trackLane.get(transitionSw.divergeTrack) ?? 1,
|
|
638
|
+
atFrac: clampFrac(transitionSw.pos),
|
|
639
|
+
doubleSide: aDbl ? "west" : "east"
|
|
640
|
+
} : null;
|
|
613
641
|
return {
|
|
614
642
|
doubleMain,
|
|
615
643
|
loop,
|
|
616
644
|
main2Extent,
|
|
645
|
+
transition,
|
|
617
646
|
loopInterchange: loop && doc.endplates.filter((e) => !e.at).length >= 2,
|
|
618
647
|
loopReturn: loop && doc.loopReturn === "main2" ? "main2" : "same",
|
|
619
648
|
loopRender: loop ? doc.loopRender ?? null : null,
|
|
@@ -725,6 +754,8 @@ function poseOverridesFromDoc(doc) {
|
|
|
725
754
|
return out;
|
|
726
755
|
}
|
|
727
756
|
|
|
757
|
+
exports.FREEMO_ENDPLATE_WIDTH_MIN_INCHES = FREEMO_ENDPLATE_WIDTH_MIN_INCHES;
|
|
758
|
+
exports.FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES = FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES;
|
|
728
759
|
exports.MAIN2_TRACK_ID = MAIN2_TRACK_ID;
|
|
729
760
|
exports.MAIN_TRACK_ID = MAIN_TRACK_ID;
|
|
730
761
|
exports.N_SCALE_RATIO = N_SCALE_RATIO;
|
|
@@ -736,6 +767,7 @@ exports.deriveEndplatePoses = deriveEndplatePoses;
|
|
|
736
767
|
exports.divergeSideForHand = divergeSideForHand;
|
|
737
768
|
exports.docToState = docToState;
|
|
738
769
|
exports.emptyEditorState = emptyEditorState;
|
|
770
|
+
exports.endplateWidthInches = endplateWidthInches;
|
|
739
771
|
exports.geometryTurnDegrees = geometryTurnDegrees;
|
|
740
772
|
exports.inchesToScaleFeet = inchesToScaleFeet;
|
|
741
773
|
exports.isLoopDoc = isLoopDoc;
|