import Module from './Module'; import { BulkheadNames } from './Constants'; /** * Filter eligble modules based on parameters * @param {Array} arr Available modules array * @param {number} maxClass Max class * @param {number} minClass Minimum class * @param {number} mass Mass * @return {Array} Fitlered module subset */ function filter(arr, maxClass, minClass, mass) { return arr.filter(m => m.class <= maxClass && m.class >= minClass && (m.maxmass === undefined || mass <= m.maxmass)); } /** * Filter SCO Modules to only return legal size. * @param {Array} arr Array of available FSD modules. * @param {number} maxSize Maximum allowable size for SCO modules. * @return {Array} Subset of modules filtered based on legal size amd type. */ function sco_filter(arr, maxSize) { return arr.filter(module => { return !(module.hasOwnProperty('name') && module['name'] === "Frame Shift Drive (SCO)" && module['class'] < maxSize); }); } /** * The available module set for a specific ship */ export default class ModuleSet { /** * Instantiate the module set * @param {Object} modules All Modules * @param {Object} shipData Ship Specifications Data (see coriolis-data/Ships) */ constructor(modules, shipData) { let maxInternal = isNaN(shipData.slots.internal[0]) ? shipData.slots.internal[0].class : shipData.slots.internal[0]; let mass = shipData.properties.hullMass + 6.5; let maxStandardArr = shipData.slots.standard; let maxHardPoint = shipData.slots.hardpoints[0]; let stnd = modules.standard; this.mass = mass; this.standard = {}; this.internal = {}; this.hardpoints = {}; this.hpClass = {}; this.intClass = {}; this.bulkheads = shipData.bulkheads.map((b, i) => { return Object.assign(new Module(), { grp: 'bh', id: i, name: BulkheadNames[i], index: i, class: '', rating: '' }, b); }); this.standard[0] = filter(stnd.pp, maxStandardArr[0], 0, mass); // Power Plant this.standard[2] = filter(stnd.fsd, maxStandardArr[2], 0, mass); // FSD this.standard[2] = sco_filter(this.standard[2], maxStandardArr[2]) // FSD - Filter SCO Modules this.standard[4] = filter(stnd.pd, maxStandardArr[4], 0, mass); // Power Distributor this.standard[6] = filter(stnd.ft, maxStandardArr[6], 0, mass); // Fuel Tank // Thrusters, filter modules by class only (to show full list of ratings for that class) let minThrusterClass = stnd.t.reduce((clazz, th) => (th.maxmass >= mass && th.class < clazz) ? th.class : clazz, maxStandardArr[1]); this.standard[1] = filter(stnd.t, maxStandardArr[1], minThrusterClass, 0); // Thrusters // Slots where module class must be equal to slot class this.standard[3] = filter(stnd.ls, maxStandardArr[3], maxStandardArr[3], 0); // Life Supprt this.standard[5] = filter(stnd.s, maxStandardArr[5], maxStandardArr[5], mass); // Sensors for (let h in modules.hardpoints) { this.hardpoints[h] = filter(modules.hardpoints[h], maxHardPoint, 0, mass); } for (let g in modules.internal) { this.internal[g] = filter(modules.internal[g], maxInternal, 0, mass); } } /** * Get the specified bulkhead * @param {integer} index Bulkhead index * @return {Object} Bulkhead module details */ getBulkhead(index) { return this.bulkheads[index] ? new Module({ template: this.bulkheads[index] }) : null; } /** * Determine the modules that areeligible for an internal slot * @param {Object} ship The ship * @param {integer} c The max class module that can be mounted in the slot * @param {Object} eligible) The map of eligible internal groups * @return {object} A map of all eligible modules by group */ getInts(ship, c, eligible) { let o = {}; for (let key in this.internal) { if (eligible && !eligible[key]) { continue; } if (key == 'pcq' && !(ship.luxuryCabins && ship.luxuryCabins === true)) { continue; } if (key == 'fh' && !(ship.fighterHangars && ship.fighterHangars === true)) { continue; } let data = filter(this.internal[key], c, 0, this.mass); if (data.length) { // If group is not empty o[key] = data; } } return o; } /** * Determining the modules that are eligible for an hardpoint slot * @param {integer} c The max class module that can be mounted in the slot * @param {Object} eligible) The map of eligible hardpoint groups * @return {object} A map of all eligible modules by group */ getHps(c, eligible) { let o = {}; for (let key in this.hardpoints) { if (eligible && !eligible[key]) { continue; } let data = filter(this.hardpoints[key], c, c ? 1 : 0, this.mass); if (data.length) { // If group is not empty o[key] = data; } } return o; } /** * Find the lightest Power Distributor that provides sufficient * energy to boost. * @param {number} boostEnergy The energy that is required to boost * @return {Object} Power Distributor */ lightestPowerDist(boostEnergy) { let pd = this.standard[4][0]; for (let p of this.standard[4]) { if (p.mass < pd.mass && p.engcap > boostEnergy) { pd = p; } } return new Module({ template: pd }); }; /** Find the power distributor that matches the requirements * @param {Object} requirements The requirements to be met (currently only support 'weprate') * @return {Object} Power distributor */ matchingPowerDist(requirements) { let pd = this.standard[4][0]; for (let p of this.standard[4]) { if (p.weprate >= requirements.weprate || p.weprate >= pd.weprate) { pd = p; } } return new Module({ template: pd }); } /** * Finds the lightest Thruster that can handle the specified tonnage * @param {number} ladenMass Ship laden mass (mass + cargo + fuel) * @return {Object} Thruster */ lightestThruster(ladenMass) { let th = this.standard[1][0]; for (let t of this.standard[1]) { if (t.mass < th.mass && t.maxmass >= ladenMass) { th = t; } } return new Module({ template: th }); }; /** * Finds the lightest usable Shield Generator * @param {number} hullMass Ship hull mass * @return {Object} Thruster */ lightestShieldGenerator(hullMass) { let sg = this.internal.sg[0]; for (let s of this.internal.sg) { if (s.mass < sg.mass && s.maxmass > hullMass) { sg = s; } } return new Module({ template: sg }); }; /** * Find the lightest Power Plant that provides sufficient power * @param {number} powerNeeded Power requirements in MJ * @param {string} rating The optional rating of the power plant * @return {Object} Power Plant */ lightestPowerPlant(powerNeeded, rating) { let pp = this.standard[0][0]; for (let p of this.standard[0]) { // Provides enough power, is lighter or the same mass as current power plant but better output/efficiency if (p.pgen >= powerNeeded && (p.mass < pp.mass || (p.mass == pp.mass && p.pgen > pp.pgen)) && (!rating || rating == p.rating)) { pp = p; } } return new Module({ template: pp }); } }