|
@@ -76,7 +76,7 @@ async function _render() {
|
|
|
renderTarget.append(
|
|
renderTarget.append(
|
|
|
renderAnalysis(analysisNodes),
|
|
renderAnalysis(analysisNodes),
|
|
|
element('p', {textContent: `total cost: ${formatWhole(cost)}`}),
|
|
element('p', {textContent: `total cost: ${formatWhole(cost)}`}),
|
|
|
- renderProduction(expertiseGroups, production, prices, recipes, buildings),
|
|
|
|
|
|
|
+ renderProduction(expertiseGroups, production, storage, prices, recipes, buildings),
|
|
|
renderMatList('extract', extract),
|
|
renderMatList('extract', extract),
|
|
|
renderMatList('buy', buy),
|
|
renderMatList('buy', buy),
|
|
|
);
|
|
);
|
|
@@ -218,8 +218,8 @@ function buildingDailyCost(building: Building, prices: Record<string, RawPrice>)
|
|
|
return cost;
|
|
return cost;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-function renderProduction(expertiseGroups: Record<string, string[]>, production: Production, prices: Record<string, RawPrice>,
|
|
|
|
|
- recipes: Record<string, Recipe>, buildings: Record<string, Building>): HTMLElement {
|
|
|
|
|
|
|
+function renderProduction(expertiseGroups: Record<string, string[]>, production: Production, storage: Record<string, number>,
|
|
|
|
|
+ prices: Record<string, RawPrice>, recipes: Record<string, Recipe>, buildings: Record<string, Building>): HTMLElement {
|
|
|
const section = element('section');
|
|
const section = element('section');
|
|
|
section.append(element('h2', {textContent: 'production'}));
|
|
section.append(element('h2', {textContent: 'production'}));
|
|
|
|
|
|
|
@@ -249,26 +249,9 @@ function renderProduction(expertiseGroups: Record<string, string[]>, production:
|
|
|
const buildingMats = element('div');
|
|
const buildingMats = element('div');
|
|
|
const mats = Object.entries(production[building]);
|
|
const mats = Object.entries(production[building]);
|
|
|
let buildingMins = 0;
|
|
let buildingMins = 0;
|
|
|
- for (const [index, [mat, amount]] of mats.entries()) {
|
|
|
|
|
- const traded = prices[mat]?.AverageTraded30D ?? 0;
|
|
|
|
|
- const span = element('span', {textContent: `${formatAmount(amount)}x${mat}`});
|
|
|
|
|
- span.style.color = traded > amount * 2 ? '#0cc' : '#c70';
|
|
|
|
|
- const consumers = matConsumers[mat];
|
|
|
|
|
- if (consumers) {
|
|
|
|
|
- span.dataset.tooltip = consumers
|
|
|
|
|
- .map((c) => `${formatAmount(c.amount)}x${mat} → ${c.downstreamMat} (${c.expertise.toLocaleLowerCase()})`)
|
|
|
|
|
- .join('\n');
|
|
|
|
|
- for (const consumer of consumers) {
|
|
|
|
|
- if (consumer.expertise == expertise) // we aren't shipping it anywhere
|
|
|
|
|
- continue;
|
|
|
|
|
- if (!shipTo[consumer.expertise])
|
|
|
|
|
- shipTo[consumer.expertise] = {};
|
|
|
|
|
- shipTo[consumer.expertise][mat] = (shipTo[consumer.expertise][mat] ?? 0) + consumer.amount;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- buildingMats.append(span);
|
|
|
|
|
- if (index < mats.length - 1)
|
|
|
|
|
- buildingMats.append(document.createTextNode(' '));
|
|
|
|
|
|
|
+ for (const [mat, amount] of mats) {
|
|
|
|
|
+ buildingMats.append(document.createTextNode(' '));
|
|
|
|
|
+ buildingMats.append(renderProductionBuildingMat(expertise, mat, amount, storage[mat] ?? 0, matConsumers, shipTo));
|
|
|
|
|
|
|
|
const recipe = recipes[mat];
|
|
const recipe = recipes[mat];
|
|
|
const outputPerRun = recipe.outputs.find((o) => o.material_ticker === mat)!.material_amount;
|
|
const outputPerRun = recipe.outputs.find((o) => o.material_ticker === mat)!.material_amount;
|
|
@@ -298,6 +281,28 @@ function renderProduction(expertiseGroups: Record<string, string[]>, production:
|
|
|
return section;
|
|
return section;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+function renderProductionBuildingMat(expertise: string, mat: string, amount: number, inStorage: number,
|
|
|
|
|
+ matConsumers: Record<string, {downstreamMat: string, expertise: string, amount: number}[]>,
|
|
|
|
|
+ shipTo: Record<string, Record<string, number>>): HTMLElement {
|
|
|
|
|
+ const span = element('span', {textContent: `${formatAmount(amount)}x${mat} (${inStorage})`});
|
|
|
|
|
+ const percent = Math.min(inStorage / (amount * 2), 1);
|
|
|
|
|
+ span.style.color = `color-mix(in xyz, #0aa ${percent * 100}%, #f80 )`;
|
|
|
|
|
+ const consumers = matConsumers[mat];
|
|
|
|
|
+ if (consumers) {
|
|
|
|
|
+ span.dataset.tooltip = consumers
|
|
|
|
|
+ .map((c) => `${formatAmount(c.amount)}x${mat} → ${c.downstreamMat} (${c.expertise.toLocaleLowerCase()})`)
|
|
|
|
|
+ .join('\n');
|
|
|
|
|
+ for (const consumer of consumers) {
|
|
|
|
|
+ if (consumer.expertise == expertise) // we aren't shipping it anywhere
|
|
|
|
|
+ continue;
|
|
|
|
|
+ if (!shipTo[consumer.expertise])
|
|
|
|
|
+ shipTo[consumer.expertise] = {};
|
|
|
|
|
+ shipTo[consumer.expertise][mat] = (shipTo[consumer.expertise][mat] ?? 0) + consumer.amount;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return span;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
async function fetchStorage(): Promise<Record<string, number>> {
|
|
async function fetchStorage(): Promise<Record<string, number>> {
|
|
|
if (!apiKey.value)
|
|
if (!apiKey.value)
|
|
|
return {};
|
|
return {};
|