Fix retrofit cost

This commit is contained in:
Felix Linker
2020-11-01 19:54:48 +01:00
parent f2b7daac82
commit f865ef6c6c

View File

@@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import cn from 'classnames'; import cn from 'classnames';
import Persist from '../stores/Persist'; import Persist from '../stores/Persist';
import Ship from '../shipyard/Ship'; import { Factory, Ship } from 'ed-forge';
import { Insurance } from '../shipyard/Constants'; import { Insurance } from '../shipyard/Constants';
import TranslatedComponent from './TranslatedComponent'; import TranslatedComponent from './TranslatedComponent';
import { ShoppingIcon } from './SvgIcons'; import { ShoppingIcon } from './SvgIcons';
@@ -28,13 +28,15 @@ export default class CostSection extends TranslatedComponent {
super(props); super(props);
autoBind(this); autoBind(this);
const { ship, buildName } = props;
this.shipType = ship.getShipType();
this.state = { this.state = {
retrofitName: this._defaultRetrofitName(props.ship, props.buildName), retrofitName: Persist.hasBuild(ship.getShipType(), buildName) ? buildName : null,
shipDiscount: Persist.getShipDiscount(), shipDiscount: Persist.getShipDiscount(),
moduleDiscount: Persist.getModuleDiscount(), moduleDiscount: Persist.getModuleDiscount(),
insurance: Insurance[Persist.getInsurance()], insurance: Insurance[Persist.getInsurance()],
tab: Persist.getCostTab(), tab: Persist.getCostTab(),
buildOptions: Persist.getBuildsNamesFor(props.ship.getShipType()), buildOptions: Persist.getBuildsNamesFor(ship.getShipType()),
predicate: 'cr', predicate: 'cr',
desc: true, desc: true,
excluded: {}, excluded: {},
@@ -43,36 +45,15 @@ export default class CostSection extends TranslatedComponent {
/** /**
* Create a ship instance to base/reference retrofit changes from * Create a ship instance to base/reference retrofit changes from
* @param {string} ship Ship
* @param {string} name Build name
* @param {Ship} retrofitShip Existing retrofit ship
* @return {Ship} Retrofit ship * @return {Ship} Retrofit ship
*/ */
_buildRetrofitShip(ship, name, retrofitShip) { _buildRetrofitShip() {
// TODO: once ships have been persisted, this can be fixed const { retrofitName } = this.state;
return ship; if (Persist.hasBuild(this.shipType, retrofitName)) {
// let data = Ships[shipId]; // Retrieve the basic ship properties, slots and defaults return new Ship(Persist.getBuild(this.shipType, retrofitName));
} else {
// if (!retrofitShip) { // Don't create a new instance unless needed return Factory.newShip(this.shipType);
// retrofitShip = new Ship(shipId, data.properties, data.slots); // Create a new Ship for retrofit comparison }
// }
// if (Persist.hasBuild(shipId, name)) {
// retrofitShip.buildFrom(Persist.getBuild(shipId, name)); // Populate modules from existing build
// } else {
// retrofitShip.buildWith(data.defaults); // Populate with default components
// }
// return retrofitShip;
}
/**
* Get the default retrofit build name if it exists
* @param {string} ship Ship
* @param {string} name Build name
* @return {string} Build name or null
*/
_defaultRetrofitName(ship, name) {
return Persist.hasBuild(ship.getShipType(), name) ? name : null;
} }
/** /**
@@ -220,8 +201,8 @@ export default class CostSection extends TranslatedComponent {
*/ */
_retrofitInfo() { _retrofitInfo() {
const { ship } = this.props; const { ship } = this.props;
const { desc, moduleDiscount, predicate, retrofitName } = this.state; const { desc, moduleDiscount, predicate, retrofitName, excluded } = this.state;
const retrofitShip = this._buildRetrofitShip(ship, retrofitName); const retrofitShip = this._buildRetrofitShip();
const currentModules = ship.getModules(); const currentModules = ship.getModules();
const oldModules = retrofitShip.getModules(); const oldModules = retrofitShip.getModules();
@@ -229,37 +210,38 @@ export default class CostSection extends TranslatedComponent {
const sellModules = differenceBy(oldModules, currentModules, (m) => m.getItem()); const sellModules = differenceBy(oldModules, currentModules, (m) => m.getItem());
let modules = []; let modules = [];
for (let m of buyModules) { let totalCost = 0;
const key = `buy_${m.getSlot()}`; const addModule = (m, costFactor) => {
const key = `${m.getItem()}@${m.getSlot()}`;
const cost = costFactor * m.readMeta('cost') * (1 - moduleDiscount);
modules.push({ modules.push({
key, key, cost,
cost: m.readMeta('cost') * (1 - moduleDiscount), rating: m.getClassRating(),
buyRating: m.getClassRating(), item: m.readMeta('type'),
buyItem: m.readMeta('type'),
}); });
if (!excluded[key]) {
totalCost += cost;
}
};
for (let m of buyModules) {
addModule(m, 1);
} }
for (let m of sellModules) { for (let m of sellModules) {
const key = `sell_${m.getSlot()}`; addModule(m, -1);
modules.push({
key,
cost: -1 * m.readMeta('cost') * moduleDiscount,
sellRating: m.getClassRating(),
sellItem: m.readMeta('type'),
});
} }
let _sortF = undefined; let _sortF = undefined;
switch (predicate) { switch (predicate) {
case 'cr': _sortF = (o) => o.cost; case 'cr': _sortF = (o) => o.cost; break;
case 'm': case 'm':
default: _sortF = (o) => o.buyItem || o.sellItem; default: _sortF = (o) => o.item; break;
}; };
modules = sortBy(modules, _sortF); modules = sortBy(modules, _sortF);
if (desc) { if (desc) {
reverse(modules); reverse(modules);
} }
return modules; return [totalCost, modules];
} }
/** /**
@@ -267,46 +249,18 @@ export default class CostSection extends TranslatedComponent {
* @return {React.Component} Tab contents * @return {React.Component} Tab contents
*/ */
_retrofitTab() { _retrofitTab() {
let { excluded, moduleDiscount, retrofitName } = this.state; let { buildOptions, excluded, moduleDiscount, retrofitName } = this.state;
const { termtip, tooltip } = this.context; const { termtip, tooltip } = this.context;
let { translate, formats, units } = this.context.language; let { translate, formats, units } = this.context.language;
let int = formats.int; let int = formats.int;
let options = [<option key='stock' value=''>{translate('Stock')}</option>];
for (let opt of this.state.buildOptions) {
options.push(<option key={opt} value={opt}>{opt}</option>);
}
const retrofitInfo = this._retrofitInfo();
const retrofitTotal = 0;
let rows = [];
for (let i of retrofitInfo) {
const disabled = excluded[i.key];
rows.push(
<tr key={i.key} className={cn('highlight', { disabled })}
onClick={() => this._toggleExcluded(i.key)}>
<td className='ptr' style={{ width: '1em' }}>{i.buyRating}</td>
<td className='le ptr shorten cap'>{translate(i.buyItem)}</td>
<td className='ptr' style={{ width: '1em' }}>{i.sellRating}</td>
<td className='le ptr shorten cap'>{translate(i.sellItem)}</td>
<td colSpan='2' className={cn('ri ptr', disabled ? 'disabled' : (i.cost < 0 ? 'secondary-disabled' : 'warning'))}>
{int(i.cost)}{units.CR}
</td>
</tr>
);
retrofitTotal += disabled ? 0 : i.cost;
}
if (!rows.length) {
rows = <tr><td colSpan='7' style={{ padding: '3em 0' }}>{translate('PHRASE_NO_RETROCH')}</td></tr>;
}
const [retrofitTotal, retrofitInfo] = this._retrofitInfo();
return <div> return <div>
<div className='scroll-x'> <div className='scroll-x'>
<table style={{ width: '100%' }}> <table style={{ width: '100%' }}>
<thead> <thead>
<tr className='main'> <tr className='main'>
<th colSpan='2' className='sortable le' onClick={() => this._sortBy('m')}>{translate('sell')}</th> <th colSpan='2' className='sortable le' onClick={() => this._sortBy('m')}>{translate('module')}</th>
<th colSpan='2' className='sortable le' onClick={() => this._sortBy('m')}>{translate('buy')}</th>
<th colSpan='2' className='sortable le' onClick={() => this._sortBy('cr')}> <th colSpan='2' className='sortable le' onClick={() => this._sortBy('cr')}>
{translate('net cost')} {translate('net cost')}
{moduleDiscount ? <u className='cap optional-hide' style={{ marginLeft: '0.5em' }}>{`[${translate('modules')} -${formats.pct(moduleDiscount)}]`}</u> : null} {moduleDiscount ? <u className='cap optional-hide' style={{ marginLeft: '0.5em' }}>{`[${translate('modules')} -${formats.pct(moduleDiscount)}]`}</u> : null}
@@ -314,20 +268,33 @@ export default class CostSection extends TranslatedComponent {
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{rows} {retrofitInfo.length ?
retrofitInfo.map((info) => (
<tr key={info.key} className={cn('highlight', { disabled: excluded[info.key] })}
onClick={() => this._toggleExcluded(info.key)}>
<td className='ptr' style={{ width: '1em' }}>{info.rating}</td>
<td className='le ptr shorten cap'>{translate(info.item)}</td>
<td colSpan="2" className={cn('ri ptr', excluded[info.key] ? 'disabled' : (info.cost < 0 ? 'secondary-disabled' : 'warning'))}>
{int(info.cost)}{units.CR}
</td>
</tr>
)) : (
<tr><td colSpan='7' style={{ padding: '3em 0' }}>{translate('PHRASE_NO_RETROCH')}</td></tr>
)}
<tr className='ri'> <tr className='ri'>
<td className='lbl' ><button onClick={this._eddbShoppingList} onMouseOver={termtip.bind(null, 'PHRASE_REFIT_SHOPPING_LIST')} onMouseOut={tooltip.bind(null, null)}><ShoppingIcon className='lg' style={{ fill: 'black' }}/></button></td> <td className='lbl' ><button onClick={this._eddbShoppingList} onMouseOver={termtip.bind(null, 'PHRASE_REFIT_SHOPPING_LIST')} onMouseOut={tooltip.bind(null, null)}><ShoppingIcon className='lg' style={{ fill: 'black' }}/></button></td>
<td colSpan='3' className='lbl' >{translate('cost')}</td> <td className='lbl' >{translate('cost')}</td>
<td colSpan='2' className={cn('val', retrofitTotal > 0 ? 'warning' : 'secondary-disabled')} style={{ borderBottom:'none' }}> <td colSpan='2' className={cn('val', retrofitTotal > 0 ? 'warning' : 'secondary-disabled')} style={{ borderBottom:'none' }}>
{int(retrofitTotal)}{units.CR} {int(retrofitTotal)}{units.CR}
</td> </td>
</tr> </tr>
<tr className='ri'> <tr className='ri'>
<td colSpan='4' className='lbl cap' >{translate('retrofit from')}</td> <td colSpan='2' className='lbl cap' >{translate('retrofit from')}</td>
<td className='val cen' style={{ borderRight: 'none', width: '1em' }}><u className='primary-disabled'>&#9662;</u></td> <td className='val cen' style={{ borderRight: 'none', width: '1em' }}><u className='primary-disabled'>&#9662;</u></td>
<td className='val' style={{ borderLeft:'none', padding: 0 }}> <td className='val' style={{ borderLeft:'none', padding: 0 }}>
<select style={{ width: '100%', padding: 0 }} value={retrofitName || translate('Stock')} onChange={this._onBaseRetrofitChange}> <select style={{ width: '100%', padding: 0 }} value={retrofitName || translate('Stock')} onChange={this._onBaseRetrofitChange}>
{options} <option key='stock' value=''>{translate('Stock')}</option>
{buildOptions.map((opt) => <option key={opt} value={opt}>{opt}</option>)}
</select> </select>
</td> </td>
</tr> </tr>