@willcgage/module-schematic 0.75.0 → 0.76.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
@@ -31,10 +31,28 @@ function moduleSections(doc) {
31
31
  ...typeof len === "number" && Number.isFinite(len) && len > 0 ? { lengthInches: len } : {},
32
32
  ...sec.geometryType ? { geometryType: sec.geometryType } : {},
33
33
  ...typeof deg === "number" && Number.isFinite(deg) ? { geometryDegrees: deg } : {},
34
- ...typeof off === "number" && Number.isFinite(off) ? { geometryOffsetInches: off } : {}
34
+ ...typeof off === "number" && Number.isFinite(off) ? { geometryOffsetInches: off } : {},
35
+ // The board's two ends (#130). Written only when actually described —
36
+ // an absent end is an ordinary internal joint, and an empty object
37
+ // would claim the owner had said something about it.
38
+ ...sectionEnd(sec.endA) ? { endA: sectionEnd(sec.endA) } : {},
39
+ ...sectionEnd(sec.endB) ? { endB: sectionEnd(sec.endB) } : {}
35
40
  };
36
41
  });
37
42
  }
43
+ function sectionEnd(end) {
44
+ if (!end) return null;
45
+ const config = end.config === "single" || end.config === "double" || end.config === "none" ? end.config : null;
46
+ const w = end.widthInches;
47
+ const o = end.trackOffsetInches;
48
+ const out = {
49
+ ...config ? { config } : {},
50
+ ...typeof w === "number" && Number.isFinite(w) && w > 0 ? { widthInches: w } : {},
51
+ // Signed, and 0 is meaningful ("explicitly centred", #93) — keep any finite.
52
+ ...typeof o === "number" && Number.isFinite(o) ? { trackOffsetInches: o } : {}
53
+ };
54
+ return Object.keys(out).length ? out : null;
55
+ }
38
56
  function sectionFootprints(doc, derive) {
39
57
  const spans = derive ? sectionSpans(doc) : [];
40
58
  const spanOf = new Map(spans.map((sp) => [sp.id, sp]));
@@ -627,6 +645,42 @@ function usableCapacity(input) {
627
645
  scaleFeet: Math.round(inchesToScaleFeet(usable))
628
646
  };
629
647
  }
648
+ function assessSectionEnd(end, opts = {}) {
649
+ const config = end?.config ?? "none";
650
+ const widthInches = endplateWidthInches({ widthInches: end?.widthInches });
651
+ const trackOffsetInches = endplateTrackOffsetInches(
652
+ end?.trackOffsetInches,
653
+ config,
654
+ opts.main2Below
655
+ );
656
+ const described = config === "single" || config === "double";
657
+ if (!described) {
658
+ return { described: false, conforming: false, issues: [], config, widthInches, trackOffsetInches };
659
+ }
660
+ const issues = checkEndplateWidth({
661
+ widthInches: end?.widthInches,
662
+ config,
663
+ trackOffsetInches: end?.trackOffsetInches,
664
+ main2Below: opts.main2Below
665
+ });
666
+ return { described: true, conforming: issues.length === 0, issues, config, widthInches, trackOffsetInches };
667
+ }
668
+ function assessSectionJoint(west, east, opts = {}) {
669
+ const w = assessSectionEnd(west, opts);
670
+ const e = assessSectionEnd(east, opts);
671
+ let reason = null;
672
+ if (!w.described || !e.described) {
673
+ reason = "an internal joint \u2014 neither end has been described as an interface";
674
+ if (w.described !== e.described)
675
+ reason = `only the ${w.described ? "west" : "east"} side is described as an endplate`;
676
+ } else if (!w.conforming || !e.conforming) {
677
+ const bad = !w.conforming ? w : e;
678
+ reason = bad.issues[0]?.message ?? "an end doesn't meet the standard";
679
+ } else if (w.config !== e.config) {
680
+ reason = `${w.config} meets ${e.config} \u2014 the track counts differ`;
681
+ }
682
+ return { west: w, east: e, standardInterface: reason === null, reason };
683
+ }
630
684
  function spanOverhang(input) {
631
685
  const lo = Math.min(input.fromPos, input.toPos);
632
686
  const hi = Math.max(input.fromPos, input.toPos);
@@ -2446,6 +2500,8 @@ exports.TIE_HALF_LENGTH_INCHES = TIE_HALF_LENGTH_INCHES;
2446
2500
  exports.TURNOUT_LEAD_INCHES_PER_FROG = TURNOUT_LEAD_INCHES_PER_FROG;
2447
2501
  exports.WHOLE_MODULE_SECTION_ID = WHOLE_MODULE_SECTION_ID;
2448
2502
  exports.asModuleSchematic = asModuleSchematic;
2503
+ exports.assessSectionEnd = assessSectionEnd;
2504
+ exports.assessSectionJoint = assessSectionJoint;
2449
2505
  exports.benchworkBand = benchworkBand;
2450
2506
  exports.benchworkOutline = benchworkOutline;
2451
2507
  exports.buildCrossover = buildCrossover;