Files
Battle-for-Tismo/client/js/map_view/economic.js
T
adrien ede258d39f Added warfare depth, focused research and a reworked HUD
- Tile improvements (fortifications, radar towers, coastal cannons), trenches,
  zone of control, support-unit capture and launch transports, with parabolic
  barrage arcs drawn between attacker and target.
- Focused research that pours points straight into the chosen technology, with
  per-technology progress kept when the focus changes, plus repeatable levels.
- Popularity reworked to integer points, war and pillage effects, minority
  policies and month-over-month arrows on the nation summary.
- City progress bars, square improvement buttons, a technology tab of wide
  short cards with progress bars, transport cargo readout and double-click to
  open a city panel.
2026-09-21 01:07:36 +02:00

78 lines
2.5 KiB
JavaScript

// The economic map modes: a colour scale that turns a per-tile figure (GDP per
// capita or raw population) into a hex colour, plus the catalogue describing
// each mode.
//
// The gradient runs from yellow (poorest / smallest) to blue (richest /
// largest). Those two hues are the pair most colour-blind players can still
// tell apart, and the stops are the reversed cividis palette, which keeps a
// monotonic lightness across the whole ramp so the magnitude also reads without
// colour vision.
import { parseColour } from "./utils.js";
import { groupDigits } from "../../../shared/text_format.js";
export const ECONOMIC_GRADIENT = [
"#ffea46",
"#e4cf5b",
"#c4b56c",
"#a69d75",
"#8a8779",
"#707173",
"#575d6c",
"#39486b",
"#00306f",
"#00204d",
];
// A population map is dominated by a handful of huge cities, which would
// otherwise crush every smaller settlement to the bottom of the scale, so it is
// read logarithmically; GDP per capita stays linear.
export const ECONOMIC_MODES = {
gdp: {
id: "gdp",
label: "GDP per capita",
format: (value) => `€${groupDigits(Math.round(value))}`,
},
population: {
id: "population",
label: "Population",
format: (value) => groupDigits(Math.round(value)),
scale: (value) => Math.log1p(Math.max(0, value)),
},
};
export function isEconomicMode(mode) {
return mode === "gdp" || mode === "population";
}
// Where a value sits on the scale, clamped to 0..1. A flat range (every tile
// the same) sits in the middle so the map reads as a single mid colour. An
// optional `scale` maps the values first (the population mode reads its log).
export function economicFraction(value, min, max, scale = null) {
if (scale) {
value = scale(value);
min = scale(min);
max = scale(max);
}
if (!(max > min)) return 0.5;
const t = (value - min) / (max - min);
return Math.max(0, Math.min(1, t));
}
// The colour for a value, as a "#rrggbb" string, interpolated between the two
// gradient stops that bracket it.
export function economicColour(value, min, max, stops = ECONOMIC_GRADIENT, scale = null) {
const t = economicFraction(value, min, max, scale);
const scaled = t * (stops.length - 1);
const index = Math.min(stops.length - 2, Math.floor(scaled));
const blend = scaled - index;
const a = parseColour(stops[index]);
const b = parseColour(stops[index + 1]);
const channel = (i) => Math.round(a[i] + (b[i] - a[i]) * blend);
return `#${toHex(channel(0))}${toHex(channel(1))}${toHex(channel(2))}`;
}
function toHex(value) {
return value.toString(16).padStart(2, "0");
}