diff --git a/src/app/Coriolis.jsx b/src/app/Coriolis.jsx index a44bbd9b..7893651a 100644 --- a/src/app/Coriolis.jsx +++ b/src/app/Coriolis.jsx @@ -356,7 +356,7 @@ export default class Coriolis extends React.Component {
{window.CORIOLIS_VERSION} - {window.CORIOLIS_DATE}
- Commits since last release ({window.CORIOLIS_DATE}) + Commits since last release ({window.CORIOLIS_DATE})
; diff --git a/src/app/components/AvailableModulesMenu.jsx b/src/app/components/AvailableModulesMenu.jsx index b07b884a..a64d6609 100644 --- a/src/app/components/AvailableModulesMenu.jsx +++ b/src/app/components/AvailableModulesMenu.jsx @@ -137,7 +137,7 @@ export default class AvailableModulesMenu extends TranslatedComponent { let translate = context.language.translate; let { m, warning, shipMass, onSelect, modules, firstSlotId, lastSlotId } = props; let list, currentGroup; - + let buildGroup = this._buildGroup.bind( this, translate, @@ -149,7 +149,7 @@ export default class AvailableModulesMenu extends TranslatedComponent { onSelect(m); } ); - + if (modules instanceof Array) { list = buildGroup(modules[0].grp, modules); } else { @@ -210,7 +210,7 @@ export default class AvailableModulesMenu extends TranslatedComponent { } } let trackingFocus = false; - return { list, currentGroup, trackingFocus}; + return { list, currentGroup, trackingFocus }; } /** @@ -227,10 +227,10 @@ export default class AvailableModulesMenu extends TranslatedComponent { _buildGroup(translate, mountedModule, warningFunc, mass, onSelect, grp, modules, firstSlotId, lastSlotId) { let prevClass = null, prevRating = null, prevName; let elems = []; - + const sortedModules = modules.sort(this._moduleOrder); - - + + // Calculate the number of items per class. Used so we don't have long lists with only a few items in each row const tmp = sortedModules.map((v, i) => v['class']).reduce((count, cls) => { count[cls] = ++count[cls] || 1; return count; }, {}); const itemsPerClass = Math.max.apply(null, Object.keys(tmp).map(key => tmp[key])); @@ -240,7 +240,7 @@ export default class AvailableModulesMenu extends TranslatedComponent { let m = sortedModules[i]; let mount = null; let disabled = false; - prevName = m.name + prevName = m.name; if (ModuleUtils.isShieldGenerator(m.grp)) { // Shield generators care about maximum hull mass disabled = mass > m.maxmass; @@ -305,7 +305,7 @@ export default class AvailableModulesMenu extends TranslatedComponent { {(mount ? ' ' : '') + m.class + m.rating + (m.missile ? '/' + m.missile : '') + (m.name ? ' ' + translate(m.name) : '')} ); - + itemsOnThisRow++; prevClass = m.class; prevRating = m.rating; @@ -369,21 +369,21 @@ export default class AvailableModulesMenu extends TranslatedComponent { */ _keyDown(select, event) { - var className = event.currentTarget.attributes['class'].value; - if (event.key == 'Enter' && className.indexOf('disabled') < 0 && className.indexOf('active') < 0) { + let className = event.currentTarget.attributes['class'].value; + if (event.key == 'Enter' && className.indexOf('disabled') < 0 && className.indexOf('active') < 0) { select(); - return + return; } - var elemId = event.currentTarget.attributes['data-id'].value; + let elemId = event.currentTarget.attributes['data-id'].value; if (className.indexOf('disabled') < 0 && event.key == 'Tab') { if (event.shiftKey && elemId == this.firstSlotId) { event.preventDefault(); this.slotItems[this.lastSlotId].focus(); - return; + return; } if (!event.shiftKey && elemId == this.lastSlotId) { event.preventDefault(); - this.slotItems[this.firstSlotId].focus(); + this.slotItems[this.firstSlotId].focus(); return; } } @@ -391,10 +391,10 @@ export default class AvailableModulesMenu extends TranslatedComponent { /** * Key Up - * + * */ _keyUp(select,event) { - //nothing here yet + // nothing here yet } /** @@ -487,7 +487,7 @@ export default class AvailableModulesMenu extends TranslatedComponent { * @return {React.Component} List */ render() { - console.log("Tracking focus? " + this.state.trackingFocus); + console.log('Tracking focus? ' + this.state.trackingFocus); return (
this.node = node} className={cn('select', this.props.className)} diff --git a/src/app/components/Header.jsx b/src/app/components/Header.jsx index cd6db5e5..4b886596 100644 --- a/src/app/components/Header.jsx +++ b/src/app/components/Header.jsx @@ -505,8 +505,8 @@ export default class Header extends TranslatedComponent { return (
{this.props.appCacheUpdate &&
window.location.reload() }>{translate('PHRASE_UPDATE_RDY')}
} - {this.props.appCache ? - {"View Release Changes"} + {this.props.appCache ? + {'View Release Changes'} : null} diff --git a/src/app/components/ModificationsMenu.jsx b/src/app/components/ModificationsMenu.jsx index fea6cd28..de1146ca 100644 --- a/src/app/components/ModificationsMenu.jsx +++ b/src/app/components/ModificationsMenu.jsx @@ -13,7 +13,7 @@ import { getPercent, setRandom, specialToolTip -} from '../utils/BlueprintFunctions' +} from '../utils/BlueprintFunctions'; /** * Modifications menu @@ -50,8 +50,8 @@ export default class ModificationsMenu extends TranslatedComponent { this.firstModId = null; this.firstBPLabel = null;// First item in mod menu this.lastModId = null; - this.lastNeId = null;//Last number editor id. Used to set focus to last number editor when shift-tab pressed on first element in mod menu. - this.modValDidChange = false; //used to determine if component update was caused by change in modification value. + this.lastNeId = null;// Last number editor id. Used to set focus to last number editor when shift-tab pressed on first element in mod menu. + this.modValDidChange = false; // used to determine if component update was caused by change in modification value. this._handleModChange = this._handleModChange.bind(this); this.state = { @@ -78,19 +78,19 @@ export default class ModificationsMenu extends TranslatedComponent { // Grade is a string in the JSON so make it a number grade = Number(grade); const classes = cn('c', { - active: m.blueprint && blueprint.id === m.blueprint.id && grade === m.blueprint.grade + active: m.blueprint && blueprint.id === m.blueprint.id && grade === m.blueprint.grade }); const close = this._blueprintSelected.bind(this, blueprintName, grade); const key = blueprintName + ':' + grade; const tooltipContent = blueprintTooltip(translate, blueprint.grades[grade], Modifications.modules[m.grp].blueprints[blueprintName].grades[grade].engineers, m.grp); - - + + blueprintGrades.unshift(
  • this.modItems[key] = modItem}>{grade}
  • ); } if (blueprintGrades) { const thisLen = blueprintGrades.length; if (this.firstModId == null) this.firstModId = blueprintGrades[0].key; - this.lastModId = blueprintGrades[thisLen-1].key; + this.lastModId = blueprintGrades[thisLen - 1].key; blueprints.push(
    {translate(blueprint.name)}
    ); blueprints.push(
      {blueprintGrades}
    ); } @@ -104,37 +104,36 @@ export default class ModificationsMenu extends TranslatedComponent { * @param {SyntheticEvent} event Event * */ - + _keyDown(event) { - var className = null; - var elemId = null; + let className = null; + let elemId = null; if (event.currentTarget.attributes['class']) className = event.currentTarget.attributes['class'].value; if (event.currentTarget.attributes['data-id']) elemId = event.currentTarget.attributes['data-id'].value; - + if (event.key == 'Enter' && className.indexOf('disabled') < 0 && className.indexOf('active') < 0) { event.stopPropagation(); if (elemId != null) { this.modItems[elemId].click(); } else { - event.currentTarget.click(); } - return + return; } if (event.key == 'Tab') { - //Shift-Tab + // Shift-Tab if(event.shiftKey) { if (elemId == this.firstModId && elemId != null) { // Initial modification menu event.preventDefault(); this.modItems[this.lastModId].focus(); - return; - } else if (event.currentTarget.className.indexOf("button-inline-menu") >= 0 && event.currentTarget.previousElementSibling == null && this.lastNeId != null && this.modItems[this.lastNeId] != null) { + return; + } else if (event.currentTarget.className.indexOf('button-inline-menu') >= 0 && event.currentTarget.previousElementSibling == null && this.lastNeId != null && this.modItems[this.lastNeId] != null) { // shift-tab on first element in modifications menu. set focus to last number editor field if open event.preventDefault(); this.modItems[this.lastNeId].lastChild.focus(); return; - } else if (event.currentTarget.className.indexOf("button-inline-menu") >= 0 && event.currentTarget.previousElementSibling == null) { + } else if (event.currentTarget.className.indexOf('button-inline-menu') >= 0 && event.currentTarget.previousElementSibling == null) { // shift-tab on button-inline-menu with no number editor event.preventDefault(); event.currentTarget.parentElement.lastElementChild.focus(); @@ -143,9 +142,9 @@ export default class ModificationsMenu extends TranslatedComponent { if (elemId == this.lastModId && elemId != null) { // Initial modification menu event.preventDefault(); - this.modItems[this.firstModId].focus(); + this.modItems[this.firstModId].focus(); return; - } else if (event.currentTarget.className.indexOf("button-inline-menu") >= 0 && event.currentTarget.nextSibling == null && event.currentTarget.nodeName != "TD") { + } else if (event.currentTarget.className.indexOf('button-inline-menu') >= 0 && event.currentTarget.nextSibling == null && event.currentTarget.nodeName != 'TD') { // Experimental menu event.preventDefault(); event.currentTarget.parentElement.firstElementChild.focus(); @@ -154,11 +153,10 @@ export default class ModificationsMenu extends TranslatedComponent { event.preventDefault(); this.modItems[this.firstBPLabel].focus(); } - } } } - + /** * Render the specials @@ -167,7 +165,6 @@ export default class ModificationsMenu extends TranslatedComponent { * @return {Object} list: Array of React Components */ _renderSpecials(props, context) { - const { m } = props; const { language, tooltip, termtip } = context; const translate = language.translate; @@ -181,7 +178,7 @@ export default class ModificationsMenu extends TranslatedComponent { continue; } const classes = cn('button-inline-menu', { - active: m.blueprint && m.blueprint.special && m.blueprint.special.edname == specialName + active: m.blueprint && m.blueprint.special && m.blueprint.special.edname == specialName }); const close = this._specialSelected.bind(this, specialName); if (m.blueprint && m.blueprint.name) { @@ -200,7 +197,7 @@ export default class ModificationsMenu extends TranslatedComponent { } } } - console.log("_renderSpecials. specials: %O", specials); + console.log('_renderSpecials. specials: %O', specials); return specials; } @@ -219,7 +216,7 @@ export default class ModificationsMenu extends TranslatedComponent { modifications.push(); } } - console.log("_renderModifications. modItems: %O", this.modItems); + console.log('_renderModifications. modItems: %O', this.modItems); return modifications; } @@ -280,10 +277,10 @@ export default class ModificationsMenu extends TranslatedComponent { _rollFifty() { const { m, ship } = this.props; setPercent(ship, m, 50); - + // this will change the values in the modifications. Set modDidChange to true to prevent focus change when component updates this._handleModChange(true); - + this.props.onChange(); } @@ -293,10 +290,10 @@ export default class ModificationsMenu extends TranslatedComponent { _rollRandom() { const { m, ship } = this.props; setRandom(ship, m); - + // this will change the values in the modifications. Set modDidChange to true to prevent focus change when component updates this._handleModChange(true); - + this.props.onChange(); } @@ -306,10 +303,10 @@ export default class ModificationsMenu extends TranslatedComponent { _rollBest() { const { m, ship } = this.props; setPercent(ship, m, 100); - + // this will change the values in the modifications. Set modDidChange to true to prevent focus change when component updates this._handleModChange(true); - + this.props.onChange(); } @@ -319,13 +316,11 @@ export default class ModificationsMenu extends TranslatedComponent { _rollWorst() { const { m, ship } = this.props; setPercent(ship, m, 0); - + // this will change the values in the modifications. Set modDidChange to true to prevent focus change when component updates this._handleModChange(true); - - this.props.onChange(); - + this.props.onChange(); } /** @@ -374,9 +369,8 @@ export default class ModificationsMenu extends TranslatedComponent { } } } else { - this._handleModChange(false);//Need to reset if component update due to value change + this._handleModChange(false);// Need to reset if component update due to value change } - } componentWillUnmount() { @@ -407,7 +401,7 @@ export default class ModificationsMenu extends TranslatedComponent { let haveBlueprint = false; let blueprintTt; let blueprintCv; - //TODO: Fix this to actually find the correct blueprint. + // TODO: Fix this to actually find the correct blueprint. if (!m.blueprint || !m.blueprint.name || !m.blueprint.fdname || !Modifications.modules[m.grp].blueprints || !Modifications.modules[m.grp].blueprints[m.blueprint.fdname]) { this.props.ship.clearModuleBlueprint(m); this.props.ship.clearModuleSpecial(m); @@ -440,7 +434,7 @@ export default class ModificationsMenu extends TranslatedComponent { const showReset = !blueprintMenuOpened && (!specialMenuOpened || !specials.length) && haveBlueprint; const showMods = !blueprintMenuOpened && (!specialMenuOpened || !specials.length) && haveBlueprint; if (haveBlueprint) { - this.firstBPLabel = blueprintLabel + this.firstBPLabel = blueprintLabel; } else { this.firstBPLabel = 'selectBP'; } @@ -451,20 +445,20 @@ export default class ModificationsMenu extends TranslatedComponent { onContextMenu={stopCtxPropagation} ref={modItem => this.modItems['modMainDiv'] = modItem} > - { showBlueprintsMenu | showSpecialsMenu ? '' : haveBlueprint ? -
    this.modItems[this.firstBPLabel] = modItems}>{blueprintLabel}
    : + { showBlueprintsMenu | showSpecialsMenu ? '' : haveBlueprint ? +
    this.modItems[this.firstBPLabel] = modItems}>{blueprintLabel}
    :
    this.modItems[this.firstBPLabel] = modItems}>{translate('PHRASE_SELECT_BLUEPRINT')}
    } { showBlueprintsMenu ? this._renderBlueprints(this.props, this.context) : null } { showSpecial & !showSpecialsMenu ?
    {specialLabel}
    : null } { showSpecialsMenu ? specials : null } { showReset ?
    { translate('reset') }
    : null } { showRolls ? - + { showRolls ? - + diff --git a/src/app/components/ShipSummaryTable.jsx b/src/app/components/ShipSummaryTable.jsx index e22863c0..fc094093 100644 --- a/src/app/components/ShipSummaryTable.jsx +++ b/src/app/components/ShipSummaryTable.jsx @@ -19,11 +19,11 @@ export default class ShipSummaryTable extends TranslatedComponent { }; constructor(props) { - super(props) + super(props); this.didContextChange = this.didContextChange.bind(this); this.state = { shieldColour: 'blue' - } + }; } /** @@ -56,7 +56,7 @@ export default class ShipSummaryTable extends TranslatedComponent { } this.state = { shieldColour - } + }; return
    { translate('roll') }: { translate('roll') }: { translate('0%') } { translate('50%') } { translate('100%') }
    @@ -140,8 +140,8 @@ export default class ShipSummaryTable extends TranslatedComponent { - - + + diff --git a/src/app/components/Slider.jsx b/src/app/components/Slider.jsx index a1efbf94..bde1c2d0 100644 --- a/src/app/components/Slider.jsx +++ b/src/app/components/Slider.jsx @@ -1,361 +1,353 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -const MARGIN_LR = 8; // Left/ Right margin - -/** - * Horizontal Slider - */ -export default class Slider extends React.Component { - - static defaultProps = { - axis: false, - min: 0, - max: 1, - scale: 1 // SVG render scale - }; - - static propTypes = { - axis: PropTypes.bool, - axisUnit: PropTypes.string,//units (T, M, etc.) - max: PropTypes.number, - min: PropTypes.number, - onChange: PropTypes.func.isRequired,// function which determins percent value - onResize: PropTypes.func, - percent: PropTypes.number.isRequired,//value of slider - scale: PropTypes.number - }; - - /** - * Constructor - * @param {Object} props React Component properties - */ - constructor(props) { - super(props); - this._down = this._down.bind(this); - this._move = this._move.bind(this); - this._up = this._up.bind(this); - this._keyup = this._keyup.bind(this); - this._keydown = this._keydown.bind(this); - this._touchstart = this._touchstart.bind(this); - this._touchend = this._touchend.bind(this); - - this._updatePercent = this._updatePercent.bind(this); - this._updateDimensions = this._updateDimensions.bind(this); - - this.state = { width: 0 }; - } - - /** - * On Mouse/Touch down handler - * @param {SyntheticEvent} event Event - */ - _down(event) { - - let rect = event.currentTarget.getBoundingClientRect(); - this.left = rect.left; - this.width = rect.width; - this._move(event); - this.touchStartTimer = setTimeout(() => this.sliderInputBox._setDisplay('block'), 1500); - } - - /** - * Update the slider percentage on move - * @param {SyntheticEvent} event Event - */ - _move(event) { - if(this.width !== null && this.left != null) { - let clientX = event.touches ? event.touches[0].clientX : event.clientX; - event.preventDefault(); - this._updatePercent(clientX - this.left, this.width); - } - } - - /** - * On Mouse/Touch up handler - * @param {Event} event DOM Event - */ - _up(event) { - this.sliderInputBox.sliderVal.focus(); - clearTimeout(this.touchStartTimer); - event.preventDefault(); - this.left = null; - this.width = null; - } - - - /** - * Key up handler for keyboard. - * display the number field then set focus to it - * when "Enter" key is pressed - * @param {Event} event Keyboard event - */ - _keyup(event) { - switch (event.key) { - case 'Enter': - event.preventDefault(); - this.sliderInputBox._setDisplay('block'); - //this.enterTimer = setTimeout(() => this.sliderInputBox.sliderVal.focus(), 10); - return; - default: - return; - } - - } - /** - * Key down handler - * increment slider position by +/- 1 when right/left arrow key is pressed or held - * @param {Event} event - */ - _keydown(event) { - - switch (event.key) { - case 'ArrowRight': - var newVal = this.props.percent*this.props.max + 1; - if (newVal <= this.props.max) this.props.onChange(newVal/this.props.max); - return; - case 'ArrowLeft': - var newVal = this.props.percent*this.props.max - 1; - if (newVal >= 0) this.props.onChange(newVal/this.props.max); - return; - default: - return; - } - } - - /** - * Touch start handler - * @param {Event} event DOM Event - * - */ - _touchstart(event) { - this.touchStartTimer = setTimeout(() => this.sliderInputBox._setDisplay('block'), 1500); - } - - _touchend(event) { - this.sliderInputBox.sliderVal.focus(); - clearTimeout(this.touchStartTimer); - } - - /** - * Determine if the user is still dragging - * @param {SyntheticEvent} event Event - */ - _enter(event) { - if(event.buttons !== 1) { - this.left = null; - this.width = null; - } - } - - /** - * Update the slider percentage - * @param {number} pos Slider drag position - * @param {number} width Slider width - * @param {Event} event DOM Event - */ - _updatePercent(pos, width) { - this.props.onChange(Math.min(Math.max(pos / width, 0), 1)); - } - - /** - * Update dimenions from rendered DOM - */ - _updateDimensions() { - this.setState({ - outerWidth: this.node.getBoundingClientRect().width - }); - } - - /** - * Add listeners when about to mount - */ - componentWillMount() { - if (this.props.onResize) { - this.resizeListener = this.props.onResize(this._updateDimensions); - } - } - - /** - * Trigger DOM updates on mount - */ - componentDidMount() { - this._updateDimensions(); - - } - - /** - * Remove listeners on unmount - */ - componentWillUnmount() { - if (this.resizeListener) { - this.resizeListener.remove(); - } - } - - /** - * Render the slider - * @return {React.Component} The slider - */ - render() { - let outerWidth = this.state.outerWidth; - let { axis, axisUnit, min, max, scale } = this.props; - - let style = { - width: '100%', - height: axis ? '2.5em' : '1.5em', - boxSizing: 'border-box' - }; - - if (!outerWidth) { - return this.node = node} />; - } - - let margin = MARGIN_LR * scale; - let width = outerWidth - (margin * 2); - let pctPos = width * this.props.percent; - - return
    this.node = node} tabIndex="0"> - - - - - {axis && - {min + axisUnit} - {(min + max / 2) + axisUnit} - {max + axisUnit} - } - - this.sliderInputBox = tb} - onChange={this.props.onChange} - percent={this.props.percent} - axisUnit={this.props.axisUnit} - scale={this.props.scale} - max={this.props.max} - - /> -
    ; - } - -} -/** - * New component to add keyboard support for sliders - works on all devices (desktop, iOS, Android) - **/ - class TextInputBox extends React.Component { - static propTypes = { - axisUnit: PropTypes.string,//units (T, M, etc.) - max: PropTypes.number, - onChange: PropTypes.func.isRequired,// function which determins percent value - percent: PropTypes.number.isRequired,//value of slider - scale: PropTypes.number - }; - constructor(props) { - super(props); - this._handleFocus = this._handleFocus.bind(this); - this._handleBlur = this._handleBlur.bind(this); - this._handleChange = this._handleChange.bind(this); - //this._keydown = this._keydown.bind(this); - this._keyup = this._keyup.bind(this); - this.state = this._getInitialState(); - this.percent = this.props.percent; - this.max = this.props.max; - this.state.inputValue = this.percent * this.max; - } - - componentWillReceiveProps(nextProps, nextState) { - var nextValue = nextProps.percent * nextProps.max; - // See https://stackoverflow.com/questions/32414308/updating-state-on-props-change-in-react-form - if (nextValue !== this.state.inputValue && nextValue <= nextProps.max) { - this.setState({ inputValue: nextValue }); - } - } - componentDidUpdate(prevProps, prevState) { - - if (prevState.divStyle.display == 'none' && this.state.divStyle.display == 'block') { - this.enterTimer = setTimeout(() => this.sliderVal.focus(), 10); - } - - if (prevProps.max !== this.props.max && this.state.inputValue > this.props.max) { - // they chose a different module - this.setState({ inputValue: this.props.max }); - } - - if (this.state.inputValue != prevState.inputValue && prevProps.max == this.props.max) { - this.props.onChange(this.state.inputValue/this.props.max); - } - - } - - _getInitialState() { - return { - divStyle: {display:'none'}, - inputStyle: {width:'4em'}, - labelStyle: {marginLeft: '.1em'}, - maxLength:5, - size:5, - min:0, - tabIndex:-1, - type:'number', - readOnly: true - } - } - - _setDisplay(val) { - this.setState({ - divStyle: {display:val} - }); - } - - _handleFocus() { - this.setState({ - inputValue:this._getValue() - }); - } - - _handleBlur() { - this._setDisplay('none'); - if (this.state.inputValue !== '') { - this.props.onChange(this.state.inputValue/this.props.max); - } else { - this.state.inputValue = this.props.percent * this.props.max; - } - - } - - _getValue() { - return this.state.inputValue; - } - - _handleChange(event) { - if (event.target.value < 0) { - this.setState({inputValue: 0}); - } else if (event.target.value <= this.props.max) { - this.setState({inputValue: event.target.value}); - } else { - this.setState({inputValue: this.props.max}); - } - } - - /** - * Key up handler for input field. - * If user hits Enter key, blur/close the input field - * @param {Event} event Keyboard event - */ - _keyup(event) { - switch (event.key) { - case 'Enter': - this.sliderVal.blur(); - return; - default: - return; - } - - } - - render() { - let { axisUnit, onChange, percent, scale } = this.props; - return
    {this._handleBlur()}} onFocus={() => {this._handleFocus()}} type={this.state.type} ref={(ip) => this.sliderVal = ip}/>{this.props.axisUnit}
    ; - } - } - +import React from 'react'; +import PropTypes from 'prop-types'; + +const MARGIN_LR = 8; // Left/ Right margin + +/** + * Horizontal Slider + */ +export default class Slider extends React.Component { + + static defaultProps = { + axis: false, + min: 0, + max: 1, + scale: 1 // SVG render scale + }; + + static propTypes = { + axis: PropTypes.bool, + axisUnit: PropTypes.string,// units (T, M, etc.) + max: PropTypes.number, + min: PropTypes.number, + onChange: PropTypes.func.isRequired,// function which determins percent value + onResize: PropTypes.func, + percent: PropTypes.number.isRequired,// value of slider + scale: PropTypes.number + }; + + /** + * Constructor + * @param {Object} props React Component properties + */ + constructor(props) { + super(props); + this._down = this._down.bind(this); + this._move = this._move.bind(this); + this._up = this._up.bind(this); + this._keyup = this._keyup.bind(this); + this._keydown = this._keydown.bind(this); + this._touchstart = this._touchstart.bind(this); + this._touchend = this._touchend.bind(this); + + this._updatePercent = this._updatePercent.bind(this); + this._updateDimensions = this._updateDimensions.bind(this); + + this.state = { width: 0 }; + } + + /** + * On Mouse/Touch down handler + * @param {SyntheticEvent} event Event + */ + _down(event) { + let rect = event.currentTarget.getBoundingClientRect(); + this.left = rect.left; + this.width = rect.width; + this._move(event); + this.touchStartTimer = setTimeout(() => this.sliderInputBox._setDisplay('block'), 1500); + } + + /** + * Update the slider percentage on move + * @param {SyntheticEvent} event Event + */ + _move(event) { + if(this.width !== null && this.left != null) { + let clientX = event.touches ? event.touches[0].clientX : event.clientX; + event.preventDefault(); + this._updatePercent(clientX - this.left, this.width); + } + } + + /** + * On Mouse/Touch up handler + * @param {Event} event DOM Event + */ + _up(event) { + this.sliderInputBox.sliderVal.focus(); + clearTimeout(this.touchStartTimer); + event.preventDefault(); + this.left = null; + this.width = null; + } + + + /** + * Key up handler for keyboard. + * display the number field then set focus to it + * when "Enter" key is pressed + * @param {Event} event Keyboard event + */ + _keyup(event) { + switch (event.key) { + case 'Enter': + event.preventDefault(); + this.sliderInputBox._setDisplay('block'); + // this.enterTimer = setTimeout(() => this.sliderInputBox.sliderVal.focus(), 10); + return; + default: + return; + } + } + /** + * Key down handler + * increment slider position by +/- 1 when right/left arrow key is pressed or held + * @param {Event} event + */ + _keydown(event) { + switch (event.key) { + case 'ArrowRight': + let newVal = this.props.percent * this.props.max + 1; + if (newVal <= this.props.max) this.props.onChange(newVal / this.props.max); + return; + case 'ArrowLeft': + let newVal = this.props.percent * this.props.max - 1; + if (newVal >= 0) this.props.onChange(newVal / this.props.max); + return; + default: + return; + } + } + + /** + * Touch start handler + * @param {Event} event DOM Event + * + */ + _touchstart(event) { + this.touchStartTimer = setTimeout(() => this.sliderInputBox._setDisplay('block'), 1500); + } + + _touchend(event) { + this.sliderInputBox.sliderVal.focus(); + clearTimeout(this.touchStartTimer); + } + + /** + * Determine if the user is still dragging + * @param {SyntheticEvent} event Event + */ + _enter(event) { + if(event.buttons !== 1) { + this.left = null; + this.width = null; + } + } + + /** + * Update the slider percentage + * @param {number} pos Slider drag position + * @param {number} width Slider width + * @param {Event} event DOM Event + */ + _updatePercent(pos, width) { + this.props.onChange(Math.min(Math.max(pos / width, 0), 1)); + } + + /** + * Update dimenions from rendered DOM + */ + _updateDimensions() { + this.setState({ + outerWidth: this.node.getBoundingClientRect().width + }); + } + + /** + * Add listeners when about to mount + */ + componentWillMount() { + if (this.props.onResize) { + this.resizeListener = this.props.onResize(this._updateDimensions); + } + } + + /** + * Trigger DOM updates on mount + */ + componentDidMount() { + this._updateDimensions(); + } + + /** + * Remove listeners on unmount + */ + componentWillUnmount() { + if (this.resizeListener) { + this.resizeListener.remove(); + } + } + + /** + * Render the slider + * @return {React.Component} The slider + */ + render() { + let outerWidth = this.state.outerWidth; + let { axis, axisUnit, min, max, scale } = this.props; + + let style = { + width: '100%', + height: axis ? '2.5em' : '1.5em', + boxSizing: 'border-box' + }; + + if (!outerWidth) { + return this.node = node} />; + } + + let margin = MARGIN_LR * scale; + let width = outerWidth - (margin * 2); + let pctPos = width * this.props.percent; + + return
    this.node = node} tabIndex="0"> + + + + + {axis && + {min + axisUnit} + {(min + max / 2) + axisUnit} + {max + axisUnit} + } + + this.sliderInputBox = tb} + onChange={this.props.onChange} + percent={this.props.percent} + axisUnit={this.props.axisUnit} + scale={this.props.scale} + max={this.props.max} + + /> +
    ; + } + +} +/** + * New component to add keyboard support for sliders - works on all devices (desktop, iOS, Android) + **/ +class TextInputBox extends React.Component { + static propTypes = { + axisUnit: PropTypes.string,// units (T, M, etc.) + max: PropTypes.number, + onChange: PropTypes.func.isRequired,// function which determins percent value + percent: PropTypes.number.isRequired,// value of slider + scale: PropTypes.number + }; + constructor(props) { + super(props); + this._handleFocus = this._handleFocus.bind(this); + this._handleBlur = this._handleBlur.bind(this); + this._handleChange = this._handleChange.bind(this); + // this._keydown = this._keydown.bind(this); + this._keyup = this._keyup.bind(this); + this.state = this._getInitialState(); + this.percent = this.props.percent; + this.max = this.props.max; + this.state.inputValue = this.percent * this.max; + } + + componentWillReceiveProps(nextProps, nextState) { + let nextValue = nextProps.percent * nextProps.max; + // See https://stackoverflow.com/questions/32414308/updating-state-on-props-change-in-react-form + if (nextValue !== this.state.inputValue && nextValue <= nextProps.max) { + this.setState({ inputValue: nextValue }); + } + } + componentDidUpdate(prevProps, prevState) { + if (prevState.divStyle.display == 'none' && this.state.divStyle.display == 'block') { + this.enterTimer = setTimeout(() => this.sliderVal.focus(), 10); + } + + if (prevProps.max !== this.props.max && this.state.inputValue > this.props.max) { + // they chose a different module + this.setState({ inputValue: this.props.max }); + } + + if (this.state.inputValue != prevState.inputValue && prevProps.max == this.props.max) { + this.props.onChange(this.state.inputValue / this.props.max); + } + } + + _getInitialState() { + return { + divStyle: { display:'none' }, + inputStyle: { width:'4em' }, + labelStyle: { marginLeft: '.1em' }, + maxLength:5, + size:5, + min:0, + tabIndex:-1, + type:'number', + readOnly: true + }; + } + + _setDisplay(val) { + this.setState({ + divStyle: { display:val } + }); + } + + _handleFocus() { + this.setState({ + inputValue:this._getValue() + }); + } + + _handleBlur() { + this._setDisplay('none'); + if (this.state.inputValue !== '') { + this.props.onChange(this.state.inputValue / this.props.max); + } else { + this.state.inputValue = this.props.percent * this.props.max; + } + } + + _getValue() { + return this.state.inputValue; + } + + _handleChange(event) { + if (event.target.value < 0) { + this.setState({ inputValue: 0 }); + } else if (event.target.value <= this.props.max) { + this.setState({ inputValue: event.target.value }); + } else { + this.setState({ inputValue: this.props.max }); + } + } + + /** + * Key up handler for input field. + * If user hits Enter key, blur/close the input field + * @param {Event} event Keyboard event + */ + _keyup(event) { + switch (event.key) { + case 'Enter': + this.sliderVal.blur(); + return; + default: + return; + } + } + + render() { + let { axisUnit, onChange, percent, scale } = this.props; + return
    {this._handleBlur();}} onFocus={() => {this._handleFocus();}} type={this.state.type} ref={(ip) => this.sliderVal = ip}/>{this.props.axisUnit}
    ; + } + } + diff --git a/src/app/components/Slot.jsx b/src/app/components/Slot.jsx index c8b4c32f..7efec1ea 100644 --- a/src/app/components/Slot.jsx +++ b/src/app/components/Slot.jsx @@ -81,17 +81,17 @@ export default class Slot extends TranslatedComponent { * we do more or less the same thing * in every section when Enter key is pressed * on a focusable item - * + * */ _keyDown(event) { if (event.key == 'Enter') { - if(event.target.className == 'r') { - console.log("Slot: Enter key pressed on mod icon"); - this._toggleModifications(); - } else { - console.log("Slot: Enter key pressed on: %O", event.target); - } - this.props.onOpen(event); + if(event.target.className == 'r') { + console.log('Slot: Enter key pressed on mod icon'); + this._toggleModifications(); + } else { + console.log('Slot: Enter key pressed on: %O', event.target); + } + this.props.onOpen(event); } } /** @@ -154,7 +154,7 @@ export default class Slot extends TranslatedComponent { ); } - + /** * Toggle the modifications flag when selecting the modifications icon */ diff --git a/src/app/components/StandardSlot.jsx b/src/app/components/StandardSlot.jsx index cfca8530..18b12137 100644 --- a/src/app/components/StandardSlot.jsx +++ b/src/app/components/StandardSlot.jsx @@ -40,12 +40,12 @@ export default class StandardSlot extends TranslatedComponent { this.slotDiv = null; } - _keyDown(event) { + _keyDown(event) { if (event.key == 'Enter') { - if(event.target.className == 'r') { - this._toggleModifications(); - } - this.props.onOpen(event); + if(event.target.className == 'r') { + this._toggleModifications(); + } + this.props.onOpen(event); } } @@ -151,7 +151,6 @@ export default class StandardSlot extends TranslatedComponent { * Toggle the modifications flag when selecting the modifications icon */ _toggleModifications() { - this._modificationsSelected = !this._modificationsSelected; } } diff --git a/src/app/pages/OutfittingPage.jsx b/src/app/pages/OutfittingPage.jsx index 5b6d5a61..ac346a8f 100644 --- a/src/app/pages/OutfittingPage.jsx +++ b/src/app/pages/OutfittingPage.jsx @@ -554,17 +554,17 @@ export default class OutfittingPage extends Page { const shipSummaryMarker = `${ship.name}${_sStr}${_iStr}${_hStr}${_pStr}${_mStr}${ship.ladenMass}${cargo}${fuel}`; const requirements = Ships[ship.id].requirements; - var requirementElements = []; + let requirementElements = []; function renderRequirement(className, textKey, tooltipTextKey) { - requirementElements.push(
    {translate(textKey)}
    ); + requirementElements.push(
    {translate(textKey)}
    ); } if (requirements) { requirements.federationRank && renderRequirement('federation', 'federation rank ' + requirements.federationRank, 'federation rank required'); requirements.empireRank && renderRequirement('empire', 'empire rank ' + requirements.empireRank, 'empire rank required'); requirements.horizons && renderRequirement('horizons', 'horizons', 'horizons required'); - requirements.horizonsEarlyAdoption && renderRequirement('horizons', 'horizons early adoption', 'horizons early adoption required'); + requirements.horizonsEarlyAdoption && renderRequirement('horizons', 'horizons early adoption', 'horizons early adoption required'); } return ( @@ -602,7 +602,7 @@ export default class OutfittingPage extends Page { {/* Main tables */} - + diff --git a/src/app/pages/ShipyardPage.jsx b/src/app/pages/ShipyardPage.jsx index 09a09182..5f5e1842 100644 --- a/src/app/pages/ShipyardPage.jsx +++ b/src/app/pages/ShipyardPage.jsx @@ -274,11 +274,11 @@ export default class ShipyardPage extends Page { for (let s of shipSummaries) { let shipSortValue = s[shipPredicate]; - if( shipPredicateIndex != undefined ) { + if(shipPredicateIndex != undefined) { shipSortValue = shipSortValue[shipPredicateIndex]; } - if( shipSortValue != lastShipSortValue ) { + if(shipSortValue != lastShipSortValue) { backgroundHighlight = !backgroundHighlight; lastShipSortValue = shipSortValue; } @@ -396,4 +396,4 @@ export default class ShipyardPage extends Page { ); } -} \ No newline at end of file +} diff --git a/src/app/shipyard/Module.js b/src/app/shipyard/Module.js index 440604b3..c5cde25d 100755 --- a/src/app/shipyard/Module.js +++ b/src/app/shipyard/Module.js @@ -136,7 +136,7 @@ export default class Module { if (modification.type === 'percentage') { modValue = this.getModValue(name) / 10000; } else if (modification.type === 'numeric') { - modValue = this.getModValue(name)/ 100; + modValue = this.getModValue(name) / 100; } else { modValue = this.getModValue(name); } diff --git a/src/app/shipyard/ShipRoles.js b/src/app/shipyard/ShipRoles.js index a30cb5ae..62c4e00c 100644 --- a/src/app/shipyard/ShipRoles.js +++ b/src/app/shipyard/ShipRoles.js @@ -1,5 +1,5 @@ -import * as ModuleUtils from './ModuleUtils' -import { canMount } from '../utils/SlotFunctions' +import * as ModuleUtils from './ModuleUtils'; +import { canMount } from '../utils/SlotFunctions'; /** * Standard / typical role for multi-purpose or combat (if shielded with better bulkheads) @@ -7,20 +7,20 @@ import { canMount } from '../utils/SlotFunctions' * @param {Boolean} shielded True if shield generator should be included * @param {integer} bulkheadIndex Bulkhead to use see Constants.BulkheadNames */ -export function multiPurpose (ship, shielded, bulkheadIndex) { +export function multiPurpose(ship, shielded, bulkheadIndex) { ship.useStandard('A') .use(ship.standard[3], ModuleUtils.standard(3, ship.standard[3].maxClass + 'D')) // D Life Support .use(ship.standard[5], ModuleUtils.standard(5, ship.standard[5].maxClass + 'D')) // D Sensors - .useBulkhead(bulkheadIndex) + .useBulkhead(bulkheadIndex); if (shielded) { - ship.internal.some(function (slot) { + ship.internal.some(function(slot) { if (canMount(ship, slot, 'sg')) { // Assuming largest slot can hold an eligible shield - ship.use(slot, ModuleUtils.findInternal('sg', slot.maxClass, 'A')) - ship.setSlotEnabled(slot, true) - return true + ship.use(slot, ModuleUtils.findInternal('sg', slot.maxClass, 'A')); + ship.setSlotEnabled(slot, true); + return true; } - }) + }); } } @@ -30,51 +30,51 @@ export function multiPurpose (ship, shielded, bulkheadIndex) { * @param {Boolean} shielded True if shield generator should be included * @param {Object} standardOpts [Optional] Standard module optional overrides */ -export function trader (ship, shielded, standardOpts) { - let usedSlots = [] - let bstCount = 2 - let sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass) +export function trader(ship, shielded, standardOpts) { + let usedSlots = []; + let bstCount = 2; + let sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass); ship.useStandard('A') .use(ship.standard[3], ModuleUtils.standard(3, ship.standard[3].maxClass + 'D')) // D Life Support .use(ship.standard[1], ModuleUtils.standard(1, ship.standard[1].maxClass + 'D')) // D Life Support .use(ship.standard[4], ModuleUtils.standard(4, ship.standard[4].maxClass + 'D')) // D Life Support - .use(ship.standard[5], ModuleUtils.standard(5, ship.standard[5].maxClass + 'D')) // D Sensors + .use(ship.standard[5], ModuleUtils.standard(5, ship.standard[5].maxClass + 'D')); // D Sensors - const shieldOrder = [1, 2, 3, 4, 5, 6, 7, 8] + const shieldOrder = [1, 2, 3, 4, 5, 6, 7, 8]; const shieldInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1) .filter(a => (!a.eligible) || a.eligible.sg) .filter(a => a.maxClass >= sg.class) - .sort((a, b) => shieldOrder.indexOf(a.maxClass) - shieldOrder.indexOf(b.maxClass)) - shieldInternals.some(function (slot) { + .sort((a, b) => shieldOrder.indexOf(a.maxClass) - shieldOrder.indexOf(b.maxClass)); + shieldInternals.some(function(slot) { if (canMount(ship, slot, 'sg')) { // Assuming largest slot can hold an eligible shield - const shield = ModuleUtils.findInternal('sg', slot.maxClass, 'A') + const shield = ModuleUtils.findInternal('sg', slot.maxClass, 'A'); if (shield && shield.maxmass > ship.hullMass) { - ship.use(slot, shield) - ship.setSlotEnabled(slot, true) - usedSlots.push(slot) - return true + ship.use(slot, shield); + ship.setSlotEnabled(slot, true); + usedSlots.push(slot); + return true; } } - }) + }); // Fill the empty internals with cargo racks for (let i = ship.internal.length; i--;) { - let slot = ship.internal[i] + let slot = ship.internal[i]; if (usedSlots.indexOf(slot) == -1 && canMount(ship, slot, 'cr')) { - ship.use(slot, ModuleUtils.findInternal('cr', slot.maxClass, 'E')) + ship.use(slot, ModuleUtils.findInternal('cr', slot.maxClass, 'E')); } } // Empty the hardpoints for (let s of ship.hardpoints) { - ship.use(s, null) + ship.use(s, null); } for (let s of ship.hardpoints) { if (s.maxClass == 0 && bstCount) { // Mount up to 2 boosters - ship.use(s, ModuleUtils.hardpoints('04')) - bstCount-- + ship.use(s, ModuleUtils.hardpoints('04')); + bstCount--; } else { - ship.use(s, null) + ship.use(s, null); } } // ship.useLightestStandard(standardOpts); @@ -85,127 +85,127 @@ export function trader (ship, shielded, standardOpts) { * @param {Ship} ship Ship instance * @param {Boolean} planetary True if Planetary Vehicle Hangar (PVH) should be included */ -export function explorer (ship, planetary) { - let standardOpts = {ppRating: 'A'}, - heatSinkCount = 2, // Fit 2 heat sinks if possible - usedSlots = [], - sgSlot, - fuelScoopSlot, - sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass) +export function explorer(ship, planetary) { + let standardOpts = { ppRating: 'A' }, + heatSinkCount = 2, // Fit 2 heat sinks if possible + usedSlots = [], + sgSlot, + fuelScoopSlot, + sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass); if (!planetary) { // Non-planetary explorers don't really need to boost - standardOpts.pd = '1D' + standardOpts.pd = '1D'; } // Cargo hatch can be disabled - ship.setSlotEnabled(ship.cargoHatch, false) + ship.setSlotEnabled(ship.cargoHatch, false); // Advanced Discovery Scanner - class 1 or higher - const adsOrder = [1, 2, 3, 4, 5, 6, 7, 8] + const adsOrder = [1, 2, 3, 4, 5, 6, 7, 8]; const adsInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1) .filter(a => (!a.eligible) || a.eligible.sc) - .sort((a, b) => adsOrder.indexOf(a.maxClass) - adsOrder.indexOf(b.maxClass)) + .sort((a, b) => adsOrder.indexOf(a.maxClass) - adsOrder.indexOf(b.maxClass)); for (let i = 0; i < adsInternals.length; i++) { if (canMount(ship, adsInternals[i], 'sc')) { - ship.use(adsInternals[i], ModuleUtils.internal('2f')) - usedSlots.push(adsInternals[i]) - break + ship.use(adsInternals[i], ModuleUtils.internal('2f')); + usedSlots.push(adsInternals[i]); + break; } } if (planetary) { // Planetary Vehicle Hangar - class 2 or higher - const pvhOrder = [2, 3, 4, 5, 6, 7, 8, 1] + const pvhOrder = [2, 3, 4, 5, 6, 7, 8, 1]; const pvhInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1) .filter(a => (!a.eligible) || a.eligible.pv) - .sort((a, b) => pvhOrder.indexOf(a.maxClass) - pvhOrder.indexOf(b.maxClass)) + .sort((a, b) => pvhOrder.indexOf(a.maxClass) - pvhOrder.indexOf(b.maxClass)); for (let i = 0; i < pvhInternals.length; i++) { if (canMount(ship, pvhInternals[i], 'pv')) { // Planetary Vehical Hangar only has even classes - const pvhClass = pvhInternals[i].maxClass % 2 === 1 ? pvhInternals[i].maxClass - 1 : pvhInternals[i].maxClass - ship.use(pvhInternals[i], ModuleUtils.findInternal('pv', pvhClass, 'G')) // G is lower mass - ship.setSlotEnabled(pvhInternals[i], false) // Disable power for Planetary Vehical Hangar - usedSlots.push(pvhInternals[i]) - break + const pvhClass = pvhInternals[i].maxClass % 2 === 1 ? pvhInternals[i].maxClass - 1 : pvhInternals[i].maxClass; + ship.use(pvhInternals[i], ModuleUtils.findInternal('pv', pvhClass, 'G')); // G is lower mass + ship.setSlotEnabled(pvhInternals[i], false); // Disable power for Planetary Vehical Hangar + usedSlots.push(pvhInternals[i]); + break; } } } // Shield generator - const shieldOrder = [1, 2, 3, 4, 5, 6, 7, 8] + const shieldOrder = [1, 2, 3, 4, 5, 6, 7, 8]; const shieldInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1) .filter(a => (!a.eligible) || a.eligible.sg) .filter(a => a.maxClass >= sg.class) - .sort((a, b) => shieldOrder.indexOf(a.maxClass) - shieldOrder.indexOf(b.maxClass)) + .sort((a, b) => shieldOrder.indexOf(a.maxClass) - shieldOrder.indexOf(b.maxClass)); for (let i = 0; i < shieldInternals.length; i++) { if (canMount(ship, shieldInternals[i], 'sg')) { - ship.use(shieldInternals[i], sg) - usedSlots.push(shieldInternals[i]) - sgSlot = shieldInternals[i] - break + ship.use(shieldInternals[i], sg); + usedSlots.push(shieldInternals[i]); + sgSlot = shieldInternals[i]; + break; } } // Detailed Surface Scanner - const dssOrder = [1, 2, 3, 4, 5, 6, 7, 8] + const dssOrder = [1, 2, 3, 4, 5, 6, 7, 8]; const dssInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1) .filter(a => (!a.eligible) || a.eligible.sc) - .sort((a, b) => dssOrder.indexOf(a.maxClass) - dssOrder.indexOf(b.maxClass)) + .sort((a, b) => dssOrder.indexOf(a.maxClass) - dssOrder.indexOf(b.maxClass)); for (let i = 0; i < dssInternals.length; i++) { if (canMount(ship, dssInternals[i], 'sc')) { - ship.use(dssInternals[i], ModuleUtils.internal('2i')) - usedSlots.push(dssInternals[i]) - break + ship.use(dssInternals[i], ModuleUtils.internal('2i')); + usedSlots.push(dssInternals[i]); + break; } } // Fuel scoop - best possible - const fuelScoopOrder = [8, 7, 6, 5, 4, 3, 2, 1] + const fuelScoopOrder = [8, 7, 6, 5, 4, 3, 2, 1]; const fuelScoopInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1) .filter(a => (!a.eligible) || a.eligible.fs) - .sort((a, b) => fuelScoopOrder.indexOf(a.maxClass) - fuelScoopOrder.indexOf(b.maxClass)) + .sort((a, b) => fuelScoopOrder.indexOf(a.maxClass) - fuelScoopOrder.indexOf(b.maxClass)); for (let i = 0; i < fuelScoopInternals.length; i++) { if (canMount(ship, fuelScoopInternals[i], 'fs')) { - ship.use(fuelScoopInternals[i], ModuleUtils.findInternal('fs', fuelScoopInternals[i].maxClass, 'A')) - usedSlots.push(fuelScoopInternals[i]) - fuelScoopSlot = fuelScoopInternals[i] - break + ship.use(fuelScoopInternals[i], ModuleUtils.findInternal('fs', fuelScoopInternals[i].maxClass, 'A')); + usedSlots.push(fuelScoopInternals[i]); + fuelScoopSlot = fuelScoopInternals[i]; + break; } } // AFMUs - fill as they are 0-weight - const afmuOrder = [8, 7, 6, 5, 4, 3, 2, 1] + const afmuOrder = [8, 7, 6, 5, 4, 3, 2, 1]; const afmuInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1) .filter(a => (!a.eligible) || a.eligible.pc) - .sort((a, b) => afmuOrder.indexOf(a.maxClass) - afmuOrder.indexOf(b.maxClass)) + .sort((a, b) => afmuOrder.indexOf(a.maxClass) - afmuOrder.indexOf(b.maxClass)); for (let i = 0; i < afmuInternals.length; i++) { if (canMount(ship, afmuInternals[i], 'am')) { - ship.use(afmuInternals[i], ModuleUtils.findInternal('am', afmuInternals[i].maxClass, 'A')) - usedSlots.push(afmuInternals[i]) - ship.setSlotEnabled(afmuInternals[i], false) // Disable power for AFM Unit + ship.use(afmuInternals[i], ModuleUtils.findInternal('am', afmuInternals[i].maxClass, 'A')); + usedSlots.push(afmuInternals[i]); + ship.setSlotEnabled(afmuInternals[i], false); // Disable power for AFM Unit } } for (let s of ship.hardpoints) { if (s.maxClass == 0 && heatSinkCount) { // Mount up to 2 heatsinks - ship.use(s, ModuleUtils.hardpoints('02')) - ship.setSlotEnabled(s, heatSinkCount == 2) // Only enable a single Heatsink - heatSinkCount-- + ship.use(s, ModuleUtils.hardpoints('02')); + ship.setSlotEnabled(s, heatSinkCount == 2); // Only enable a single Heatsink + heatSinkCount--; } else { - ship.use(s, null) + ship.use(s, null); } } if (sgSlot && fuelScoopSlot) { // The SG and Fuel scoop to not need to be powered at the same time if (sgSlot.m.getPowerUsage() > fuelScoopSlot.m.getPowerUsage()) { // The Shield generator uses the most power - ship.setSlotEnabled(fuelScoopSlot, false) + ship.setSlotEnabled(fuelScoopSlot, false); } else { // The Fuel scoop uses the most power - ship.setSlotEnabled(sgSlot, false) + ship.setSlotEnabled(sgSlot, false); } } - ship.useLightestStandard(standardOpts) + ship.useLightestStandard(standardOpts); } /** @@ -213,188 +213,188 @@ export function explorer (ship, planetary) { * @param {Ship} ship Ship instance * @param {Boolean} shielded True if shield generator should be included */ -export function miner (ship, shielded) { - shielded = true - let standardOpts = {ppRating: 'A'}, - miningLaserCount = 2, - usedSlots = [], - sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass) +export function miner(ship, shielded) { + shielded = true; + let standardOpts = { ppRating: 'A' }, + miningLaserCount = 2, + usedSlots = [], + sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass); // Cargo hatch should be enabled - ship.setSlotEnabled(ship.cargoHatch, true) + ship.setSlotEnabled(ship.cargoHatch, true); // Largest possible refinery - const refineryOrder = [4, 5, 6, 7, 8, 3, 2, 1] + const refineryOrder = [4, 5, 6, 7, 8, 3, 2, 1]; const refineryInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1) .filter(a => (!a.eligible) || a.eligible.rf) - .sort((a, b) => refineryOrder.indexOf(a.maxClass) - refineryOrder.indexOf(b.maxClass)) + .sort((a, b) => refineryOrder.indexOf(a.maxClass) - refineryOrder.indexOf(b.maxClass)); for (let i = 0; i < refineryInternals.length; i++) { if (canMount(ship, refineryInternals[i], 'rf')) { - ship.use(refineryInternals[i], ModuleUtils.findInternal('rf', Math.min(refineryInternals[i].maxClass, 4), 'A')) - usedSlots.push(refineryInternals[i]) - break + ship.use(refineryInternals[i], ModuleUtils.findInternal('rf', Math.min(refineryInternals[i].maxClass, 4), 'A')); + usedSlots.push(refineryInternals[i]); + break; } } // Prospector limpet controller - 3A if possible - const prospectorOrder = [3, 4, 5, 6, 7, 8, 2, 1] + const prospectorOrder = [3, 4, 5, 6, 7, 8, 2, 1]; const prospectorInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1) .filter(a => (!a.eligible) || a.eligible.pc) - .sort((a, b) => prospectorOrder.indexOf(a.maxClass) - prospectorOrder.indexOf(b.maxClass)) + .sort((a, b) => prospectorOrder.indexOf(a.maxClass) - prospectorOrder.indexOf(b.maxClass)); for (let i = 0; i < prospectorInternals.length; i++) { if (canMount(ship, prospectorInternals[i], 'pc')) { // Prospector only has odd classes - const prospectorClass = prospectorInternals[i].maxClass % 2 === 0 ? prospectorInternals[i].maxClass - 1 : prospectorInternals[i].maxClass - ship.use(prospectorInternals[i], ModuleUtils.findInternal('pc', prospectorClass, 'A')) - usedSlots.push(prospectorInternals[i]) - break + const prospectorClass = prospectorInternals[i].maxClass % 2 === 0 ? prospectorInternals[i].maxClass - 1 : prospectorInternals[i].maxClass; + ship.use(prospectorInternals[i], ModuleUtils.findInternal('pc', prospectorClass, 'A')); + usedSlots.push(prospectorInternals[i]); + break; } } // Shield generator if required if (shielded) { - const shieldOrder = [1, 2, 3, 4, 5, 6, 7, 8] + const shieldOrder = [1, 2, 3, 4, 5, 6, 7, 8]; const shieldInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1) .filter(a => (!a.eligible) || a.eligible.sg) .filter(a => a.maxClass >= sg.class) - .sort((a, b) => shieldOrder.indexOf(a.maxClass) - shieldOrder.indexOf(b.maxClass)) + .sort((a, b) => shieldOrder.indexOf(a.maxClass) - shieldOrder.indexOf(b.maxClass)); for (let i = 0; i < shieldInternals.length; i++) { if (canMount(ship, shieldInternals[i], 'sg')) { - ship.use(shieldInternals[i], sg) - usedSlots.push(shieldInternals[i]) - break + ship.use(shieldInternals[i], sg); + usedSlots.push(shieldInternals[i]); + break; } } } // Dual mining lasers of highest possible class; remove anything else - const miningLaserOrder = [2, 3, 4, 1, 0] - const miningLaserHardpoints = ship.hardpoints.concat().sort(function (a, b) { - return miningLaserOrder.indexOf(a.maxClass) - miningLaserOrder.indexOf(b.maxClass) - }) + const miningLaserOrder = [2, 3, 4, 1, 0]; + const miningLaserHardpoints = ship.hardpoints.concat().sort(function(a, b) { + return miningLaserOrder.indexOf(a.maxClass) - miningLaserOrder.indexOf(b.maxClass); + }); for (let s of miningLaserHardpoints) { if (s.maxClass >= 1 && miningLaserCount) { - ship.use(s, ModuleUtils.hardpoints(s.maxClass >= 2 ? '2m' : '2l')) - miningLaserCount-- + ship.use(s, ModuleUtils.hardpoints(s.maxClass >= 2 ? '2m' : '2l')); + miningLaserCount--; } else { - ship.use(s, null) + ship.use(s, null); } } // Number of collector limpets required to be active is a function of the size of the ship and the power of the lasers const miningLaserDps = ship.hardpoints.filter(h => h.m != null) - .reduce(function (a, b) { - return a + b.m.getDps() - }, 0) + .reduce(function(a, b) { + return a + b.m.getDps(); + }, 0); // Find out how many internal slots we have, and their potential cargo size const potentialCargo = ship.internal.filter(a => usedSlots.indexOf(a) == -1) .filter(a => (!a.eligible) || a.eligible.cr) - .map(b => Math.pow(2, b.maxClass)) + .map(b => Math.pow(2, b.maxClass)); // One collector for each 1.25 DPS, multiply by 1.25 for medium ships and 1.5 for large ships as they have further to travel // 0 if we only have 1 cargo slot, otherwise minium of 1 and maximum of 6 (excluding size modifier) - const sizeModifier = ship.class == 2 ? 1.2 : ship.class == 3 ? 1.5 : 1 - let collectorLimpetsRequired = potentialCargo.length == 1 ? 0 : Math.ceil(sizeModifier * Math.min(6, Math.floor(miningLaserDps / 1.25))) + const sizeModifier = ship.class == 2 ? 1.2 : ship.class == 3 ? 1.5 : 1; + let collectorLimpetsRequired = potentialCargo.length == 1 ? 0 : Math.ceil(sizeModifier * Math.min(6, Math.floor(miningLaserDps / 1.25))); if (collectorLimpetsRequired > 0) { - const collectorOrder = [1, 2, 3, 4, 5, 6, 7, 8] + const collectorOrder = [1, 2, 3, 4, 5, 6, 7, 8]; const collectorInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1) .filter(a => (!a.eligible) || a.eligible.cc) - .sort((a, b) => collectorOrder.indexOf(a.maxClass) - collectorOrder.indexOf(b.maxClass)) + .sort((a, b) => collectorOrder.indexOf(a.maxClass) - collectorOrder.indexOf(b.maxClass)); // Always keep at least 2 slots free for cargo racks (1 for shielded) for (let i = 0; i < collectorInternals.length - (shielded ? 1 : 2) && collectorLimpetsRequired > 0; i++) { if (canMount(ship, collectorInternals[i], 'cc')) { // Collector only has odd classes - const collectorClass = collectorInternals[i].maxClass % 2 === 0 ? collectorInternals[i].maxClass - 1 : collectorInternals[i].maxClass - ship.use(collectorInternals[i], ModuleUtils.findInternal('cc', collectorClass, 'D')) - usedSlots.push(collectorInternals[i]) - collectorLimpetsRequired -= collectorInternals[i].m.maximum + const collectorClass = collectorInternals[i].maxClass % 2 === 0 ? collectorInternals[i].maxClass - 1 : collectorInternals[i].maxClass; + ship.use(collectorInternals[i], ModuleUtils.findInternal('cc', collectorClass, 'D')); + usedSlots.push(collectorInternals[i]); + collectorLimpetsRequired -= collectorInternals[i].m.maximum; } } } // Power distributor to power the mining lasers indefinitely const wepRateRequired = ship.hardpoints.filter(h => h.m != null) - .reduce(function (a, b) { - return a + b.m.getEps() - }, 0) - standardOpts.pd = ship.getAvailableModules().matchingPowerDist({weprate: wepRateRequired}).id + .reduce(function(a, b) { + return a + b.m.getEps(); + }, 0); + standardOpts.pd = ship.getAvailableModules().matchingPowerDist({ weprate: wepRateRequired }).id; // Fill the empty internals with cargo racks for (let i = ship.internal.length; i--;) { - let slot = ship.internal[i] + let slot = ship.internal[i]; if (usedSlots.indexOf(slot) == -1 && canMount(ship, slot, 'cr')) { - ship.use(slot, ModuleUtils.findInternal('cr', slot.maxClass, 'E')) + ship.use(slot, ModuleUtils.findInternal('cr', slot.maxClass, 'E')); } } - ship.useLightestStandard(standardOpts) + ship.useLightestStandard(standardOpts); } /** * Racer Role * @param {Ship} ship Ship instance */ -export function racer (ship) { +export function racer(ship) { let standardOpts = {}, - usedSlots = [], - sgSlot, - sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass) + usedSlots = [], + sgSlot, + sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass); // Cargo hatch can be disabled - ship.setSlotEnabled(ship.cargoHatch, false) + ship.setSlotEnabled(ship.cargoHatch, false); // Shield generator - const shieldOrder = [1, 2, 3, 4, 5, 6, 7, 8] + const shieldOrder = [1, 2, 3, 4, 5, 6, 7, 8]; const shieldInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1) .filter(a => (!a.eligible) || a.eligible.sg) .filter(a => a.maxClass >= sg.class) - .sort((a, b) => shieldOrder.indexOf(a.maxClass) - shieldOrder.indexOf(b.maxClass)) + .sort((a, b) => shieldOrder.indexOf(a.maxClass) - shieldOrder.indexOf(b.maxClass)); for (let i = 0; i < shieldInternals.length; i++) { if (canMount(ship, shieldInternals[i], 'sg')) { - ship.use(shieldInternals[i], sg) - usedSlots.push(shieldInternals[i]) - sgSlot = shieldInternals[i] - break + ship.use(shieldInternals[i], sg); + usedSlots.push(shieldInternals[i]); + sgSlot = shieldInternals[i]; + break; } } // Empty the hardpoints for (let s of ship.hardpoints) { - ship.use(s, null) + ship.use(s, null); } // Empty the internals for (let i = ship.internal.length; i--;) { - let slot = ship.internal[i] + let slot = ship.internal[i]; if (usedSlots.indexOf(slot) == -1) { - ship.use(slot, null) + ship.use(slot, null); } } // Best thrusters if (ship.standard[1].maxClass === 3) { - standardOpts.th = 'tz' + standardOpts.th = 'tz'; } else if (ship.standard[1].maxClass === 2) { - standardOpts.th = 'u0' + standardOpts.th = 'u0'; } else { - standardOpts.th = ship.standard[1].maxClass + 'A' + standardOpts.th = ship.standard[1].maxClass + 'A'; } // Best power distributor for more boosting - standardOpts.pd = ship.standard[4].maxClass + 'A' + standardOpts.pd = ship.standard[4].maxClass + 'A'; // Smallest possible FSD drive - standardOpts.fsd = '2D' + standardOpts.fsd = '2D'; // Minimal fuel tank - standardOpts.ft = '1C' + standardOpts.ft = '1C'; // Disable nearly everything - standardOpts.fsdDisabled = true - standardOpts.sDisabled = true - standardOpts.pdDisabled = true - standardOpts.lsDisabled = true + standardOpts.fsdDisabled = true; + standardOpts.sDisabled = true; + standardOpts.pdDisabled = true; + standardOpts.lsDisabled = true; - ship.useLightestStandard(standardOpts) + ship.useLightestStandard(standardOpts); // Apply engineering to each module // ship.standard[1].m.blueprint = getBlueprint('Engine_Dirty', ship.standard[0]); diff --git a/src/app/utils/BlueprintFunctions.js b/src/app/utils/BlueprintFunctions.js index 53b02f69..b806b4c1 100644 --- a/src/app/utils/BlueprintFunctions.js +++ b/src/app/utils/BlueprintFunctions.js @@ -18,36 +18,35 @@ export function specialToolTip(translate, blueprint, grp, m, specialName) { if (m) { // We also add in any benefits from specials that aren't covered above if (m.blueprint) { - for (const feature in Modifications.modifierActions[specialName]) { + for (const feature in Modifications.modifierActions[specialName]) { // if (!blueprint.features[feature] && !m.mods.feature) { - const featureDef = Modifications.modifications[feature]; - if (featureDef && !featureDef.hidden) { - let symbol = ''; - if (feature === 'jitter') { - symbol = '°'; - } else if (featureDef.type === 'percentage') { - symbol = '%'; - } - let current = m.getModValue(feature) - m.getModValue(feature, true); - if (featureDef.type === 'percentage') { - current = Math.round(current / 10) / 10; - } else if (featureDef.type === 'numeric') { - current /= 100; - } - const currentIsBeneficial = isValueBeneficial(feature, current); + const featureDef = Modifications.modifications[feature]; + if (featureDef && !featureDef.hidden) { + let symbol = ''; + if (feature === 'jitter') { + symbol = '°'; + } else if (featureDef.type === 'percentage') { + symbol = '%'; + } + let current = m.getModValue(feature) - m.getModValue(feature, true); + if (featureDef.type === 'percentage') { + current = Math.round(current / 10) / 10; + } else if (featureDef.type === 'numeric') { + current /= 100; + } + const currentIsBeneficial = isValueBeneficial(feature, current); - effects.push( - - - - - - - ); - } + effects.push( + + + + + + + ); + } } - } } @@ -289,7 +288,7 @@ export function isValueBeneficial(feature, value) { */ export function getBlueprint(name, module) { // Start with a copy of the blueprint - const findMod = val => Object.keys(Modifications.blueprints).find(elem => elem.toString().toLowerCase().search(val.toString().toLowerCase().replace(/(OutfittingFieldType_|persecond)/igm, '')) >= 0) + const findMod = val => Object.keys(Modifications.blueprints).find(elem => elem.toString().toLowerCase().search(val.toString().toLowerCase().replace(/(OutfittingFieldType_|persecond)/igm, '')) >= 0); const found = Modifications.blueprints[findMod(name)]; if (!found || !found.fdname) { return {}; @@ -382,36 +381,35 @@ export function getPercent(m) { let result = null; const features = m.blueprint.grades[m.blueprint.grade].features; for (const featureName in features) { - - if (features[featureName][0] === features[featureName][1]) { - continue; - } - - let value = _getValue(m, featureName); - let mult; + if (features[featureName][0] === features[featureName][1]) { + continue; + } + + let value = _getValue(m, featureName); + let mult; if (Modifications.modifications[featureName].higherbetter) { // Higher is better, but is this making it better or worse? if (features[featureName][0] < 0 || (features[featureName][0] === 0 && features[featureName][1] < 0)) { - mult = Math.round((value - features[featureName][1]) / (features[featureName][0] - features[featureName][1]) * 100); + mult = Math.round((value - features[featureName][1]) / (features[featureName][0] - features[featureName][1]) * 100); } else { - mult = Math.round((value - features[featureName][0]) / (features[featureName][1] - features[featureName][0]) * 100); + mult = Math.round((value - features[featureName][0]) / (features[featureName][1] - features[featureName][0]) * 100); } } else { // Higher is worse, but is this making it better or worse? if (features[featureName][0] < 0 || (features[featureName][0] === 0 && features[featureName][1] < 0)) { - mult = Math.round((value - features[featureName][0]) / (features[featureName][1] - features[featureName][0]) * 100); + mult = Math.round((value - features[featureName][0]) / (features[featureName][1] - features[featureName][0]) * 100); } else { - mult = Math.round((value - features[featureName][1]) / (features[featureName][0] - features[featureName][1]) * 100); + mult = Math.round((value - features[featureName][1]) / (features[featureName][0] - features[featureName][1]) * 100); } } - - if (result && result != mult) { - return null; - } else if (result != mult) { - result = mult; - } + + if (result && result != mult) { + return null; + } else if (result != mult) { + result = mult; + } } - + return result; } diff --git a/src/app/utils/CompanionApiUtils.js b/src/app/utils/CompanionApiUtils.js index 4f6d86e0..1755bb27 100644 --- a/src/app/utils/CompanionApiUtils.js +++ b/src/app/utils/CompanionApiUtils.js @@ -318,7 +318,7 @@ function _addModifications(module, modifiers, blueprint, grade, specialModificat if (!modifiers) return; let special; if (specialModifications) { - special = Modifications.specials[Object.keys(specialModifications)[0]] + special = Modifications.specials[Object.keys(specialModifications)[0]]; } for (const i in modifiers) { // Some special modifications @@ -345,7 +345,7 @@ function _addModifications(module, modifiers, blueprint, grade, specialModificat let value; if (i === 'OutfittingFieldType_DefenceModifierShieldMultiplier') { value = modifiers[i].value - 1; - } else if (i === 'OutfittingFieldType_DefenceModifierHealthMultiplier' && blueprint.startsWith('Armour_')) { + } else if (i === 'OutfittingFieldType_DefenceModifierHealthMultiplier' && blueprint.startsWith('Armour_')) { value = (modifiers[i].value - module.hullboost) / module.hullboost; } else if (i === 'OutfittingFieldType_DefenceModifierHealthMultiplier') { value = modifiers[i].value / module.hullboost; diff --git a/src/app/utils/JournalUtils.js b/src/app/utils/JournalUtils.js index 08b39a96..89381b03 100644 --- a/src/app/utils/JournalUtils.js +++ b/src/app/utils/JournalUtils.js @@ -1,26 +1,26 @@ -import Ship from '../shipyard/Ship' -import { HARDPOINT_NUM_TO_CLASS, shipModelFromJson } from './CompanionApiUtils' -import { Ships } from 'coriolis-data/dist' -import Module from '../shipyard/Module' -import { Modules } from 'coriolis-data/dist' -import { Modifications } from 'coriolis-data/dist' -import { getBlueprint } from './BlueprintFunctions' +import Ship from '../shipyard/Ship'; +import { HARDPOINT_NUM_TO_CLASS, shipModelFromJson } from './CompanionApiUtils'; +import { Ships } from 'coriolis-data/dist'; +import Module from '../shipyard/Module'; +import { Modules } from 'coriolis-data/dist'; +import { Modifications } from 'coriolis-data/dist'; +import { getBlueprint } from './BlueprintFunctions'; /** * Obtain a module given its FD Name * @param {string} fdname the FD Name of the module * @return {Module} the module */ -function _moduleFromFdName (fdname) { - if (!fdname) return null - fdname = fdname.toLowerCase() +function _moduleFromFdName(fdname) { + if (!fdname) return null; + fdname = fdname.toLowerCase(); // Check standard modules for (const grp in Modules.standard) { if (Modules.standard.hasOwnProperty(grp)) { for (const i in Modules.standard[grp]) { if (Modules.standard[grp][i].symbol && Modules.standard[grp][i].symbol.toLowerCase() === fdname) { // Found it - return new Module({template: Modules.standard[grp][i]}) + return new Module({ template: Modules.standard[grp][i] }); } } } @@ -32,7 +32,7 @@ function _moduleFromFdName (fdname) { for (const i in Modules.hardpoints[grp]) { if (Modules.hardpoints[grp][i].symbol && Modules.hardpoints[grp][i].symbol.toLowerCase() === fdname) { // Found it - return new Module({template: Modules.hardpoints[grp][i]}) + return new Module({ template: Modules.hardpoints[grp][i] }); } } } @@ -44,14 +44,14 @@ function _moduleFromFdName (fdname) { for (const i in Modules.internal[grp]) { if (Modules.internal[grp][i].symbol && Modules.internal[grp][i].symbol.toLowerCase() === fdname) { // Found it - return new Module({template: Modules.internal[grp][i]}) + return new Module({ template: Modules.internal[grp][i] }); } } } } // Not found - return null + return null; } /** @@ -59,16 +59,16 @@ function _moduleFromFdName (fdname) { * @param {object} json the Loadout event JSON * @return {Ship} the built ship */ -export function shipFromLoadoutJSON (json) { +export function shipFromLoadoutJSON(json) { // Start off building a basic ship - const shipModel = shipModelFromJson(json) + const shipModel = shipModelFromJson(json); if (!shipModel) { - throw 'No such ship found: "' + json.Ship + '"' + throw 'No such ship found: "' + json.Ship + '"'; } - const shipTemplate = Ships[shipModel] + const shipTemplate = Ships[shipModel]; - let ship = new Ship(shipModel, shipTemplate.properties, shipTemplate.slots) - ship.buildWith(null) + let ship = new Ship(shipModel, shipTemplate.properties, shipTemplate.slots); + ship.buildWith(null); // Initial Ship building, don't do engineering yet. let opts = []; @@ -76,135 +76,135 @@ export function shipFromLoadoutJSON (json) { switch (module.Slot.toLowerCase()) { // Cargo Hatch. case 'cargohatch': - ship.cargoHatch.enabled = module.On - ship.cargoHatch.priority = module.Priority - break + ship.cargoHatch.enabled = module.On; + ship.cargoHatch.priority = module.Priority; + break; // Add the bulkheads case 'armour': if (module.Item.toLowerCase().endsWith('_armour_grade1')) { - ship.useBulkhead(0, true) + ship.useBulkhead(0, true); } else if (module.Item.toLowerCase().endsWith('_armour_grade2')) { - ship.useBulkhead(1, true) + ship.useBulkhead(1, true); } else if (module.Item.toLowerCase().endsWith('_armour_grade3')) { - ship.useBulkhead(2, true) + ship.useBulkhead(2, true); } else if (module.Item.toLowerCase().endsWith('_armour_mirrored')) { - ship.useBulkhead(3, true) + ship.useBulkhead(3, true); } else if (module.Item.toLowerCase().endsWith('_armour_reactive')) { - ship.useBulkhead(4, true) + ship.useBulkhead(4, true); } else { - throw 'Unknown bulkheads "' + module.Item + '"' + throw 'Unknown bulkheads "' + module.Item + '"'; } - ship.bulkheads.enabled = true - if (module.Engineering) _addModifications(ship.bulkheads.m, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect) - break + ship.bulkheads.enabled = true; + if (module.Engineering) _addModifications(ship.bulkheads.m, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect); + break; case 'powerplant': - const powerplant = _moduleFromFdName(module.Item) - ship.use(ship.standard[0], powerplant, true) - ship.standard[0].enabled = module.On - ship.standard[0].priority = module.Priority - if (module.Engineering) _addModifications(powerplant, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect) - break + const powerplant = _moduleFromFdName(module.Item); + ship.use(ship.standard[0], powerplant, true); + ship.standard[0].enabled = module.On; + ship.standard[0].priority = module.Priority; + if (module.Engineering) _addModifications(powerplant, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect); + break; case 'mainengines': - const thrusters = _moduleFromFdName(module.Item) - ship.use(ship.standard[1], thrusters, true) - ship.standard[1].enabled = module.On - ship.standard[1].priority = module.Priority - if (module.Engineering) _addModifications(thrusters, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect) - break + const thrusters = _moduleFromFdName(module.Item); + ship.use(ship.standard[1], thrusters, true); + ship.standard[1].enabled = module.On; + ship.standard[1].priority = module.Priority; + if (module.Engineering) _addModifications(thrusters, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect); + break; case 'frameshiftdrive': - const frameshiftdrive = _moduleFromFdName(module.Item) - ship.use(ship.standard[2], frameshiftdrive, true) - ship.standard[2].enabled = module.On - ship.standard[2].priority = module.Priority - if (module.Engineering) _addModifications(frameshiftdrive, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect) - break + const frameshiftdrive = _moduleFromFdName(module.Item); + ship.use(ship.standard[2], frameshiftdrive, true); + ship.standard[2].enabled = module.On; + ship.standard[2].priority = module.Priority; + if (module.Engineering) _addModifications(frameshiftdrive, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect); + break; case 'lifesupport': - const lifesupport = _moduleFromFdName(module.Item) - ship.use(ship.standard[3], lifesupport, true) - ship.standard[3].enabled = module.On === true - ship.standard[3].priority = module.Priority - if (module.Engineering) _addModifications(lifesupport, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect) - break + const lifesupport = _moduleFromFdName(module.Item); + ship.use(ship.standard[3], lifesupport, true); + ship.standard[3].enabled = module.On === true; + ship.standard[3].priority = module.Priority; + if (module.Engineering) _addModifications(lifesupport, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect); + break; case 'powerdistributor': - const powerdistributor = _moduleFromFdName(module.Item) - ship.use(ship.standard[4], powerdistributor, true) - ship.standard[4].enabled = module.On - ship.standard[4].priority = module.Priority - if (module.Engineering) _addModifications(powerdistributor, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect) - break + const powerdistributor = _moduleFromFdName(module.Item); + ship.use(ship.standard[4], powerdistributor, true); + ship.standard[4].enabled = module.On; + ship.standard[4].priority = module.Priority; + if (module.Engineering) _addModifications(powerdistributor, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect); + break; case 'radar': - const sensors = _moduleFromFdName(module.Item) - ship.use(ship.standard[5], sensors, true) - ship.standard[5].enabled = module.On - ship.standard[5].priority = module.Priority - if (module.Engineering) _addModifications(sensors, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect) - break + const sensors = _moduleFromFdName(module.Item); + ship.use(ship.standard[5], sensors, true); + ship.standard[5].enabled = module.On; + ship.standard[5].priority = module.Priority; + if (module.Engineering) _addModifications(sensors, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect); + break; case 'fueltank': - const fueltank = _moduleFromFdName(module.Item) - ship.use(ship.standard[6], fueltank, true) - ship.standard[6].enabled = true - ship.standard[6].priority = 0 - break + const fueltank = _moduleFromFdName(module.Item); + ship.use(ship.standard[6], fueltank, true); + ship.standard[6].enabled = true; + ship.standard[6].priority = 0; + break; default: } for (const module of json.Modules) { if (module.Slot.toLowerCase().search(/hardpoint/) !== -1) { // Add hardpoints let hardpoint; - let hardpointClassNum = -1 - let hardpointSlotNum = -1 - let hardpointArrayNum = 0 + let hardpointClassNum = -1; + let hardpointSlotNum = -1; + let hardpointArrayNum = 0; for (let i in shipTemplate.slots.hardpoints) { if (shipTemplate.slots.hardpoints[i] === hardpointClassNum) { // Another slot of the same class - hardpointSlotNum++ + hardpointSlotNum++; } else { // The first slot of a new class - hardpointClassNum = shipTemplate.slots.hardpoints[i] - hardpointSlotNum = 1 + hardpointClassNum = shipTemplate.slots.hardpoints[i]; + hardpointSlotNum = 1; } // Now that we know what we're looking for, find it - const hardpointName = HARDPOINT_NUM_TO_CLASS[hardpointClassNum] + 'Hardpoint' + hardpointSlotNum - const hardpointSlot = json.Modules.find(elem => elem.Slot.toLowerCase() === hardpointName.toLowerCase()) + const hardpointName = HARDPOINT_NUM_TO_CLASS[hardpointClassNum] + 'Hardpoint' + hardpointSlotNum; + const hardpointSlot = json.Modules.find(elem => elem.Slot.toLowerCase() === hardpointName.toLowerCase()); if (!hardpointSlot) { // This can happen with old imports that don't contain new hardpoints } else if (!hardpointSlot) { // No module } else { - hardpoint = _moduleFromFdName(hardpointSlot.Item) - ship.use(ship.hardpoints[hardpointArrayNum], hardpoint, true) - ship.hardpoints[hardpointArrayNum].enabled = hardpointSlot.On - ship.hardpoints[hardpointArrayNum].priority = hardpointSlot.Priority - opts.push({coriolisMod: hardpoint, json: hardpointSlot}); + hardpoint = _moduleFromFdName(hardpointSlot.Item); + ship.use(ship.hardpoints[hardpointArrayNum], hardpoint, true); + ship.hardpoints[hardpointArrayNum].enabled = hardpointSlot.On; + ship.hardpoints[hardpointArrayNum].priority = hardpointSlot.Priority; + opts.push({ coriolisMod: hardpoint, json: hardpointSlot }); } - hardpointArrayNum++ + hardpointArrayNum++; } } if (module.Slot.toLowerCase().search(/slot\d/) !== -1) { - let internalSlotNum = 1 - let militarySlotNum = 1 + let internalSlotNum = 1; + let militarySlotNum = 1; for (let i in shipTemplate.slots.internal) { - const isMilitary = isNaN(shipTemplate.slots.internal[i]) ? shipTemplate.slots.internal[i].name = 'military' : false + const isMilitary = isNaN(shipTemplate.slots.internal[i]) ? shipTemplate.slots.internal[i].name = 'military' : false; // The internal slot might be a standard or a military slot. Military slots have a different naming system - let internalSlot = null + let internalSlot = null; if (isMilitary) { - const internalName = 'Military0' + militarySlotNum - internalSlot = json.Modules.find(elem => elem.Slot.toLowerCase() === internalName.toLowerCase()) - militarySlotNum++ + const internalName = 'Military0' + militarySlotNum; + internalSlot = json.Modules.find(elem => elem.Slot.toLowerCase() === internalName.toLowerCase()); + militarySlotNum++; } else { // Slot numbers are not contiguous so handle skips. while (internalSlot === null && internalSlotNum < 99) { // Slot sizes have no relationship to the actual size, either, so check all possibilities for (let slotsize = 0; slotsize < 9; slotsize++) { - const internalName = 'Slot' + (internalSlotNum <= 9 ? '0' : '') + internalSlotNum + '_Size' + slotsize + const internalName = 'Slot' + (internalSlotNum <= 9 ? '0' : '') + internalSlotNum + '_Size' + slotsize; if (json.Modules.find(elem => elem.Slot.toLowerCase() === internalName.toLowerCase())) { internalSlot = json.Modules.find(elem => elem.Slot.toLowerCase() === internalName.toLowerCase()); - break + break; } } - internalSlotNum++ + internalSlotNum++; } } @@ -213,12 +213,12 @@ export function shipFromLoadoutJSON (json) { } else if (!internalSlot) { // No module } else { - const internalJson = internalSlot - const internal = _moduleFromFdName(internalJson.Item) - ship.use(ship.internal[i], internal, true) - ship.internal[i].enabled = internalJson.On === true - ship.internal[i].priority = internalJson.Priority - opts.push({coriolisMod: internal, json: internalSlot}); + const internalJson = internalSlot; + const internal = _moduleFromFdName(internalJson.Item); + ship.use(ship.internal[i], internal, true); + ship.internal[i].enabled = internalJson.On === true; + ship.internal[i].priority = internalJson.Priority; + opts.push({ coriolisMod: internal, json: internalSlot }); } } } @@ -226,17 +226,17 @@ export function shipFromLoadoutJSON (json) { } for (const i of opts) { - if (i.json.Engineering) _addModifications(i.coriolisMod, i.json.Engineering.Modifiers, i.json.Engineering.BlueprintName, i.json.Engineering.Level, i.json.Engineering.ExperimentalEffect) + if (i.json.Engineering) _addModifications(i.coriolisMod, i.json.Engineering.Modifiers, i.json.Engineering.BlueprintName, i.json.Engineering.Level, i.json.Engineering.ExperimentalEffect); } // We don't have any information on it so guess it's priority 5 and disabled if (!ship.cargoHatch) { - ship.cargoHatch.enabled = false - ship.cargoHatch.priority = 4 + ship.cargoHatch.enabled = false; + ship.cargoHatch.priority = 4; } - console.log(ship) + console.log(ship); // Now update the ship's codes before returning it - return ship.updatePowerPrioritesString().updatePowerEnabledString().updateModificationsString() + return ship.updatePowerPrioritesString().updatePowerEnabledString().updateModificationsString(); } /** @@ -247,18 +247,18 @@ export function shipFromLoadoutJSON (json) { * @param {Object} grade the grade of the modification * @param {Object} specialModifications special modification */ -function _addModifications (module, modifiers, blueprint, grade, specialModifications) { - if (!modifiers) return - let special +function _addModifications(module, modifiers, blueprint, grade, specialModifications) { + if (!modifiers) return; + let special; if (specialModifications) { - special = Modifications.specials[specialModifications] + special = Modifications.specials[specialModifications]; } for (const i in modifiers) { // Some special modifications // Look up the modifiers to find what we need to do - const findMod = val => Object.keys(Modifications.modifierActions).find(elem => elem.toString().toLowerCase().replace(/(outfittingfieldtype_|persecond)/igm, '') === val.toString().toLowerCase().replace(/(outfittingfieldtype_|persecond)/igm, '')) - const modifierActions = Modifications.modifierActions[findMod(modifiers[i].Label)] - //TODO: Figure out how to scale this value. + const findMod = val => Object.keys(Modifications.modifierActions).find(elem => elem.toString().toLowerCase().replace(/(outfittingfieldtype_|persecond)/igm, '') === val.toString().toLowerCase().replace(/(outfittingfieldtype_|persecond)/igm, '')); + const modifierActions = Modifications.modifierActions[findMod(modifiers[i].Label)]; + // TODO: Figure out how to scale this value. if (!!modifiers[i].LessIsGood) { } @@ -267,26 +267,26 @@ function _addModifications (module, modifiers, blueprint, grade, specialModifica value = modifiers[i].Value * 100; } if (modifiers[i].Label.search('Resistance') >= 0) { - value = (modifiers[i].Value * 100) - (modifiers[i].OriginalValue * 100) + value = (modifiers[i].Value * 100) - (modifiers[i].OriginalValue * 100); } // Carry out the required changes for (const action in modifierActions) { if (isNaN(modifierActions[action])) { - module.setModValue(action, modifierActions[action]) + module.setModValue(action, modifierActions[action]); } else { - module.setModValue(action, value) + module.setModValue(action, value); } } } // Add the blueprint definition, grade and special if (blueprint) { - module.blueprint = getBlueprint(blueprint, module) + module.blueprint = getBlueprint(blueprint, module); if (grade) { - module.blueprint.grade = Number(grade) + module.blueprint.grade = Number(grade); } if (special) { - module.blueprint.special = special + module.blueprint.special = special; } } }
    {int(ship.shieldThermRes * 100) + '%'} {int(sgMetrics && sgMetrics.generator ? sgMetrics.total / sgMetrics.absolute.total : 0)} {int(sgMetrics && sgMetrics.generator ? sgMetrics.total / sgMetrics.explosive.total : 0)}{int(sgMetrics && sgMetrics.generator ? sgMetrics.total / sgMetrics.kinetic.total : 0 )}{int(sgMetrics && sgMetrics.generator ? sgMetrics.total / sgMetrics.thermal.total : 0 )}{int(sgMetrics && sgMetrics.generator ? sgMetrics.total / sgMetrics.kinetic.total : 0)}{int(sgMetrics && sgMetrics.generator ? sgMetrics.total / sgMetrics.thermal.total : 0)} {sgMetrics && sgMetrics.recover ? formats.time(sgMetrics.recover) : 0} {sgMetrics && sgMetrics.recharge ? formats.time(sgMetrics.recharge) : 0}
    {translate(feature, grp)} {current}{symbol} 
    {translate(feature, grp)} {current}{symbol}