2025-03-06 16:46:25 +01:00
|
|
|
import { Level, Palette, RawLevel, Upgrade } from "./types";
|
2025-03-06 14:06:02 +01:00
|
|
|
import _palette from "./palette.json";
|
|
|
|
import _rawLevelsList from "./levels.json";
|
|
|
|
import _appVersion from "./version.json";
|
2025-03-06 16:46:25 +01:00
|
|
|
import { rawUpgrades } from "./rawUpgrades";
|
2025-03-12 15:15:02 +01:00
|
|
|
import _backgrounds from "./backgrounds.json";
|
|
|
|
const backgrounds = _backgrounds as string[]
|
2025-03-06 14:06:02 +01:00
|
|
|
const palette = _palette as Palette;
|
|
|
|
|
2025-03-06 16:46:25 +01:00
|
|
|
const rawLevelsList = _rawLevelsList as RawLevel[];
|
2025-03-06 14:06:02 +01:00
|
|
|
|
|
|
|
export const appVersion = _appVersion as string;
|
|
|
|
|
2025-03-06 16:46:25 +01:00
|
|
|
let attributed = 0;
|
|
|
|
|
|
|
|
let levelIconHTMLCanvas = document.createElement("canvas");
|
2025-03-06 14:06:02 +01:00
|
|
|
const levelIconHTMLCanvasCtx = levelIconHTMLCanvas.getContext("2d", {
|
2025-03-06 16:46:25 +01:00
|
|
|
antialias: false,
|
|
|
|
alpha: true,
|
2025-03-06 14:06:02 +01:00
|
|
|
}) as CanvasRenderingContext2D;
|
|
|
|
|
2025-03-06 16:46:25 +01:00
|
|
|
function levelIconHTML(
|
|
|
|
bricks: string[],
|
|
|
|
levelSize: number,
|
|
|
|
levelName: string,
|
|
|
|
color: string,
|
|
|
|
) {
|
|
|
|
const size = 40;
|
|
|
|
const c = levelIconHTMLCanvas;
|
|
|
|
const ctx = levelIconHTMLCanvasCtx;
|
|
|
|
c.width = size;
|
|
|
|
c.height = size;
|
|
|
|
|
|
|
|
if (color) {
|
|
|
|
ctx.fillStyle = color;
|
|
|
|
ctx.fillRect(0, 0, size, size);
|
|
|
|
} else {
|
|
|
|
ctx.clearRect(0, 0, size, size);
|
|
|
|
}
|
|
|
|
const pxSize = size / levelSize;
|
|
|
|
for (let x = 0; x < levelSize; x++) {
|
|
|
|
for (let y = 0; y < levelSize; y++) {
|
|
|
|
const c = bricks[y * levelSize + x];
|
|
|
|
if (c) {
|
|
|
|
ctx.fillStyle = c;
|
|
|
|
ctx.fillRect(
|
|
|
|
Math.floor(pxSize * x),
|
|
|
|
Math.floor(pxSize * y),
|
|
|
|
Math.ceil(pxSize),
|
|
|
|
Math.ceil(pxSize),
|
|
|
|
);
|
|
|
|
}
|
2025-03-06 14:06:02 +01:00
|
|
|
}
|
2025-03-06 16:46:25 +01:00
|
|
|
}
|
|
|
|
// I don't think many blind people will benefit for this but it's nice to have something to put in "alt"
|
|
|
|
return `<img alt="${levelName}" width="${size}" height="${size}" src="${c.toDataURL()}"/>`;
|
2025-03-06 14:06:02 +01:00
|
|
|
}
|
|
|
|
|
2025-03-11 13:56:42 +01:00
|
|
|
export const icons = {} as { [k: string]: string };
|
2025-03-06 14:06:02 +01:00
|
|
|
|
2025-03-06 16:46:25 +01:00
|
|
|
export const allLevels = rawLevelsList
|
|
|
|
.map((level) => {
|
2025-03-11 13:56:42 +01:00
|
|
|
const bricks = level.bricks
|
|
|
|
.split("")
|
|
|
|
.map((c) => palette[c])
|
|
|
|
.slice(0, level.size * level.size);
|
2025-03-06 16:46:25 +01:00
|
|
|
const icon = levelIconHTML(bricks, level.size, level.name, level.color);
|
|
|
|
icons[level.name] = icon;
|
2025-03-12 15:15:02 +01:00
|
|
|
let svg = level.svg!==null && backgrounds[level.svg]
|
|
|
|
|
2025-03-06 14:06:02 +01:00
|
|
|
if (!level.color && !svg) {
|
2025-03-12 15:15:02 +01:00
|
|
|
svg = backgrounds[attributed % backgrounds.length];
|
2025-03-06 16:46:25 +01:00
|
|
|
attributed++;
|
2025-03-06 14:06:02 +01:00
|
|
|
}
|
|
|
|
return {
|
2025-03-06 16:46:25 +01:00
|
|
|
...level,
|
|
|
|
bricks,
|
|
|
|
icon,
|
|
|
|
svg,
|
|
|
|
};
|
|
|
|
})
|
2025-03-10 15:05:48 +01:00
|
|
|
.filter((l) => !l.name.startsWith("icon:"))
|
2025-03-11 13:56:42 +01:00
|
|
|
.map((l, li) => ({
|
|
|
|
...l,
|
|
|
|
threshold:
|
|
|
|
li < 8
|
|
|
|
? 0
|
|
|
|
: Math.round(
|
|
|
|
Math.min(Math.pow(10, 1 + (li + l.size) / 30) * 10, 5000) * li,
|
|
|
|
),
|
|
|
|
sortKey: ((Math.random() + 3) / 3.5) * l.bricks.filter((i) => i).length,
|
|
|
|
})) as Level[];
|
2025-03-06 16:46:25 +01:00
|
|
|
|
|
|
|
export const upgrades = rawUpgrades.map((u) => ({
|
|
|
|
...u,
|
|
|
|
icon: icons["icon:" + u.id],
|
|
|
|
})) as Upgrade[];
|