const { nanoid } = require('nanoid') const US_LIQUID_GALLONS_TO_CUBIC_INCHES = 231 const CUBIC_INCHES_TO_US_LIQUID_GALLONS = 1 / US_LIQUID_GALLONS_TO_CUBIC_INCHES const toLiquid = cubicInches => cubicInches * CUBIC_INCHES_TO_US_LIQUID_GALLONS const fromLiquid = gallons => gallons * US_LIQUID_GALLONS_TO_CUBIC_INCHES const makeContainerT = (inputs, outputs, container) => [ inputs, outputs, container, ] const fromConfig = { tank_1: { inputs: [1], outputs: ['foo'], dims: { l: 24, w: 12, h: 12 }, }, sump_1: { inputs: [], outputs: [], dims: { l: 18, w: 12, h: 12 }, }, ato_1: { inputs: [], outputs: [], dims: { l: 6, w: 12, h: 12 }, }, } const digestConfig = config => { const sys = new System() for (const [containerName, inputsOutputsDims] of Object.entries(config)) { const { inputs, outputs, dims } = inputsOutputsDims const containerT = makeContainerT( inputs, outputs, new Container(dims, 0, containerName) ) sys.add(containerT[2].id, containerT) } return sys } class InOut { constructor() { this.value = null } } /** Holds systems or containers */ class Controller {} /** Holds systems or containers */ class System { constructor() { this.inventory = {} } get inputs() { return Object.values(this.inventory).map(containerT => containerT[0]) } get outputs() { return Object.values(this.inventory).map(containerT => containerT[1]) } get containers() { return Object.values(this.inventory).map(containerT => containerT[2]) } add(id, containerT) { this.inventory[id] = containerT } inputsFor({ id }) { return Object.values(this.inventory).find( containerT => containerT[2].id == id )[0] } outputsFor({ id }) { return Object.values(this.inventory).find( containerT => containerT[2].id == id )[1] } } class Container { constructor({ l, w, h }, level = 0, label) { this._id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT" this._label = label ? label : '' this.l = l this.w = w this.h = h this.level = level } get id() { return this._id } get label() { return this._label } get liquidVolumeCapacity() { return toLiquid(this.l * this.w * this.h) } get liquidVolumeFilled() { return toLiquid(this.l * this.w * this.level) } get liquidVolumeRemaining() { return this.liquidVolumeCapacity - this.liquidVolumeFilled } setLevel(updatedLevel) { this.level = updatedLevel } } const _changeLevel = (amount, container) => { const updatedLevel = fromLiquid(container.liquidVolumeFilled + amount) / container.l / container.w container.setLevel(updatedLevel) } const fill = ({ container, amount }) => _changeLevel(amount, container) const drain = ({ container, amount }) => _changeLevel(-1 * amount, container) mySystem = digestConfig(fromConfig) const tanks = mySystem.containers console.log('mySystem :>> ', mySystem.inventory) console.log('tank :>> ', tanks[0].liquidVolumeCapacity) console.log('tank :>> ', tanks[0].liquidVolumeFilled) fill({ container: tanks[0], amount: 10 }) console.log('tank :>> ', tanks[0].liquidVolumeFilled) console.log('refs intact?', mySystem.containers[0] === tanks[0]) drain({ container: tanks[0], amount: 3 }) console.log('tank :>> ', tanks[0].liquidVolumeFilled) console.log('inputs :>> ', mySystem.inputsFor(tanks[0])) console.log('outputs :>> ', mySystem.outputsFor(tanks[0]))