import { Constants } from "./Constants.js"; /** * Gets a component which represents the specified {@link game `game`}. * * @param {import("./Game.js").Game} game * The game represented in this app. * * @returns {NodeDescriptor} * The rendered node. */ export function App(game) { return [ "div", { onclick: (event) => { let target = /** @type {HTMLElement} */ (event.target); for (let y = 0; y < game.board.length; y++) { let rowLength = game.board[y].length; for (let x = 0; x < rowLength; x++) { let node = document.querySelector(".board").children.item(y * rowLength + x); if (node === target || node.contains(target)) { if (game.addChip(x, y)) { game.state.turnCount++; game.draw(); } } } } } }, [ Board, game.board ], [ "div", { className: "log" }, game.winner ? `Player ${Constants.PLAYER_NAMES[game.winner]} wins!` : `It's player "${Constants.PLAYER_NAMES[game.currentPlayer]}"s turn` ] ]; } /** * Renders an element which represents the specified {@link board `board`}. * * @param {Board} board * The board represented in this element. * * @returns {NodeDescriptor} * The rendered element. */ export function Board(board) { let fields = board.flatMap((row) => row); return [ "div", { className: "board" }, ...fields.map( (field) => { return /** @type {NodeDescriptor} */([Field, field]); }), ["div", { style: "clear: both;" }] ]; } /** * Renders an element which represents the specified {@link field `field`}. * * @param {CellOwner} field * The field to represent. * * @returns {NodeDescriptor} * The rendered element. */ export function Field(field) { return [ "div", { className: "field" }, ...( field !== "" ? [ /** @type {NodeDescriptor} */ ([ "div", { className: `piece ${Constants.PLAYER_NAMES[field]}` } ]) ] : []) ]; }