176 lines
6.0 KiB
JavaScript
176 lines
6.0 KiB
JavaScript
// Server-side economy helpers — mirrors public/src/economy.js
|
||
// Uses raw DB rows instead of a client-side cells Map.
|
||
|
||
// ── Label constants (mirrors public/src/planetEconomy.js) ─────────────────────
|
||
|
||
const resources = {
|
||
common: {
|
||
rock: "Roches communes",
|
||
wood: "Bois communs",
|
||
mineral: "Minérais communs",
|
||
stones: "Gemmes communes",
|
||
liquid: "Eau salée",
|
||
oil: "Fioul brut",
|
||
gas: "Gaz communs",
|
||
grain: "Céréales",
|
||
livestock: "Bétail commun",
|
||
fish: "Poissons commun",
|
||
plant: "Plantes communes",
|
||
goods: "Biens de consommation",
|
||
animals: "Animaux domestiques",
|
||
science: "Sites archéologiques",
|
||
factory: "Usines standards",
|
||
acid: "Acides pauvres",
|
||
},
|
||
rare: {
|
||
rock: "Roches rares",
|
||
wood: "Bois renforcés",
|
||
mineral: "Minérais rares",
|
||
stones: "Gemmes rares",
|
||
liquid: "Eau douce",
|
||
oil: "Fioul raffiné",
|
||
gas: "Gaz nobles",
|
||
grain: "Fruits",
|
||
livestock: "Bétail raffiné",
|
||
fish: "Poissons raffinés",
|
||
plant: "Plantes rares",
|
||
goods: "Biens de luxe",
|
||
animals: "Animaux exotiques",
|
||
science: "Artéfacts anciens",
|
||
factory: "Usines planétaires",
|
||
acid: "Acides riches",
|
||
},
|
||
};
|
||
|
||
const elements = {
|
||
common: "Matières premières",
|
||
petrol: "Hydrocarbures",
|
||
food: "Nourriture",
|
||
medic: "Médicaments",
|
||
science: "Science",
|
||
industry: "Industrie",
|
||
money: "Finance",
|
||
goods: "Biens",
|
||
};
|
||
|
||
// ── Pre-built lookup maps ─────────────────────────────────────────────────────
|
||
|
||
/** French resource label → { cat: "common"|"rare", key: string } */
|
||
const LABEL_TO_RESOURCE = new Map();
|
||
for (const [cat, entries] of Object.entries(resources)) {
|
||
for (const [key, label] of Object.entries(entries)) {
|
||
LABEL_TO_RESOURCE.set(label, { cat, key });
|
||
}
|
||
}
|
||
|
||
/** French element label → config key (e.g. "Matières premières" → "common") */
|
||
const ELEMENT_LABEL_TO_KEY = Object.fromEntries(
|
||
Object.entries(elements).map(([key, label]) => [label, key])
|
||
);
|
||
|
||
// ── Income computation ────────────────────────────────────────────────────────
|
||
|
||
/**
|
||
* Population-based income multiplier (mirrors public/src/economy.js).
|
||
* Base factor = billions / 10, plus an efficiency boost for smaller populations:
|
||
* 0–10 B → ×10, 10–100 B → ×5, 100–1000 B → ×2.5, >1000 B → ×1
|
||
*
|
||
* @param {number} billions
|
||
* @returns {number}
|
||
*/
|
||
function populationFactor(billions) {
|
||
const base = billions / 10;
|
||
let boost;
|
||
if (billions < 10) boost = 10;
|
||
else if (billions < 100) boost = 5;
|
||
else if (billions < 1000) boost = 2.5;
|
||
else boost = 1;
|
||
return base * boost;
|
||
}
|
||
|
||
/**
|
||
* Compute total income per second for a team from DB grid rows.
|
||
*
|
||
* @param {string} team - "blue" or "red"
|
||
* @param {Array<{ has_planet: boolean, planet_json: object|null, discovered_by: string }>} rows
|
||
* @param {{ common: object, rare: object }} resourceWorth
|
||
* @returns {number} credits per second
|
||
*/
|
||
export function computeTeamIncome(team, rows, resourceWorth) {
|
||
let total = 0;
|
||
for (const row of rows) {
|
||
if (row.discovered_by !== team) continue;
|
||
if (!row.has_planet || !row.planet_json) continue;
|
||
const { naturalResources, population } = row.planet_json;
|
||
if (!naturalResources) continue;
|
||
const popFactor = population ? populationFactor(population.billions) : 1;
|
||
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;
|
||
total += (pct / 100) * worth * popFactor;
|
||
}
|
||
}
|
||
return total;
|
||
}
|
||
|
||
// ── Element bonus computation ─────────────────────────────────────────────────
|
||
|
||
/**
|
||
* Compute cumulative element bonus (%) for a team from DB grid rows.
|
||
*
|
||
* @param {string} team - "blue" or "red"
|
||
* @param {Array<{ has_planet: boolean, planet_json: object|null, discovered_by: string }>} rows
|
||
* @param {object} elementWorth - { common: 1, petrol: 3, ... }
|
||
* @returns {number} bonus in percent
|
||
*/
|
||
export function computeTeamElementBonus(team, rows, elementWorth) {
|
||
let bonus = 0;
|
||
for (const row of rows) {
|
||
if (row.discovered_by !== team) continue;
|
||
if (!row.has_planet || !row.planet_json) continue;
|
||
const { production } = row.planet_json;
|
||
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;
|
||
bonus += (pct / 100) * worth;
|
||
}
|
||
}
|
||
return bonus;
|
||
}
|
||
|
||
// ── Military power computation ────────────────────────────────────────────────
|
||
|
||
const POP_LABEL_TO_KEY = new Map([
|
||
["Humains", "humans"],
|
||
["Presque'humains", "near"],
|
||
["Aliens", "aliens"],
|
||
]);
|
||
|
||
/**
|
||
* Compute total military power (in billions) for a team from DB grid rows.
|
||
*
|
||
* @param {string} team - "blue" or "red"
|
||
* @param {Array<{ has_planet: boolean, planet_json: object|null, discovered_by: string }>} rows
|
||
* @param {object} militaryPower - { humans: 10, near: 5, aliens: 1 }
|
||
* @returns {number} military power in billions
|
||
*/
|
||
export function computeTeamMilitaryPower(team, rows, militaryPower) {
|
||
let total = 0;
|
||
for (const row of rows) {
|
||
if (row.discovered_by !== team) continue;
|
||
if (!row.has_planet || !row.planet_json) continue;
|
||
const pop = row.planet_json.population;
|
||
if (!pop) continue;
|
||
const key = POP_LABEL_TO_KEY.get(pop.majority);
|
||
if (!key) continue;
|
||
const pct = militaryPower?.[key] ?? 0;
|
||
if (pct === 0) continue;
|
||
total += pop.billions * pct / 100;
|
||
}
|
||
return total;
|
||
}
|