@willcgage/module-schematic 0.19.0 → 0.21.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
@@ -92,6 +92,8 @@ interface SchematicTurnout {
92
92
  kind?: TurnoutKind;
93
93
  name?: string | null;
94
94
  address?: string | null;
95
+ /** Frog number ("size") — #4, #6, #8, etc. Governs the diverging angle. */
96
+ size?: number | null;
95
97
  }
96
98
  interface SchematicSignal {
97
99
  id: string;
@@ -147,16 +149,27 @@ type IndustryLabelMode = "none" | "cars" | "inches";
147
149
  * offset to `side`. The span length gives its car capacity; the dispatcher and
148
150
  * crews read where cars set out. Mirrors a `freemon_industries` row.
149
151
  */
152
+ /** One car-spot span of an industry on a track — an industry may have several
153
+ * (a house track serving one customer across multiple spot tracks, #54). */
154
+ interface IndustrySpot {
155
+ track: string;
156
+ fromPos: number;
157
+ toPos: number;
158
+ side?: SignalSide;
159
+ }
150
160
  interface SchematicIndustry {
151
161
  id: string;
152
162
  name: string;
153
163
  /** Industry type value from the lookup (e.g. "team_track", "grain"). */
154
164
  type?: string | null;
155
- /** The track this industry spots cars on (a spur/siding id, or the main). */
165
+ /** The primary track this industry spots cars on (a spur/siding id or main).
166
+ * Additional spots (other tracks) live in `spots`. */
156
167
  track: string;
157
- /** The car-spot span along that track, inches from endplate A. */
168
+ /** The primary car-spot span along `track`, inches from endplate A. */
158
169
  fromPos: number;
159
170
  toPos: number;
171
+ /** Extra car-spot spans on other tracks — the industry's house-track spots. */
172
+ spots?: IndustrySpot[];
160
173
  /** Which side of the track the building + label sit on. */
161
174
  side?: SignalSide;
162
175
  /** Secondary readout at the label — a car count, a length, or none. */
@@ -340,6 +353,8 @@ interface EditorTurnout {
340
353
  onTrack: string;
341
354
  divergeTrack: string;
342
355
  kind: TurnoutKind;
356
+ /** Frog number ("size") — #4, #6, #8, etc. Governs the diverging angle. */
357
+ size?: number;
343
358
  }
344
359
  interface EditorCpSignal {
345
360
  id: string;
@@ -371,6 +386,8 @@ interface EditorIndustry {
371
386
  track: string;
372
387
  fromPos: number;
373
388
  toPos: number;
389
+ /** Extra car-spot spans on other tracks (house-track spots, #54). */
390
+ spots: IndustrySpot[];
374
391
  side: SignalSide;
375
392
  labelMode: IndustryLabelMode;
376
393
  carTypes: string[];
@@ -705,4 +722,4 @@ declare function poseOverridesFromDoc(doc: ModuleSchematicDoc): Record<string, {
705
722
  heading: number;
706
723
  }>;
707
724
 
708
- export { type BenchworkPoint, type BranchConnector, type DrawCrossing, type DrawCrossover, type DrawIndustry, type DrawSignal, type DrawTrack, type DrawTurnout, type EditorBranch, type EditorControlPoint, type EditorCpSignal, type EditorCrossing, type EditorIndustry, type EditorState, type EditorTrack, type EditorTurnout, type EndplateBConfig, type EndplatePose, FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, type GeometryType, type IndustryLabelMode, MAIN2_TRACK_ID, MAIN_TRACK_ID, type ModuleFeatures, type ModuleFootprint, type ModuleFootprintInput, type ModuleGeometryInput, type ModuleSchematicDoc, type ModuleTrackRow, N_CAR_LENGTH_INCHES, N_SCALE_RATIO, type OutlineFace, type SchematicBlock, type SchematicControlPoint, type SchematicCrossing, type SchematicEndplate, type SchematicEndplateTrack, type SchematicIndustry, type SchematicSignal, type SchematicTrack, type SchematicTurnout, type SignalFacing, type SignalSide, type TrackConfig, type TrackRole, type TurnoutKind, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateWidthInches, geometryTurnDegrees, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, moduleCenterline, moduleFeatures, moduleFootprint, nextId, poseNeedsManual, poseOverridesFromDoc, sampleBenchworkOutline, samplePath, scaleFeetToInches, stateToDoc, trackPath };
725
+ export { type BenchworkPoint, type BranchConnector, type DrawCrossing, type DrawCrossover, type DrawIndustry, type DrawSignal, type DrawTrack, type DrawTurnout, type EditorBranch, type EditorControlPoint, type EditorCpSignal, type EditorCrossing, type EditorIndustry, type EditorState, type EditorTrack, type EditorTurnout, type EndplateBConfig, type EndplatePose, FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, type GeometryType, type IndustryLabelMode, type IndustrySpot, MAIN2_TRACK_ID, MAIN_TRACK_ID, type ModuleFeatures, type ModuleFootprint, type ModuleFootprintInput, type ModuleGeometryInput, type ModuleSchematicDoc, type ModuleTrackRow, N_CAR_LENGTH_INCHES, N_SCALE_RATIO, type OutlineFace, type SchematicBlock, type SchematicControlPoint, type SchematicCrossing, type SchematicEndplate, type SchematicEndplateTrack, type SchematicIndustry, type SchematicSignal, type SchematicTrack, type SchematicTurnout, type SignalFacing, type SignalSide, type TrackConfig, type TrackRole, type TurnoutKind, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateWidthInches, geometryTurnDegrees, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, moduleCenterline, moduleFeatures, moduleFootprint, nextId, poseNeedsManual, poseOverridesFromDoc, sampleBenchworkOutline, samplePath, scaleFeetToInches, stateToDoc, trackPath };
package/dist/index.d.ts CHANGED
@@ -92,6 +92,8 @@ interface SchematicTurnout {
92
92
  kind?: TurnoutKind;
93
93
  name?: string | null;
94
94
  address?: string | null;
95
+ /** Frog number ("size") — #4, #6, #8, etc. Governs the diverging angle. */
96
+ size?: number | null;
95
97
  }
96
98
  interface SchematicSignal {
97
99
  id: string;
@@ -147,16 +149,27 @@ type IndustryLabelMode = "none" | "cars" | "inches";
147
149
  * offset to `side`. The span length gives its car capacity; the dispatcher and
148
150
  * crews read where cars set out. Mirrors a `freemon_industries` row.
149
151
  */
152
+ /** One car-spot span of an industry on a track — an industry may have several
153
+ * (a house track serving one customer across multiple spot tracks, #54). */
154
+ interface IndustrySpot {
155
+ track: string;
156
+ fromPos: number;
157
+ toPos: number;
158
+ side?: SignalSide;
159
+ }
150
160
  interface SchematicIndustry {
151
161
  id: string;
152
162
  name: string;
153
163
  /** Industry type value from the lookup (e.g. "team_track", "grain"). */
154
164
  type?: string | null;
155
- /** The track this industry spots cars on (a spur/siding id, or the main). */
165
+ /** The primary track this industry spots cars on (a spur/siding id or main).
166
+ * Additional spots (other tracks) live in `spots`. */
156
167
  track: string;
157
- /** The car-spot span along that track, inches from endplate A. */
168
+ /** The primary car-spot span along `track`, inches from endplate A. */
158
169
  fromPos: number;
159
170
  toPos: number;
171
+ /** Extra car-spot spans on other tracks — the industry's house-track spots. */
172
+ spots?: IndustrySpot[];
160
173
  /** Which side of the track the building + label sit on. */
161
174
  side?: SignalSide;
162
175
  /** Secondary readout at the label — a car count, a length, or none. */
@@ -340,6 +353,8 @@ interface EditorTurnout {
340
353
  onTrack: string;
341
354
  divergeTrack: string;
342
355
  kind: TurnoutKind;
356
+ /** Frog number ("size") — #4, #6, #8, etc. Governs the diverging angle. */
357
+ size?: number;
343
358
  }
344
359
  interface EditorCpSignal {
345
360
  id: string;
@@ -371,6 +386,8 @@ interface EditorIndustry {
371
386
  track: string;
372
387
  fromPos: number;
373
388
  toPos: number;
389
+ /** Extra car-spot spans on other tracks (house-track spots, #54). */
390
+ spots: IndustrySpot[];
374
391
  side: SignalSide;
375
392
  labelMode: IndustryLabelMode;
376
393
  carTypes: string[];
@@ -705,4 +722,4 @@ declare function poseOverridesFromDoc(doc: ModuleSchematicDoc): Record<string, {
705
722
  heading: number;
706
723
  }>;
707
724
 
708
- export { type BenchworkPoint, type BranchConnector, type DrawCrossing, type DrawCrossover, type DrawIndustry, type DrawSignal, type DrawTrack, type DrawTurnout, type EditorBranch, type EditorControlPoint, type EditorCpSignal, type EditorCrossing, type EditorIndustry, type EditorState, type EditorTrack, type EditorTurnout, type EndplateBConfig, type EndplatePose, FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, type GeometryType, type IndustryLabelMode, MAIN2_TRACK_ID, MAIN_TRACK_ID, type ModuleFeatures, type ModuleFootprint, type ModuleFootprintInput, type ModuleGeometryInput, type ModuleSchematicDoc, type ModuleTrackRow, N_CAR_LENGTH_INCHES, N_SCALE_RATIO, type OutlineFace, type SchematicBlock, type SchematicControlPoint, type SchematicCrossing, type SchematicEndplate, type SchematicEndplateTrack, type SchematicIndustry, type SchematicSignal, type SchematicTrack, type SchematicTurnout, type SignalFacing, type SignalSide, type TrackConfig, type TrackRole, type TurnoutKind, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateWidthInches, geometryTurnDegrees, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, moduleCenterline, moduleFeatures, moduleFootprint, nextId, poseNeedsManual, poseOverridesFromDoc, sampleBenchworkOutline, samplePath, scaleFeetToInches, stateToDoc, trackPath };
725
+ export { type BenchworkPoint, type BranchConnector, type DrawCrossing, type DrawCrossover, type DrawIndustry, type DrawSignal, type DrawTrack, type DrawTurnout, type EditorBranch, type EditorControlPoint, type EditorCpSignal, type EditorCrossing, type EditorIndustry, type EditorState, type EditorTrack, type EditorTurnout, type EndplateBConfig, type EndplatePose, FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, type GeometryType, type IndustryLabelMode, type IndustrySpot, MAIN2_TRACK_ID, MAIN_TRACK_ID, type ModuleFeatures, type ModuleFootprint, type ModuleFootprintInput, type ModuleGeometryInput, type ModuleSchematicDoc, type ModuleTrackRow, N_CAR_LENGTH_INCHES, N_SCALE_RATIO, type OutlineFace, type SchematicBlock, type SchematicControlPoint, type SchematicCrossing, type SchematicEndplate, type SchematicEndplateTrack, type SchematicIndustry, type SchematicSignal, type SchematicTrack, type SchematicTurnout, type SignalFacing, type SignalSide, type TrackConfig, type TrackRole, type TurnoutKind, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateWidthInches, geometryTurnDegrees, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, moduleCenterline, moduleFeatures, moduleFootprint, nextId, poseNeedsManual, poseOverridesFromDoc, sampleBenchworkOutline, samplePath, scaleFeetToInches, stateToDoc, trackPath };
package/dist/index.js CHANGED
@@ -363,7 +363,8 @@ function stateToDoc(state, recordNumber) {
363
363
  onTrack: t.onTrack,
364
364
  divergeTrack: t.divergeTrack,
365
365
  kind: t.kind,
366
- name: t.name || void 0
366
+ name: t.name || void 0,
367
+ ...t.size ? { size: t.size } : {}
367
368
  })),
368
369
  ...state.crossings.length > 0 ? {
369
370
  crossings: state.crossings.map((x) => ({
@@ -396,6 +397,7 @@ function stateToDoc(state, recordNumber) {
396
397
  track: ind.track,
397
398
  fromPos: ind.fromPos,
398
399
  toPos: ind.toPos,
400
+ ...ind.spots?.length ? { spots: ind.spots } : {},
399
401
  side: ind.side,
400
402
  ...ind.labelMode && ind.labelMode !== "none" ? { labelMode: ind.labelMode } : {},
401
403
  ...ind.carTypes.length ? { carTypes: ind.carTypes } : {},
@@ -519,7 +521,8 @@ function docToState(doc, fallbackLength, moduleTracks = []) {
519
521
  pos: sc(t.pos),
520
522
  onTrack: t.onTrack,
521
523
  divergeTrack: t.divergeTrack,
522
- kind: t.kind ?? "right"
524
+ kind: t.kind ?? "right",
525
+ ...t.size ? { size: t.size } : {}
523
526
  })),
524
527
  controlPoints: readControlPoints(d, sc),
525
528
  industries: (d.industries ?? []).map((ind) => ({
@@ -529,6 +532,12 @@ function docToState(doc, fallbackLength, moduleTracks = []) {
529
532
  track: ind.track,
530
533
  fromPos: sc(ind.fromPos ?? 0),
531
534
  toPos: ind.toPos != null ? sc(ind.toPos) : len,
535
+ spots: (ind.spots ?? []).map((s) => ({
536
+ track: s.track,
537
+ fromPos: sc(s.fromPos ?? 0),
538
+ toPos: s.toPos != null ? sc(s.toPos) : len,
539
+ ...s.side ? { side: s.side } : {}
540
+ })),
532
541
  side: ind.side ?? "above",
533
542
  labelMode: ind.labelMode ?? "none",
534
543
  carTypes: Array.isArray(ind.carTypes) ? ind.carTypes : [],
@@ -832,21 +841,27 @@ function moduleFeatures(doc) {
832
841
  posFrac: clampFrac(e.at.pos),
833
842
  side: e.at.side === "down" ? "down" : "up"
834
843
  }));
835
- const industries = (doc.industries ?? []).map((ind) => {
836
- const from = ind.fromPos ?? 0;
837
- const to = ind.toPos ?? len;
838
- return {
839
- id: ind.id,
840
- name: ind.name ?? "",
841
- type: ind.type ?? null,
842
- fromFrac: clampFrac(Math.min(from, to)),
843
- toFrac: clampFrac(Math.max(from, to)),
844
- lane: trackLane.get(ind.track) ?? 0,
845
- side: ind.side ?? "above",
846
- labelMode: ind.labelMode ?? "none",
847
- cars: carCapacity(from, to),
848
- carTypes: Array.isArray(ind.carTypes) ? ind.carTypes : []
849
- };
844
+ const industries = (doc.industries ?? []).flatMap((ind) => {
845
+ const spots = [
846
+ { track: ind.track, fromPos: ind.fromPos, toPos: ind.toPos, side: ind.side },
847
+ ...ind.spots ?? []
848
+ ];
849
+ return spots.map((sp, i) => {
850
+ const from = sp.fromPos ?? 0;
851
+ const to = sp.toPos ?? len;
852
+ return {
853
+ id: i === 0 ? ind.id : `${ind.id}-s${i}`,
854
+ name: ind.name ?? "",
855
+ type: ind.type ?? null,
856
+ fromFrac: clampFrac(Math.min(from, to)),
857
+ toFrac: clampFrac(Math.max(from, to)),
858
+ lane: trackLane.get(sp.track) ?? 0,
859
+ side: sp.side ?? "above",
860
+ labelMode: ind.labelMode ?? "none",
861
+ cars: carCapacity(from, to),
862
+ carTypes: Array.isArray(ind.carTypes) ? ind.carTypes : []
863
+ };
864
+ });
850
865
  });
851
866
  const allLanes = [
852
867
  0,