@shipload/sdk 1.0.0-next.25 → 1.0.0-next.27

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.
@@ -55,7 +55,7 @@ export const GATHERER_DEPTH_TABLE: readonly GathererDepthParams[] = [
55
55
  {floor: 46000, slope: 12},
56
56
  {floor: 53500, slope: 10},
57
57
  {floor: 60000, slope: 5},
58
- {floor: 63500, slope: 2},
58
+ {floor: 63537, slope: 2},
59
59
  ]
60
60
 
61
61
  export const GATHERER_DEPTH_MAX_TIER = 10
@@ -175,6 +175,7 @@ import {decodeCraftedItemStats} from './crafting'
175
175
  import {
176
176
  applySlotMultiplier,
177
177
  clampUint16,
178
+ clampUint32,
178
179
  getSlotAmp,
179
180
  type InstalledModule,
180
181
  } from '../entities/slot-multiplier'
@@ -346,8 +347,8 @@ export function computeEntityCapabilities(
346
347
  }
347
348
  if (hasGenerator) {
348
349
  result.generator = {
349
- capacity: clampUint16(totalGenCapacity),
350
- recharge: clampUint16(totalGenRecharge),
350
+ capacity: clampUint32(totalGenCapacity),
351
+ recharge: clampUint32(totalGenRecharge),
351
352
  }
352
353
  }
353
354
  if (hasGatherer) {
@@ -28,7 +28,7 @@ export class Entity extends ServerContract.Types.entity_info {
28
28
  }
29
29
 
30
30
  get isIdle(): boolean {
31
- return this.is_idle
31
+ return schedule.isIdle(this)
32
32
  }
33
33
 
34
34
  get sched(): ScheduleAccessor {
@@ -11,6 +11,7 @@ import {getItem} from '../data/catalog'
11
11
  import {getModuleCapabilityType, moduleAccepts, moduleSlotTypeToCode} from '../capabilities/modules'
12
12
  import {computeEntityCapabilities} from '../derivation/capabilities'
13
13
  import {packedModulesToInstalled} from './slot-multiplier'
14
+ import {LANE_MOBILITY} from '../scheduling/schedule'
14
15
 
15
16
  export interface PackedModuleInput {
16
17
  itemId: number
@@ -29,6 +30,7 @@ export interface EntityStateInput {
29
30
  energy?: number
30
31
  modules?: PackedModuleInput[]
31
32
  schedule?: ServerContract.Types.schedule
33
+ lanes?: ServerContract.Types.lane[]
32
34
  cargo?: ServerContract.Types.cargo_item[]
33
35
  }
34
36
 
@@ -86,6 +88,17 @@ export function makeEntity(packedItemId: number, state: EntityStateInput): Entit
86
88
  const layout = getEntityLayout(packedItemId)?.slots ?? []
87
89
  const mods = state.modules ?? []
88
90
 
91
+ const lanes =
92
+ state.lanes ??
93
+ (state.schedule
94
+ ? [
95
+ ServerContract.Types.lane.from({
96
+ lane_key: UInt8.from(LANE_MOBILITY),
97
+ schedule: state.schedule,
98
+ }),
99
+ ]
100
+ : [])
101
+
89
102
  const info: Record<string, unknown> = {
90
103
  type: template.kind,
91
104
  id: UInt64.from(state.id),
@@ -95,14 +108,10 @@ export function makeEntity(packedItemId: number, state: EntityStateInput): Entit
95
108
  item_id: UInt16.from(state.itemId ?? template.itemId),
96
109
  cargomass: UInt32.from(state.cargomass ?? 0),
97
110
  cargo: state.cargo || [],
98
- is_idle: !state.schedule,
99
- current_task_elapsed: UInt32.from(0),
100
- current_task_remaining: UInt32.from(0),
101
- pending_tasks: [],
111
+ lanes,
102
112
  }
103
113
 
104
114
  if (state.energy !== undefined) info.energy = UInt16.from(state.energy)
105
- if (state.schedule) info.schedule = state.schedule
106
115
 
107
116
  if (kind === 'container') {
108
117
  info.modules = []
@@ -28,6 +28,8 @@ export function clampUint16(value: number): number {
28
28
  return Math.min(value, U16_MAX)
29
29
  }
30
30
 
31
+ export const clampUint32 = (v: number): number => Math.min(Math.max(Math.floor(v), 0), 4294967295)
32
+
31
33
  export function applySlotMultiplier(value: number, outputPct: number): number {
32
34
  return clampUint16(Math.floor((value * outputPct) / 100))
33
35
  }
@@ -28,6 +28,7 @@ export type movement_stats = ServerContract.Types.movement_stats
28
28
  export type energy_stats = ServerContract.Types.energy_stats
29
29
  export type loader_stats = ServerContract.Types.loader_stats
30
30
  export type schedule = ServerContract.Types.schedule
31
+ export type lane = ServerContract.Types.lane
31
32
  export type task = ServerContract.Types.task
32
33
  export type cargo_item = ServerContract.Types.cargo_item
33
34
  export type entity_row = ServerContract.Types.entity_row
@@ -177,7 +178,19 @@ export type {
177
178
  } from './travel/travel'
178
179
 
179
180
  export * as schedule from './scheduling/schedule'
180
- export type {Scheduleable, ScheduleData} from './scheduling/schedule'
181
+ export {LANE_MOBILITY, LANE_BARRIER} from './scheduling/schedule'
182
+ export type {
183
+ ScheduleData,
184
+ LaneView,
185
+ OrderedTask,
186
+ ResolvedEvent,
187
+ } from './scheduling/schedule'
188
+ export {
189
+ candidateLaneCompletesAt,
190
+ laneKeyForModule,
191
+ rawScheduleEnd,
192
+ workerLaneKey,
193
+ } from './scheduling/lanes'
181
194
  export {ScheduleAccessor, createScheduleAccessor} from './scheduling/accessor'
182
195
  export {InventoryAccessor, createInventoryAccessor} from './entities/inventory-accessor'
183
196
  export type {HasCargo} from './entities/inventory-accessor'
@@ -191,13 +204,11 @@ export {
191
204
  createProjectedEntity,
192
205
  projectEntity,
193
206
  projectEntityAt,
194
- projectFromCurrentState,
195
- projectFromCurrentStateAt,
207
+ projectRemainingAt,
196
208
  validateSchedule,
197
209
  } from './scheduling/projection'
198
210
  export type {
199
211
  Projectable,
200
- ProjectableSnapshot,
201
212
  ProjectedEntity,
202
213
  ProjectionOptions,
203
214
  } from './scheduling/projection'
@@ -205,6 +216,15 @@ export type {
205
216
  export {taskCargoChanges} from './scheduling/task-cargo'
206
217
  export type {TaskCargoChange, TaskCargoDirection} from './scheduling/task-cargo'
207
218
 
219
+ export {
220
+ projectedCargoAvailableAt,
221
+ availableForItem,
222
+ cargoReadyAt,
223
+ taskCargoEffect,
224
+ } from './scheduling/availability'
225
+
226
+ export {maxCraftable} from './capabilities/craftable'
227
+
208
228
  export {energyAtTime} from './scheduling/energy'
209
229
 
210
230
  export * from './types/capabilities'
@@ -65,13 +65,22 @@ export class ActionsManager extends BaseManager {
65
65
  return this.server.action('resolve', params)
66
66
  }
67
67
 
68
- cancel(entityId: UInt64Type, count: UInt64Type): Action {
68
+ cancel(entityId: UInt64Type, laneKey: number, count: UInt64Type): Action {
69
69
  return this.server.action('cancel', {
70
70
  id: UInt64.from(entityId),
71
+ lane_key: UInt8.from(laneKey),
71
72
  count: UInt64.from(count),
72
73
  })
73
74
  }
74
75
 
76
+ retarget(sourceId: UInt64Type, taskIndex: UInt64Type, newDestId: UInt64Type): Action {
77
+ return this.server.action('retarget', {
78
+ source_id: UInt64.from(sourceId),
79
+ task_index: UInt64.from(taskIndex),
80
+ new_dest_id: UInt64.from(newDestId),
81
+ })
82
+ }
83
+
75
84
  recharge(entityId: UInt64Type): Action {
76
85
  return this.server.action('recharge', {
77
86
  id: UInt64.from(entityId),
@@ -252,6 +261,12 @@ export class ActionsManager extends BaseManager {
252
261
  })
253
262
  }
254
263
 
264
+ claimStarter(owner: NameType): Action {
265
+ return this.server.action('claimstarter', {
266
+ owner: Name.from(owner),
267
+ })
268
+ }
269
+
255
270
  async wrapEntity(
256
271
  owner: NameType,
257
272
  entityId: UInt64Type,
@@ -67,7 +67,8 @@ export interface ScheduledBuild {
67
67
  hasStarted: boolean
68
68
  startsAt: number
69
69
  completesAt: number
70
- trailingCancelCount: number
70
+ cancelable: boolean
71
+ blockingTaskCount: number
71
72
  }
72
73
 
73
74
  export interface Reservation {
@@ -4,6 +4,7 @@ import type {ServerContract} from '../contracts'
4
4
  import {PlotManager} from './plot'
5
5
  import {getItem} from '../data/catalog'
6
6
  import {calc_craft_duration} from '../capabilities/crafting'
7
+ import {getLanes, getTasks} from '../scheduling/schedule'
7
8
  import {TaskType} from '../types'
8
9
  import type {
9
10
  BuildableTarget,
@@ -94,43 +95,43 @@ export class ConstructionManager extends BaseManager {
94
95
  const buckets = new Map<string, Map<string, InboundTransfer>>()
95
96
  const nowMs = now.getTime()
96
97
  for (const entity of entities) {
97
- const schedule = entity.schedule
98
- if (!schedule) continue
99
98
  const entityIdStr = entity.id.toString()
100
99
  const sourceName = entity.entity_name || entityIdStr
101
- const startedMs = schedule.started.toDate().getTime()
102
- let cumulativeSec = 0
103
- for (const task of schedule.tasks) {
104
- cumulativeSec += task.duration.toNumber()
105
- if (!isTransferTask(task)) continue
106
- if (!task.entitytarget) continue
107
- const projectedEndMs = startedMs + cumulativeSec * 1000
108
- if (projectedEndMs < nowMs) continue
109
- const targetIdStr = task.entitytarget.entity_id.toString()
110
- const etaSeconds = Math.max(0, Math.round((projectedEndMs - nowMs) / 1000))
111
- let perTarget = buckets.get(targetIdStr)
112
- if (!perTarget) {
113
- perTarget = new Map()
114
- buckets.set(targetIdStr, perTarget)
115
- }
116
- for (const c of task.cargo) {
117
- const itemId = c.item_id.toNumber()
118
- const quantity = c.quantity.toNumber()
119
- if (quantity === 0) continue
120
- const key = `${entityIdStr}#${itemId}`
121
- const existing = perTarget.get(key)
122
- if (existing) {
123
- existing.quantity += quantity
124
- existing.etaSeconds = Math.min(existing.etaSeconds, etaSeconds)
125
- } else {
126
- perTarget.set(key, {
127
- sourceEntityId: entity.id,
128
- sourceEntityType: entity.type,
129
- sourceName,
130
- itemId,
131
- quantity,
132
- etaSeconds,
133
- })
100
+ for (const lane of getLanes(entity)) {
101
+ const startedMs = lane.schedule.started.toDate().getTime()
102
+ let cumulativeSec = 0
103
+ for (const task of lane.schedule.tasks) {
104
+ cumulativeSec += task.duration.toNumber()
105
+ if (!isTransferTask(task)) continue
106
+ if (!task.entitytarget) continue
107
+ const projectedEndMs = startedMs + cumulativeSec * 1000
108
+ if (projectedEndMs < nowMs) continue
109
+ const targetIdStr = task.entitytarget.entity_id.toString()
110
+ const etaSeconds = Math.max(0, Math.round((projectedEndMs - nowMs) / 1000))
111
+ let perTarget = buckets.get(targetIdStr)
112
+ if (!perTarget) {
113
+ perTarget = new Map()
114
+ buckets.set(targetIdStr, perTarget)
115
+ }
116
+ for (const c of task.cargo) {
117
+ const itemId = c.item_id.toNumber()
118
+ const quantity = c.quantity.toNumber()
119
+ if (quantity === 0) continue
120
+ const key = `${entityIdStr}#${itemId}`
121
+ const existing = perTarget.get(key)
122
+ if (existing) {
123
+ existing.quantity += quantity
124
+ existing.etaSeconds = Math.min(existing.etaSeconds, etaSeconds)
125
+ } else {
126
+ perTarget.set(key, {
127
+ sourceEntityId: entity.id,
128
+ sourceEntityType: entity.type,
129
+ sourceName,
130
+ itemId,
131
+ quantity,
132
+ etaSeconds,
133
+ })
134
+ }
134
135
  }
135
136
  }
136
137
  }
@@ -142,51 +143,107 @@ export class ConstructionManager extends BaseManager {
142
143
  return out
143
144
  }
144
145
 
146
+ private plotReservation(
147
+ plot: ServerContract.Types.entity_info,
148
+ now: Date
149
+ ): {
150
+ builderId: UInt64
151
+ group?: UInt64
152
+ startsAt: number
153
+ completesAt: number
154
+ hasStarted: boolean
155
+ } | null {
156
+ for (const lane of getLanes(plot)) {
157
+ const startedMs = lane.schedule.started.toDate().getTime()
158
+ let startSec = 0
159
+ for (const task of lane.schedule.tasks) {
160
+ if (task.type.toNumber() === TaskType.RESERVED) {
161
+ if (!task.entitytarget) return null
162
+ const startsAt = startedMs + startSec * 1000
163
+ const completesAt = startsAt + task.duration.toNumber() * 1000
164
+ return {
165
+ builderId: task.entitytarget.entity_id,
166
+ group: task.entitygroup ?? undefined,
167
+ startsAt,
168
+ completesAt,
169
+ hasStarted: startsAt <= now.getTime(),
170
+ }
171
+ }
172
+ startSec += task.duration.toNumber()
173
+ }
174
+ }
175
+ return null
176
+ }
177
+
178
+ private builderCancelability(
179
+ builder: ServerContract.Types.entity_info | undefined,
180
+ group: UInt64 | undefined
181
+ ): {cancelable: boolean; blockingTaskCount: number} {
182
+ if (!builder || group === undefined) {
183
+ return {cancelable: false, blockingTaskCount: 0}
184
+ }
185
+ for (const lane of getLanes(builder)) {
186
+ const tasks = lane.schedule.tasks
187
+ const buildIdx = tasks.findIndex(
188
+ (t) =>
189
+ t.type.toNumber() === TaskType.BUILDPLOT &&
190
+ t.entitygroup !== undefined &&
191
+ t.entitygroup.equals(group)
192
+ )
193
+ if (buildIdx < 0) continue
194
+ const trailing = tasks.length - 1 - buildIdx
195
+ return {cancelable: trailing === 0, blockingTaskCount: trailing}
196
+ }
197
+ return {cancelable: false, blockingTaskCount: 0}
198
+ }
199
+
200
+ private buildFromReservation(
201
+ res: {
202
+ builderId: UInt64
203
+ group?: UInt64
204
+ startsAt: number
205
+ completesAt: number
206
+ hasStarted: boolean
207
+ },
208
+ builder: ServerContract.Types.entity_info | undefined
209
+ ): ScheduledBuild {
210
+ const {cancelable, blockingTaskCount} = this.builderCancelability(builder, res.group)
211
+ return {
212
+ shipId: res.builderId,
213
+ shipName: builder?.entity_name || res.builderId.toString(),
214
+ hasStarted: res.hasStarted,
215
+ startsAt: res.startsAt,
216
+ completesAt: res.completesAt,
217
+ cancelable,
218
+ blockingTaskCount,
219
+ }
220
+ }
221
+
145
222
  scheduledBuildFor(
146
- plotId: UInt64,
223
+ plot: ServerContract.Types.entity_info,
147
224
  entities: ServerContract.Types.entity_info[],
148
225
  now: Date
149
226
  ): ScheduledBuild | null {
150
- return this.scheduledBuildsByTarget(entities, now).get(plotId.toString()) ?? null
227
+ const res = this.plotReservation(plot, now)
228
+ if (!res) return null
229
+ const builder = entities.find((e) => e.id.equals(res.builderId))
230
+ return this.buildFromReservation(res, builder)
151
231
  }
152
232
 
153
233
  scheduledBuildsByTarget(
154
234
  entities: ServerContract.Types.entity_info[],
155
235
  now: Date
156
236
  ): Map<string, ScheduledBuild> {
157
- const nowMs = now.getTime()
158
- const best = new Map<string, ScheduledBuild>()
237
+ const byId = new Map(entities.map((e) => [e.id.toString(), e]))
238
+ const out = new Map<string, ScheduledBuild>()
159
239
  for (const entity of entities) {
160
- const schedule = entity.schedule
161
- if (!schedule) continue
162
- const startedMs = schedule.started.toDate().getTime()
163
- const tasks = schedule.tasks
164
- let cumulativeSec = 0
165
- for (let i = 0; i < tasks.length; i++) {
166
- const task = tasks[i]
167
- const startSec = cumulativeSec
168
- cumulativeSec += task.duration.toNumber()
169
- if (task.type.toNumber() !== TaskType.BUILDPLOT) continue
170
- if (!task.entitytarget) continue
171
- const completesAt = startedMs + cumulativeSec * 1000
172
- if (completesAt < nowMs) continue
173
- const startsAt = startedMs + startSec * 1000
174
- const targetId = task.entitytarget.entity_id.toString()
175
- const candidate: ScheduledBuild = {
176
- shipId: entity.id,
177
- shipName: entity.entity_name || entity.id.toString(),
178
- hasStarted: startsAt <= nowMs,
179
- startsAt,
180
- completesAt,
181
- trailingCancelCount: tasks.length - 1 - i,
182
- }
183
- const existing = best.get(targetId)
184
- if (!existing || candidate.completesAt < existing.completesAt) {
185
- best.set(targetId, candidate)
186
- }
187
- }
240
+ if (entity.type.toString() !== 'plot') continue
241
+ const res = this.plotReservation(entity, now)
242
+ if (!res) continue
243
+ const builder = byId.get(res.builderId.toString())
244
+ out.set(entity.id.toString(), this.buildFromReservation(res, builder))
188
245
  }
189
- return best
246
+ return out
190
247
  }
191
248
 
192
249
  reservationsFrom(
@@ -303,9 +360,8 @@ function isTransferTask(task: ServerContract.Types.task): boolean {
303
360
  }
304
361
 
305
362
  function reservationsOf(source: ServerContract.Types.entity_info): Reservation[] {
306
- if (!source.schedule) return []
307
363
  const out = new Map<string, Reservation>()
308
- for (const task of source.schedule.tasks) {
364
+ for (const task of getTasks(source)) {
309
365
  if (!isTransferTask(task)) continue
310
366
  if (!task.entitytarget) continue
311
367
  const targetType = task.entitytarget.entity_type
@@ -1,86 +1,128 @@
1
1
  import type {ServerContract} from '../contracts'
2
2
  import type {TaskType} from '../types'
3
- import type {ScheduleData} from './schedule'
4
- import * as schedule from './schedule'
3
+ import * as core from './lane-core'
4
+ import {
5
+ activeTasks,
6
+ getLane,
7
+ getLanes,
8
+ hasSchedule,
9
+ isIdle,
10
+ LANE_MOBILITY,
11
+ type LaneView,
12
+ type ScheduleData,
13
+ } from './schedule'
5
14
 
6
15
  type Task = ServerContract.Types.task
7
16
 
8
17
  export class ScheduleAccessor {
9
- constructor(private entity: ScheduleData) {}
18
+ private _laneResolved = false
19
+ private _lane: LaneView | undefined
20
+
21
+ constructor(
22
+ private entity: ScheduleData,
23
+ private laneKey: number = LANE_MOBILITY
24
+ ) {}
25
+
26
+ private get lane(): LaneView | undefined {
27
+ if (!this._laneResolved) {
28
+ this._lane = getLane(this.entity, this.laneKey)
29
+ this._laneResolved = true
30
+ }
31
+ return this._lane
32
+ }
33
+
34
+ forLane(laneKey: number): ScheduleAccessor {
35
+ return new ScheduleAccessor(this.entity, laneKey)
36
+ }
37
+
38
+ get lanes(): LaneView[] {
39
+ return getLanes(this.entity)
40
+ }
10
41
 
11
42
  get hasSchedule(): boolean {
12
- return schedule.hasSchedule(this.entity)
43
+ return hasSchedule(this.entity)
13
44
  }
14
45
 
15
46
  get isIdle(): boolean {
16
- return schedule.isIdle(this.entity)
47
+ return isIdle(this.entity)
17
48
  }
18
49
 
19
50
  get tasks(): Task[] {
20
- return schedule.getTasks(this.entity)
51
+ return this.lane?.schedule.tasks ?? []
52
+ }
53
+
54
+ activeTasks(now: Date): Task[] {
55
+ return activeTasks(this.entity, now)
21
56
  }
22
57
 
23
58
  duration(): number {
24
- return schedule.scheduleDuration(this.entity)
59
+ return this.lane ? core.laneDuration(this.lane.schedule) : 0
25
60
  }
26
61
 
27
62
  elapsed(now: Date): number {
28
- return schedule.scheduleElapsed(this.entity, now)
63
+ return this.lane ? core.laneElapsed(this.lane.schedule, now) : 0
29
64
  }
30
65
 
31
66
  remaining(now: Date): number {
32
- return schedule.scheduleRemaining(this.entity, now)
67
+ return this.lane ? core.laneRemaining(this.lane.schedule, now) : 0
68
+ }
69
+
70
+ startsIn(now: Date): number {
71
+ return this.lane ? core.laneStartsIn(this.lane.schedule, now) : 0
33
72
  }
34
73
 
35
74
  complete(now: Date): boolean {
36
- return schedule.scheduleComplete(this.entity, now)
75
+ return this.lane ? core.laneComplete(this.lane.schedule, now) : false
37
76
  }
38
77
 
39
78
  currentTaskIndex(now: Date): number {
40
- return schedule.currentTaskIndex(this.entity, now)
79
+ return this.lane ? core.currentTaskIndexForLane(this.lane.schedule, now) : -1
41
80
  }
42
81
 
43
82
  currentTask(now: Date): Task | undefined {
44
- return schedule.currentTask(this.entity, now)
83
+ return this.lane ? core.currentTask(this.lane.schedule, now) : undefined
45
84
  }
46
85
 
47
86
  currentTaskType(now: Date): TaskType | undefined {
48
- return schedule.currentTaskType(this.entity, now)
87
+ return this.lane ? core.currentTaskType(this.lane.schedule, now) : undefined
49
88
  }
50
89
 
51
90
  taskStartTime(index: number): number {
52
- return schedule.getTaskStartTime(this.entity, index)
91
+ return this.lane ? core.laneTaskStartTime(this.lane.schedule, index) : 0
53
92
  }
54
93
 
55
94
  taskElapsed(index: number, now: Date): number {
56
- return schedule.getTaskElapsed(this.entity, index, now)
95
+ return this.lane ? core.laneTaskElapsed(this.lane.schedule, index, now) : 0
57
96
  }
58
97
 
59
98
  taskRemaining(index: number, now: Date): number {
60
- return schedule.getTaskRemaining(this.entity, index, now)
99
+ return this.lane ? core.laneTaskRemaining(this.lane.schedule, index, now) : 0
61
100
  }
62
101
 
63
102
  taskComplete(index: number, now: Date): boolean {
64
- return schedule.isTaskComplete(this.entity, index, now)
103
+ return this.lane ? core.laneTaskComplete(this.lane.schedule, index, now) : false
65
104
  }
66
105
 
67
106
  taskInProgress(index: number, now: Date): boolean {
68
- return schedule.isTaskInProgress(this.entity, index, now)
107
+ return this.lane ? core.laneTaskInProgress(this.lane.schedule, index, now) : false
69
108
  }
70
109
 
71
110
  currentTaskProgress(now: Date): number {
72
- return schedule.currentTaskProgress(this.entity, now)
111
+ return this.lane ? core.currentTaskProgress(this.lane.schedule, now) : 0
73
112
  }
74
113
 
75
114
  currentTaskProgressFloat(now: Date): number {
76
- return schedule.currentTaskProgressFloat(this.entity, now)
115
+ return this.lane ? core.currentTaskProgressFloatForLane(this.lane.schedule, now) : 0
77
116
  }
78
117
 
79
118
  progress(now: Date): number {
80
- return schedule.scheduleProgress(this.entity, now)
119
+ return this.lane ? core.laneProgress(this.lane.schedule, now) : 0
81
120
  }
82
121
  }
83
122
 
84
- export function createScheduleAccessor(entity: ScheduleData): ScheduleAccessor {
85
- return new ScheduleAccessor(entity)
123
+ export function createScheduleAccessor(
124
+ entity: ScheduleData,
125
+ laneKey: number = LANE_MOBILITY
126
+ ): ScheduleAccessor {
127
+ return new ScheduleAccessor(entity, laneKey)
86
128
  }