@shipload/sdk 1.0.0-next.72 → 1.0.0-next.73

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.
@@ -0,0 +1,184 @@
1
+ {
2
+ "types": [
3
+ {
4
+ "type": 0,
5
+ "positionBound": false,
6
+ "mobility": false,
7
+ "consumer": false,
8
+ "isTerminal": false,
9
+ "capsPlan": false,
10
+ "cargoEffectResolve": true
11
+ },
12
+ {
13
+ "type": 1,
14
+ "positionBound": false,
15
+ "mobility": true,
16
+ "consumer": false,
17
+ "isTerminal": false,
18
+ "capsPlan": false,
19
+ "cargoEffectResolve": true
20
+ },
21
+ {
22
+ "type": 2,
23
+ "positionBound": false,
24
+ "mobility": false,
25
+ "consumer": false,
26
+ "isTerminal": false,
27
+ "capsPlan": false,
28
+ "cargoEffectResolve": true
29
+ },
30
+ {
31
+ "type": 3,
32
+ "positionBound": true,
33
+ "mobility": false,
34
+ "consumer": false,
35
+ "isTerminal": false,
36
+ "capsPlan": false,
37
+ "cargoEffectResolve": true
38
+ },
39
+ {
40
+ "type": 4,
41
+ "positionBound": true,
42
+ "mobility": false,
43
+ "consumer": true,
44
+ "isTerminal": false,
45
+ "capsPlan": false,
46
+ "cargoEffectResolve": true
47
+ },
48
+ {
49
+ "type": 5,
50
+ "positionBound": true,
51
+ "mobility": false,
52
+ "consumer": false,
53
+ "isTerminal": false,
54
+ "capsPlan": false,
55
+ "cargoEffectResolve": true
56
+ },
57
+ {
58
+ "type": 6,
59
+ "positionBound": false,
60
+ "mobility": true,
61
+ "consumer": false,
62
+ "isTerminal": false,
63
+ "capsPlan": false,
64
+ "cargoEffectResolve": true
65
+ },
66
+ {
67
+ "type": 7,
68
+ "positionBound": false,
69
+ "mobility": false,
70
+ "consumer": true,
71
+ "isTerminal": false,
72
+ "capsPlan": false,
73
+ "cargoEffectResolve": false
74
+ },
75
+ {
76
+ "type": 9,
77
+ "positionBound": false,
78
+ "mobility": true,
79
+ "consumer": false,
80
+ "isTerminal": false,
81
+ "capsPlan": false,
82
+ "cargoEffectResolve": true
83
+ },
84
+ {
85
+ "type": 10,
86
+ "positionBound": false,
87
+ "mobility": false,
88
+ "consumer": false,
89
+ "isTerminal": false,
90
+ "capsPlan": false,
91
+ "cargoEffectResolve": false
92
+ },
93
+ {
94
+ "type": 11,
95
+ "positionBound": false,
96
+ "mobility": false,
97
+ "consumer": false,
98
+ "isTerminal": true,
99
+ "capsPlan": true,
100
+ "cargoEffectResolve": false
101
+ },
102
+ {
103
+ "type": 12,
104
+ "positionBound": false,
105
+ "mobility": false,
106
+ "consumer": false,
107
+ "isTerminal": false,
108
+ "capsPlan": false,
109
+ "cargoEffectResolve": true
110
+ },
111
+ {
112
+ "type": 13,
113
+ "positionBound": false,
114
+ "mobility": false,
115
+ "consumer": false,
116
+ "isTerminal": true,
117
+ "capsPlan": true,
118
+ "cargoEffectResolve": false
119
+ },
120
+ {
121
+ "type": 15,
122
+ "positionBound": true,
123
+ "mobility": false,
124
+ "consumer": false,
125
+ "isTerminal": false,
126
+ "capsPlan": false,
127
+ "cargoEffectResolve": false
128
+ },
129
+ {
130
+ "type": 16,
131
+ "positionBound": false,
132
+ "mobility": false,
133
+ "consumer": false,
134
+ "isTerminal": false,
135
+ "capsPlan": false,
136
+ "cargoEffectResolve": true
137
+ },
138
+ {
139
+ "type": 17,
140
+ "positionBound": true,
141
+ "mobility": false,
142
+ "consumer": true,
143
+ "isTerminal": false,
144
+ "capsPlan": false,
145
+ "cargoEffectResolve": false
146
+ },
147
+ {
148
+ "type": 18,
149
+ "positionBound": true,
150
+ "mobility": false,
151
+ "consumer": false,
152
+ "isTerminal": false,
153
+ "capsPlan": false,
154
+ "cargoEffectResolve": true
155
+ },
156
+ {
157
+ "type": 20,
158
+ "positionBound": false,
159
+ "mobility": false,
160
+ "consumer": true,
161
+ "isTerminal": false,
162
+ "capsPlan": false,
163
+ "cargoEffectResolve": false
164
+ },
165
+ {
166
+ "type": 21,
167
+ "positionBound": true,
168
+ "mobility": false,
169
+ "consumer": true,
170
+ "isTerminal": false,
171
+ "capsPlan": false,
172
+ "cargoEffectResolve": false
173
+ },
174
+ {
175
+ "type": 22,
176
+ "positionBound": true,
177
+ "mobility": false,
178
+ "consumer": false,
179
+ "isTerminal": false,
180
+ "capsPlan": false,
181
+ "cargoEffectResolve": false
182
+ }
183
+ ]
184
+ }
@@ -6,7 +6,7 @@ import {getKindMeta, getTemplateMeta} from '../data/kind-registry'
6
6
  import type {EntityTypeName} from '../data/kind-registry'
7
7
  import {getEntityLayout} from '../data/recipes-runtime'
8
8
  import type {EntitySlot} from '../data/recipes-runtime'
9
- import {itemMetadata} from '../data/metadata'
9
+ import {getItemFamily} from '../data/metadata'
10
10
  import {getItem} from '../data/catalog'
11
11
  import {getModuleCapabilityType, moduleAccepts, moduleSlotTypeToCode} from '../capabilities/modules'
12
12
  import {computeEntityCapabilities} from '../derivation/capabilities'
@@ -52,7 +52,7 @@ function assignModulesToSlots(
52
52
  try {
53
53
  modName = getItem(mod.itemId).name
54
54
  } catch {
55
- modName = itemMetadata[mod.itemId]?.name ?? `item ${mod.itemId}`
55
+ modName = getItemFamily(mod.itemId)?.name ?? `item ${mod.itemId}`
56
56
  }
57
57
  throw new Error(
58
58
  `No compatible slot for module ${modName} (type ${modType}) on ${entityLabel}`
@@ -124,6 +124,8 @@ export {
124
124
  categoryFromIndex,
125
125
  categoryLabelFromIndex,
126
126
  } from './data/catalog'
127
+ export {getItemFamily, itemFamilies, itemFamilyKey} from './data/metadata'
128
+ export type {ItemFamily} from './data/metadata'
127
129
  export {getCurrentEpoch, getEpochInfo} from './scheduling/epoch'
128
130
  export type {EpochInfo} from './scheduling/epoch'
129
131
  export {
@@ -374,12 +376,18 @@ export {
374
376
  derivedLoaders,
375
377
  estimateUnwrapDuration,
376
378
  incomingHoldMass,
379
+ projectCargomass,
377
380
  projectedPeakCargomass,
378
381
  receiveFits,
379
382
  unwrapLoadDuration,
380
383
  unwrapTransitDuration,
381
384
  } from './scheduling/unwrap'
382
- export type {DerivedLoaders, UnwrapDestination, UnwrapItem} from './scheduling/unwrap'
385
+ export type {
386
+ CargomassProjection,
387
+ DerivedLoaders,
388
+ UnwrapDestination,
389
+ UnwrapItem,
390
+ } from './scheduling/unwrap'
383
391
 
384
392
  export {
385
393
  projectedCargoAvailableAt,
@@ -610,6 +610,18 @@ export class ActionsManager extends BaseManager {
610
610
  })
611
611
  }
612
612
 
613
+ blenddepot(
614
+ depotId: UInt64Type,
615
+ owner: NameType,
616
+ inputs: ServerContract.ActionParams.Type.cargo_item[]
617
+ ): Action {
618
+ return this.server.action('blenddepot', {
619
+ depot_id: UInt64.from(depotId),
620
+ owner: Name.from(owner),
621
+ inputs,
622
+ })
623
+ }
624
+
613
625
  deploy(
614
626
  entityId: UInt64Type,
615
627
  ref: ServerContract.ActionParams.Type.cargo_ref,
@@ -4,7 +4,7 @@ import type {ResourceCategory} from '../types'
4
4
  import {getItem, getModules} from '../data/catalog'
5
5
  import {ENTITY_SHIP, getPackedEntityType} from '../data/kind-registry'
6
6
  import {getEntityLayout} from '../data/recipes-runtime'
7
- import {entityMetadata, itemMetadata} from '../data/metadata'
7
+ import {entityMetadata, getItemFamily} from '../data/metadata'
8
8
  import {
9
9
  getModuleCapabilityType,
10
10
  isModuleItem,
@@ -370,7 +370,7 @@ function resolveEntity(
370
370
  modName = modItem.name
371
371
  modTier = modItem.tier
372
372
  } catch {
373
- modName = itemMetadata[modItemId]?.name ?? 'Module'
373
+ modName = getItemFamily(modItemId)?.name ?? 'Module'
374
374
  }
375
375
  const group = computeCapabilityGroup(modType, decodedStats, modTier, slot.outputPct)
376
376
  return {
@@ -5,8 +5,14 @@ import {
5
5
  unwrapLoadDuration,
6
6
  estimateUnwrapDuration,
7
7
  incomingHoldMass,
8
+ projectCargomass,
8
9
  projectedPeakCargomass,
9
10
  } from './unwrap'
11
+ import {TimePoint, UInt8, UInt16, UInt32, UInt64} from '@wharfkit/antelope'
12
+ import {ServerContract} from '../contracts'
13
+ import {getItem} from '../data/catalog'
14
+ import {ITEM_BEAM} from '../data/item-ids'
15
+ import {TaskType} from '../types'
10
16
 
11
17
  describe('unwrap duration mirror', () => {
12
18
  test('derivedLoaders aggregates lanes like derived_loaders()', () => {
@@ -84,3 +90,57 @@ test('projectedPeakCargomass tracks the running peak from cargomass', () => {
84
90
  // No pending tasks: peak = base + candidate add.
85
91
  expect(projectedPeakCargomass(entity, new Date(0), 500)).toBe(1500)
86
92
  })
93
+
94
+ const DEPOSIT_START = new Date('2026-09-20T07:48:37.000Z')
95
+ const BEAM_QTY = 2_500
96
+ const BEAM_MASS = getItem(ITEM_BEAM).mass
97
+
98
+ function unloadingShip(projectedAtMs?: number) {
99
+ const cargo = ServerContract.Types.cargo_item.from({
100
+ item_id: UInt16.from(ITEM_BEAM),
101
+ quantity: UInt32.from(BEAM_QTY),
102
+ stats: UInt64.from(0),
103
+ modules: [],
104
+ })
105
+ const lane = ServerContract.Types.lane.from({
106
+ lane_key: UInt8.from(0),
107
+ schedule: ServerContract.Types.schedule.from({
108
+ started: TimePoint.fromMilliseconds(DEPOSIT_START.getTime()),
109
+ tasks: [
110
+ ServerContract.Types.task.from({
111
+ type: UInt8.from(TaskType.CIVIC_DEPOSIT),
112
+ duration: UInt32.from(1_309),
113
+ cancelable: UInt8.from(2),
114
+ cargo: [cargo],
115
+ couplings: [],
116
+ }),
117
+ ],
118
+ }),
119
+ })
120
+ return {
121
+ cargomass: BEAM_QTY * BEAM_MASS,
122
+ lanes: [lane],
123
+ holds: [],
124
+ projected_at:
125
+ projectedAtMs === undefined ? undefined : TimePoint.fromMilliseconds(projectedAtMs),
126
+ }
127
+ }
128
+
129
+ const UNLOAD_ENDS = new Date(DEPOSIT_START.getTime() + 1_309_000)
130
+ const AFTER_UNLOAD = new Date(UNLOAD_ENDS.getTime() + 60_000)
131
+
132
+ test('projectCargomass reports the mass held at the candidate and the peak around it', () => {
133
+ const plan = projectCargomass(unloadingShip(), AFTER_UNLOAD, 400 * BEAM_MASS)
134
+ // The queued unload empties the hold before the candidate lands.
135
+ expect(plan.used).toBe(400 * BEAM_MASS)
136
+ expect(plan.peak).toBe(BEAM_QTY * BEAM_MASS)
137
+ })
138
+
139
+ test('a task already applied to a projected row is not replayed', () => {
140
+ const applied = unloadingShip(UNLOAD_ENDS.getTime())
141
+ applied.cargomass = 0
142
+ const plan = projectCargomass(applied, AFTER_UNLOAD, 400 * BEAM_MASS)
143
+ expect(plan.used).toBe(400 * BEAM_MASS)
144
+ expect(plan.peak).toBe(400 * BEAM_MASS)
145
+ expect(projectedPeakCargomass(applied, AFTER_UNLOAD, 400 * BEAM_MASS)).toBe(plan.peak)
146
+ })
@@ -133,28 +133,44 @@ function cargoListMass(items: CargoItem[]): number {
133
133
  return m
134
134
  }
135
135
 
136
- export function projectedPeakCargomass(
137
- entity: sched.ScheduleData & {cargomass: number | {toNumber(): number}},
136
+ export interface CargomassProjection {
137
+ used: number
138
+ peak: number
139
+ }
140
+
141
+ export function projectCargomass(
142
+ entity: sched.AnchoredScheduleData & {cargomass: number | {toNumber(): number}},
138
143
  at: Date,
139
144
  addMass: number,
140
145
  removeMass = 0
141
- ): number {
142
- const events: {t: number; delta: number}[] = []
143
- for (const ordered of sched.orderedTasks(entity)) {
146
+ ): CargomassProjection {
147
+ const events: {t: number; delta: number; candidate: boolean}[] = []
148
+ for (const ordered of sched.unappliedTasks(entity)) {
144
149
  const eff = taskCargoEffect(ordered.task)
145
150
  const delta = cargoListMass(eff.added) - cargoListMass(eff.removed)
146
- events.push({t: ordered.completesAt.getTime(), delta})
151
+ events.push({t: ordered.completesAt.getTime(), delta, candidate: false})
147
152
  }
148
- events.push({t: at.getTime(), delta: addMass - removeMass})
153
+ events.push({t: at.getTime(), delta: addMass - removeMass, candidate: true})
149
154
  events.sort((a, b) => (a.t !== b.t ? a.t - b.t : b.delta - a.delta))
150
155
  let running = Number(entity.cargomass)
151
156
  let peak = running
157
+ let used = running
152
158
  for (const e of events) {
153
159
  running += e.delta
154
160
  if (running < 0) running = 0
155
161
  if (running > peak) peak = running
162
+ if (e.candidate) used = running
156
163
  }
157
- return Math.min(peak, 0xffff_ffff)
164
+ return {used: Math.min(used, 0xffff_ffff), peak: Math.min(peak, 0xffff_ffff)}
165
+ }
166
+
167
+ export function projectedPeakCargomass(
168
+ entity: sched.AnchoredScheduleData & {cargomass: number | {toNumber(): number}},
169
+ at: Date,
170
+ addMass: number,
171
+ removeMass = 0
172
+ ): number {
173
+ return projectCargomass(entity, at, addMass, removeMass).peak
158
174
  }
159
175
 
160
176
  export function receiveFits(
package/src/types.ts CHANGED
@@ -208,6 +208,7 @@ export const CATEGORY_LABELS: Record<ResourceCategory, string> = {
208
208
 
209
209
  export interface Item {
210
210
  id: number
211
+ family: string
211
212
  name: string
212
213
  description: string
213
214
  color: string