Files
star-wars-wild-space/server/helpers/economy.js
T
2026-04-02 15:51:59 +02:00

176 lines
6.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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:
* 010 B → ×10, 10100 B → ×5, 1001000 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;
}