@willcgage/module-schematic 0.65.0 → 0.66.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.d.cts CHANGED
@@ -972,24 +972,32 @@ interface DrawCrossover {
972
972
  toLane: number;
973
973
  }
974
974
  /**
975
- * A route leaving the module at a third endplate (#170) Main 3, whatever the
976
- * owner labels it (#181). Drawn as an ELBOW: it diverges from its host main at
977
- * `posFrac`, drops to its own `lane`, then runs to `endFrac` and ends at an
978
- * endplate face.
975
+ * A route leaving the module at a third endplate — and an endplate is an
976
+ * endplate, whatever letter it carries (#183).
979
977
  *
980
- * The run is the branch's OWN arc length laid along the strip, not its
981
- * projection onto the module axis a square 90° exit projects to zero, which
982
- * is exactly the case that made branches invisible here. Straightening the
983
- * route out at its true length is the same idiom this whole view applies to the
984
- * main; `posFrac endFrac` is therefore a real axis, and `lengthInches` maps
985
- * onto it, so anything positioned along the branch has somewhere to draw.
978
+ * There is no split in the standard between "the two ends" and "the others": an
979
+ * endplate is the standardised face where a module joins another module, and a
980
+ * module may present two, three, or one. So a route to C is drawn the way a
981
+ * route to A or B is drawn **it runs to the edge of the module and terminates
982
+ * in an endplate face carrying its letter**, rather than stopping partway along
983
+ * the strip as a stub.
984
+ *
985
+ * ⚠️ Because it runs the full width it would otherwise read as just another
986
+ * parallel main, which is exactly the confusion a dispatcher must not have. Its
987
+ * lane is therefore placed with a clear GAP beyond every other lane (see
988
+ * `laneGapFromOthers`), and it ends at a plate rather than running off the edge.
989
+ * The two requirements — full width, and not-a-parallel-main — are in tension by
990
+ * design, and the separation is what resolves it.
991
+ *
992
+ * The LETTER is the module's own fact and is fine to draw. The DESTINATION
993
+ * ("to Fillmore") depends on which module is physically attached at that
994
+ * junction, so it stays Free-Dispatcher's to derive at runtime.
986
995
  */
987
996
  interface BranchConnector {
988
997
  /** Endplate id — "C", "D", … */
989
998
  id: string;
990
- /** The endplate's label. MR draws no text (the destination depends on what's
991
- * physically attached, so FD derives the panel label at runtime) — this is
992
- * the owner's local name, for tooltips and FD's fallback. */
999
+ /** The owner's local name for the plate. NOT the destination that depends
1000
+ * on what's physically attached, so FD derives it at runtime. */
993
1001
  label: string;
994
1002
  /** The route's own name, from the track. */
995
1003
  name: string;
@@ -1005,12 +1013,15 @@ interface BranchConnector {
1005
1013
  fromLane: number;
1006
1014
  /** Which side of the module it exits. */
1007
1015
  side: "up" | "down";
1008
- /** The branch's own lane, signed by `side` and placed clear of every other
1009
- * lane (so it never collides) — already folded into laneMin/laneMax. */
1016
+ /** The branch's own lane, signed by `side`, placed a clear GAP beyond every
1017
+ * other lane so it can't be mistaken for a parallel main — already folded
1018
+ * into laneMin/laneMax. */
1010
1019
  lane: number;
1011
- /** Where the run ends, and the endplate face is drawn. */
1020
+ /** Where the run ends and the endplate face is drawn: the module EDGE, 0 or
1021
+ * 1, because this is an end of the module like any other (#183). */
1012
1022
  endFrac: number;
1013
- /** The route's own arc length, inches. */
1023
+ /** The route's own arc length on this module, inches — for the tooltip. The
1024
+ * drawn run is the strip's width, not this. */
1014
1025
  lengthInches: number;
1015
1026
  }
1016
1027
  /** An industry — draw a car-spot span beside its track's lane, on `side`, with
package/dist/index.d.ts CHANGED
@@ -972,24 +972,32 @@ interface DrawCrossover {
972
972
  toLane: number;
973
973
  }
974
974
  /**
975
- * A route leaving the module at a third endplate (#170) Main 3, whatever the
976
- * owner labels it (#181). Drawn as an ELBOW: it diverges from its host main at
977
- * `posFrac`, drops to its own `lane`, then runs to `endFrac` and ends at an
978
- * endplate face.
975
+ * A route leaving the module at a third endplate — and an endplate is an
976
+ * endplate, whatever letter it carries (#183).
979
977
  *
980
- * The run is the branch's OWN arc length laid along the strip, not its
981
- * projection onto the module axis a square 90° exit projects to zero, which
982
- * is exactly the case that made branches invisible here. Straightening the
983
- * route out at its true length is the same idiom this whole view applies to the
984
- * main; `posFrac endFrac` is therefore a real axis, and `lengthInches` maps
985
- * onto it, so anything positioned along the branch has somewhere to draw.
978
+ * There is no split in the standard between "the two ends" and "the others": an
979
+ * endplate is the standardised face where a module joins another module, and a
980
+ * module may present two, three, or one. So a route to C is drawn the way a
981
+ * route to A or B is drawn **it runs to the edge of the module and terminates
982
+ * in an endplate face carrying its letter**, rather than stopping partway along
983
+ * the strip as a stub.
984
+ *
985
+ * ⚠️ Because it runs the full width it would otherwise read as just another
986
+ * parallel main, which is exactly the confusion a dispatcher must not have. Its
987
+ * lane is therefore placed with a clear GAP beyond every other lane (see
988
+ * `laneGapFromOthers`), and it ends at a plate rather than running off the edge.
989
+ * The two requirements — full width, and not-a-parallel-main — are in tension by
990
+ * design, and the separation is what resolves it.
991
+ *
992
+ * The LETTER is the module's own fact and is fine to draw. The DESTINATION
993
+ * ("to Fillmore") depends on which module is physically attached at that
994
+ * junction, so it stays Free-Dispatcher's to derive at runtime.
986
995
  */
987
996
  interface BranchConnector {
988
997
  /** Endplate id — "C", "D", … */
989
998
  id: string;
990
- /** The endplate's label. MR draws no text (the destination depends on what's
991
- * physically attached, so FD derives the panel label at runtime) — this is
992
- * the owner's local name, for tooltips and FD's fallback. */
999
+ /** The owner's local name for the plate. NOT the destination that depends
1000
+ * on what's physically attached, so FD derives it at runtime. */
993
1001
  label: string;
994
1002
  /** The route's own name, from the track. */
995
1003
  name: string;
@@ -1005,12 +1013,15 @@ interface BranchConnector {
1005
1013
  fromLane: number;
1006
1014
  /** Which side of the module it exits. */
1007
1015
  side: "up" | "down";
1008
- /** The branch's own lane, signed by `side` and placed clear of every other
1009
- * lane (so it never collides) — already folded into laneMin/laneMax. */
1016
+ /** The branch's own lane, signed by `side`, placed a clear GAP beyond every
1017
+ * other lane so it can't be mistaken for a parallel main — already folded
1018
+ * into laneMin/laneMax. */
1010
1019
  lane: number;
1011
- /** Where the run ends, and the endplate face is drawn. */
1020
+ /** Where the run ends and the endplate face is drawn: the module EDGE, 0 or
1021
+ * 1, because this is an end of the module like any other (#183). */
1012
1022
  endFrac: number;
1013
- /** The route's own arc length, inches. */
1023
+ /** The route's own arc length on this module, inches — for the tooltip. The
1024
+ * drawn run is the strip's width, not this. */
1014
1025
  lengthInches: number;
1015
1026
  }
1016
1027
  /** An industry — draw a car-spot span beside its track's lane, on `side`, with
package/dist/index.js CHANGED
@@ -1777,8 +1777,9 @@ function moduleFeatures(doc) {
1777
1777
  ...crossings.flatMap((x) => [x.laneA, x.laneB]),
1778
1778
  ...crossovers.flatMap((x) => [x.fromLane, x.toLane])
1779
1779
  ];
1780
- let upLane = Math.max(...baseLanes, 0);
1781
- let downLane = Math.min(...baseLanes, 0);
1780
+ const LANE_GAP_FROM_OTHERS = 2;
1781
+ let upLane = Math.max(...baseLanes, 0) + (LANE_GAP_FROM_OTHERS - 1);
1782
+ let downLane = Math.min(...baseLanes, 0) - (LANE_GAP_FROM_OTHERS - 1);
1782
1783
  const branchConnectors = doc.endplates.filter(
1783
1784
  (e) => e.id !== "A" && e.id !== "B" && e.at && !!e.trackId && (doc.tracks ?? []).some((t) => t.id === e.trackId)
1784
1785
  ).map((e) => {
@@ -1789,10 +1790,6 @@ function moduleFeatures(doc) {
1789
1790
  const lane = side === "down" ? --downLane : ++upLane;
1790
1791
  const runInches = pathLengthInches(trk.path) || Math.abs(e.at.pos - startPos) || FREEMO_ENDPLATE_WIDTH_MIN_INCHES;
1791
1792
  const toB = e.at.pos >= startPos;
1792
- const fits = (p) => p >= 0 && p <= len;
1793
- const ahead = startPos + runInches;
1794
- const behind = startPos - runInches;
1795
- const endPos = toB && fits(ahead) ? ahead : !toB && fits(behind) ? behind : fits(toB ? behind : ahead) ? toB ? behind : ahead : ahead;
1796
1793
  return {
1797
1794
  id: e.id,
1798
1795
  label: e.label ?? e.id,
@@ -1803,7 +1800,7 @@ function moduleFeatures(doc) {
1803
1800
  fromLane: sw ? trackLane.get(sw.onTrack) ?? 0 : 0,
1804
1801
  side,
1805
1802
  lane,
1806
- endFrac: clampFrac(endPos),
1803
+ endFrac: toB ? 1 : 0,
1807
1804
  lengthInches: runInches
1808
1805
  };
1809
1806
  });