@willcgage/module-schematic 0.105.0 → 0.107.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 CHANGED
@@ -1703,6 +1703,33 @@ var FAST_TRACKS_N_ME55_CROSSOVERS = [
1703
1703
  };
1704
1704
  });
1705
1705
  var DEFAULT_FLEX_PART_ID = "atlas-c55-n-flex";
1706
+ var GENERIC_TURNOUT_FROG_NUMBERS = [4, 5, 6, 7, 8, 10];
1707
+ function genericTurnoutPart(frogNumber, library = ATLAS_CODE55_N) {
1708
+ const derived = "derived";
1709
+ const lead = leadInchesForSize(frogNumber, library);
1710
+ const past = pastFrogInchesForSize(frogNumber, library);
1711
+ const why = `Interpolated across the measured parts by frog number \u2014 a stand-in, not a reading. No points offset: it is not a function of the frog number (the measured #5, #7 and #10 read 1.75\u2033, 0.625\u2033 and 0.5625\u2033), so this part begins AT the points, as a hand-laid turnout does.`;
1712
+ return {
1713
+ id: `generic-turnout-${frogNumber}`,
1714
+ manufacturer: "Generic",
1715
+ line: "N scale",
1716
+ scale: "N",
1717
+ name: `#${frogNumber} Turnout (make unknown)`,
1718
+ kind: "turnout",
1719
+ frogNumber,
1720
+ provisional: true,
1721
+ pointsOffset: { inches: 0, source: derived, note: why },
1722
+ lead: { inches: lead, source: derived, note: why },
1723
+ frogOffset: { inches: lead, source: derived, note: why },
1724
+ overallLength: { inches: lead + past, source: derived, note: why }
1725
+ };
1726
+ }
1727
+ var GENERIC_TURNOUTS = GENERIC_TURNOUT_FROG_NUMBERS.map(
1728
+ (n) => genericTurnoutPart(n)
1729
+ );
1730
+ function provisionalParts(library = BUILT_IN_TRACK_PARTS) {
1731
+ return library.filter((p) => p.provisional);
1732
+ }
1706
1733
  var GENERIC_END_OF_TRACK = [
1707
1734
  {
1708
1735
  id: "generic-bumper",
@@ -1718,7 +1745,11 @@ var BUILT_IN_TRACK_PARTS = [
1718
1745
  ...FAST_TRACKS_N_ME55,
1719
1746
  ...FAST_TRACKS_N_ME55_CROSSOVERS,
1720
1747
  ...FLEX_TRACK_PARTS,
1721
- ...GENERIC_END_OF_TRACK
1748
+ ...GENERIC_END_OF_TRACK,
1749
+ // ⚠️ LAST, AND PROVISIONAL. These are stand-ins, not products; every path that
1750
+ // resolves a turnout automatically filters them out, and every picker that
1751
+ // offers them must say what they are.
1752
+ ...GENERIC_TURNOUTS
1722
1753
  ];
1723
1754
  function flexParts(library = BUILT_IN_TRACK_PARTS) {
1724
1755
  return library.filter((p) => p.kind === "flex");
@@ -1846,7 +1877,9 @@ function partExtentForSize(size, library = BUILT_IN_TRACK_PARTS) {
1846
1877
  return part && part.frogNumber === size ? partExtent(part) : null;
1847
1878
  }
1848
1879
  function turnoutPartForSize(size, library = BUILT_IN_TRACK_PARTS) {
1849
- const turnouts = library.filter((p) => p.kind === "turnout" && p.frogNumber != null);
1880
+ const turnouts = library.filter(
1881
+ (p) => p.kind === "turnout" && p.frogNumber != null && !p.provisional
1882
+ );
1850
1883
  if (!turnouts.length) return null;
1851
1884
  const dist = (p) => Math.abs(p.frogNumber - size);
1852
1885
  return turnouts.reduce((best, p) => {
@@ -1859,12 +1892,12 @@ function turnoutPartForSize(size, library = BUILT_IN_TRACK_PARTS) {
1859
1892
  }
1860
1893
  function measuredLeadPoints(library) {
1861
1894
  return library.filter(
1862
- (p) => p.kind === "turnout" && p.frogNumber != null && p.lead?.source === "measured"
1895
+ (p) => p.kind === "turnout" && p.frogNumber != null && p.lead?.source === "measured" && !p.provisional
1863
1896
  ).map((p) => ({ n: p.frogNumber, lead: p.lead.inches })).sort((a, b) => a.n - b.n);
1864
1897
  }
1865
1898
  function leadInchesForSize(size, library = BUILT_IN_TRACK_PARTS) {
1866
1899
  const exact = library.find(
1867
- (p) => p.kind === "turnout" && p.frogNumber === size && p.lead != null
1900
+ (p) => p.kind === "turnout" && p.frogNumber === size && p.lead != null && !p.provisional
1868
1901
  );
1869
1902
  if (exact) return exact.lead.inches;
1870
1903
  const pts = measuredLeadPoints(library);
@@ -3165,7 +3198,9 @@ function deriveGraphDoc(doc, library = BUILT_IN_TRACK_PARTS) {
3165
3198
  return { doc: out.doc, warnings: out.warnings };
3166
3199
  }
3167
3200
  function placeableTurnoutParts(library, kind) {
3168
- return library.filter((p) => kind.includes(p.kind) && partGeometryGap(p) == null);
3201
+ return library.filter(
3202
+ (p) => kind.includes(p.kind) && !p.provisional && partGeometryGap(p) == null
3203
+ );
3169
3204
  }
3170
3205
  function moduleConversionReport(doc, library = BUILT_IN_TRACK_PARTS) {
3171
3206
  if (doc.graph?.pieces?.length) {
@@ -3182,7 +3217,29 @@ function moduleConversionReport(doc, library = BUILT_IN_TRACK_PARTS) {
3182
3217
  const straight = placeableTurnoutParts(library, ["turnout"]);
3183
3218
  const curved = placeableTurnoutParts(library, ["curved-turnout"]);
3184
3219
  const blockers = [];
3220
+ const assemblyPart = /* @__PURE__ */ new Map();
3221
+ for (const t of doc.tracks ?? []) {
3222
+ if (t.role !== "crossover" || !t.crossoverPartId) continue;
3223
+ const part = library.find((p) => p.id === t.crossoverPartId);
3224
+ if (!part || part.kind !== "crossover" || partGeometryGap(part)) continue;
3225
+ for (const sw of doc.turnouts ?? [])
3226
+ if (sw.divergeTrack === t.id) assemblyPart.set(sw.id, part);
3227
+ }
3185
3228
  const turnouts = (doc.turnouts ?? []).map((t) => {
3229
+ const asm = assemblyPart.get(t.id);
3230
+ if (asm)
3231
+ return {
3232
+ id: t.id,
3233
+ name: t.name,
3234
+ pos: t.pos,
3235
+ size: t.size,
3236
+ statedPartId: t.partId,
3237
+ partId: asm.id,
3238
+ from: "assembly",
3239
+ source: partGeometry(asm, library)?.source ?? null,
3240
+ why: null,
3241
+ candidates: []
3242
+ };
3186
3243
  const wantCurved = t.curved === true;
3187
3244
  const pool = wantCurved ? curved : straight;
3188
3245
  const base = {
@@ -4256,6 +4313,8 @@ exports.FREEMO_MAIN_MIN_RADIUS_INCHES = FREEMO_MAIN_MIN_RADIUS_INCHES;
4256
4313
  exports.FREEMO_REVERSE_CURVE_STRAIGHT_INCHES = FREEMO_REVERSE_CURVE_STRAIGHT_INCHES;
4257
4314
  exports.FREEMO_TRACK_SPACING_INCHES = FREEMO_TRACK_SPACING_INCHES;
4258
4315
  exports.GENERIC_END_OF_TRACK = GENERIC_END_OF_TRACK;
4316
+ exports.GENERIC_TURNOUTS = GENERIC_TURNOUTS;
4317
+ exports.GENERIC_TURNOUT_FROG_NUMBERS = GENERIC_TURNOUT_FROG_NUMBERS;
4259
4318
  exports.JOINT_SNAP_INCHES = JOINT_SNAP_INCHES;
4260
4319
  exports.MAIN2_TRACK_ID = MAIN2_TRACK_ID;
4261
4320
  exports.MAIN_TRACK_ID = MAIN_TRACK_ID;
@@ -4302,6 +4361,7 @@ exports.flexUsage = flexUsage;
4302
4361
  exports.frogCasting = frogCasting;
4303
4362
  exports.frogNumberFromName = frogNumberFromName;
4304
4363
  exports.fromSectionRelative = fromSectionRelative;
4364
+ exports.genericTurnoutPart = genericTurnoutPart;
4305
4365
  exports.geometryTurnDegrees = geometryTurnDegrees;
4306
4366
  exports.graphToDoc = graphToDoc;
4307
4367
  exports.hasNoFarEndplate = hasNoFarEndplate;
@@ -4337,6 +4397,7 @@ exports.pieceRoutePaths = pieceRoutePaths;
4337
4397
  exports.placedJoints = placedJoints;
4338
4398
  exports.poseNeedsManual = poseNeedsManual;
4339
4399
  exports.poseOverridesFromDoc = poseOverridesFromDoc;
4400
+ exports.provisionalParts = provisionalParts;
4340
4401
  exports.remapPos = remapPos;
4341
4402
  exports.resizeFlexPiece = resizeFlexPiece;
4342
4403
  exports.resolveGraphAnchor = resolveGraphAnchor;