From 7052c74171bc8a9e8741315d55863be4609071bc Mon Sep 17 00:00:00 2001 From: Maciej Caderek Date: Sun, 16 Jan 2022 05:20:19 +0100 Subject: [PATCH] WIP --- src/board/layers/drawPieces.ts | 8 ++-- src/board/styles-board/index.ts | 2 + src/board/styles-board/lichess.ts | 42 ++++++++++++++++ src/game/Game.ts | 28 +---------- src/game/PGNHelpers.ts | 79 +++++++++++++++++++++++++++++++ src/main.ts | 30 +++++++----- src/test-data/pgns.ts | 19 ++++++++ 7 files changed, 168 insertions(+), 40 deletions(-) create mode 100644 src/board/styles-board/lichess.ts create mode 100644 src/game/PGNHelpers.ts diff --git a/src/board/layers/drawPieces.ts b/src/board/layers/drawPieces.ts index 6c08e24..f09f04d 100644 --- a/src/board/layers/drawPieces.ts +++ b/src/board/layers/drawPieces.ts @@ -19,7 +19,7 @@ const drawPieces = async ( type: PieceType; color: PieceColor; }; - const img = await ImagesCache.get("tatiana", type, color); + const img = await ImagesCache.get("cburnett", type, color); const rank = flipped ? tiles - 1 - y : y; const file = flipped ? tiles - 1 - x : x; @@ -34,9 +34,11 @@ const drawPieces = async ( } if (color === check && type === "k") { - filters.push(`drop-shadow(0 0 ${squareSize * 0.1}px orange)`); + filters.push(`drop-shadow(0 0 ${squareSize * 0.07}px #ffa600)`); + filters.push(`drop-shadow(0 0 ${squareSize * 0.07}px #ffa600)`); } else if (color === mate && type === "k") { - filters.push(`drop-shadow(0 0 ${squareSize * 0.1}px red)`); + filters.push(`drop-shadow(0 0 ${squareSize * 0.07}px #ff002f)`); + filters.push(`drop-shadow(0 0 ${squareSize * 0.07}px #ff002f)`); } ctx.filter = filters.length > 0 ? filters.join(" ") : "none"; diff --git a/src/board/styles-board/index.ts b/src/board/styles-board/index.ts index 58d7656..166c649 100644 --- a/src/board/styles-board/index.ts +++ b/src/board/styles-board/index.ts @@ -3,6 +3,7 @@ import calm from "./calm"; import standard from "./standard"; import glass from "./glass"; // import kittens from "./kittens"; +import lichess from "./lichess"; import lila from "./lila"; import mono from "./mono"; import peach from "./peach"; @@ -12,6 +13,7 @@ export default { calm, glass, // kittens, + lichess, lila, mono, peach, diff --git a/src/board/styles-board/lichess.ts b/src/board/styles-board/lichess.ts new file mode 100644 index 0000000..af617cc --- /dev/null +++ b/src/board/styles-board/lichess.ts @@ -0,0 +1,42 @@ +import { Style } from "../../types"; + +const style: Style = { + name: "Lichess", + background: { + type: "solid", + data: { + color: "transparent", + }, + }, + dark: { + type: "solid", + data: { + color: "#b58863", + }, + }, + light: { + type: "solid", + data: { + color: "#f0d9b5", + }, + }, + moveIndicator: { + type: "solid", + data: { + color: "rgba(155,199,0,0.41)", + }, + }, + border: null, + // border: { + // type: "solid", + // data: { + // color: "#896d56", + // }, + // }, + coords: { + lightColor: "#f0d9b5", + darkColor: "#b58863", + }, +}; + +export default style; diff --git a/src/game/Game.ts b/src/game/Game.ts index 8dc2dd6..31d8969 100644 --- a/src/game/Game.ts +++ b/src/game/Game.ts @@ -1,4 +1,5 @@ import { Chess, ChessInstance, Move } from "chess.js"; +import { cleanPGN } from "./PGNHelpers"; class Game { private game: ChessInstance; @@ -12,33 +13,8 @@ class Game { this.moves = []; } - private cleanPGN(pgn: string) { - const game = new Chess(); - game.load_pgn(pgn); - game.delete_comments(); - const [_, moves] = game.pgn().split("\n\n"); - - const header = Object.entries(game.header()) - .filter(([key]) => - [ - "event", - "site", - "white", - "black", - "date", - "result", - "opening", - ].includes(key.toLowerCase()) - ) - .map(([key, val]) => `[${key} "${val}"]`) - .sort() - .join("\n"); - - return [header, moves].join("\n\n"); - } - loadPGN(pgn: string) { - this.game.load_pgn(this.cleanPGN(pgn)); + this.game.load_pgn(cleanPGN(pgn)); this.game.delete_comments(); this.moves = this.game.history({ verbose: true }); this.currentPly = 0; diff --git a/src/game/PGNHelpers.ts b/src/game/PGNHelpers.ts new file mode 100644 index 0000000..9283b29 --- /dev/null +++ b/src/game/PGNHelpers.ts @@ -0,0 +1,79 @@ +import { Chess } from "chess.js"; + +const PGN_KEYS_TO_SHORT = { + Event: "E", + Site: "S", + White: "W", + Black: "B", + Date: "D", + Result: "R", + FEN: "F", +}; + +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(); + const [_, moves] = game.pgn().split("\n\n"); + + const header = Object.entries(game.header()) + .filter(([key]) => PGN_KEYS.includes(key)) + .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]) => `${key[0].toUpperCase()} ${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 }; diff --git a/src/main.ts b/src/main.ts index eaf29ea..aa2eaa0 100644 --- a/src/main.ts +++ b/src/main.ts @@ -5,18 +5,22 @@ import styles from "./board/styles-board"; import Game from "./game/Game"; import pgns from "./test-data/pgns"; import createSimpleGIF from "./gif/createSimpleGIF"; +import { compressPGN, decompressPGN } from "./game/PGNHelpers"; const $app = document.querySelector("#app"); const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); -const play = async (board: Board, pgn: string, interval: number) => { - const game = new Game().loadPGN(pgn); +const play = async (board: Board, pgn: string | null, interval: number) => { + const game = new Game(); + + if (pgn) { + game.loadPGN(pgn); + } + // game.goto(28); await board.render(game.getBoardData()); - console.log(game.pgn()); - while (true) { const move = game.next(); @@ -28,7 +32,7 @@ const play = async (board: Board, pgn: string, interval: number) => { await board.render(game.getBoardData(), move); } - await delay(interval); + await delay(interval * 3); play(board, pgn, interval); }; @@ -42,17 +46,21 @@ const createDownloadLink = async (pgn: string, style: Style) => { }; const main = async () => { - const style = styles.calm; - // Object.values(styles).forEach((style, i) => { + const style = styles.avocado; + + const hash = window.location.hash; + const pgn = hash === "" ? null : decompressPGN(hash.slice(1)); const board = new Board(8).setStyle(style).setSize(720).showBorder(); + window.location.hash = "#alala"; + $app?.appendChild(board.canvas); - play(board, pgns[0], 1000); - // }); + play(board, pgn, 1000); - // const link = await createDownloadLink(pgns[0], styles.peach); - // document.body.appendChild(link); + // createDownloadLink(pgns[0], style).then((link) => { + // document.body.appendChild(link); + // }); }; main(); diff --git a/src/test-data/pgns.ts b/src/test-data/pgns.ts index e86f996..9619761 100644 --- a/src/test-data/pgns.ts +++ b/src/test-data/pgns.ts @@ -20,6 +20,25 @@ is hanging, the bishop is blocked because of the Queen.--Fischer} b5 10.Nxb5 cxb5 11.Bxb5+ Nbd7 12.O-O-O Rd8 13.Rxd7 Rxd7 14.Rd1 Qe6 15.Bxd7+ Nxd7 16.Qb8+ Nxb8 17.Rd8# 1-0`, + `[Event "Casual Bullet game"] +[Site "https://lichess.org/9PndkM3J"] +[Date "2022.01.15"] +[White "Anonymous"] +[Black "Anonymous"] +[Result "1-0"] +[UTCDate "2022.01.15"] +[UTCTime "19:04:57"] +[WhiteElo "?"] +[BlackElo "?"] +[Variant "Standard"] +[TimeControl "60+0"] +[ECO "A00"] +[Opening "Polish Opening"] +[Termination "Normal"] +[Annotator "lichess.org"] + +1. b4 { A00 Polish Opening } e5 2. Bb2 Nc6 3. b5 Nd4 4. e3 Nxb5 5. Bxb5 c6 6. Be2 Nf6 7. Bxe5 d6 8. Bb2 Be7 9. Nf3 O-O 10. O-O Bg4 11. d3 d5 12. Nbd2 Rc8 13. Qc1 Be6 14. c4 d4 15. Bxd4 Bg4 16. Bb2 Qc7 17. Qc3 Bxf3 18. Bxf3 Rcd8 19. Ne4 a5 20. a3 b5 21. Rad1 b4 22. axb4 Bxb4 23. Nxf6+ gxf6 24. Qxf6 Rd6 25. Qg7# { White wins by checkmate. } 1-0`, + `[Event "Hoogovens Group A"] [Site "Wijk aan Zee NED"] [Date "1999.01.20"]