@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.
- package/dist/features/lv-figures.js +7 -1
- package/dist/features/lv-figures.js.map +1 -1
- package/dist/mcs-carrier-holder.js +64 -8
- package/dist/mcs-carrier-holder.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/src/features/lv-figures.ts +8 -1
- package/src/mcs-carrier-holder.ts +62 -7
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@fmsim/machine",
|
|
3
3
|
"description": "Layout View를 구성하는 설비(machine)들과 유닛을 구현한 모듈입니다.",
|
|
4
4
|
"author": "heartyoh",
|
|
5
|
-
"version": "3.0.0-beta.
|
|
5
|
+
"version": "3.0.0-beta.7",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/index.js",
|
|
8
8
|
"things-scene": true,
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
"migration": "things-factory-migration"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@fmsim/api": "^3.0.0-beta.
|
|
30
|
-
"@fmsim/figure-capabilities": "^3.0.0-beta.
|
|
29
|
+
"@fmsim/api": "^3.0.0-beta.7",
|
|
30
|
+
"@fmsim/figure-capabilities": "^3.0.0-beta.7",
|
|
31
31
|
"@hatiolab/figure-model": "^0.12.0",
|
|
32
32
|
"@hatiolab/things-scene": "^10.1.90",
|
|
33
33
|
"@operato/slot-layout-editor": "^10.29.33",
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"prettier --write"
|
|
60
60
|
]
|
|
61
61
|
},
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "3d79ed4f842108b845268b5d4b229927ff77700f"
|
|
63
63
|
}
|
|
@@ -103,12 +103,19 @@ export function LVVehicle<T extends new (...args: any[]) => any>(Base: T) {
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
/**
|
|
106
|
-
* `fmsim.CarrierHolder` on a figure: carriers
|
|
106
|
+
* `fmsim.CarrierHolder` on a figure: its carriers stand in its places -- a gripper, a lift plate, a fork's tiers -- and
|
|
107
|
+
* go with them; one without places keeps them in a pile on its top. Carriers change hands at the transport surface, so a
|
|
108
|
+
* holder that takes them on its
|
|
107
109
|
* top stands that tall when nothing else says -- as fmsim's own AGV and shuttle do. A machine's height wins (whichever is
|
|
108
110
|
* worn over the other); a holder that hangs them or hangs itself from the ceiling (an OHT) keeps its own.
|
|
109
111
|
*/
|
|
110
112
|
export function FigureCarrierHolder<T extends new (...args: any[]) => any>(Base: T) {
|
|
111
113
|
return class extends CarrierHolder(Base) {
|
|
114
|
+
/** Its carriers stand in its own places, which go with the parts that carry them (ADR-0167 decision 23) */
|
|
115
|
+
get fillsPlaces(): boolean {
|
|
116
|
+
return true
|
|
117
|
+
}
|
|
118
|
+
|
|
112
119
|
get effectiveDepth(): number | undefined {
|
|
113
120
|
const given = super.effectiveDepth
|
|
114
121
|
if (given !== undefined) return given
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
ItemsDataBinding,
|
|
7
7
|
Model,
|
|
8
8
|
TRANSFER_SLOT_KEY,
|
|
9
|
+
drawingScaleFor,
|
|
9
10
|
figureLegendSourcesChanged,
|
|
10
11
|
itemTypeEntryOf,
|
|
11
12
|
itemTypeTableOf,
|
|
@@ -16,7 +17,7 @@ import { colourAndEffect } from './features/legend-rows'
|
|
|
16
17
|
import { HOLDER_ANCHOR, type ItemDims, type ResolvedSlot } from '@hatiolab/figure-model'
|
|
17
18
|
import { carrierHolderProperties } from '@fmsim/figure-capabilities'
|
|
18
19
|
import MCSUnit from './mcs-unit.js'
|
|
19
|
-
import { incomingFromV2 } from './utils/load-address'
|
|
20
|
+
import { incomingFromV2, resolveOccupancy, type IncomingCarrier, type LoadLayout, type OccupancyResult } from './utils/load-address'
|
|
20
21
|
|
|
21
22
|
/**
|
|
22
23
|
* A holder's slots outside its layout (common item contract 3.4): every carrier of a holder without a layout stands in
|
|
@@ -99,15 +100,67 @@ export function CarrierHolder<T extends new (...args: any[]) => any>(Base: T) {
|
|
|
99
100
|
}
|
|
100
101
|
|
|
101
102
|
/**
|
|
102
|
-
*
|
|
103
|
-
*
|
|
103
|
+
* Whether carriers stand in the holder's own places (ADR-0167 decision 23): a figure holder's places -- a gripper, a
|
|
104
|
+
* lift plate, the tiers on a fork -- carry what stands on them as the figure moves. fmsim's own holders keep theirs: a
|
|
105
|
+
* pile, or the layout their data addresses (LoadLayoutHolder).
|
|
106
|
+
*/
|
|
107
|
+
get fillsPlaces(): boolean {
|
|
108
|
+
return false
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** The holder's places as the last records took them: an addressed carrier keeps its slot while it is still there */
|
|
112
|
+
_placeOccupancy?: OccupancyResult
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* One record per carrier the data names, bottom first: MULTICARRIERS in order, then the representative. A carrier is
|
|
116
|
+
* told its own keys and whether to show its text. They stand in the pile, unless the holder fills its places.
|
|
104
117
|
*/
|
|
105
118
|
carrierRecords(data: Record<string, any> | undefined): CarrierRecord[] {
|
|
106
|
-
|
|
107
|
-
|
|
119
|
+
const incoming = incomingFromV2(data)
|
|
120
|
+
const record = (c: IncomingCarrier, slotId: string): CarrierRecord => ({
|
|
121
|
+
slotId,
|
|
108
122
|
itemId: c.name,
|
|
109
123
|
itemState: this.carrierStateOf(c.record, c.record === data)
|
|
110
|
-
})
|
|
124
|
+
})
|
|
125
|
+
const places = this.fillsPlaces ? (((this as any).slots ?? []) as Array<{ id: string; maxCount?: number }>) : []
|
|
126
|
+
if (!places.length) return incoming.map(c => record(c, PILE_SLOT))
|
|
127
|
+
|
|
128
|
+
/* A carrier its data addresses (a layout's TIER/SLOT) stands at that address, as on a crane; a wrong address beside the holder. */
|
|
129
|
+
const layout = this._placeLayout
|
|
130
|
+
const occupancy = layout ? resolveOccupancy(layout, incoming, this._placeOccupancy) : undefined
|
|
131
|
+
this._placeOccupancy = occupancy
|
|
132
|
+
const slotOf = new Map<string, string>()
|
|
133
|
+
for (const [key, list] of occupancy?.slots ?? []) {
|
|
134
|
+
const [tier, slot] = key.split(':').map(Number)
|
|
135
|
+
for (const c of list) slotOf.set(c.name, `t${tier}_s${slot}`)
|
|
136
|
+
}
|
|
137
|
+
for (const c of occupancy?.addressError ?? []) slotOf.set(c.name, EXCEPTION_SLOT)
|
|
138
|
+
|
|
139
|
+
/* 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. */
|
|
140
|
+
const room = new Map(places.map(p => [p.id, p.maxCount ?? 1]))
|
|
141
|
+
for (const slotId of slotOf.values()) if (room.has(slotId)) room.set(slotId, room.get(slotId)! - 1)
|
|
142
|
+
const unplaced = incoming.filter(c => !slotOf.has(c.name))
|
|
143
|
+
const heldIn = new Map(((this as any)._items as any[]).map(item => [item.state?.id, item[TRANSFER_SLOT_KEY]] as const))
|
|
144
|
+
for (const c of unplaced) {
|
|
145
|
+
const kept = heldIn.get(c.name)
|
|
146
|
+
if (kept && (room.get(kept) ?? 0) > 0) {
|
|
147
|
+
slotOf.set(c.name, kept)
|
|
148
|
+
room.set(kept, room.get(kept)! - 1)
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
for (const c of unplaced) {
|
|
152
|
+
if (slotOf.has(c.name)) continue
|
|
153
|
+
const free = places.find(p => (room.get(p.id) ?? 0) > 0)
|
|
154
|
+
slotOf.set(c.name, free ? free.id : EXCEPTION_SLOT)
|
|
155
|
+
if (free) room.set(free.id, room.get(free.id)! - 1)
|
|
156
|
+
}
|
|
157
|
+
return incoming.map(c => record(c, slotOf.get(c.name)!))
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** The layout addresses are read by: the holder's, when it holds and the drawing's scale is known */
|
|
161
|
+
get _placeLayout(): LoadLayout | undefined {
|
|
162
|
+
const sel = (this as any).effectiveLayout
|
|
163
|
+
return sel?.status === 'valid' && drawingScaleFor(this as any).known ? (sel.layout as LoadLayout) : undefined
|
|
111
164
|
}
|
|
112
165
|
|
|
113
166
|
/** What a carrier is told: its own keys (the representative's are picked out of the holder data), and its text */
|
|
@@ -201,7 +254,9 @@ export function CarrierHolder<T extends new (...args: any[]) => any>(Base: T) {
|
|
|
201
254
|
*/
|
|
202
255
|
itemShownDimsOf(_carrier: any, slot: ResolvedSlot, slotId: string): ItemDims | null {
|
|
203
256
|
/* Elsewhere outside the layout, a holder that keeps carriers there says (the exception area: LoadLayoutHolder). */
|
|
204
|
-
|
|
257
|
+
/* A place that says no size (a gripper): the carrier is shown at its own (ADR-0167 decision 23). */
|
|
258
|
+
if (slotId !== PILE_SLOT && slotId !== EXCEPTION_SLOT && !slot?.allowed) return null
|
|
259
|
+
if (slotId === PILE_SLOT || slotId === EXCEPTION_SLOT) {
|
|
205
260
|
const k = (this as any).mmPerSceneUnit
|
|
206
261
|
const { width = 0, height = 0 } = (this as any).state
|
|
207
262
|
const w = Math.abs(width) * PILE_PLAN_RATIO
|