165 lines
6.4 KiB
JavaScript
165 lines
6.4 KiB
JavaScript
import { resources, elements } from "./planetEconomy.js";
|
|
|
|
// ── Sort state ────────────────────────────────────────────────────────────────
|
|
|
|
/** 0=Ressource, 1=Rareté, 2=Valeur, 3=Revenu/s */
|
|
let _sortCol = 3;
|
|
let _sortDir = "desc";
|
|
|
|
export function setEconSort(col, dir) {
|
|
_sortCol = col;
|
|
_sortDir = dir;
|
|
}
|
|
|
|
export function getEconSort() {
|
|
return { col: _sortCol, dir: _sortDir };
|
|
}
|
|
|
|
// ── Label → resource key lookup ───────────────────────────────────────────────
|
|
|
|
/** Map from French label string → { cat: "common"|"rare", key: string } */
|
|
const LABEL_TO_RESOURCE = (() => {
|
|
const map = new Map();
|
|
for (const [cat, entries] of Object.entries(resources)) {
|
|
for (const [key, label] of Object.entries(entries)) {
|
|
map.set(label, { cat, key });
|
|
}
|
|
}
|
|
return map;
|
|
})();
|
|
|
|
// ── Income calculation ────────────────────────────────────────────────────────
|
|
|
|
/**
|
|
* Compute income per second for a team based on their discovered planets.
|
|
*
|
|
* @param {string} team - "blue" or "red"
|
|
* @param {Map<string, { discoveredBy: string, hasPlanet: boolean, planet: object|null }>} cells
|
|
* @param {object} resourceWorth - { common: { rock: 1, ... }, rare: { rock: 3, ... } }
|
|
* @returns {{ total: number, byResource: Map<string, number> }}
|
|
* byResource keys are resource label strings (French names), values are credits/sec
|
|
*/
|
|
export function computeTeamIncome(team, cells, resourceWorth) {
|
|
/** @type {Map<string, number>} label → cumulative income/sec */
|
|
const byResource = new Map();
|
|
let total = 0;
|
|
|
|
for (const [, meta] of cells) {
|
|
if (meta.discoveredBy !== team) continue;
|
|
if (!meta.hasPlanet || !meta.planet) continue;
|
|
const { naturalResources } = meta.planet;
|
|
if (!naturalResources) continue;
|
|
|
|
for (const [label, pct] of Object.entries(naturalResources)) {
|
|
const info = LABEL_TO_RESOURCE.get(label);
|
|
if (!info) continue;
|
|
const worth = resourceWorth?.[info.cat]?.[info.key] ?? 0;
|
|
if (worth === 0) continue;
|
|
const income = (pct / 100) * worth;
|
|
byResource.set(label, (byResource.get(label) ?? 0) + income);
|
|
total += income;
|
|
}
|
|
}
|
|
|
|
return { total, byResource };
|
|
}
|
|
|
|
// ── Element bonus calculation ─────────────────────────────────────────────────
|
|
|
|
/**
|
|
* Reverse map: French element label → config key
|
|
* e.g. "Matières premières" → "common", "Hydrocarbures" → "petrol"
|
|
*/
|
|
const ELEMENT_LABEL_TO_KEY = Object.fromEntries(
|
|
Object.entries(elements).map(([key, label]) => [label, key])
|
|
);
|
|
|
|
/**
|
|
* Compute cumulative element bonus for a team based on their planets' production.
|
|
* planet.production stores French label strings as keys (values from elements const).
|
|
* bonus = sum_over_planets( sum_over_elements( elementShare% / 100 * elementWorth[key] ) )
|
|
*
|
|
* @param {string} team
|
|
* @param {Map<string, { discoveredBy: string, hasPlanet: boolean, planet: object|null }>} cells
|
|
* @param {object} elementWorth - { common: 1, petrol: 3, ... }
|
|
* @returns {number} bonus value (use as %)
|
|
*/
|
|
export function computeTeamElementBonus(team, cells, elementWorth) {
|
|
let bonus = 0;
|
|
for (const [, meta] of cells) {
|
|
if (meta.discoveredBy !== team) continue;
|
|
if (!meta.hasPlanet || !meta.planet) continue;
|
|
const { production } = meta.planet;
|
|
if (!production) continue;
|
|
for (const [elementLabel, pct] of Object.entries(production)) {
|
|
// production keys are French labels; map back to config key
|
|
const elementKey = ELEMENT_LABEL_TO_KEY[elementLabel] ?? elementLabel;
|
|
const worth = elementWorth?.[elementKey] ?? 0;
|
|
if (worth === 0) continue;
|
|
bonus += (pct / 100) * worth;
|
|
}
|
|
}
|
|
return bonus;
|
|
}
|
|
|
|
export { elements };
|
|
|
|
// ── Resource table for the sidebar ───────────────────────────────────────────
|
|
|
|
/**
|
|
* Renders the resource overview table for the economy panel.
|
|
*
|
|
* @param {object} resourceWorth - { common: {…}, rare: {…} }
|
|
* @param {Map<string, number>} teamByResource - income/sec per label for current team
|
|
* @returns {string} HTML string
|
|
*/
|
|
export function renderResourceTable(resourceWorth, teamByResource) {
|
|
const rows = [];
|
|
|
|
for (const [cat, entries] of Object.entries(resources)) {
|
|
for (const [key, label] of Object.entries(entries)) {
|
|
const worth = resourceWorth?.[cat]?.[key] ?? 0;
|
|
const income = teamByResource?.get(label) ?? 0;
|
|
const incomeStr = income > 0 ? `+${income.toFixed(3)}/s` : "—";
|
|
const catLabel = cat === "rare" ? "Rare" : "Commun";
|
|
rows.push({ label, catLabel, worth, income, incomeStr });
|
|
}
|
|
}
|
|
|
|
// Sort by selected column
|
|
const mult = _sortDir === "asc" ? 1 : -1;
|
|
rows.sort((a, b) => {
|
|
if (_sortCol === 0) return mult * a.label.localeCompare(b.label, "fr");
|
|
if (_sortCol === 1) return mult * a.catLabel.localeCompare(b.catLabel, "fr");
|
|
if (_sortCol === 2) return mult * (a.worth - b.worth);
|
|
if (_sortCol === 3) return mult * (a.income - b.income);
|
|
return b.income - a.income || b.worth - a.worth;
|
|
});
|
|
|
|
const tableRows = rows
|
|
.map(({ label, catLabel, worth, incomeStr, income }) => {
|
|
const incomeClass = income > 0 ? " econ-income--positive" : "";
|
|
return `<tr>
|
|
<td class="econ-label">${label}</td>
|
|
<td class="econ-cat econ-cat--${catLabel.toLowerCase()}">${catLabel}</td>
|
|
<td class="econ-worth">${worth}</td>
|
|
<td class="econ-income${incomeClass}">${incomeStr}</td>
|
|
</tr>`;
|
|
})
|
|
.join("");
|
|
|
|
const thLabels = ["Ressource", "Rareté", "Valeur", "Revenu/s"];
|
|
const headers = thLabels
|
|
.map((lbl, i) => {
|
|
const isActive = i === _sortCol;
|
|
const indicator = isActive ? (_sortDir === "asc" ? " ▲" : " ▼") : " ⇅";
|
|
const activeClass = isActive ? " econTh--active" : "";
|
|
return `<th class="econTh${activeClass}" data-sort-col="${i}">${lbl}<span class="econSortIcon">${indicator}</span></th>`;
|
|
})
|
|
.join("");
|
|
|
|
return `<table class="econTable">
|
|
<thead><tr>${headers}</tr></thead>
|
|
<tbody>${tableRows}</tbody>
|
|
</table>`;
|
|
} |