Remove winning party

This commit is contained in:
Andras Schmelczer 2026-04-09 21:58:24 +01:00
parent 8614acdfae
commit a98c54c5b8
12 changed files with 36 additions and 89 deletions

View file

@ -232,14 +232,6 @@ export const ENUM_PALETTE: [number, number, number][] = [
* Any value not listed falls back to ENUM_PALETTE by index.
*/
export const ENUM_COLOR_OVERRIDES: Record<string, Record<string, [number, number, number]>> = {
'Winning party': {
Labour: [220, 36, 31], // Labour red
Conservative: [0, 135, 220], // Conservative blue
'Liberal Democrat': [253, 187, 48], // Lib Dem gold
'Reform UK': [18, 178, 196], // Reform teal
Green: [106, 176, 35], // Green party green
'Other parties': [148, 130, 160], // muted purple
},
'Property type': {
Detached: [249, 115, 22], // orange
'Semi-Detached': [59, 130, 246], // blue

View file

@ -86,6 +86,32 @@ export function formatNumber(value: number | undefined, decimals = 0): string {
return decimals > 0 ? value.toFixed(decimals) : Math.round(value).toLocaleString();
}
/**
* Compute percentages that always sum to exactly 100, using the largest-remainder
* (Hamilton) method. Floors each raw percentage, then distributes the residual to
* the segments with the largest fractional parts. Eliminates rounding drift where
* three 33.3% segments would otherwise display as "33%, 33%, 33% = 99%".
*
* Assumes `total` equals (or closely equals) the sum of `values`.
*/
export function roundedPercentages(values: number[], total: number, decimals = 0): number[] {
if (total <= 0 || values.length === 0) return values.map(() => 0);
const scale = 10 ** decimals;
const targetSum = 100 * scale;
const raw = values.map((v) => (v / total) * 100 * scale);
const floors = raw.map((r) => Math.floor(r));
const result = floors.slice();
let diff = targetSum - floors.reduce((a, b) => a + b, 0);
const order = raw
.map((r, i) => ({ i, frac: r - floors[i] }))
.sort((a, b) => b.frac - a.frac);
for (let k = 0; k < order.length && diff > 0; k++) {
result[order[k].i] += 1;
diff -= 1;
}
return result.map((v) => v / scale);
}
export function formatRelativeTime(isoDate: string): string {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const i18n = require('../i18n').default as {