From 6c87d2353766abe8bc83d0ad56cec01e4dd5db86 Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Mon, 15 May 2023 23:59:41 -0400 Subject: [PATCH] Start making the UI state really send messages to and recieve response from the core --- kifu/pwa/src/assertNever.ts | 1 + kifu/pwa/src/components/Board.ts | 48 ++++++++++++++++---- kifu/pwa/src/main.ts | 76 ++++++++++++++++++++++++++++++-- 3 files changed, 113 insertions(+), 12 deletions(-) create mode 100644 kifu/pwa/src/assertNever.ts diff --git a/kifu/pwa/src/assertNever.ts b/kifu/pwa/src/assertNever.ts new file mode 100644 index 0000000..6e622d1 --- /dev/null +++ b/kifu/pwa/src/assertNever.ts @@ -0,0 +1 @@ +export const assertNever = (_: never) => {}; diff --git a/kifu/pwa/src/components/Board.ts b/kifu/pwa/src/components/Board.ts index 7ddb849..04bbb28 100644 --- a/kifu/pwa/src/components/Board.ts +++ b/kifu/pwa/src/components/Board.ts @@ -1,19 +1,25 @@ -import { BoardElement, Color } from "core-types"; +import { BoardElement, Color, Size, CoreRequest } from "core-types"; +import { assertNever } from "../assertNever"; const MARGIN = 20; const BOARD_WIDTH = 800; const BOARD_HEIGHT = 800; type Pixel = { x: number; y: number }; -type Address = { column: number; row: number }; +type Coordinate = { column: number; row: number }; + +export interface GoBoardProps { + board: BoardElement; + onClick: (_: CoreRequest) => void; +} export class GoBoard { private board: BoardElement; private pen: Pen; - private cursorLocation: Address | null; + private cursorLocation: Coordinate | null; canvas: HTMLCanvasElement; - constructor(board: BoardElement) { + constructor({ board, onClick }: GoBoardProps) { this.board = board; this.canvas = document.createElement("canvas"); this.canvas.width = BOARD_WIDTH; @@ -43,9 +49,30 @@ export class GoBoard { this.renderBoard(); } }; + + this.canvas.onclick = (_) => { + console.log("clicked on ", this.cursorLocation); + if (this.cursorLocation) { + const intersection = + this.board.spaces[boardAddress(this.board.size, this.cursorLocation)]; + switch (intersection.type) { + case "Unplayable": + break; + case "Empty": + console.log("need to run action: ", intersection.content); + onClick(intersection.content); + break; + case "Filled": + break; + default: + assertNever(intersection); + } + } + }; } setBoard(board: BoardElement) { + console.log("setting an updated board: ", board); this.board = board; this.pen = new Pen( @@ -119,7 +146,7 @@ class Pen { this.vspaceBetween = (height - margin * 2) / (rows - 1); } - starPoint(ctx: CanvasRenderingContext2D, addr: Address) { + starPoint(ctx: CanvasRenderingContext2D, addr: Coordinate) { ctx.fillStyle = "rgba(0, 0, 0, 1.0);"; const pixel = this.position(addr); ctx.moveTo(pixel.x, pixel.y); @@ -127,7 +154,7 @@ class Pen { ctx.fill(); } - ghostStone(ctx: CanvasRenderingContext2D, addr: Address, color: Color) { + ghostStone(ctx: CanvasRenderingContext2D, addr: Coordinate, color: Color) { switch (color) { case Color.White: ctx.fillStyle = "rgba(230, 230, 230, 0.5)"; @@ -140,7 +167,7 @@ class Pen { this.drawStone(ctx, addr); } - drawStone(ctx: CanvasRenderingContext2D, addr: Address) { + drawStone(ctx: CanvasRenderingContext2D, addr: Coordinate) { const radius = this.hspaceBetween / 2 - 2; const pixel = this.position(addr); ctx.moveTo(pixel.x, pixel.y); @@ -148,14 +175,14 @@ class Pen { ctx.fill(); } - position(addr: Address): Pixel { + position(addr: Coordinate): Pixel { return { x: this.margin + addr.column * this.hspaceBetween, y: this.margin + addr.row * this.vspaceBetween, }; } - address(pixel: Pixel): Address | null { + address(pixel: Pixel): Coordinate | null { if ( Math.round(pixel.x) < this.margin || Math.round(pixel.y) < this.margin @@ -173,3 +200,6 @@ class Pen { } } } + +const boardAddress = (size: Size, coordinate: Coordinate): number => + coordinate.column + size.width * coordinate.row; diff --git a/kifu/pwa/src/main.ts b/kifu/pwa/src/main.ts index 7174fc0..20a3a94 100644 --- a/kifu/pwa/src/main.ts +++ b/kifu/pwa/src/main.ts @@ -1,21 +1,91 @@ import { GoBoard } from "./components/Board"; +import { CoreRequest, CoreResponse } from "core-types"; import { CoreApi, initCore } from "./coreApi"; +import { assertNever } from "./assertNever"; + +/* +const processResponse = (response: CoreResponse) => { + const root = document.getElementById("root"); + if (!root) { + return; + } + +}; +*/ + +class UIState { + private currentView: GoBoard | null; + private rootElement: HTMLElement; + coreApi: CoreApi; + + constructor(coreApi: CoreApi, root: HTMLElement) { + this.currentView = null; + this.rootElement = root; + this.coreApi = coreApi; + + if (!root) { + console.log("root element not found"); + return; + } + } + + processResponse(response: CoreResponse) { + switch (response.type) { + case "PlayingFieldView": + if (this.currentView) { + this.currentView.setBoard(response.content.board); + } else { + this.currentView = new GoBoard({ + board: response.content.board, + onClick: async (request: CoreRequest) => { + const response = await this.coreApi.dispatch(request); + this.processResponse(response); + }, + }); + this.rootElement?.appendChild(this.currentView.canvas); + this.currentView.renderBoard(); + } + break; + default: + console.log("impossible branch: ", response); + alert("impossible branch"); + // assertNever(response); + break; + } + } +} const main = async () => { let coreApi = await initCore(); - let response = await coreApi.playingField(); + let response = await coreApi.dispatch({ type: "PlayingField" }); + const root = document.getElementById("root"); + + if (!root) { + console.log("root element not present"); + return; + } + + const uiState = new UIState(coreApi, root); + uiState.processResponse(response); + + /* console.log("playing field response: ", response); - const root = document.getElementById("root"); if (!root) { alert("could not retrieve the app root container"); return; } - const board = new GoBoard(response.board); + const board = new GoBoard({ + board: response.content.board, + onClick: async (request: CoreRequest) => { + const response = await coreApi.dispatch(request); + }, + }); root.appendChild(board.canvas); console.log("constructed board: ", board); board.renderBoard(); + */ }; main();