mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-12 06:12:18 +00:00
102 lines
3.3 KiB
JavaScript
102 lines
3.3 KiB
JavaScript
#!/usr/bin/env node
|
||
/**
|
||
* Build the owner flag sheet the orbital Cockpit marks a satellite's owner
|
||
* country with (`src/ui/ownerFlag.js`): every flag in OWNER_COUNTRY_CODES
|
||
* (`src/layers/satellites/classes.js`), drawn from the flag-icons 4:3 SVGs
|
||
* at twice the readout's 20 × 15 px, in one PNG the app loads at startup.
|
||
*
|
||
* src/data/local_data/owner_flags/owner_flags.png the sheet
|
||
* src/ui/ownerFlagSheet.js its layout (generated)
|
||
*
|
||
* Flag i (in the sorted code list) sits at column i % COLUMNS, row
|
||
* floor(i / COLUMNS), each cell followed by a GUTTER of transparent pixels. A rerun with the same flag-icons and sharp versions
|
||
* reproduces both files.
|
||
*
|
||
* Usage: node scripts/build-owner-flags.mjs
|
||
*/
|
||
|
||
import { readFile, writeFile } from 'node:fs/promises';
|
||
import { createRequire } from 'node:module';
|
||
import path from 'node:path';
|
||
import { fileURLToPath } from 'node:url';
|
||
import * as prettier from 'prettier';
|
||
import sharp from 'sharp';
|
||
import { OWNER_COUNTRY_CODES } from '../src/layers/satellites/classes.js';
|
||
|
||
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
||
const require = createRequire(import.meta.url);
|
||
const FLAGS_DIR = path.join(
|
||
path.dirname(require.resolve('flag-icons/package.json')),
|
||
'flags/4x3',
|
||
);
|
||
const FLAG_ICONS_VERSION = require('flag-icons/package.json').version;
|
||
|
||
/** One flag's cell, CSS pixels × 2. */
|
||
export const CELL = Object.freeze({ width: 40, height: 30 });
|
||
/**
|
||
* Transparent sheet pixels after each flag, so a browser smoothing a scaled
|
||
* flag (a 125% display) never reaches into its neighbour.
|
||
*/
|
||
export const GUTTER = 2;
|
||
export const COLUMNS = 16;
|
||
|
||
const SHEET = path.join(
|
||
ROOT,
|
||
'src/data/local_data/owner_flags/owner_flags.png',
|
||
);
|
||
const LAYOUT = path.join(ROOT, 'src/ui/ownerFlagSheet.js');
|
||
|
||
async function flagCell(code) {
|
||
const svg = await readFile(path.join(FLAGS_DIR, `${code.toLowerCase()}.svg`));
|
||
return sharp(svg, { density: 300 })
|
||
.resize(CELL.width, CELL.height, { fit: 'fill' })
|
||
.png()
|
||
.toBuffer();
|
||
}
|
||
|
||
const codes = [...OWNER_COUNTRY_CODES];
|
||
const rows = Math.ceil(codes.length / COLUMNS);
|
||
const pitchX = CELL.width + GUTTER;
|
||
const pitchY = CELL.height + GUTTER;
|
||
const cells = await Promise.all(codes.map(flagCell));
|
||
const sheet = await sharp({
|
||
create: {
|
||
width: COLUMNS * pitchX,
|
||
height: rows * pitchY,
|
||
channels: 4,
|
||
background: { r: 0, g: 0, b: 0, alpha: 0 },
|
||
},
|
||
})
|
||
.composite(
|
||
cells.map((input, i) => ({
|
||
input,
|
||
left: (i % COLUMNS) * pitchX,
|
||
top: Math.floor(i / COLUMNS) * pitchY,
|
||
})),
|
||
)
|
||
.png({ compressionLevel: 9, palette: true, quality: 100, effort: 10 })
|
||
.toBuffer();
|
||
await writeFile(SHEET, sheet);
|
||
|
||
const layout = `// Generated by scripts/build-owner-flags.mjs from flag-icons ${FLAG_ICONS_VERSION}; do not edit.
|
||
/** The owner flag sheet's layout: flag i at column i % columns, row i / columns. */
|
||
export const OWNER_FLAG_SHEET = Object.freeze({
|
||
cellWidthPx: ${CELL.width},
|
||
cellHeightPx: ${CELL.height},
|
||
gutterPx: ${GUTTER},
|
||
columns: ${COLUMNS},
|
||
rows: ${rows},
|
||
codes: Object.freeze(${JSON.stringify(codes)}),
|
||
});
|
||
`;
|
||
await writeFile(
|
||
LAYOUT,
|
||
await prettier.format(layout, {
|
||
...(await prettier.resolveConfig(LAYOUT)),
|
||
filepath: LAYOUT,
|
||
}),
|
||
);
|
||
console.log(
|
||
`Wrote ${codes.length} flags (${COLUMNS} × ${rows}), ${(sheet.length / 1024).toFixed(1)} KB.`,
|
||
);
|