@shipload/sdk 1.0.0-next.51 → 1.0.0-next.52
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/lib/shipload.d.ts +470 -157
- package/lib/shipload.js +2309 -492
- package/lib/shipload.js.map +1 -1
- package/lib/shipload.m.js +2279 -491
- package/lib/shipload.m.js.map +1 -1
- package/lib/testing.d.ts +123 -8
- package/lib/testing.js +450 -19
- package/lib/testing.js.map +1 -1
- package/lib/testing.m.js +451 -20
- package/lib/testing.m.js.map +1 -1
- package/package.json +1 -1
- package/src/capabilities/crafting.ts +10 -1
- package/src/capabilities/gathering.ts +1 -1
- package/src/capabilities/hauling.ts +0 -5
- package/src/capabilities/modules.ts +6 -0
- package/src/capabilities/movement.ts +1 -1
- package/src/contracts/server.ts +293 -13
- package/src/data/capabilities.ts +11 -2
- package/src/data/entities.json +235 -20
- package/src/data/item-ids.ts +10 -0
- package/src/data/items.json +61 -0
- package/src/data/kind-registry.json +53 -1
- package/src/data/kind-registry.ts +5 -0
- package/src/data/metadata.ts +74 -5
- package/src/data/recipes-runtime.ts +1 -0
- package/src/data/recipes.json +887 -118
- package/src/derivation/capabilities.test.ts +81 -4
- package/src/derivation/capabilities.ts +162 -57
- package/src/derivation/crafting.ts +2 -0
- package/src/derivation/recipe-usage.test.ts +10 -7
- package/src/derivation/rollups.ts +16 -0
- package/src/derivation/stat-scaling.ts +12 -0
- package/src/entities/makers.ts +10 -1
- package/src/index-module.ts +29 -3
- package/src/managers/actions.ts +77 -46
- package/src/managers/construction-types.ts +2 -2
- package/src/managers/construction.ts +15 -15
- package/src/managers/plot.ts +1 -1
- package/src/nft/buildImmutableData.ts +55 -9
- package/src/nft/description.ts +99 -36
- package/src/planner/planner.test.ts +50 -41
- package/src/resolution/resolve-item.test.ts +1 -1
- package/src/resolution/resolve-item.ts +26 -11
- package/src/scheduling/availability.ts +7 -6
- package/src/scheduling/cancel.test.ts +40 -6
- package/src/scheduling/cancel.ts +21 -29
- package/src/scheduling/jobs.ts +71 -0
- package/src/scheduling/lanes.ts +29 -0
- package/src/scheduling/projection.ts +42 -25
- package/src/scheduling/task-cargo.ts +1 -1
- package/src/testing/projection-parity.ts +2 -2
- package/src/travel/reach.ts +4 -6
- package/src/travel/route-planner.ts +60 -49
- package/src/travel/route-simulator.ts +3 -7
- package/src/travel/travel.ts +14 -5
- package/src/types/capabilities.ts +9 -3
- package/src/types.ts +5 -3
- package/src/managers/flatten-gather-plan.test.ts +0 -80
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
import {distanceBetweenPoints, findNearbyPlanets} from './travel'
|
|
2
|
-
import {hasSystem} from '../utils/system'
|
|
3
1
|
import {nearbyWormholes, wormholeAt} from '../derivation/wormhole'
|
|
4
|
-
import {PRECISION} from '../types'
|
|
5
2
|
import {Checksum256, type Checksum256Type} from '@wharfkit/antelope'
|
|
6
3
|
|
|
7
4
|
export interface Coord {
|
|
@@ -26,6 +23,19 @@ export interface RoutePlan {
|
|
|
26
23
|
totalDistance: number
|
|
27
24
|
}
|
|
28
25
|
|
|
26
|
+
export interface RouteLegInput {
|
|
27
|
+
from: Coord
|
|
28
|
+
to: Coord
|
|
29
|
+
distance: number
|
|
30
|
+
isDestination: boolean
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Returns the elapsed-time search cost for a leg, or null when the leg is not contract-feasible.
|
|
35
|
+
*/
|
|
36
|
+
export type RouteLegCost = (leg: RouteLegInput) => number | null
|
|
37
|
+
export type RouteHeuristicCost = (from: Coord, dest: Coord) => number
|
|
38
|
+
|
|
29
39
|
export type RouteFailureReason = 'empty-destination' | 'no-path' | 'max-legs'
|
|
30
40
|
|
|
31
41
|
export interface RouteFailure {
|
|
@@ -46,6 +56,8 @@ export interface PlanRouteParams {
|
|
|
46
56
|
corridorSlack?: number
|
|
47
57
|
nodeBudget?: number
|
|
48
58
|
maxLegs?: number
|
|
59
|
+
legCost?: RouteLegCost
|
|
60
|
+
heuristicCost?: RouteHeuristicCost
|
|
49
61
|
}
|
|
50
62
|
|
|
51
63
|
const key = (c: Coord): string => `${c.x},${c.y}`
|
|
@@ -65,12 +77,25 @@ export function planRoute(params: PlanRouteParams): RouteResult {
|
|
|
65
77
|
}
|
|
66
78
|
|
|
67
79
|
const straightLine = dist(origin, dest)
|
|
68
|
-
|
|
80
|
+
if (straightLine <= perLegReach) {
|
|
81
|
+
const directCost = params.legCost?.({
|
|
82
|
+
from: origin,
|
|
83
|
+
to: dest,
|
|
84
|
+
distance: straightLine,
|
|
85
|
+
isDestination: true,
|
|
86
|
+
})
|
|
87
|
+
if (directCost !== null) {
|
|
88
|
+
return {ok: true, waypoints: [dest], legs: 1, totalDistance: straightLine}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const heuristic = (c: Coord): number =>
|
|
92
|
+
params.heuristicCost?.(c, dest) ??
|
|
93
|
+
(params.legCost ? 0 : Math.ceil(dist(c, dest) / perLegReach))
|
|
69
94
|
|
|
70
95
|
const gScore = new Map<string, number>([[key(origin), 0]])
|
|
71
96
|
const cameFrom = new Map<string, Coord>()
|
|
72
|
-
const frontier: {coord: Coord;
|
|
73
|
-
{coord: origin,
|
|
97
|
+
const frontier: {coord: Coord; legs: number; cost: number; f: number; remaining: number}[] = [
|
|
98
|
+
{coord: origin, legs: 0, cost: 0, f: heuristic(origin), remaining: straightLine},
|
|
74
99
|
]
|
|
75
100
|
|
|
76
101
|
let furthest = origin
|
|
@@ -88,6 +113,7 @@ export function planRoute(params: PlanRouteParams): RouteResult {
|
|
|
88
113
|
}
|
|
89
114
|
}
|
|
90
115
|
const current = frontier.splice(bestIdx, 1)[0]
|
|
116
|
+
if (current.cost !== gScore.get(key(current.coord))) continue
|
|
91
117
|
|
|
92
118
|
if (sameCoord(current.coord, dest)) {
|
|
93
119
|
return reconstruct(cameFrom, origin, dest)
|
|
@@ -105,20 +131,31 @@ export function planRoute(params: PlanRouteParams): RouteResult {
|
|
|
105
131
|
dist(origin, n.coord) + dist(n.coord, dest) <= straightLine + corridorSlack
|
|
106
132
|
if (!inCorridor) continue
|
|
107
133
|
|
|
108
|
-
const
|
|
109
|
-
if (
|
|
134
|
+
const tentativeLegs = current.legs + 1
|
|
135
|
+
if (tentativeLegs > maxLegs) {
|
|
110
136
|
cappedByMaxLegs = true
|
|
111
137
|
continue
|
|
112
138
|
}
|
|
139
|
+
const evaluatedCost = params.legCost?.({
|
|
140
|
+
from: current.coord,
|
|
141
|
+
to: n.coord,
|
|
142
|
+
distance: n.dist,
|
|
143
|
+
isDestination: sameCoord(n.coord, dest),
|
|
144
|
+
})
|
|
145
|
+
if (evaluatedCost === null) continue
|
|
146
|
+
const legCost = evaluatedCost ?? 1
|
|
147
|
+
if (!(legCost >= 0) || !Number.isFinite(legCost)) continue
|
|
113
148
|
const nk = key(n.coord)
|
|
114
|
-
|
|
115
|
-
|
|
149
|
+
const nextCost = current.cost + legCost
|
|
150
|
+
if (nextCost < (gScore.get(nk) ?? Infinity)) {
|
|
151
|
+
gScore.set(nk, nextCost)
|
|
116
152
|
cameFrom.set(nk, current.coord)
|
|
117
153
|
const remaining = dist(n.coord, dest)
|
|
118
154
|
frontier.push({
|
|
119
155
|
coord: n.coord,
|
|
120
|
-
|
|
121
|
-
|
|
156
|
+
legs: tentativeLegs,
|
|
157
|
+
cost: nextCost,
|
|
158
|
+
f: nextCost + heuristic(n.coord),
|
|
122
159
|
remaining,
|
|
123
160
|
})
|
|
124
161
|
}
|
|
@@ -180,50 +217,24 @@ export interface ScanProvider {
|
|
|
180
217
|
): {x: number; y: number; locType: number}[]
|
|
181
218
|
}
|
|
182
219
|
|
|
183
|
-
|
|
184
|
-
const graphCache = new Map<string, SystemGraph
|
|
185
|
-
|
|
186
|
-
// Inject a fast (e.g. wasm) location-type backend; null restores the pure-JS path. Clears the graph cache.
|
|
187
|
-
export function setScanProvider(provider: ScanProvider | null): void {
|
|
188
|
-
scanProvider = provider
|
|
189
|
-
graphCache.clear()
|
|
190
|
-
}
|
|
220
|
+
// Keyed by provider identity, so pass a stable one (the `@shipload/sdk/scan` namespace).
|
|
221
|
+
const graphCache = new WeakMap<ScanProvider, Map<string, SystemGraph>>()
|
|
191
222
|
|
|
192
|
-
export function sdkSystemGraph(seed: Checksum256Type): SystemGraph {
|
|
223
|
+
export function sdkSystemGraph(seed: Checksum256Type, scan: ScanProvider): SystemGraph {
|
|
193
224
|
const s = Checksum256.from(seed)
|
|
194
225
|
const seedHex = s.toString()
|
|
195
|
-
|
|
226
|
+
let bySeed = graphCache.get(scan)
|
|
227
|
+
if (!bySeed) {
|
|
228
|
+
bySeed = new Map()
|
|
229
|
+
graphCache.set(scan, bySeed)
|
|
230
|
+
}
|
|
231
|
+
const cached = bySeed.get(seedHex)
|
|
196
232
|
if (cached) return cached
|
|
197
|
-
const graph =
|
|
198
|
-
|
|
233
|
+
const graph = wasmSystemGraph(s, seedHex, scan)
|
|
234
|
+
bySeed.set(seedHex, graph)
|
|
199
235
|
return graph
|
|
200
236
|
}
|
|
201
237
|
|
|
202
|
-
// Travelable nodes mirror the contract's is_travelable: systems plus wormhole mouths.
|
|
203
|
-
function jsSystemGraph(s: Checksum256): SystemGraph {
|
|
204
|
-
return {
|
|
205
|
-
hasSystem: (c) => hasSystem(s, {x: c.x, y: c.y}) || wormholeAt(s, c.x, c.y) !== null,
|
|
206
|
-
nearby: (c, reachTiles) => {
|
|
207
|
-
const seen = new Set<string>([`${c.x},${c.y}`])
|
|
208
|
-
const out: Neighbor[] = []
|
|
209
|
-
for (const d of findNearbyPlanets(s, {x: c.x, y: c.y}, reachTiles * PRECISION)) {
|
|
210
|
-
const coord = {x: Number(d.destination.x), y: Number(d.destination.y)}
|
|
211
|
-
const k = `${coord.x},${coord.y}`
|
|
212
|
-
if (seen.has(k)) continue
|
|
213
|
-
seen.add(k)
|
|
214
|
-
out.push({coord, dist: Number(d.distance) / PRECISION})
|
|
215
|
-
}
|
|
216
|
-
for (const coord of nearbyWormholes(s, c.x, c.y, reachTiles)) {
|
|
217
|
-
const k = `${coord.x},${coord.y}`
|
|
218
|
-
if (seen.has(k)) continue
|
|
219
|
-
seen.add(k)
|
|
220
|
-
out.push({coord, dist: Math.hypot(coord.x - c.x, coord.y - c.y)})
|
|
221
|
-
}
|
|
222
|
-
return out
|
|
223
|
-
},
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
238
|
const SCAN_BUCKET = 48
|
|
228
239
|
|
|
229
240
|
function wasmSystemGraph(s: Checksum256, seedHex: string, scan: ScanProvider): SystemGraph {
|
|
@@ -12,7 +12,7 @@ export interface RouteMoverInput {
|
|
|
12
12
|
hasMovement: boolean
|
|
13
13
|
engines?: {thrust: number; drain: number}
|
|
14
14
|
generator?: {capacity: number; recharge: number}
|
|
15
|
-
hauler?: {capacity: number;
|
|
15
|
+
hauler?: {capacity: number; efficiency: number}
|
|
16
16
|
mass: number
|
|
17
17
|
energy: number
|
|
18
18
|
priorMobilityEnd: number
|
|
@@ -80,18 +80,14 @@ export function simulateRoute(
|
|
|
80
80
|
for (const to of waypoints) {
|
|
81
81
|
const distance = distanceBetweenPoints(from.x, from.y, to.x, to.y)
|
|
82
82
|
const distanceNum = Number(distance)
|
|
83
|
-
const distanceCells =
|
|
83
|
+
const distanceCells = distanceNum / PRECISION
|
|
84
84
|
|
|
85
85
|
const energyCostByMover: Record<string, number> = {}
|
|
86
86
|
|
|
87
87
|
for (const m of movers) {
|
|
88
88
|
if (!m.hasMovement || !m.engines) continue
|
|
89
89
|
const key = String(m.ref.entityId)
|
|
90
|
-
|
|
91
|
-
if (m.hauler) {
|
|
92
|
-
cost += Math.trunc(distanceCells) * m.hauler.drain * haulCount
|
|
93
|
-
}
|
|
94
|
-
energyCostByMover[key] = cost
|
|
90
|
+
energyCostByMover[key] = Number(calc_energyusage(distance, m.engines.drain))
|
|
95
91
|
}
|
|
96
92
|
|
|
97
93
|
let rechargeBefore = false
|
package/src/travel/travel.ts
CHANGED
|
@@ -14,7 +14,6 @@ import {
|
|
|
14
14
|
type Checksum256,
|
|
15
15
|
Int64,
|
|
16
16
|
type Int64Type,
|
|
17
|
-
UInt16,
|
|
18
17
|
UInt32,
|
|
19
18
|
type UInt32Type,
|
|
20
19
|
UInt64,
|
|
@@ -197,7 +196,7 @@ export function calc_ship_rechargetime(ship: ShipLike): UInt32 {
|
|
|
197
196
|
if (!ship.generator) return UInt32.from(0)
|
|
198
197
|
return calc_rechargetime(
|
|
199
198
|
ship.generator.capacity,
|
|
200
|
-
ship.energy ??
|
|
199
|
+
ship.energy ?? UInt32.from(0),
|
|
201
200
|
ship.generator.recharge
|
|
202
201
|
)
|
|
203
202
|
}
|
|
@@ -206,6 +205,16 @@ export function calc_flighttime(distance: UInt64Type, acceleration: number): UIn
|
|
|
206
205
|
return UInt32.from(2 * Math.sqrt(Number(distance) / acceleration))
|
|
207
206
|
}
|
|
208
207
|
|
|
208
|
+
export function calc_travel_flighttime(distance: UInt64Type, acceleration: number): UInt32 {
|
|
209
|
+
const cruiseTransitionDistance = 2 * PRECISION
|
|
210
|
+
if (Number(distance) <= cruiseTransitionDistance) {
|
|
211
|
+
return calc_flighttime(distance, acceleration)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const cruiseVelocity = Math.sqrt(acceleration * cruiseTransitionDistance)
|
|
215
|
+
return UInt32.from(Number(distance) / cruiseVelocity + cruiseVelocity / acceleration)
|
|
216
|
+
}
|
|
217
|
+
|
|
209
218
|
export function calc_transit_duration(ax: number, ay: number, bx: number, by: number): UInt32 {
|
|
210
219
|
const distance = distanceBetweenPoints(ax, ay, bx, by)
|
|
211
220
|
return UInt32.from(Math.floor(distance.toNumber() / (PRECISION * WH.TRANSIT_SPEED)))
|
|
@@ -235,7 +244,7 @@ export function calc_loader_acceleration(ship: ShipLike, mass: UInt64): number {
|
|
|
235
244
|
|
|
236
245
|
export function calc_ship_flighttime(ship: ShipLike, mass: UInt64, distance: UInt64): UInt32 {
|
|
237
246
|
const acceleration = calc_ship_acceleration(ship, mass)
|
|
238
|
-
return
|
|
247
|
+
return calc_travel_flighttime(distance, acceleration)
|
|
239
248
|
}
|
|
240
249
|
|
|
241
250
|
export function calc_ship_acceleration(ship: ShipLike, mass: UInt64): number {
|
|
@@ -286,11 +295,11 @@ export function calc_group_flighttime(
|
|
|
286
295
|
effectiveThrust = Math.trunc((totalThrust * 1000) / penaltyMilli)
|
|
287
296
|
}
|
|
288
297
|
const acceleration = calc_acceleration(effectiveThrust, totalMass)
|
|
289
|
-
return
|
|
298
|
+
return calc_travel_flighttime(distance, acceleration)
|
|
290
299
|
}
|
|
291
300
|
|
|
292
301
|
export function calc_energyusage(distance: UInt64Type, drain: UInt32Type): UInt32 {
|
|
293
|
-
return UInt64.from(distance).
|
|
302
|
+
return UInt64.from(distance).multiplying(drain).dividing(PRECISION)
|
|
294
303
|
}
|
|
295
304
|
|
|
296
305
|
export function calculateTransferTime(
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {Name,
|
|
1
|
+
import type {Name, UInt32, UInt8} from '@wharfkit/antelope'
|
|
2
2
|
import type {ServerContract} from '../contracts'
|
|
3
3
|
|
|
4
4
|
export interface LoaderStats {
|
|
@@ -18,13 +18,18 @@ export interface CrafterStats {
|
|
|
18
18
|
drain: {toNumber(): number}
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
export interface BuilderStats {
|
|
22
|
+
speed: {toNumber(): number}
|
|
23
|
+
drain: {toNumber(): number}
|
|
24
|
+
}
|
|
25
|
+
|
|
21
26
|
export interface MovementCapability {
|
|
22
27
|
engines: ServerContract.Types.movement_stats
|
|
23
28
|
generator: ServerContract.Types.energy_stats
|
|
24
29
|
}
|
|
25
30
|
|
|
26
31
|
export interface EnergyCapability {
|
|
27
|
-
energy:
|
|
32
|
+
energy: UInt32
|
|
28
33
|
}
|
|
29
34
|
|
|
30
35
|
export interface StorageCapability {
|
|
@@ -58,6 +63,7 @@ export interface EntityCapabilities {
|
|
|
58
63
|
loaders?: LoaderStats
|
|
59
64
|
gatherer?: GathererStats
|
|
60
65
|
crafter?: CrafterStats
|
|
66
|
+
builder?: BuilderStats
|
|
61
67
|
hauler?: ServerContract.Types.hauler_stats
|
|
62
68
|
launcher?: ServerContract.Types.launcher_stats
|
|
63
69
|
}
|
|
@@ -65,7 +71,7 @@ export interface EntityCapabilities {
|
|
|
65
71
|
export interface EntityState {
|
|
66
72
|
owner: Name
|
|
67
73
|
location: ServerContract.Types.coordinates
|
|
68
|
-
energy?:
|
|
74
|
+
energy?: UInt32
|
|
69
75
|
cargomass: UInt32
|
|
70
76
|
cargo: ServerContract.Types.cargo_item[]
|
|
71
77
|
}
|
package/src/types.ts
CHANGED
|
@@ -38,7 +38,7 @@ export interface ClusterSlotType {
|
|
|
38
38
|
export interface ShipLike {
|
|
39
39
|
coordinates: ServerContract.Types.coordinates
|
|
40
40
|
hullmass?: UInt32
|
|
41
|
-
energy?:
|
|
41
|
+
energy?: UInt32
|
|
42
42
|
engines?: ServerContract.Types.movement_stats
|
|
43
43
|
generator?: ServerContract.Types.energy_stats
|
|
44
44
|
loader_lanes?: ServerContract.Types.loader_lane[]
|
|
@@ -60,15 +60,15 @@ export enum TaskType {
|
|
|
60
60
|
GATHER = 5,
|
|
61
61
|
WARP = 6,
|
|
62
62
|
CRAFT = 7,
|
|
63
|
-
DEPLOY = 8,
|
|
64
63
|
TRANSIT = 9,
|
|
65
64
|
UNWRAP = 10,
|
|
66
65
|
UNDEPLOY = 11,
|
|
66
|
+
LAUNCH = 12,
|
|
67
67
|
DEMOLISH = 13,
|
|
68
|
-
CLAIMPLOT = 14,
|
|
69
68
|
BUILDPLOT = 15,
|
|
70
69
|
CHARGE = 16,
|
|
71
70
|
UPGRADE = 17,
|
|
71
|
+
SHUTTLE = 18,
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
export enum HoldKind {
|
|
@@ -76,6 +76,7 @@ export enum HoldKind {
|
|
|
76
76
|
PUSH = 2,
|
|
77
77
|
GATHER = 3,
|
|
78
78
|
BUILD = 4,
|
|
79
|
+
FLIGHT = 5,
|
|
79
80
|
UPGRADE = 6,
|
|
80
81
|
}
|
|
81
82
|
|
|
@@ -138,6 +139,7 @@ export type ModuleType =
|
|
|
138
139
|
| 'loader'
|
|
139
140
|
| 'warp'
|
|
140
141
|
| 'crafter'
|
|
142
|
+
| 'builder'
|
|
141
143
|
| 'launcher'
|
|
142
144
|
| 'storage'
|
|
143
145
|
| 'hauler'
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import {expect, test, describe} from 'bun:test'
|
|
2
|
-
import {makeClient} from '@wharfkit/mock-data'
|
|
3
|
-
import {Serializer} from '@wharfkit/antelope'
|
|
4
|
-
import type {GatherPlan} from '../planner'
|
|
5
|
-
import {ActionsManager} from './actions'
|
|
6
|
-
import {ServerContract} from '../contracts'
|
|
7
|
-
|
|
8
|
-
const client = makeClient('https://jungle4.greymass.com')
|
|
9
|
-
|
|
10
|
-
function makeActions() {
|
|
11
|
-
const realServer = new ServerContract.Contract({client})
|
|
12
|
-
const stubServer = {
|
|
13
|
-
account: realServer.account,
|
|
14
|
-
action: realServer.action.bind(realServer),
|
|
15
|
-
}
|
|
16
|
-
const context = {server: stubServer} as any
|
|
17
|
-
return new ActionsManager(context)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function fakePlan(): GatherPlan {
|
|
21
|
-
return {
|
|
22
|
-
cycles: [
|
|
23
|
-
{
|
|
24
|
-
rechargeBefore: false,
|
|
25
|
-
rechargeSeconds: 0,
|
|
26
|
-
gatherSeconds: 10,
|
|
27
|
-
batchOre: 30,
|
|
28
|
-
limpets: [
|
|
29
|
-
{slot: 0, quantity: 20, durationSeconds: 10},
|
|
30
|
-
{slot: 1, quantity: 10, durationSeconds: 8},
|
|
31
|
-
],
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
rechargeBefore: true,
|
|
35
|
-
rechargeSeconds: 5,
|
|
36
|
-
gatherSeconds: 10,
|
|
37
|
-
batchOre: 30,
|
|
38
|
-
limpets: [{slot: 0, quantity: 30, durationSeconds: 10}],
|
|
39
|
-
},
|
|
40
|
-
],
|
|
41
|
-
cycleCount: 2,
|
|
42
|
-
totalOre: 60,
|
|
43
|
-
totalSeconds: 25,
|
|
44
|
-
cap: 'requested',
|
|
45
|
-
reachingCount: 2,
|
|
46
|
-
totalLimpets: 2,
|
|
47
|
-
warnings: [],
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
describe('flattenGatherPlan', () => {
|
|
52
|
-
test('flattens cycles to [recharge?, gather x limpets] in order with slots', () => {
|
|
53
|
-
const actions = makeActions().flattenGatherPlan(fakePlan(), {
|
|
54
|
-
sourceId: 1,
|
|
55
|
-
destinationId: 1,
|
|
56
|
-
stratum: 100,
|
|
57
|
-
})
|
|
58
|
-
expect(actions.map((a) => a.name.toString())).toEqual([
|
|
59
|
-
'gather',
|
|
60
|
-
'gather',
|
|
61
|
-
'recharge',
|
|
62
|
-
'gather',
|
|
63
|
-
])
|
|
64
|
-
expect(actions.filter((a) => a.name.toString() === 'recharge').length).toBe(1)
|
|
65
|
-
const gatherSlots = actions
|
|
66
|
-
.filter((a) => a.name.toString() === 'gather')
|
|
67
|
-
.map((a) => {
|
|
68
|
-
const decoded = Serializer.decode({data: a.data, type: ServerContract.Types.gather})
|
|
69
|
-
return Number(decoded.slot)
|
|
70
|
-
})
|
|
71
|
-
expect(gatherSlots).toEqual([0, 1, 0])
|
|
72
|
-
})
|
|
73
|
-
|
|
74
|
-
test('empty plan produces no actions', () => {
|
|
75
|
-
const empty = {...fakePlan(), cycles: [], cycleCount: 0, totalOre: 0}
|
|
76
|
-
expect(
|
|
77
|
-
makeActions().flattenGatherPlan(empty, {sourceId: 1, destinationId: 1, stratum: 100})
|
|
78
|
-
).toHaveLength(0)
|
|
79
|
-
})
|
|
80
|
-
})
|