|
|
@@ -232,6 +232,10 @@ async function render() {
|
|
|
|
|
|
savedBuilding = '';
|
|
|
|
|
|
+ const filteredProfits = profits.filter(p => {
|
|
|
+
|
|
|
+ savedBuilding = '';
|
|
|
+
|
|
|
const filteredProfits = profits.filter(p => {
|
|
|
const volumeRatio = p.output_per_day / p.average_traded_7d;
|
|
|
if (!lowVolume.checked && volumeRatio > 0.05) return false;
|
|
|
@@ -379,6 +383,30 @@ async function render() {
|
|
|
capexCell.dataset.tooltip += `\nShip CapEx: ${formatSigFig(p.activeShipCapex)} (${formatSigFig(p.shipsNeeded)} ships)`;
|
|
|
}
|
|
|
|
|
|
+ const marketCell = tr.querySelectorAll('td')[7];
|
|
|
+ marketCell.dataset.tooltip = `Market Capacity: ${formatSigFig(p.average_traded_7d)} traded/day ÷ ${formatSigFig(p.output_per_day / (p.area / 500))} produced/day/base = ${formatSigFig(p.market_capacity_base)} equivalent bases`;
|
|
|
+ const runs_per_base = p.runs_per_day / (p.area / 500);
|
|
|
+
|
|
|
+ profitCell.dataset.tooltip = formatMatPrices(p.outputs, revenueMetric, runs_per_base) + '\n\n' +
|
|
|
+ formatMatPrices(p.input_costs, opexMetric, runs_per_base) + '\n' +
|
|
|
+ '+ worker consumables\n\n' +
|
|
|
+ `(${formatSigFig(p.revenue_val)} - ${formatSigFig(p.opex_val)}) = ${formatSigFig(p.profit_per_base)}`;
|
|
|
+
|
|
|
+ const capexCell = tr.querySelectorAll('td')[4];
|
|
|
+ capexCell.dataset.tooltip = `Base Construction: ${formatSigFig(p.capex[capexMetric] / (p.area / 500))}`;
|
|
|
+
|
|
|
+ if (workingCapitalOption !== 'omit') {
|
|
|
+ capexCell.dataset.tooltip += `\nWorking Capital (${formatSigFig(p.activeWorkingCapitalDays)} days): ${formatSigFig(p.opex_val * p.activeWorkingCapitalDays)}`;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (targetPermitOption !== 'omit' && p.hq_capex > 0) {
|
|
|
+ capexCell.dataset.tooltip += `\nHQ Upgrade (Permit ${targetPermitOption}): ${formatSigFig(p.hq_capex)}`;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (roundTripOption !== 'omit') {
|
|
|
+ capexCell.dataset.tooltip += `\nShip CapEx: ${formatSigFig(p.activeShipCapex)} (${formatSigFig(p.shipsNeeded)} ships)`;
|
|
|
+ }
|
|
|
+
|
|
|
const marketCell = tr.querySelectorAll('td')[7];
|
|
|
marketCell.dataset.tooltip = `Market Capacity: ${formatSigFig(p.average_traded_7d)} traded/day ÷ ${formatSigFig(p.output_per_day / (p.area / 500))} produced/day/base = ${formatSigFig(p.market_capacity_base)} equivalent bases`;
|
|
|
|
|
|
@@ -456,6 +484,12 @@ function color(n: number, low: number, high: number): string {
|
|
|
return `color-mix(in xyz, #0aa ${scale * 100}%, #f80)`;
|
|
|
}
|
|
|
|
|
|
+function formatMatPrices(matPrices: MatPrice[], metric: MetricType, runs_per_day: number): string {
|
|
|
+ return matPrices.map(({ticker, amount, vwap_7d, bid, ask}) => {
|
|
|
+ const val = metric === 'vwap' ? vwap_7d : metric === 'bid' ? (bid ?? vwap_7d) : (ask ?? vwap_7d);
|
|
|
+ const daily_amount = amount * runs_per_day;
|
|
|
+ return `${ticker}: ${formatSigFig(daily_amount)} × ${formatSigFig(val)} = ${formatSigFig(daily_amount * val)}`;
|
|
|
+ }).join('\n');
|
|
|
function formatMatPrices(matPrices: MatPrice[], metric: MetricType, runs_per_day: number): string {
|
|
|
return matPrices.map(({ticker, amount, vwap_7d, bid, ask}) => {
|
|
|
const val = metric === 'vwap' ? vwap_7d : metric === 'bid' ? (bid ?? vwap_7d) : (ask ?? vwap_7d);
|
|
|
@@ -477,6 +511,12 @@ interface Metrics {
|
|
|
ask: number;
|
|
|
}
|
|
|
|
|
|
+interface Metrics {
|
|
|
+ vwap: number;
|
|
|
+ bid: number;
|
|
|
+ ask: number;
|
|
|
+}
|
|
|
+
|
|
|
interface Profit {
|
|
|
outputs: MatPrice[]
|
|
|
recipe: string
|
|
|
@@ -491,6 +531,9 @@ interface Profit {
|
|
|
logistics_per_base: number
|
|
|
normalized_logistics_per_base: number
|
|
|
logistics_bottleneck: string
|
|
|
+ logistics_per_base: number
|
|
|
+ normalized_logistics_per_base: number
|
|
|
+ logistics_bottleneck: string
|
|
|
output_per_day: number
|
|
|
average_traded_7d: number
|
|
|
market_capacity_base: number
|
|
|
@@ -517,6 +560,8 @@ interface MatPrice {
|
|
|
vwap_7d: number
|
|
|
bid: number | null
|
|
|
ask: number | null
|
|
|
+ bid: number | null
|
|
|
+ ask: number | null
|
|
|
}
|
|
|
|
|
|
interface Building {
|