fix: Making the scoreBoard clearer
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { resources, elements } from "./planetEconomy.js";
|
||||
|
||||
// ── Sort state ────────────────────────────────────────────────────────────────
|
||||
// ── Sort state (resources) ────────────────────────────────────────────────────
|
||||
|
||||
/** 0=Ressource, 1=Rareté, 2=Valeur, 3=Revenu/s */
|
||||
let _sortCol = 3;
|
||||
@@ -15,6 +15,21 @@ export function getEconSort() {
|
||||
return { col: _sortCol, dir: _sortDir };
|
||||
}
|
||||
|
||||
// ── Sort state (elements) ─────────────────────────────────────────────────────
|
||||
|
||||
/** 0=Élément, 1=Valeur/élément, 2=Bonus % */
|
||||
let _elemSortCol = 2;
|
||||
let _elemSortDir = "desc";
|
||||
|
||||
export function setElemSort(col, dir) {
|
||||
_elemSortCol = col;
|
||||
_elemSortDir = dir;
|
||||
}
|
||||
|
||||
export function getElemSort() {
|
||||
return { col: _elemSortCol, dir: _elemSortDir };
|
||||
}
|
||||
|
||||
// ── Label → resource key lookup ───────────────────────────────────────────────
|
||||
|
||||
/** Map from French label string → { cat: "common"|"rare", key: string } */
|
||||
@@ -102,6 +117,35 @@ export function computeTeamElementBonus(team, cells, elementWorth) {
|
||||
return bonus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute per-element bonus breakdown for a team.
|
||||
*
|
||||
* @param {string} team
|
||||
* @param {Map<string, { discoveredBy: string, hasPlanet: boolean, planet: object|null }>} cells
|
||||
* @param {object} elementWorth - { common: 1, petrol: 3, ... }
|
||||
* @returns {{ total: number, byElement: Map<string, number> }}
|
||||
* byElement keys are French element label strings, values are cumulative bonus %
|
||||
*/
|
||||
export function computeTeamElementBonusDetailed(team, cells, elementWorth) {
|
||||
const byElement = new Map();
|
||||
let total = 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)) {
|
||||
const elementKey = ELEMENT_LABEL_TO_KEY[elementLabel] ?? elementLabel;
|
||||
const worth = elementWorth?.[elementKey] ?? 0;
|
||||
if (worth === 0) continue;
|
||||
const bonus = (pct / 100) * worth;
|
||||
byElement.set(elementLabel, (byElement.get(elementLabel) ?? 0) + bonus);
|
||||
total += bonus;
|
||||
}
|
||||
}
|
||||
return { total, byElement };
|
||||
}
|
||||
|
||||
export { elements };
|
||||
|
||||
// ── Resource table for the sidebar ───────────────────────────────────────────
|
||||
@@ -158,6 +202,64 @@ export function renderResourceTable(resourceWorth, teamByResource) {
|
||||
})
|
||||
.join("");
|
||||
|
||||
return `<table class="econTable">
|
||||
<thead><tr>${headers}</tr></thead>
|
||||
<tbody>${tableRows}</tbody>
|
||||
</table>`;
|
||||
}
|
||||
|
||||
// ── Element bonus table for the sidebar ──────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Renders the element bonus breakdown table.
|
||||
*
|
||||
* @param {object} elementWorth - { common: 1, petrol: 3, ... }
|
||||
* @param {Map<string, number>} teamByElement - bonus per element label for current team
|
||||
* @returns {string} HTML string
|
||||
*/
|
||||
export function renderElementBonusTable(elementWorth, teamByElement) {
|
||||
const rows = [];
|
||||
|
||||
for (const [key, label] of Object.entries(elements)) {
|
||||
const worth = elementWorth?.[key] ?? 0;
|
||||
const bonus = teamByElement?.get(label) ?? 0;
|
||||
const bonusStr = bonus > 0 ? `+${bonus.toFixed(3)}%` : "—";
|
||||
rows.push({ label, worth, bonus, bonusStr });
|
||||
}
|
||||
|
||||
const mult = _elemSortDir === "asc" ? 1 : -1;
|
||||
rows.sort((a, b) => {
|
||||
if (_elemSortCol === 0) return mult * a.label.localeCompare(b.label, "fr");
|
||||
if (_elemSortCol === 1) return mult * (a.worth - b.worth);
|
||||
if (_elemSortCol === 2) return mult * (a.bonus - b.bonus);
|
||||
return b.bonus - a.bonus || b.worth - a.worth;
|
||||
});
|
||||
|
||||
if (rows.every(r => r.bonus === 0)) {
|
||||
return `<p class="econEmpty">Aucune tuile conquise avec des éléments de production.</p>`;
|
||||
}
|
||||
|
||||
const tableRows = rows
|
||||
.map(({ label, worth, bonus, bonusStr }) => {
|
||||
const bonusClass = bonus > 0 ? " econ-income--positive" : "";
|
||||
return `<tr>
|
||||
<td class="econ-label">${label}</td>
|
||||
<td class="econ-worth">${worth}</td>
|
||||
<td class="econ-income${bonusClass}">${bonusStr}</td>
|
||||
</tr>`;
|
||||
})
|
||||
.join("");
|
||||
|
||||
const thLabels = ["Élément", "Val./élément", "Bonus %"];
|
||||
const headers = thLabels
|
||||
.map((lbl, i) => {
|
||||
const isActive = i === _elemSortCol;
|
||||
const indicator = isActive ? (_elemSortDir === "asc" ? " ▲" : " ▼") : " ⇅";
|
||||
const activeClass = isActive ? " econTh--active" : "";
|
||||
return `<th class="econTh${activeClass}" data-elem-sort-col="${i}">${lbl}<span class="econSortIcon">${indicator}</span></th>`;
|
||||
})
|
||||
.join("");
|
||||
|
||||
return `<table class="econTable">
|
||||
<thead><tr>${headers}</tr></thead>
|
||||
<tbody>${tableRows}</tbody>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { fnv1a32, hash2u32, mulberry32 } from "./rng.js";
|
||||
import { formatPlanet, generatePlanet } from "./planetGeneration.js";
|
||||
import { apiFetchConfig, apiFetchScores, apiFetchGrid, apiRevealCell, apiFetchEconScores, apiTickEconScores, apiFetchElementBonus, apiTickElementBonus, apiFetchDbInfo, apiFetchVictoryPoints } from "./api.js";
|
||||
import { computeTeamIncome, computeTeamElementBonus, renderResourceTable, setEconSort, getEconSort } from "./economy.js";
|
||||
import { computeTeamIncome, computeTeamElementBonus, computeTeamElementBonusDetailed, renderResourceTable, renderElementBonusTable, setEconSort, getEconSort, setElemSort, getElemSort } from "./economy.js";
|
||||
|
||||
// ── Constants ─────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -163,6 +163,7 @@ const econScoreBlueEl = document.getElementById("econScoreBlue");
|
||||
const econScoreRedEl = document.getElementById("econScoreRed");
|
||||
const econDeltaBlueEl = document.getElementById("econDeltaBlue");
|
||||
const econDeltaRedEl = document.getElementById("econDeltaRed");
|
||||
const elemBonusTableEl = document.getElementById("elementBonusTableBody");
|
||||
const teamCorner = document.getElementById("teamCorner");
|
||||
const teamTrack = document.getElementById("teamSegmentedTrack");
|
||||
const teamBlueBtn = document.getElementById("teamBlue");
|
||||
@@ -333,6 +334,14 @@ export function updateEconomyDisplay() {
|
||||
if (resourceTableEl) {
|
||||
resourceTableEl.innerHTML = renderResourceTable(worth, teamIncome.byResource);
|
||||
}
|
||||
|
||||
const elemWorth = GAME_CONFIG.elementWorth;
|
||||
const teamElemBonus = currentTeam === "blue"
|
||||
? computeTeamElementBonusDetailed("blue", cells, elemWorth)
|
||||
: computeTeamElementBonusDetailed("red", cells, elemWorth);
|
||||
if (elemBonusTableEl) {
|
||||
elemBonusTableEl.innerHTML = renderElementBonusTable(elemWorth, teamElemBonus.byElement);
|
||||
}
|
||||
}
|
||||
|
||||
// ── Economic score ────────────────────────────────────────────────────────────
|
||||
@@ -718,6 +727,18 @@ resourceTableEl?.addEventListener("click", (ev) => {
|
||||
updateEconomyDisplay();
|
||||
});
|
||||
|
||||
elemBonusTableEl?.addEventListener("click", (ev) => {
|
||||
const th = ev.target.closest("th[data-elem-sort-col]");
|
||||
if (!th) return;
|
||||
const col = Number(th.dataset.elemSortCol);
|
||||
const { col: curCol, dir: curDir } = getElemSort();
|
||||
const newDir = col === curCol
|
||||
? (curDir === "asc" ? "desc" : "asc")
|
||||
: (col === 0 ? "asc" : "desc");
|
||||
setElemSort(col, newDir);
|
||||
updateEconomyDisplay();
|
||||
});
|
||||
|
||||
canvas.addEventListener("mousemove", (ev) => { lastPointerEvent = ev; refreshCursor(ev); });
|
||||
canvas.addEventListener("mouseleave", () => { lastPointerEvent = null; canvas.style.cursor = "default"; });
|
||||
canvas.addEventListener("click", onCanvasClick);
|
||||
|
||||
Reference in New Issue
Block a user