@willcgage/module-schematic 0.79.0 → 0.80.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
@@ -1528,8 +1528,60 @@ var FLEX_TRACK_PARTS = [
1528
1528
  }
1529
1529
  }
1530
1530
  ];
1531
+ var FAST_TRACKS_N_ME55 = [
1532
+ // [kind, N, angle°, divergingR, defaultLength, minLength, substitutionR]
1533
+ ["turnout", 4, 14.04, 8, 4.57, 3.43, 11],
1534
+ ["turnout", 4.5, 12.53, 11, 5, 3.9, 14],
1535
+ ["turnout", 5, 11.31, 14, 5.39, 3.92, 17],
1536
+ ["turnout", 6, 9.46, 23, 6.26, 4.3, 24],
1537
+ ["turnout", 7, 8.13, 27, 7.4, 5.44, 34],
1538
+ ["turnout", 8, 7.13, 36, 8, 5.93, 42],
1539
+ ["turnout", 9, 6.34, 50, 8.38, 6.42, 57],
1540
+ ["turnout", 10, 5.71, 64, 9.15, 6.8, 70],
1541
+ ["turnout", 12, 4.76, 82, 10.34, 7.95, 90],
1542
+ ["wye", 4, 14.04, 23, 4.63, 3.48, 27],
1543
+ ["wye", 5, 11.31, 25, 5.23, 3.81, 30],
1544
+ ["wye", 6, 9.46, 35, 5.99, 4.3, 47],
1545
+ ["wye", 8, 7.13, 70, 8.22, 5.93, 94],
1546
+ ["wye", 10, 5.71, 89, 9.47, 6.97, 130]
1547
+ ].map(([kind, n, deg, divR, dflt, min, subR]) => {
1548
+ const code = kind === "wye" ? "y" : "t";
1549
+ const spec = "handlaidtrack.com Detailed Specifications, read 2026-07-26";
1550
+ const manufacturer = "manufacturer";
1551
+ return {
1552
+ id: `fast-tracks-n-me55-${code}-${n}`,
1553
+ manufacturer: "Fast Tracks",
1554
+ line: "Code 55",
1555
+ scale: "N",
1556
+ // Named for what the OWNER has, not what Fast Tracks sell. They sell a jig;
1557
+ // the person picking this in the editor is holding the turnout they built
1558
+ // on it. `buildable` and the AF-… part number carry the fixture fact.
1559
+ name: `#${n} ${kind === "wye" ? "Wye" : "Turnout"}`,
1560
+ kind,
1561
+ partNumbers: { single: `AF-N-${code.toUpperCase()}-${n}-ME55` },
1562
+ frogNumber: n,
1563
+ buildable: true,
1564
+ actualAngle: {
1565
+ deg,
1566
+ source: manufacturer,
1567
+ note: `${spec}. Matches atan(1/${n}) to the published digits \u2014 Fast Tracks build to TRUE frog ratios, unlike Atlas's sectional angles.`
1568
+ },
1569
+ divergingRadius: { inches: divR, source: manufacturer, note: spec },
1570
+ overallLength: {
1571
+ inches: dflt,
1572
+ source: manufacturer,
1573
+ note: `${spec}. The DEFAULT length \u2014 this is a fixture, so the builder chooses.`
1574
+ },
1575
+ minimumLength: { inches: min, source: manufacturer, note: spec },
1576
+ substitutionRadius: { inches: subR, source: manufacturer, note: spec }
1577
+ };
1578
+ });
1531
1579
  var DEFAULT_FLEX_PART_ID = "atlas-c55-n-flex";
1532
- var BUILT_IN_TRACK_PARTS = [...ATLAS_CODE55_N, ...FLEX_TRACK_PARTS];
1580
+ var BUILT_IN_TRACK_PARTS = [
1581
+ ...ATLAS_CODE55_N,
1582
+ ...FAST_TRACKS_N_ME55,
1583
+ ...FLEX_TRACK_PARTS
1584
+ ];
1533
1585
  function flexParts(library = BUILT_IN_TRACK_PARTS) {
1534
1586
  return library.filter((p) => p.kind === "flex");
1535
1587
  }
@@ -1656,9 +1708,14 @@ function partExtentForSize(size, library = BUILT_IN_TRACK_PARTS) {
1656
1708
  function turnoutPartForSize(size, library = BUILT_IN_TRACK_PARTS) {
1657
1709
  const turnouts = library.filter((p) => p.kind === "turnout" && p.frogNumber != null);
1658
1710
  if (!turnouts.length) return null;
1659
- return turnouts.reduce(
1660
- (best, p) => Math.abs(p.frogNumber - size) < Math.abs(best.frogNumber - size) ? p : best
1661
- );
1711
+ const dist = (p) => Math.abs(p.frogNumber - size);
1712
+ return turnouts.reduce((best, p) => {
1713
+ const d = dist(p);
1714
+ const bd = dist(best);
1715
+ if (d !== bd) return d < bd ? p : best;
1716
+ if (!partExtent(best) && partExtent(p)) return p;
1717
+ return best;
1718
+ });
1662
1719
  }
1663
1720
  function measuredLeadPoints(library) {
1664
1721
  return library.filter(
@@ -1666,8 +1723,10 @@ function measuredLeadPoints(library) {
1666
1723
  ).map((p) => ({ n: p.frogNumber, lead: p.lead.inches })).sort((a, b) => a.n - b.n);
1667
1724
  }
1668
1725
  function leadInchesForSize(size, library = BUILT_IN_TRACK_PARTS) {
1669
- const part = turnoutPartForSize(size, library);
1670
- if (part?.lead && part.frogNumber === size) return part.lead.inches;
1726
+ const exact = library.find(
1727
+ (p) => p.kind === "turnout" && p.frogNumber === size && p.lead != null
1728
+ );
1729
+ if (exact) return exact.lead.inches;
1671
1730
  const pts = measuredLeadPoints(library);
1672
1731
  if (!pts.length) return size * TURNOUT_LEAD_INCHES_PER_FROG;
1673
1732
  if (pts.length === 1) return size / pts[0].n * pts[0].lead;
@@ -1844,6 +1903,11 @@ function storedPartToTrackPart(row) {
1844
1903
  if (overall) part.overallLength = overall;
1845
1904
  const diverging = dim(row.divergingLengthInches, row.divergingLengthSource);
1846
1905
  if (diverging) part.divergingLength = diverging;
1906
+ const minimum = dim(row.minimumLengthInches, row.minimumLengthSource);
1907
+ if (minimum) part.minimumLength = minimum;
1908
+ const substitution = dim(row.substitutionRadiusInches, row.substitutionRadiusSource);
1909
+ if (substitution) part.substitutionRadius = substitution;
1910
+ if (row.buildable) part.buildable = true;
1847
1911
  if (lead) part.lead = lead;
1848
1912
  const outer = dim(row.outerRadiusInches, row.radiusSource);
1849
1913
  const inner = dim(row.innerRadiusInches, row.radiusSource);
@@ -2545,6 +2609,7 @@ exports.CODE55_RAIL_HEIGHT_INCHES = CODE55_RAIL_HEIGHT_INCHES;
2545
2609
  exports.DEFAULT_FLEX_PART_ID = DEFAULT_FLEX_PART_ID;
2546
2610
  exports.ENDPLATE_FASCIA_CLEAR_INCHES = ENDPLATE_FASCIA_CLEAR_INCHES;
2547
2611
  exports.ENDPLATE_LEAD_INCHES = ENDPLATE_LEAD_INCHES;
2612
+ exports.FAST_TRACKS_N_ME55 = FAST_TRACKS_N_ME55;
2548
2613
  exports.FLEX_TRACK_PARTS = FLEX_TRACK_PARTS;
2549
2614
  exports.FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES = FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES;
2550
2615
  exports.FREEMO_ENDPLATE_WIDTH_MIN_INCHES = FREEMO_ENDPLATE_WIDTH_MIN_INCHES;