@fmsim/machine 3.0.0-beta.5 → 3.0.0-beta.7

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.
@@ -97,12 +97,18 @@ export function LVVehicle(Base) {
97
97
  return Kind(VehicleTravel(Base), 'vehicleType', figure => { var _a; return (((_a = figure === null || figure === void 0 ? void 0 : figure.constructor) === null || _a === void 0 ? void 0 : _a.placement) === 'ceiling' ? 'oht' : 'agv'); });
98
98
  }
99
99
  /**
100
- * `fmsim.CarrierHolder` on a figure: carriers change hands at the transport surface, so a holder that takes them on its
100
+ * `fmsim.CarrierHolder` on a figure: its carriers stand in its places -- a gripper, a lift plate, a fork's tiers -- and
101
+ * go with them; one without places keeps them in a pile on its top. Carriers change hands at the transport surface, so a
102
+ * holder that takes them on its
101
103
  * top stands that tall when nothing else says -- as fmsim's own AGV and shuttle do. A machine's height wins (whichever is
102
104
  * worn over the other); a holder that hangs them or hangs itself from the ceiling (an OHT) keeps its own.
103
105
  */
104
106
  export function FigureCarrierHolder(Base) {
105
107
  return class extends CarrierHolder(Base) {
108
+ /** Its carriers stand in its own places, which go with the parts that carry them (ADR-0167 decision 23) */
109
+ get fillsPlaces() {
110
+ return true;
111
+ }
106
112
  get effectiveDepth() {
107
113
  var _a, _b;
108
114
  const given = super.effectiveDepth;
@@ -1 +1 @@
1
- {"version":3,"file":"lv-figures.js","sourceRoot":"","sources":["../../src/features/lv-figures.ts"],"names":[],"mappings":"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","sourcesContent":["import { figureLegendSourcesChanged, registerFigureCapability, registerFigureLegendResolver } from '@hatiolab/things-scene'\nimport { CARRIER_HOLDER, MACHINE, STATUS, STATUS_LEGEND_ROLE, UNIT, VEHICLE, carrierHolderProperties, statusProperties } from '@fmsim/figure-capabilities'\nimport { themesAnimationMap, themesColorMap } from '@fmsim/api'\nimport { boardLegendOfRow, colourAndEffect, parseLegendIfString } from './legend-rows'\nimport { MACHINE_HEIGHTS, TRANSPORT_SURFACE_HEIGHT } from './lv-heights'\nimport { VehicleTravel } from './vehicle-travel'\nimport { CarrierHolder } from '../mcs-carrier-holder'\n\n/*\n * fmsim's figure capabilities (ADR-0167 decision 22): what a figure is in LV -- fmsim.Machine, fmsim.Unit or\n * fmsim.Vehicle, one at most -- and the features worn with any of them, fmsim.Status and fmsim.CarrierHolder. A kind\n * says its type (`lvType`), the board row a status follows; the features are the mixins fmsim's own wear.\n */\n\n/**\n * STATUS as the figure takes it: a code, so a number (MCS sends 4001) is given as its text ('4001'). The status table reads\n * STATUS as a text and a figure refuses data whose value is not of the declared kind; the component's own data is not changed.\n */\nexport function statusAsCode(data: any): any {\n return data && typeof data === 'object' && typeof data.STATUS === 'number' ? { ...data, STATUS: String(data.STATUS) } : data\n}\n\n/**\n * `fmsim.Status`: the figure follows the board row of its kind's type, a change of its legend has its tables chosen\n * again, and its STATUS reaches the figure as a code. The colour is its capability's table, drawn by things-scene.\n */\nexport function StatusFigure<T extends new (...args: any[]) => any>(Base: T) {\n return class extends Base {\n _statusInputs?: unknown\n\n /** The figure's inputs, given the data's STATUS as a code when they are made (a new release starts them again) */\n get figureInputs(): any {\n const inputs = super.figureInputs\n if (inputs && inputs !== this._statusInputs) {\n this._statusInputs = inputs\n if (typeof (this as any).state?.data?.STATUS === 'number') inputs.setData(statusAsCode((this as any).state.data))\n }\n return inputs\n }\n\n /** The board row its status follows: its kind's type, none without a kind */\n get statusLegendRow(): string | undefined {\n return (this as any).lvType\n }\n\n get legendRowsUsed(): string[] {\n const row = this.statusLegendRow\n return [...((super.legendRowsUsed as string[] | undefined) ?? []), ...(row ? [row] : [])]\n }\n\n onchange(after: Record<string, any>, before: Record<string, any>) {\n super.onchange?.(after && 'data' in after ? { ...after, data: statusAsCode(after.data) } : after, before)\n if (after && 'legendName' in after) figureLegendSourcesChanged(this)\n }\n }\n}\n\n/** An LV kind: its type, chosen or its default, is `lvType`; another type has the figure's legends chosen again. */\nfunction Kind<T extends new (...args: any[]) => any>(Base: T, property: string, defaultOf: (figure: any) => string) {\n return class extends Base {\n get lvType(): string {\n const chosen = (this as any).state?.[property]\n return typeof chosen === 'string' && chosen ? chosen : defaultOf(this)\n }\n\n onchange(after: Record<string, any>, before: Record<string, any>) {\n super.onchange?.(after, before)\n if (after && property in after) figureLegendSourcesChanged(this)\n }\n }\n}\n\n/**\n * `fmsim.Machine`: an LV machine of a type, equipment unless chosen -- it stands as tall as fmsim's own machine of that\n * type when the board writes no height (things-scene asks the component, `effectiveDepth`).\n */\nexport function LVMachine<T extends new (...args: any[]) => any>(Base: T) {\n return class extends Kind(Base, 'machineType', () => 'equipment') {\n get effectiveDepth(): number | undefined {\n return MACHINE_HEIGHTS[this.lvType]\n }\n\n onchange(after: Record<string, any>, before: Record<string, any>) {\n super.onchange(after, before)\n /* Another type stands at another height: the 3D object takes it */\n if (after && 'machineType' in after) {\n const real = (this as any)._realObject\n real?.updateDimension?.()\n real?.updateTransform?.()\n }\n }\n }\n}\n\n/** `fmsim.Unit`: an LV unit of a type, a port unless chosen -- a tag LV handles it by */\nexport function LVUnit<T extends new (...args: any[]) => any>(Base: T) {\n return Kind(Base, 'unitType', () => 'port')\n}\n\n/** `fmsim.Vehicle`: an LV vehicle -- it travels between nodes; its type, unless chosen, an AGV on the floor and an OHT on the ceiling */\nexport function LVVehicle<T extends new (...args: any[]) => any>(Base: T) {\n return Kind(VehicleTravel(Base), 'vehicleType', figure => (figure?.constructor?.placement === 'ceiling' ? 'oht' : 'agv'))\n}\n\n/**\n * `fmsim.CarrierHolder` on a figure: carriers change hands at the transport surface, so a holder that takes them on its\n * top stands that tall when nothing else says -- as fmsim's own AGV and shuttle do. A machine's height wins (whichever is\n * worn over the other); a holder that hangs them or hangs itself from the ceiling (an OHT) keeps its own.\n */\nexport function FigureCarrierHolder<T extends new (...args: any[]) => any>(Base: T) {\n return class extends CarrierHolder(Base) {\n get effectiveDepth(): number | undefined {\n const given = super.effectiveDepth\n if (given !== undefined) return given\n const hung = (this as any).state?.carrierMount === 'HANG' || (this as any).constructor?.placement === 'ceiling'\n return hung ? undefined : TRANSPORT_SURFACE_HEIGHT\n }\n }\n}\n\n/**\n * The legend a status figure shows its STATUS by: its own choice (`legendName`, as fmsim's own have), then the board row\n * of its kind's type; none chosen, no answer (its capability's table, fmsim's default legends).\n */\nexport function statusLegend({ component, role }: { component: any; role: string }): unknown {\n if (role !== STATUS_LEGEND_ROLE) return undefined\n const own = component?.state?.legendName\n const root = component?.root\n const row = component?.statusLegendRow\n const legend =\n (typeof own === 'string' && own && root?.state?.style ? parseLegendIfString(root.state, root.state.style[own]) : undefined) ||\n (row ? boardLegendOfRow(component, row) : undefined)\n return legend && typeof legend === 'object' ? colourAndEffect(legend) : undefined\n}\n\nregisterFigureLegendResolver(statusLegend)\nregisterFigureCapability(MACHINE, base => LVMachine(base) as never)\nregisterFigureCapability(UNIT, base => LVUnit(base) as never)\nregisterFigureCapability(VEHICLE, base => LVVehicle(base) as never)\nregisterFigureCapability({ ...STATUS, properties: statusProperties({ legends: themesColorMap }) as never }, base => StatusFigure(base) as never)\nregisterFigureCapability(\n { ...CARRIER_HOLDER, properties: carrierHolderProperties({ legends: themesColorMap, animations: themesAnimationMap, mount: true }) as never },\n base => FigureCarrierHolder(base) as never\n)\n"]}
1
+ {"version":3,"file":"lv-figures.js","sourceRoot":"","sources":["../../src/features/lv-figures.ts"],"names":[],"mappings":"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","sourcesContent":["import { figureLegendSourcesChanged, registerFigureCapability, registerFigureLegendResolver } from '@hatiolab/things-scene'\nimport { CARRIER_HOLDER, MACHINE, STATUS, STATUS_LEGEND_ROLE, UNIT, VEHICLE, carrierHolderProperties, statusProperties } from '@fmsim/figure-capabilities'\nimport { themesAnimationMap, themesColorMap } from '@fmsim/api'\nimport { boardLegendOfRow, colourAndEffect, parseLegendIfString } from './legend-rows'\nimport { MACHINE_HEIGHTS, TRANSPORT_SURFACE_HEIGHT } from './lv-heights'\nimport { VehicleTravel } from './vehicle-travel'\nimport { CarrierHolder } from '../mcs-carrier-holder'\n\n/*\n * fmsim's figure capabilities (ADR-0167 decision 22): what a figure is in LV -- fmsim.Machine, fmsim.Unit or\n * fmsim.Vehicle, one at most -- and the features worn with any of them, fmsim.Status and fmsim.CarrierHolder. A kind\n * says its type (`lvType`), the board row a status follows; the features are the mixins fmsim's own wear.\n */\n\n/**\n * STATUS as the figure takes it: a code, so a number (MCS sends 4001) is given as its text ('4001'). The status table reads\n * STATUS as a text and a figure refuses data whose value is not of the declared kind; the component's own data is not changed.\n */\nexport function statusAsCode(data: any): any {\n return data && typeof data === 'object' && typeof data.STATUS === 'number' ? { ...data, STATUS: String(data.STATUS) } : data\n}\n\n/**\n * `fmsim.Status`: the figure follows the board row of its kind's type, a change of its legend has its tables chosen\n * again, and its STATUS reaches the figure as a code. The colour is its capability's table, drawn by things-scene.\n */\nexport function StatusFigure<T extends new (...args: any[]) => any>(Base: T) {\n return class extends Base {\n _statusInputs?: unknown\n\n /** The figure's inputs, given the data's STATUS as a code when they are made (a new release starts them again) */\n get figureInputs(): any {\n const inputs = super.figureInputs\n if (inputs && inputs !== this._statusInputs) {\n this._statusInputs = inputs\n if (typeof (this as any).state?.data?.STATUS === 'number') inputs.setData(statusAsCode((this as any).state.data))\n }\n return inputs\n }\n\n /** The board row its status follows: its kind's type, none without a kind */\n get statusLegendRow(): string | undefined {\n return (this as any).lvType\n }\n\n get legendRowsUsed(): string[] {\n const row = this.statusLegendRow\n return [...((super.legendRowsUsed as string[] | undefined) ?? []), ...(row ? [row] : [])]\n }\n\n onchange(after: Record<string, any>, before: Record<string, any>) {\n super.onchange?.(after && 'data' in after ? { ...after, data: statusAsCode(after.data) } : after, before)\n if (after && 'legendName' in after) figureLegendSourcesChanged(this)\n }\n }\n}\n\n/** An LV kind: its type, chosen or its default, is `lvType`; another type has the figure's legends chosen again. */\nfunction Kind<T extends new (...args: any[]) => any>(Base: T, property: string, defaultOf: (figure: any) => string) {\n return class extends Base {\n get lvType(): string {\n const chosen = (this as any).state?.[property]\n return typeof chosen === 'string' && chosen ? chosen : defaultOf(this)\n }\n\n onchange(after: Record<string, any>, before: Record<string, any>) {\n super.onchange?.(after, before)\n if (after && property in after) figureLegendSourcesChanged(this)\n }\n }\n}\n\n/**\n * `fmsim.Machine`: an LV machine of a type, equipment unless chosen -- it stands as tall as fmsim's own machine of that\n * type when the board writes no height (things-scene asks the component, `effectiveDepth`).\n */\nexport function LVMachine<T extends new (...args: any[]) => any>(Base: T) {\n return class extends Kind(Base, 'machineType', () => 'equipment') {\n get effectiveDepth(): number | undefined {\n return MACHINE_HEIGHTS[this.lvType]\n }\n\n onchange(after: Record<string, any>, before: Record<string, any>) {\n super.onchange(after, before)\n /* Another type stands at another height: the 3D object takes it */\n if (after && 'machineType' in after) {\n const real = (this as any)._realObject\n real?.updateDimension?.()\n real?.updateTransform?.()\n }\n }\n }\n}\n\n/** `fmsim.Unit`: an LV unit of a type, a port unless chosen -- a tag LV handles it by */\nexport function LVUnit<T extends new (...args: any[]) => any>(Base: T) {\n return Kind(Base, 'unitType', () => 'port')\n}\n\n/** `fmsim.Vehicle`: an LV vehicle -- it travels between nodes; its type, unless chosen, an AGV on the floor and an OHT on the ceiling */\nexport function LVVehicle<T extends new (...args: any[]) => any>(Base: T) {\n return Kind(VehicleTravel(Base), 'vehicleType', figure => (figure?.constructor?.placement === 'ceiling' ? 'oht' : 'agv'))\n}\n\n/**\n * `fmsim.CarrierHolder` on a figure: its carriers stand in its places -- a gripper, a lift plate, a fork's tiers -- and\n * go with them; one without places keeps them in a pile on its top. Carriers change hands at the transport surface, so a\n * holder that takes them on its\n * top stands that tall when nothing else says -- as fmsim's own AGV and shuttle do. A machine's height wins (whichever is\n * worn over the other); a holder that hangs them or hangs itself from the ceiling (an OHT) keeps its own.\n */\nexport function FigureCarrierHolder<T extends new (...args: any[]) => any>(Base: T) {\n return class extends CarrierHolder(Base) {\n /** Its carriers stand in its own places, which go with the parts that carry them (ADR-0167 decision 23) */\n get fillsPlaces(): boolean {\n return true\n }\n\n get effectiveDepth(): number | undefined {\n const given = super.effectiveDepth\n if (given !== undefined) return given\n const hung = (this as any).state?.carrierMount === 'HANG' || (this as any).constructor?.placement === 'ceiling'\n return hung ? undefined : TRANSPORT_SURFACE_HEIGHT\n }\n }\n}\n\n/**\n * The legend a status figure shows its STATUS by: its own choice (`legendName`, as fmsim's own have), then the board row\n * of its kind's type; none chosen, no answer (its capability's table, fmsim's default legends).\n */\nexport function statusLegend({ component, role }: { component: any; role: string }): unknown {\n if (role !== STATUS_LEGEND_ROLE) return undefined\n const own = component?.state?.legendName\n const root = component?.root\n const row = component?.statusLegendRow\n const legend =\n (typeof own === 'string' && own && root?.state?.style ? parseLegendIfString(root.state, root.state.style[own]) : undefined) ||\n (row ? boardLegendOfRow(component, row) : undefined)\n return legend && typeof legend === 'object' ? colourAndEffect(legend) : undefined\n}\n\nregisterFigureLegendResolver(statusLegend)\nregisterFigureCapability(MACHINE, base => LVMachine(base) as never)\nregisterFigureCapability(UNIT, base => LVUnit(base) as never)\nregisterFigureCapability(VEHICLE, base => LVVehicle(base) as never)\nregisterFigureCapability({ ...STATUS, properties: statusProperties({ legends: themesColorMap }) as never }, base => StatusFigure(base) as never)\nregisterFigureCapability(\n { ...CARRIER_HOLDER, properties: carrierHolderProperties({ legends: themesColorMap, animations: themesAnimationMap, mount: true }) as never },\n base => FigureCarrierHolder(base) as never\n)\n"]}
@@ -1,11 +1,11 @@
1
1
  import { themesColorMap, themesAnimationMap } from '@fmsim/api';
2
2
  import JSON5 from 'json5';
3
- import { Capacity, Holdable, ItemsDataBinding, Model, TRANSFER_SLOT_KEY, figureLegendSourcesChanged, itemTypeEntryOf, itemTypeTableOf, registerFigureLegendResolver } from '@hatiolab/things-scene';
3
+ import { Capacity, Holdable, ItemsDataBinding, Model, TRANSFER_SLOT_KEY, drawingScaleFor, figureLegendSourcesChanged, itemTypeEntryOf, itemTypeTableOf, registerFigureLegendResolver } from '@hatiolab/things-scene';
4
4
  import { colourAndEffect } from './features/legend-rows';
5
5
  import { HOLDER_ANCHOR } from '@hatiolab/figure-model';
6
6
  import { carrierHolderProperties } from '@fmsim/figure-capabilities';
7
7
  import MCSUnit from './mcs-unit.js';
8
- import { incomingFromV2 } from './utils/load-address';
8
+ import { incomingFromV2, resolveOccupancy } from './utils/load-address';
9
9
  /**
10
10
  * A holder's slots outside its layout (common item contract 3.4): every carrier of a holder without a layout stands in
11
11
  * one pile, and a carrier whose address is unknown or wrong stands in the exception area beside the holder.
@@ -60,15 +60,68 @@ export function CarrierHolder(Base) {
60
60
  return Model.compile(Object.assign({ id: record.itemId, type: 'Carrier', left: 0, top: 0, width, height }, record.itemState), (_a = this.root) === null || _a === void 0 ? void 0 : _a.app);
61
61
  }
62
62
  /**
63
- * One record per carrier the data names, bottom first: MULTICARRIERS in order, then the representative. Without a
64
- * layout they all stand in the pile. A carrier is told its own keys and whether to show its text.
63
+ * Whether carriers stand in the holder's own places (ADR-0167 decision 23): a figure holder's places -- a gripper, a
64
+ * lift plate, the tiers on a fork -- carry what stands on them as the figure moves. fmsim's own holders keep theirs: a
65
+ * pile, or the layout their data addresses (LoadLayoutHolder).
66
+ */
67
+ get fillsPlaces() {
68
+ return false;
69
+ }
70
+ /**
71
+ * One record per carrier the data names, bottom first: MULTICARRIERS in order, then the representative. A carrier is
72
+ * told its own keys and whether to show its text. They stand in the pile, unless the holder fills its places.
65
73
  */
66
74
  carrierRecords(data) {
67
- return incomingFromV2(data).map(c => ({
68
- slotId: PILE_SLOT,
75
+ var _a, _b, _c, _d;
76
+ const incoming = incomingFromV2(data);
77
+ const record = (c, slotId) => ({
78
+ slotId,
69
79
  itemId: c.name,
70
80
  itemState: this.carrierStateOf(c.record, c.record === data)
71
- }));
81
+ });
82
+ const places = this.fillsPlaces ? ((_a = this.slots) !== null && _a !== void 0 ? _a : []) : [];
83
+ if (!places.length)
84
+ return incoming.map(c => record(c, PILE_SLOT));
85
+ /* A carrier its data addresses (a layout's TIER/SLOT) stands at that address, as on a crane; a wrong address beside the holder. */
86
+ const layout = this._placeLayout;
87
+ const occupancy = layout ? resolveOccupancy(layout, incoming, this._placeOccupancy) : undefined;
88
+ this._placeOccupancy = occupancy;
89
+ const slotOf = new Map();
90
+ for (const [key, list] of (_b = occupancy === null || occupancy === void 0 ? void 0 : occupancy.slots) !== null && _b !== void 0 ? _b : []) {
91
+ const [tier, slot] = key.split(':').map(Number);
92
+ for (const c of list)
93
+ slotOf.set(c.name, `t${tier}_s${slot}`);
94
+ }
95
+ for (const c of (_c = occupancy === null || occupancy === void 0 ? void 0 : occupancy.addressError) !== null && _c !== void 0 ? _c : [])
96
+ slotOf.set(c.name, EXCEPTION_SLOT);
97
+ /* The others fill the places in their order, each up to what it takes; one still held keeps its place. What is left over stands beside the holder. */
98
+ const room = new Map(places.map(p => { var _a; return [p.id, (_a = p.maxCount) !== null && _a !== void 0 ? _a : 1]; }));
99
+ for (const slotId of slotOf.values())
100
+ if (room.has(slotId))
101
+ room.set(slotId, room.get(slotId) - 1);
102
+ const unplaced = incoming.filter(c => !slotOf.has(c.name));
103
+ const heldIn = new Map(this._items.map(item => { var _a; return [(_a = item.state) === null || _a === void 0 ? void 0 : _a.id, item[TRANSFER_SLOT_KEY]]; }));
104
+ for (const c of unplaced) {
105
+ const kept = heldIn.get(c.name);
106
+ if (kept && ((_d = room.get(kept)) !== null && _d !== void 0 ? _d : 0) > 0) {
107
+ slotOf.set(c.name, kept);
108
+ room.set(kept, room.get(kept) - 1);
109
+ }
110
+ }
111
+ for (const c of unplaced) {
112
+ if (slotOf.has(c.name))
113
+ continue;
114
+ const free = places.find(p => { var _a; return ((_a = room.get(p.id)) !== null && _a !== void 0 ? _a : 0) > 0; });
115
+ slotOf.set(c.name, free ? free.id : EXCEPTION_SLOT);
116
+ if (free)
117
+ room.set(free.id, room.get(free.id) - 1);
118
+ }
119
+ return incoming.map(c => record(c, slotOf.get(c.name)));
120
+ }
121
+ /** The layout addresses are read by: the holder's, when it holds and the drawing's scale is known */
122
+ get _placeLayout() {
123
+ const sel = this.effectiveLayout;
124
+ return (sel === null || sel === void 0 ? void 0 : sel.status) === 'valid' && drawingScaleFor(this).known ? sel.layout : undefined;
72
125
  }
73
126
  /** What a carrier is told: its own keys (the representative's are picked out of the holder data), and its text */
74
127
  carrierStateOf(record, representative) {
@@ -160,7 +213,10 @@ export function CarrierHolder(Base) {
160
213
  */
161
214
  itemShownDimsOf(_carrier, slot, slotId) {
162
215
  /* Elsewhere outside the layout, a holder that keeps carriers there says (the exception area: LoadLayoutHolder). */
163
- if (slotId === PILE_SLOT) {
216
+ /* A place that says no size (a gripper): the carrier is shown at its own (ADR-0167 decision 23). */
217
+ if (slotId !== PILE_SLOT && slotId !== EXCEPTION_SLOT && !(slot === null || slot === void 0 ? void 0 : slot.allowed))
218
+ return null;
219
+ if (slotId === PILE_SLOT || slotId === EXCEPTION_SLOT) {
164
220
  const k = this.mmPerSceneUnit;
165
221
  const { width = 0, height = 0 } = this.state;
166
222
  const w = Math.abs(width) * PILE_PLAN_RATIO;
@@ -1 +1 @@
1
- {"version":3,"file":"mcs-carrier-holder.js","sourceRoot":"","sources":["../src/mcs-carrier-holder.ts"],"names":[],"mappings":"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","sourcesContent":["import { themesColorMap, themesAnimationMap } from '@fmsim/api'\nimport JSON5 from 'json5'\nimport {\n Capacity,\n Holdable,\n ItemsDataBinding,\n Model,\n TRANSFER_SLOT_KEY,\n figureLegendSourcesChanged,\n itemTypeEntryOf,\n itemTypeTableOf,\n registerFigureLegendResolver,\n type ItemType\n} from '@hatiolab/things-scene'\nimport { colourAndEffect } from './features/legend-rows'\nimport { HOLDER_ANCHOR, type ItemDims, type ResolvedSlot } from '@hatiolab/figure-model'\nimport { carrierHolderProperties } from '@fmsim/figure-capabilities'\nimport MCSUnit from './mcs-unit.js'\nimport { incomingFromV2 } from './utils/load-address'\n\n/**\n * A holder's slots outside its layout (common item contract 3.4): every carrier of a holder without a layout stands in\n * one pile, and a carrier whose address is unknown or wrong stands in the exception area beside the holder.\n */\nexport const PILE_SLOT = 'pile'\nexport const EXCEPTION_SLOT = 'exception'\n\n/** Where the exception area starts, past the holder's +X edge: a gap of this much of the holder's width */\nconst EXCEPTION_GAP_RATIO = 0.1\n\n/** A carrier shown in a pile is this much of its holder's plan, and half its smaller side high (fmsim v2) */\nconst PILE_PLAN_RATIO = 0.8\nconst PILE_HEIGHT_RATIO = 0.5\n\n/** The record of one carrier the holder's data names: its id, the slot it stands in, what it is told */\nexport interface CarrierRecord {\n slotId: string\n itemId: string\n itemState: { data: Record<string, any>; showText: boolean }\n}\n\n/** The properties a carrier holder adds, offering the legends this board has (ADR-0167 decision 11, 미결 1) */\nexport const CARRIER_HOLDER_PROPERTIES = carrierHolderProperties({ legends: themesColorMap, animations: themesAnimationMap })\n\n/**\n * A holder of MCS carriers, as a mixin over what holds things (`fmsim.CarrierHolder`). What it holds is the common item\n * contract's: carriers are its items (`_items`), found by their CARRIERNAME in the root (itemById), made, moved between\n * holders and let go by the one reconcile by id. MCS's part is here: reading the holder data into one record per\n * carrier, looking its CARRIERTYPE up in the domain's carrier type table (ADR-0155, theme carrier-types), and how a\n * carrier -- whose size MCS does not say -- is shown.\n */\nexport function CarrierHolder<T extends new (...args: any[]) => any>(Base: T) {\n return class extends Base {\n /** Whatever wears this is a carrier holder: the legend resolver finds it up a carrier's parents. */\n get isCarrierHolder(): true {\n return true\n }\n\n /** The board legend rows its carriers follow, with whatever else it follows (ADR-0167 decision 20) */\n get legendRowsUsed(): string[] {\n return [...((super.legendRowsUsed as string[] | undefined) ?? []), 'carrier', 'carrier-animation']\n }\n\n /** The records the reconcile took last, as JSON: the same again is not reconciled */\n _carrierRecordsTaken?: string\n\n get showOverflow() {\n return true\n }\n\n get hierarchy() {\n return {\n ...super.hierarchy,\n components: []\n }\n }\n\n // ── items: the holder data is the holder's, the records are worked out from it ─────────────\n\n _itemsFromData(): boolean {\n return false\n }\n\n _keyedById(): boolean {\n return true\n }\n\n /** A carrier the data moves here from another holder travels for two seconds */\n itemMoveAnimation() {\n return { duration: 2000, ease: 'inout' }\n }\n\n _createItemFromRecord(record: CarrierRecord): any {\n const { width, height } = (this as any).state\n return Model.compile(\n { id: record.itemId, type: 'Carrier', left: 0, top: 0, width, height, ...record.itemState },\n (this as any).root?.app\n )\n }\n\n /**\n * One record per carrier the data names, bottom first: MULTICARRIERS in order, then the representative. Without a\n * layout they all stand in the pile. A carrier is told its own keys and whether to show its text.\n */\n carrierRecords(data: Record<string, any> | undefined): CarrierRecord[] {\n return incomingFromV2(data).map(c => ({\n slotId: PILE_SLOT,\n itemId: c.name,\n itemState: this.carrierStateOf(c.record, c.record === data)\n }))\n }\n\n /** What a carrier is told: its own keys (the representative's are picked out of the holder data), and its text */\n carrierStateOf(record: Record<string, any>, representative: boolean): CarrierRecord['itemState'] {\n let data: Record<string, any> = { ...record }\n if (representative) {\n data = { CARRIERNAME: record.CARRIERNAME }\n for (const k of ['CARRIERTYPE', 'EMPTYTYPE', 'CARRIERSTATUS']) if (k in record) data[k] = record[k]\n }\n return { data, showText: !!(this as any).getState('showCarrierText') }\n }\n\n /**\n * The carrier 2D draws (fmsim v2, a rule of position): the top of the data's stack -- MULTICARRIERS bottom first, the\n * holder's own CARRIERNAME last -- when the holder holds it, else the last it holds.\n */\n get topCarrier(): any {\n const items: any[] = (this as any)._items\n const names = incomingFromV2((this as any).data).map(c => c.name)\n for (let i = names.length - 1; i >= 0; i--) {\n const held = items.find(c => c.state.id === names[i])\n if (held) return held\n }\n return items[items.length - 1]\n }\n\n /** The holder's carriers made to be what its data says now. Records the same as last time change nothing */\n syncCarriers(data: Record<string, any> | undefined) {\n const records = this.carrierRecords(data)\n const taken = JSON.stringify(records)\n if (taken === this._carrierRecordsTaken) return\n this._carrierRecordsTaken = taken\n ;(this as any)._reconcileItems(records)\n }\n\n async ready() {\n await super.ready()\n this.syncCarriers((this as any).data)\n }\n\n onchange(after: Record<string, any>, before: Record<string, any>): void {\n super.onchange(after, before)\n /* Its size moves its bottom and changes the size a pile shows carriers at: they take its plan, made and seated again. */\n if ('width' in after || 'height' in after || 'depth' in after) {\n const { width, height } = (this as any).state\n for (const carrier of (this as any)._items) if (width && height) carrier.set({ width, height })\n this._carriersSeatedAgain()\n }\n /* 이 홀더의 Carrier 들이 물려받는 범례가 바뀌었다: 그 피규어들이 범례를 다시 고른다 (ADR-0166 결정 12) */\n if ('carrierLegendName' in after || 'carrierAnimationName' in after) figureLegendSourcesChanged(this)\n if ('showCarrierText' in after || 'slotLayout' in after) {\n this._carrierRecordsTaken = undefined\n this.syncCarriers((this as any).data)\n if ('slotLayout' in after) this._carriersSeatedAgain()\n }\n }\n\n onchangeData(after: Record<string, any>, before: Record<string, any>): void {\n this.syncCarriers(after.data || {})\n super.onchangeData(after, before)\n }\n\n // ── the domain's item types ────────────────────────────────────────────────\n\n /**\n * A carrier's type (ADR-0155): the code it says (its CARRIERTYPE, trimmed and upper-cased -- doc 01, 6.8), in the\n * domain's carrier type table the scene was given when it opened. None when the table does not have it, or the scene\n * was given none.\n */\n carrierItemType(carrier: any): ItemType | null {\n const table = itemTypeTableOf(this)\n return (table && itemTypeEntryOf(table, carrier)) || null\n }\n\n /** A carrier's item type: its code, when the domain's table has it; else null */\n itemTypeOf(carrier: any): string | null {\n return this.carrierItemType(carrier)?.code ?? null\n }\n\n /**\n * A carrier's size in mm, as judged: none. MCS data does not say a carrier's size and a carrier type has none\n * (ADR-0155 amendment 1 C); a carrier is shown at the size of the place it stands in (itemShownDimsOf).\n */\n itemDimsOf(_carrier: any): ItemDims | null {\n return null\n }\n\n /**\n * The size a carrier of unknown size is shown at, in mm (for showing only, never judged). In the pile, most of the\n * holder's plan and half its smaller side high; elsewhere the box filling its slot, its height shared by the stack.\n */\n itemShownDimsOf(_carrier: any, slot: ResolvedSlot, slotId: string): ItemDims | null {\n /* Elsewhere outside the layout, a holder that keeps carriers there says (the exception area: LoadLayoutHolder). */\n if (slotId === PILE_SLOT) {\n const k = (this as any).mmPerSceneUnit\n const { width = 0, height = 0 } = (this as any).state\n const w = Math.abs(width) * PILE_PLAN_RATIO\n const d = Math.abs(height) * PILE_PLAN_RATIO\n return w > 0 && d > 0 ? { width: w * k, depth: d * k, height: Math.min(w, d) * PILE_HEIGHT_RATIO * k } : null\n }\n const layers = Number.isFinite(slot.stackLimit) && slot.stackLimit > 0 ? slot.stackLimit : 1\n return Number.isFinite(slot.allowed.width)\n ? { width: slot.allowed.width, depth: slot.allowed.depth, height: slot.allowed.height / layers }\n : null\n }\n\n /** A carrier's size as it is shown, in mm: its own, or the size its slot shows an unknown one at (its seat's) */\n carrierShownDimsOf(carrier: any): ItemDims | null {\n return (this as any).itemSeatOf(carrier)?.dims ?? null\n }\n\n /** Every carrier made again at the size it is shown at, and every slot seated again */\n _carriersSeatedAgain() {\n const items: any[] = (this as any)._items\n for (const carrier of items) carrier._realObject?.update?.()\n const slots = new Set(items.map(c => c[TRANSFER_SLOT_KEY]))\n for (const slotId of slots) (this as any)._reseatSlot(slotId)\n }\n\n // ── where carriers stand ──────────────────────────────────────────────────\n\n /**\n * Where a figure holder's carriers rest, in coordinates above the holder's bottom, and whether they stand on it or\n * hang from it, as its `carrierMount` says (ADR-0167 decision 18): on top of its body, or below it. fmsim's own\n * holders say their own (MCSCarrierHolder and those over it).\n */\n get carrierRest(): { height: number; mount: 'ON' | 'HANG' } {\n if ((this as any).state?.carrierMount === 'HANG') return { height: 0, mount: 'HANG' }\n return { height: Number((this as any)._realObject?.effectiveDepth) || 0, mount: 'ON' }\n }\n\n /** The pile, and the exception area beside the holder's +X edge. Frames in mm on the holder's own anchor (its bottom) */\n outsideSlots() {\n const k = (this as any).mmPerSceneUnit\n const { width = 0 } = (this as any).state\n const w = Math.abs(width)\n const rest = this.carrierRest\n return [\n {\n id: PILE_SLOT,\n anchorId: HOLDER_ANCHOR,\n frame: { position: { x: 0, y: rest.height * k, z: 0 }, rotation: 0 },\n mount: rest.mount\n },\n {\n id: EXCEPTION_SLOT,\n anchorId: HOLDER_ANCHOR,\n frame: {\n position: { x: (w / 2 + w * EXCEPTION_GAP_RATIO) * k + this.exceptionHalfWidth, y: 0, z: 0 },\n rotation: 0\n }\n }\n ]\n }\n\n /** Half the width of a carrier in the exception area, in mm: its edge stands past the gap */\n get exceptionHalfWidth(): number {\n return 0\n }\n\n /**\n * The holder's own anchor is its bottom's centre: a node on the frame at its 3D's origin (the box centre), half its\n * 3D's depth down, turned and moved with it. Others by the layer below.\n */\n anchorObject3D(anchorId: string): any {\n const frame = super.anchorObject3D(anchorId)\n if (anchorId !== HOLDER_ANCHOR || !frame) return frame\n let node = frame.userData.carrierAnchor\n if (!node || node.parent !== frame) {\n node = new frame.constructor()\n node.name = 'carrier-anchor'\n frame.add(node)\n frame.userData.carrierAnchor = node\n }\n node.position.set(0, -(Number((this as any)._realObject?.effectiveDepth) || 0) / 2, 0)\n return node\n }\n }\n}\n\n/* The mixins of things-scene are typed loosely: the holder is still an MCSUnit. */\ninterface MCSCarrierHolder extends MCSUnit {}\n\n/** fmsim's own carrier holder: an MCS unit that holds things, wearing `fmsim.CarrierHolder`. */\nclass MCSCarrierHolder extends CarrierHolder(ItemsDataBinding(Holdable(Capacity(MCSUnit as any)))) {\n static get properties(): any {\n return [...MCSUnit.properties, ...CARRIER_HOLDER_PROPERTIES]\n }\n\n /** On the transport surface by default (fmsim v2). A Port, Shelf or Shuttle holds them at its bottom; an OHT hangs them below. */\n get carrierRest(): { height: number; mount: 'ON' | 'HANG' } {\n return { height: 30, mount: 'ON' }\n }\n}\n\nexport default MCSCarrierHolder\n\n/*\n The legend a carrier figure shows its tables by (ADR-0166 7, 12; ADR-0167 11): the nearest carrier holder up its\n parents that chose one for the role -- carrier-legend its carrier legend, carrier-animation its carrier animation --\n then the board root's same choice; none chosen, no answer (the figure's own table, fmsim's default). Colour and effect\n only: a carrier figure's thickness is its own fixed table (ADR-0167 12).\n*/\nconst ROLE_PROPERTY: Record<string, string> = {\n 'carrier-legend': 'carrierLegendName',\n 'carrier-animation': 'carrierAnimationName'\n}\n\nexport function carrierHolderLegend({ component, role }: { component: any; role: string }): unknown {\n const property = ROLE_PROPERTY[role]\n if (!property) return undefined\n let name: unknown\n for (let at = component?.parent; at && !name; at = at.parent) if (at.isCarrierHolder) name = at.state?.[property]\n name ||= component?.root?.rootModel?.state?.[property]\n if (typeof name !== 'string' || !name) return undefined\n let legend = component?.root?.style?.[name]\n if (typeof legend === 'string') {\n try {\n legend = JSON5.parse(legend)\n } catch {\n return undefined\n }\n }\n return legend && typeof legend === 'object' ? colourAndEffect(legend) : undefined\n}\n\nregisterFigureLegendResolver(carrierHolderLegend)\n"]}
1
+ {"version":3,"file":"mcs-carrier-holder.js","sourceRoot":"","sources":["../src/mcs-carrier-holder.ts"],"names":[],"mappings":"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","sourcesContent":["import { themesColorMap, themesAnimationMap } from '@fmsim/api'\nimport JSON5 from 'json5'\nimport {\n Capacity,\n Holdable,\n ItemsDataBinding,\n Model,\n TRANSFER_SLOT_KEY,\n drawingScaleFor,\n figureLegendSourcesChanged,\n itemTypeEntryOf,\n itemTypeTableOf,\n registerFigureLegendResolver,\n type ItemType\n} from '@hatiolab/things-scene'\nimport { colourAndEffect } from './features/legend-rows'\nimport { HOLDER_ANCHOR, type ItemDims, type ResolvedSlot } from '@hatiolab/figure-model'\nimport { carrierHolderProperties } from '@fmsim/figure-capabilities'\nimport MCSUnit from './mcs-unit.js'\nimport { incomingFromV2, resolveOccupancy, type IncomingCarrier, type LoadLayout, type OccupancyResult } from './utils/load-address'\n\n/**\n * A holder's slots outside its layout (common item contract 3.4): every carrier of a holder without a layout stands in\n * one pile, and a carrier whose address is unknown or wrong stands in the exception area beside the holder.\n */\nexport const PILE_SLOT = 'pile'\nexport const EXCEPTION_SLOT = 'exception'\n\n/** Where the exception area starts, past the holder's +X edge: a gap of this much of the holder's width */\nconst EXCEPTION_GAP_RATIO = 0.1\n\n/** A carrier shown in a pile is this much of its holder's plan, and half its smaller side high (fmsim v2) */\nconst PILE_PLAN_RATIO = 0.8\nconst PILE_HEIGHT_RATIO = 0.5\n\n/** The record of one carrier the holder's data names: its id, the slot it stands in, what it is told */\nexport interface CarrierRecord {\n slotId: string\n itemId: string\n itemState: { data: Record<string, any>; showText: boolean }\n}\n\n/** The properties a carrier holder adds, offering the legends this board has (ADR-0167 decision 11, 미결 1) */\nexport const CARRIER_HOLDER_PROPERTIES = carrierHolderProperties({ legends: themesColorMap, animations: themesAnimationMap })\n\n/**\n * A holder of MCS carriers, as a mixin over what holds things (`fmsim.CarrierHolder`). What it holds is the common item\n * contract's: carriers are its items (`_items`), found by their CARRIERNAME in the root (itemById), made, moved between\n * holders and let go by the one reconcile by id. MCS's part is here: reading the holder data into one record per\n * carrier, looking its CARRIERTYPE up in the domain's carrier type table (ADR-0155, theme carrier-types), and how a\n * carrier -- whose size MCS does not say -- is shown.\n */\nexport function CarrierHolder<T extends new (...args: any[]) => any>(Base: T) {\n return class extends Base {\n /** Whatever wears this is a carrier holder: the legend resolver finds it up a carrier's parents. */\n get isCarrierHolder(): true {\n return true\n }\n\n /** The board legend rows its carriers follow, with whatever else it follows (ADR-0167 decision 20) */\n get legendRowsUsed(): string[] {\n return [...((super.legendRowsUsed as string[] | undefined) ?? []), 'carrier', 'carrier-animation']\n }\n\n /** The records the reconcile took last, as JSON: the same again is not reconciled */\n _carrierRecordsTaken?: string\n\n get showOverflow() {\n return true\n }\n\n get hierarchy() {\n return {\n ...super.hierarchy,\n components: []\n }\n }\n\n // ── items: the holder data is the holder's, the records are worked out from it ─────────────\n\n _itemsFromData(): boolean {\n return false\n }\n\n _keyedById(): boolean {\n return true\n }\n\n /** A carrier the data moves here from another holder travels for two seconds */\n itemMoveAnimation() {\n return { duration: 2000, ease: 'inout' }\n }\n\n _createItemFromRecord(record: CarrierRecord): any {\n const { width, height } = (this as any).state\n return Model.compile(\n { id: record.itemId, type: 'Carrier', left: 0, top: 0, width, height, ...record.itemState },\n (this as any).root?.app\n )\n }\n\n /**\n * Whether carriers stand in the holder's own places (ADR-0167 decision 23): a figure holder's places -- a gripper, a\n * lift plate, the tiers on a fork -- carry what stands on them as the figure moves. fmsim's own holders keep theirs: a\n * pile, or the layout their data addresses (LoadLayoutHolder).\n */\n get fillsPlaces(): boolean {\n return false\n }\n\n /** The holder's places as the last records took them: an addressed carrier keeps its slot while it is still there */\n _placeOccupancy?: OccupancyResult\n\n /**\n * One record per carrier the data names, bottom first: MULTICARRIERS in order, then the representative. A carrier is\n * told its own keys and whether to show its text. They stand in the pile, unless the holder fills its places.\n */\n carrierRecords(data: Record<string, any> | undefined): CarrierRecord[] {\n const incoming = incomingFromV2(data)\n const record = (c: IncomingCarrier, slotId: string): CarrierRecord => ({\n slotId,\n itemId: c.name,\n itemState: this.carrierStateOf(c.record, c.record === data)\n })\n const places = this.fillsPlaces ? (((this as any).slots ?? []) as Array<{ id: string; maxCount?: number }>) : []\n if (!places.length) return incoming.map(c => record(c, PILE_SLOT))\n\n /* A carrier its data addresses (a layout's TIER/SLOT) stands at that address, as on a crane; a wrong address beside the holder. */\n const layout = this._placeLayout\n const occupancy = layout ? resolveOccupancy(layout, incoming, this._placeOccupancy) : undefined\n this._placeOccupancy = occupancy\n const slotOf = new Map<string, string>()\n for (const [key, list] of occupancy?.slots ?? []) {\n const [tier, slot] = key.split(':').map(Number)\n for (const c of list) slotOf.set(c.name, `t${tier}_s${slot}`)\n }\n for (const c of occupancy?.addressError ?? []) slotOf.set(c.name, EXCEPTION_SLOT)\n\n /* The others fill the places in their order, each up to what it takes; one still held keeps its place. What is left over stands beside the holder. */\n const room = new Map(places.map(p => [p.id, p.maxCount ?? 1]))\n for (const slotId of slotOf.values()) if (room.has(slotId)) room.set(slotId, room.get(slotId)! - 1)\n const unplaced = incoming.filter(c => !slotOf.has(c.name))\n const heldIn = new Map(((this as any)._items as any[]).map(item => [item.state?.id, item[TRANSFER_SLOT_KEY]] as const))\n for (const c of unplaced) {\n const kept = heldIn.get(c.name)\n if (kept && (room.get(kept) ?? 0) > 0) {\n slotOf.set(c.name, kept)\n room.set(kept, room.get(kept)! - 1)\n }\n }\n for (const c of unplaced) {\n if (slotOf.has(c.name)) continue\n const free = places.find(p => (room.get(p.id) ?? 0) > 0)\n slotOf.set(c.name, free ? free.id : EXCEPTION_SLOT)\n if (free) room.set(free.id, room.get(free.id)! - 1)\n }\n return incoming.map(c => record(c, slotOf.get(c.name)!))\n }\n\n /** The layout addresses are read by: the holder's, when it holds and the drawing's scale is known */\n get _placeLayout(): LoadLayout | undefined {\n const sel = (this as any).effectiveLayout\n return sel?.status === 'valid' && drawingScaleFor(this as any).known ? (sel.layout as LoadLayout) : undefined\n }\n\n /** What a carrier is told: its own keys (the representative's are picked out of the holder data), and its text */\n carrierStateOf(record: Record<string, any>, representative: boolean): CarrierRecord['itemState'] {\n let data: Record<string, any> = { ...record }\n if (representative) {\n data = { CARRIERNAME: record.CARRIERNAME }\n for (const k of ['CARRIERTYPE', 'EMPTYTYPE', 'CARRIERSTATUS']) if (k in record) data[k] = record[k]\n }\n return { data, showText: !!(this as any).getState('showCarrierText') }\n }\n\n /**\n * The carrier 2D draws (fmsim v2, a rule of position): the top of the data's stack -- MULTICARRIERS bottom first, the\n * holder's own CARRIERNAME last -- when the holder holds it, else the last it holds.\n */\n get topCarrier(): any {\n const items: any[] = (this as any)._items\n const names = incomingFromV2((this as any).data).map(c => c.name)\n for (let i = names.length - 1; i >= 0; i--) {\n const held = items.find(c => c.state.id === names[i])\n if (held) return held\n }\n return items[items.length - 1]\n }\n\n /** The holder's carriers made to be what its data says now. Records the same as last time change nothing */\n syncCarriers(data: Record<string, any> | undefined) {\n const records = this.carrierRecords(data)\n const taken = JSON.stringify(records)\n if (taken === this._carrierRecordsTaken) return\n this._carrierRecordsTaken = taken\n ;(this as any)._reconcileItems(records)\n }\n\n async ready() {\n await super.ready()\n this.syncCarriers((this as any).data)\n }\n\n onchange(after: Record<string, any>, before: Record<string, any>): void {\n super.onchange(after, before)\n /* Its size moves its bottom and changes the size a pile shows carriers at: they take its plan, made and seated again. */\n if ('width' in after || 'height' in after || 'depth' in after) {\n const { width, height } = (this as any).state\n for (const carrier of (this as any)._items) if (width && height) carrier.set({ width, height })\n this._carriersSeatedAgain()\n }\n /* 이 홀더의 Carrier 들이 물려받는 범례가 바뀌었다: 그 피규어들이 범례를 다시 고른다 (ADR-0166 결정 12) */\n if ('carrierLegendName' in after || 'carrierAnimationName' in after) figureLegendSourcesChanged(this)\n if ('showCarrierText' in after || 'slotLayout' in after) {\n this._carrierRecordsTaken = undefined\n this.syncCarriers((this as any).data)\n if ('slotLayout' in after) this._carriersSeatedAgain()\n }\n }\n\n onchangeData(after: Record<string, any>, before: Record<string, any>): void {\n this.syncCarriers(after.data || {})\n super.onchangeData(after, before)\n }\n\n // ── the domain's item types ────────────────────────────────────────────────\n\n /**\n * A carrier's type (ADR-0155): the code it says (its CARRIERTYPE, trimmed and upper-cased -- doc 01, 6.8), in the\n * domain's carrier type table the scene was given when it opened. None when the table does not have it, or the scene\n * was given none.\n */\n carrierItemType(carrier: any): ItemType | null {\n const table = itemTypeTableOf(this)\n return (table && itemTypeEntryOf(table, carrier)) || null\n }\n\n /** A carrier's item type: its code, when the domain's table has it; else null */\n itemTypeOf(carrier: any): string | null {\n return this.carrierItemType(carrier)?.code ?? null\n }\n\n /**\n * A carrier's size in mm, as judged: none. MCS data does not say a carrier's size and a carrier type has none\n * (ADR-0155 amendment 1 C); a carrier is shown at the size of the place it stands in (itemShownDimsOf).\n */\n itemDimsOf(_carrier: any): ItemDims | null {\n return null\n }\n\n /**\n * The size a carrier of unknown size is shown at, in mm (for showing only, never judged). In the pile, most of the\n * holder's plan and half its smaller side high; elsewhere the box filling its slot, its height shared by the stack.\n */\n itemShownDimsOf(_carrier: any, slot: ResolvedSlot, slotId: string): ItemDims | null {\n /* Elsewhere outside the layout, a holder that keeps carriers there says (the exception area: LoadLayoutHolder). */\n /* A place that says no size (a gripper): the carrier is shown at its own (ADR-0167 decision 23). */\n if (slotId !== PILE_SLOT && slotId !== EXCEPTION_SLOT && !slot?.allowed) return null\n if (slotId === PILE_SLOT || slotId === EXCEPTION_SLOT) {\n const k = (this as any).mmPerSceneUnit\n const { width = 0, height = 0 } = (this as any).state\n const w = Math.abs(width) * PILE_PLAN_RATIO\n const d = Math.abs(height) * PILE_PLAN_RATIO\n return w > 0 && d > 0 ? { width: w * k, depth: d * k, height: Math.min(w, d) * PILE_HEIGHT_RATIO * k } : null\n }\n const layers = Number.isFinite(slot.stackLimit) && slot.stackLimit > 0 ? slot.stackLimit : 1\n return Number.isFinite(slot.allowed.width)\n ? { width: slot.allowed.width, depth: slot.allowed.depth, height: slot.allowed.height / layers }\n : null\n }\n\n /** A carrier's size as it is shown, in mm: its own, or the size its slot shows an unknown one at (its seat's) */\n carrierShownDimsOf(carrier: any): ItemDims | null {\n return (this as any).itemSeatOf(carrier)?.dims ?? null\n }\n\n /** Every carrier made again at the size it is shown at, and every slot seated again */\n _carriersSeatedAgain() {\n const items: any[] = (this as any)._items\n for (const carrier of items) carrier._realObject?.update?.()\n const slots = new Set(items.map(c => c[TRANSFER_SLOT_KEY]))\n for (const slotId of slots) (this as any)._reseatSlot(slotId)\n }\n\n // ── where carriers stand ──────────────────────────────────────────────────\n\n /**\n * Where a figure holder's carriers rest, in coordinates above the holder's bottom, and whether they stand on it or\n * hang from it, as its `carrierMount` says (ADR-0167 decision 18): on top of its body, or below it. fmsim's own\n * holders say their own (MCSCarrierHolder and those over it).\n */\n get carrierRest(): { height: number; mount: 'ON' | 'HANG' } {\n if ((this as any).state?.carrierMount === 'HANG') return { height: 0, mount: 'HANG' }\n return { height: Number((this as any)._realObject?.effectiveDepth) || 0, mount: 'ON' }\n }\n\n /** The pile, and the exception area beside the holder's +X edge. Frames in mm on the holder's own anchor (its bottom) */\n outsideSlots() {\n const k = (this as any).mmPerSceneUnit\n const { width = 0 } = (this as any).state\n const w = Math.abs(width)\n const rest = this.carrierRest\n return [\n {\n id: PILE_SLOT,\n anchorId: HOLDER_ANCHOR,\n frame: { position: { x: 0, y: rest.height * k, z: 0 }, rotation: 0 },\n mount: rest.mount\n },\n {\n id: EXCEPTION_SLOT,\n anchorId: HOLDER_ANCHOR,\n frame: {\n position: { x: (w / 2 + w * EXCEPTION_GAP_RATIO) * k + this.exceptionHalfWidth, y: 0, z: 0 },\n rotation: 0\n }\n }\n ]\n }\n\n /** Half the width of a carrier in the exception area, in mm: its edge stands past the gap */\n get exceptionHalfWidth(): number {\n return 0\n }\n\n /**\n * The holder's own anchor is its bottom's centre: a node on the frame at its 3D's origin (the box centre), half its\n * 3D's depth down, turned and moved with it. Others by the layer below.\n */\n anchorObject3D(anchorId: string): any {\n const frame = super.anchorObject3D(anchorId)\n if (anchorId !== HOLDER_ANCHOR || !frame) return frame\n let node = frame.userData.carrierAnchor\n if (!node || node.parent !== frame) {\n node = new frame.constructor()\n node.name = 'carrier-anchor'\n frame.add(node)\n frame.userData.carrierAnchor = node\n }\n node.position.set(0, -(Number((this as any)._realObject?.effectiveDepth) || 0) / 2, 0)\n return node\n }\n }\n}\n\n/* The mixins of things-scene are typed loosely: the holder is still an MCSUnit. */\ninterface MCSCarrierHolder extends MCSUnit {}\n\n/** fmsim's own carrier holder: an MCS unit that holds things, wearing `fmsim.CarrierHolder`. */\nclass MCSCarrierHolder extends CarrierHolder(ItemsDataBinding(Holdable(Capacity(MCSUnit as any)))) {\n static get properties(): any {\n return [...MCSUnit.properties, ...CARRIER_HOLDER_PROPERTIES]\n }\n\n /** On the transport surface by default (fmsim v2). A Port, Shelf or Shuttle holds them at its bottom; an OHT hangs them below. */\n get carrierRest(): { height: number; mount: 'ON' | 'HANG' } {\n return { height: 30, mount: 'ON' }\n }\n}\n\nexport default MCSCarrierHolder\n\n/*\n The legend a carrier figure shows its tables by (ADR-0166 7, 12; ADR-0167 11): the nearest carrier holder up its\n parents that chose one for the role -- carrier-legend its carrier legend, carrier-animation its carrier animation --\n then the board root's same choice; none chosen, no answer (the figure's own table, fmsim's default). Colour and effect\n only: a carrier figure's thickness is its own fixed table (ADR-0167 12).\n*/\nconst ROLE_PROPERTY: Record<string, string> = {\n 'carrier-legend': 'carrierLegendName',\n 'carrier-animation': 'carrierAnimationName'\n}\n\nexport function carrierHolderLegend({ component, role }: { component: any; role: string }): unknown {\n const property = ROLE_PROPERTY[role]\n if (!property) return undefined\n let name: unknown\n for (let at = component?.parent; at && !name; at = at.parent) if (at.isCarrierHolder) name = at.state?.[property]\n name ||= component?.root?.rootModel?.state?.[property]\n if (typeof name !== 'string' || !name) return undefined\n let legend = component?.root?.style?.[name]\n if (typeof legend === 'string') {\n try {\n legend = JSON5.parse(legend)\n } catch {\n return undefined\n }\n }\n return legend && typeof legend === 'object' ? colourAndEffect(legend) : undefined\n}\n\nregisterFigureLegendResolver(carrierHolderLegend)\n"]}