sendou.ink/app/modules/map-pool-serializer/serializer.ts
2022-08-18 17:51:14 +03:00

86 lines
1.8 KiB
TypeScript

import invariant from "tiny-invariant";
import {
modesShort,
type Stage,
stages as allStages,
stages,
} from "../in-game-lists";
import type { MapPool } from "./types";
export function mapPoolToSerializedString(mapPool: MapPool): string {
const serializedModes = [];
for (const mode of modesShort) {
const stages = mapPool[mode];
if (stages.length === 0) continue;
serializedModes.push(`${mode}:${binaryToHex(stagesToBinary(stages))}`);
}
return serializedModes.join(";").toLowerCase();
}
function stagesToBinary(input: Stage[]) {
let result = "1";
for (const stage of allStages) {
if (input.includes(stage)) {
result += "1";
} else {
result += "0";
}
}
return result;
}
function binaryToHex(binary: string) {
return parseInt(binary, 2).toString(16);
}
export function serializedStringToMapPool(serialized: string) {
const result: MapPool = {
SZ: [],
CB: [],
RM: [],
TC: [],
TW: [],
};
for (const serializedMode of serialized.split(";")) {
const [mode, mapsInHex] = serializedMode.split(":");
if (!mode || !mapsInHex) continue;
const validatedMode = modesShort.find(
(realMode) => realMode === mode.toUpperCase()
);
if (!validatedMode) continue;
const stagesBinary = hexToBinary(mapsInHex);
result[validatedMode].push(...binaryToStages(stagesBinary));
}
return result;
}
function binaryToStages(binary: string): Stage[] {
const result: Stage[] = [];
// first 1 is padding
for (let i = 1; i <= stages.length; i++) {
const letter = binary[i];
if (letter === "0" || !letter) continue;
const stage = stages[i - 1];
invariant(stage);
result.push(stage);
}
return result;
}
function hexToBinary(hex: string) {
return parseInt(hex, 16).toString(2);
}