@willcgage/module-schematic 0.92.1 → 0.93.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 +67 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +20 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +67 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2443,6 +2443,7 @@ function snapPiece(moving, others, library = BUILT_IN_TRACK_PARTS, withinInches
|
|
|
2443
2443
|
};
|
|
2444
2444
|
}
|
|
2445
2445
|
var danglingDivergeWarning = (id) => `the route diverging at ${id} is not connected to anything`;
|
|
2446
|
+
var unreachedWarning = (id) => `${id} is not reachable from the endplate \u2014 nothing connects it`;
|
|
2446
2447
|
function walkTrackGraph(graph, pieces, startAt, library = BUILT_IN_TRACK_PARTS) {
|
|
2447
2448
|
const byKey = new Map(graph.joints.map((j) => [j.key, j]));
|
|
2448
2449
|
const pieceById = new Map(pieces.map((p) => [p.id, p]));
|
|
@@ -2580,11 +2581,14 @@ function walkTrackGraph(graph, pieces, startAt, library = BUILT_IN_TRACK_PARTS)
|
|
|
2580
2581
|
if (sw && !sw.divergeRoute) sw.divergeRoute = r.id;
|
|
2581
2582
|
}
|
|
2582
2583
|
const reached = new Set(routes.flatMap((r) => r.pieces));
|
|
2584
|
+
const unreached = [];
|
|
2583
2585
|
for (const p of pieces)
|
|
2584
|
-
if (!reached.has(p.id) && !graph.unplaceable.some((u) => u.piece === p.id))
|
|
2585
|
-
warnings.push(
|
|
2586
|
+
if (!reached.has(p.id) && !graph.unplaceable.some((u) => u.piece === p.id)) {
|
|
2587
|
+
warnings.push(unreachedWarning(p.id));
|
|
2588
|
+
unreached.push(p.id);
|
|
2589
|
+
}
|
|
2586
2590
|
for (const c of graph.conflicts) warnings.push(c.reason);
|
|
2587
|
-
return { routes, turnouts, warnings, danglingDiverges };
|
|
2591
|
+
return { routes, turnouts, warnings, danglingDiverges, unreached };
|
|
2588
2592
|
}
|
|
2589
2593
|
function resolveGraphAnchor(anchor, walk, pieces, library = BUILT_IN_TRACK_PARTS) {
|
|
2590
2594
|
const piece = pieces.find((p) => p.id === anchor.piece);
|
|
@@ -2613,14 +2617,29 @@ function graphToDoc(pieces, input) {
|
|
|
2613
2617
|
const epA = endplates[0];
|
|
2614
2618
|
const epB = endplates[1];
|
|
2615
2619
|
const main = walk.routes.find((r) => r.id === "main");
|
|
2616
|
-
const
|
|
2617
|
-
const
|
|
2620
|
+
const walk2 = input.start2 ? walkTrackGraph(graph, pieces, input.start2, library) : null;
|
|
2621
|
+
const main2 = walk2?.routes.find((r) => r.id === "main") ?? null;
|
|
2622
|
+
const claimed = new Set(walk.routes.flatMap((r) => r.pieces));
|
|
2623
|
+
if (main2 && main2.pieces.some((p) => claimed.has(p))) {
|
|
2624
|
+
warnings.push(
|
|
2625
|
+
"Main 2 starts on track that Main 1 already runs along \u2014 they are one run, not two"
|
|
2626
|
+
);
|
|
2627
|
+
}
|
|
2628
|
+
const twoMains = !!main2 && !main2.pieces.some((p) => claimed.has(p));
|
|
2629
|
+
const main2Lane = twoMains ? (graph.joints.find((j) => j.key === `${input.start2.piece}.${input.start2.joint}`)?.y ?? 1) >= 0 ? 1 : -1 : 0;
|
|
2630
|
+
const lengthInches = round(Math.max(main.toPos, twoMains ? main2.toPos : 0));
|
|
2631
|
+
const branches = [
|
|
2632
|
+
...walk.routes.filter((r) => r.id !== "main" && r.pieces.length),
|
|
2633
|
+
...twoMains ? walk2.routes.filter((r) => r.id !== "main" && r.pieces.length).map((r) => ({ ...r, id: `main2:${r.id}`, bornAt: r.bornAt })) : []
|
|
2634
|
+
];
|
|
2618
2635
|
const trackIdOf = /* @__PURE__ */ new Map([["main", MAIN_TRACK_ID]]);
|
|
2636
|
+
if (twoMains) trackIdOf.set("main2:main", MAIN2_TRACK_ID);
|
|
2619
2637
|
for (const r of branches) trackIdOf.set(r.id, r.pieces[0]);
|
|
2620
2638
|
const laneOf = (r) => {
|
|
2621
2639
|
const side = Math.sign(r.lateral) || 1;
|
|
2622
2640
|
const sameSide = branches.filter((x) => (Math.sign(x.lateral) || 1) === side).sort((a, b) => Math.abs(a.lateral) - Math.abs(b.lateral));
|
|
2623
|
-
|
|
2641
|
+
const taken = side === main2Lane ? 1 : 0;
|
|
2642
|
+
return side * (sameSide.indexOf(r) + 1 + taken);
|
|
2624
2643
|
};
|
|
2625
2644
|
const tracks = [
|
|
2626
2645
|
{
|
|
@@ -2629,7 +2648,20 @@ function graphToDoc(pieces, input) {
|
|
|
2629
2648
|
lane: 0,
|
|
2630
2649
|
from: epA?.id ?? "A",
|
|
2631
2650
|
...epB ? { to: epB.id } : {}
|
|
2632
|
-
}
|
|
2651
|
+
},
|
|
2652
|
+
...twoMains ? [
|
|
2653
|
+
{
|
|
2654
|
+
id: MAIN2_TRACK_ID,
|
|
2655
|
+
role: "main",
|
|
2656
|
+
lane: main2Lane,
|
|
2657
|
+
from: epA?.id ?? "A",
|
|
2658
|
+
...epB ? { to: epB.id } : {},
|
|
2659
|
+
// ⚠️ Its own extent, because a second main need not run the whole
|
|
2660
|
+
// module: on a transition module it starts or stops partway.
|
|
2661
|
+
fromPos: round(Math.min(main2.fromPos, main2.toPos)),
|
|
2662
|
+
toPos: round(Math.max(main2.fromPos, main2.toPos))
|
|
2663
|
+
}
|
|
2664
|
+
] : []
|
|
2633
2665
|
];
|
|
2634
2666
|
for (const r of branches) {
|
|
2635
2667
|
const id = trackIdOf.get(r.id);
|
|
@@ -2647,9 +2679,29 @@ function graphToDoc(pieces, input) {
|
|
|
2647
2679
|
...meta.moduleTrackId != null ? { moduleTrackId: meta.moduleTrackId } : {}
|
|
2648
2680
|
});
|
|
2649
2681
|
}
|
|
2682
|
+
if (walk2) {
|
|
2683
|
+
const seen = /* @__PURE__ */ new Set([
|
|
2684
|
+
...walk.routes.flatMap((r) => r.pieces),
|
|
2685
|
+
...walk2.routes.flatMap((r) => r.pieces)
|
|
2686
|
+
]);
|
|
2687
|
+
const covered = new Set([...walk.unreached, ...walk2.unreached].filter((id) => seen.has(id)));
|
|
2688
|
+
const drop = new Set([...covered].map(unreachedWarning));
|
|
2689
|
+
const d2 = new Set(walk2.danglingDiverges.map(danglingDivergeWarning));
|
|
2690
|
+
for (let i = warnings.length - 1; i >= 0; i--) if (drop.has(warnings[i])) warnings.splice(i, 1);
|
|
2691
|
+
for (const w of walk2.warnings)
|
|
2692
|
+
if (!d2.has(w) && !drop.has(w) && !warnings.includes(w)) warnings.push(w);
|
|
2693
|
+
}
|
|
2650
2694
|
const pieceById = new Map(pieces.map((p) => [p.id, p]));
|
|
2651
2695
|
const turnouts = [];
|
|
2652
|
-
|
|
2696
|
+
const allTurnouts = [
|
|
2697
|
+
...walk.turnouts,
|
|
2698
|
+
...twoMains ? walk2.turnouts.map((t) => ({
|
|
2699
|
+
...t,
|
|
2700
|
+
onRoute: t.onRoute === "main" ? "main2:main" : `main2:${t.onRoute}`,
|
|
2701
|
+
divergeRoute: t.divergeRoute ? `main2:${t.divergeRoute}` : null
|
|
2702
|
+
})) : []
|
|
2703
|
+
];
|
|
2704
|
+
for (const t of allTurnouts) {
|
|
2653
2705
|
const diverge = t.divergeRoute ? trackIdOf.get(t.divergeRoute) : void 0;
|
|
2654
2706
|
if (!diverge) {
|
|
2655
2707
|
warnings.push(
|
|
@@ -2731,7 +2783,13 @@ function deriveGraphDoc(doc, library = BUILT_IN_TRACK_PARTS) {
|
|
|
2731
2783
|
...t.moduleTrackId != null ? { moduleTrackId: t.moduleTrackId } : {}
|
|
2732
2784
|
};
|
|
2733
2785
|
}
|
|
2734
|
-
const out = graphToDoc(g.pieces, {
|
|
2786
|
+
const out = graphToDoc(g.pieces, {
|
|
2787
|
+
startAt: g.startAt,
|
|
2788
|
+
start2: g.start2 ?? null,
|
|
2789
|
+
base: doc,
|
|
2790
|
+
meta,
|
|
2791
|
+
library
|
|
2792
|
+
});
|
|
2735
2793
|
return { doc: out.doc, warnings: out.warnings };
|
|
2736
2794
|
}
|
|
2737
2795
|
function frogCasting(cl, opts = {}) {
|