101 lines
2.2 KiB
TypeScript
101 lines
2.2 KiB
TypeScript
import { Chess } from "chess.js";
|
|
|
|
const PGN_KEYS_TO_SHORT = {
|
|
Event: "E",
|
|
Site: "S",
|
|
Round: "N",
|
|
White: "W",
|
|
Black: "B",
|
|
Date: "D",
|
|
Result: "R",
|
|
FEN: "F",
|
|
SetUp: "SU",
|
|
WhiteElo: "WE",
|
|
BlackElo: "BE",
|
|
};
|
|
|
|
const PGN_KEYS = Object.keys(PGN_KEYS_TO_SHORT);
|
|
|
|
const PGN_KEYS_TO_LONG = Object.fromEntries(
|
|
Object.entries(PGN_KEYS_TO_SHORT).map(([long, short]) => [short, long])
|
|
);
|
|
|
|
const cleanPGN = (pgn: string) => {
|
|
const game = new Chess();
|
|
game.load_pgn(pgn);
|
|
game.delete_comments();
|
|
|
|
if (!game.header().Result) {
|
|
const result = (pgn.trim().match(/(1-0)|(0-1)|(1\/2-1\/2)$/) || [])[0];
|
|
|
|
if (result) {
|
|
game.header("Result", result);
|
|
}
|
|
}
|
|
|
|
const headerEntries = Object.entries(game.header());
|
|
|
|
const [_, moves] =
|
|
headerEntries.length > 0
|
|
? game.pgn().split("\n\n")
|
|
: [undefined, game.pgn()];
|
|
|
|
const header = headerEntries
|
|
.filter(([key, val]) => PGN_KEYS.includes(key) && val !== "?")
|
|
.map(([key, val]) => `[${key} "${val}"]`)
|
|
.sort()
|
|
.join("\n");
|
|
|
|
return [header, moves].join("\n\n");
|
|
};
|
|
|
|
const compressPGN = (pgn: string) => {
|
|
const game = new Chess();
|
|
game.load_pgn(pgn);
|
|
|
|
const moves = game.history().join(" ");
|
|
|
|
const header = Object.entries(game.header())
|
|
.filter(([key]) => PGN_KEYS.includes(key))
|
|
.map(
|
|
([key, val]) =>
|
|
`${PGN_KEYS_TO_SHORT[key as keyof typeof PGN_KEYS_TO_SHORT]} ${val}`
|
|
)
|
|
.sort()
|
|
.join("\n");
|
|
|
|
return btoa([header, moves].join("\n\n"));
|
|
};
|
|
|
|
const decompressPGN = (compressedPGN: string) => {
|
|
const [headerRaw, movesRaw] = atob(compressedPGN).split("\n\n");
|
|
|
|
let result;
|
|
|
|
const header = headerRaw
|
|
.split("\n")
|
|
.map((entry) => {
|
|
const [shortKey, ...data] = entry.split(" ");
|
|
const value = data.join(" ");
|
|
|
|
if (shortKey === "R") {
|
|
result = value;
|
|
}
|
|
|
|
return `[${PGN_KEYS_TO_LONG[shortKey]} "${value}"]`;
|
|
})
|
|
.join("\n");
|
|
|
|
const moves =
|
|
movesRaw
|
|
.split(" ")
|
|
.map((move, index) =>
|
|
index % 2 === 0 ? `${index / 2 + 1}. ${move}` : move
|
|
)
|
|
.join(" ") + ` ${result}`;
|
|
|
|
return [header, moves].join("\n\n");
|
|
};
|
|
|
|
export { cleanPGN, compressPGN, decompressPGN };
|