@willcgage/module-schematic 0.106.0 → 0.108.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) {
@@ -3246,6 +3281,15 @@ function moduleConversionReport(doc, library = BUILT_IN_TRACK_PARTS) {
3246
3281
  candidates
3247
3282
  };
3248
3283
  });
3284
+ const mainIds = new Set((doc.tracks ?? []).filter((t) => t.role === "main").map((t) => t.id));
3285
+ for (const t of doc.turnouts ?? []) {
3286
+ if (!mainIds.has(t.divergeTrack)) continue;
3287
+ blockers.push({
3288
+ kind: "turnout-opens-a-main",
3289
+ ref: t.id,
3290
+ why: `${t.name || t.id} opens ${t.divergeTrack}, which is a main \u2014 a main that begins at a turnout cannot be laid as pieces yet, and converting anyway would drop both it and the turnout`
3291
+ });
3292
+ }
3249
3293
  for (const c of doc.crossings ?? [])
3250
3294
  blockers.push({
3251
3295
  kind: "crossing",
@@ -4278,6 +4322,8 @@ exports.FREEMO_MAIN_MIN_RADIUS_INCHES = FREEMO_MAIN_MIN_RADIUS_INCHES;
4278
4322
  exports.FREEMO_REVERSE_CURVE_STRAIGHT_INCHES = FREEMO_REVERSE_CURVE_STRAIGHT_INCHES;
4279
4323
  exports.FREEMO_TRACK_SPACING_INCHES = FREEMO_TRACK_SPACING_INCHES;
4280
4324
  exports.GENERIC_END_OF_TRACK = GENERIC_END_OF_TRACK;
4325
+ exports.GENERIC_TURNOUTS = GENERIC_TURNOUTS;
4326
+ exports.GENERIC_TURNOUT_FROG_NUMBERS = GENERIC_TURNOUT_FROG_NUMBERS;
4281
4327
  exports.JOINT_SNAP_INCHES = JOINT_SNAP_INCHES;
4282
4328
  exports.MAIN2_TRACK_ID = MAIN2_TRACK_ID;
4283
4329
  exports.MAIN_TRACK_ID = MAIN_TRACK_ID;
@@ -4324,6 +4370,7 @@ exports.flexUsage = flexUsage;
4324
4370
  exports.frogCasting = frogCasting;
4325
4371
  exports.frogNumberFromName = frogNumberFromName;
4326
4372
  exports.fromSectionRelative = fromSectionRelative;
4373
+ exports.genericTurnoutPart = genericTurnoutPart;
4327
4374
  exports.geometryTurnDegrees = geometryTurnDegrees;
4328
4375
  exports.graphToDoc = graphToDoc;
4329
4376
  exports.hasNoFarEndplate = hasNoFarEndplate;
@@ -4359,6 +4406,7 @@ exports.pieceRoutePaths = pieceRoutePaths;
4359
4406
  exports.placedJoints = placedJoints;
4360
4407
  exports.poseNeedsManual = poseNeedsManual;
4361
4408
  exports.poseOverridesFromDoc = poseOverridesFromDoc;
4409
+ exports.provisionalParts = provisionalParts;
4362
4410
  exports.remapPos = remapPos;
4363
4411
  exports.resizeFlexPiece = resizeFlexPiece;
4364
4412
  exports.resolveGraphAnchor = resolveGraphAnchor;