UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

130 lines (101 loc) 3.99 kB
import { ResourceAllocationSolver } from "./ResourceAllocationSolver.js"; import { assert } from "../../../core/assert.js"; import { buildPromiseChain } from "../../../core/process/buildPromiseChain.js"; export class StrategicResourceAllocator { constructor() { /** * * @type {TacticalModule[]} */ this.modules = []; /** * @private * @type {Array<function(ActionSequence[]):Promise<ActionSequence[]>>} */ this.sequenceTransformers = []; } /** * Add a sequence transformer, these are applied as a final step during resource allocation * @param {function(ActionSequence[]):Promise<ActionSequence[]>} t */ addTransformer(t) { this.sequenceTransformers.push(t); } /** * * @param {TacticalModule} module */ addTacticalModule(module) { assert.defined(module, 'module'); assert.notNull(module, 'module'); assert.equal(module.isTacticalModule, true, 'module.TacticalModule !== true'); this.modules.push(module); } /** * @template A * @param {Resource[]} resources * @returns {Promise<A[]>} actions */ allocate(resources) { /** * * @type {Map<ResourceAllocationBid, TacticalModule>} */ const bids = new Map(); return new Promise((resolve, reject) => { const moduleResults = this.modules.map(m => { const promise = m.collectBids(resources); assert.defined(promise, 'promise'); assert.notNull(promise, 'promise'); assert.isFunction(promise.then, "promise.then"); promise.then(moduleBids => { assert.isArray(moduleBids, 'moduleBids'); moduleBids.forEach(b => bids.set(b, m)); }); return promise; }); resolve(moduleResults); }) .then(moduleResults => Promise.all(moduleResults)) .then(() => { /** * * @type {ResourceAllocationSolver} */ const solver = new ResourceAllocationSolver(); //set resources solver.addResources(resources); //set bids bids.forEach((m, b) => solver.addBid(b)); /** * * @type {ResourceAllocationBid[]} */ const allocations = solver.solve(); const actionSequences = allocations.map(a => a.actions); //sort action sequences based on their priorities, higher priority sequences first actionSequences.sort((a, b) => { const aPriority = a.getPriority(); const bPriority = b.getPriority(); return bPriority - aPriority }); return actionSequences; }) .then(sequences => { // Apply sequence transformers const sequenceTransformers = this.sequenceTransformers; const nSequenceTransformers = sequenceTransformers.length; const factories = []; for (let i = 0; i < nSequenceTransformers; i++) { const sequenceProcessor = sequenceTransformers[i]; factories.push(input => sequenceProcessor(input)); } return buildPromiseChain({ factories, head: Promise.resolve(sequences) }); }) .then(sequences => { //extract actions from sequences in order const actions = sequences.map(s => s.actions).flat(); return actions; }); } }