diff --git a/src/game.rs b/src/game.rs index 9cf0180..88094a6 100644 --- a/src/game.rs +++ b/src/game.rs @@ -361,6 +361,23 @@ impl Game { } + pub fn get_remaining_tiles(&self) -> usize { + self.tile_pool.len() + } + + pub fn get_player_tile_count(&self, player: &str) -> Result { + let tray = match self.player_states.get_tray(&player) { + None => {return Err(format!("Player {} not found", player))} + Some(x) => {x} + }; + + Ok( + tray.letters.iter() + .filter(|l| l.is_some()) + .count() + ) + } + } #[derive(Serialize, Deserialize, Tsify, Debug)] diff --git a/src/wasm.rs b/src/wasm.rs index 234e238..f03a336 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -155,4 +155,25 @@ impl GameWasm { self.0.current_player_name() } + pub fn get_remaining_tiles(&self) -> usize { + self.0.get_remaining_tiles() + } + + pub fn get_player_tile_count(&self, player: &str) -> Result { + match self.0.get_player_tile_count(player) { + Ok(count) => { + Ok(serde_wasm_bindgen::to_value(&MyResult{ + response_type: ResponseType::OK, + value: count, + })?) + }, + Err(msg) => { + Ok(serde_wasm_bindgen::to_value(&MyResult{ + response_type: ResponseType::OK, + value: msg, + })?) + } + } + } + } \ No newline at end of file diff --git a/ui/src/Game.tsx b/ui/src/Game.tsx index a3f5ce3..78cd2a7 100644 --- a/ui/src/Game.tsx +++ b/ui/src/Game.tsx @@ -108,7 +108,7 @@ export function Game(props: { function runAI() { const result: TurnAdvanceResult = props.wasm.advance_turn(); if(result.type == "AIMove"){ - handlePlayerAction(result.action, "AI"); + handlePlayerAction(result.action, props.settings.aiName); } else { // this would be quite surprising console.error({result}); @@ -179,6 +179,21 @@ export function Game(props: { } }, [logInfo]); + const remainingTiles = useMemo(() => { + return props.wasm.get_remaining_tiles(); + }, [turnCount]); + + const remainingAITiles = useMemo(() => { + let result = props.wasm.get_player_tile_count(props.settings.aiName) as MyResult; + if(result.response_type == "OK") { + return result.value as number; + } else { + console.error(result.value); + return -1; + } + + }, [turnCount]); + function handlePlayerAction(action: TurnAction, playerName: string) { if (action.type == "PlayTiles"){ @@ -213,73 +228,85 @@ export function Game(props: { +
+
+
+ {remainingTiles} letters remaining +
+
+ {props.settings.aiName} has {remainingAITiles} tiles +
+ +
+ + +
+ + + +
+
- - }}>{confirmedScorePoints > -1 ? `Score ${confirmedScorePoints} points ✅` : "Check"} - - - ; } diff --git a/ui/src/index.tsx b/ui/src/index.tsx index 809f67c..591daa0 100644 --- a/ui/src/index.tsx +++ b/ui/src/index.tsx @@ -51,6 +51,7 @@ async function run() { root.render(); diff --git a/ui/src/style.less b/ui/src/style.less index 954b421..080ab22 100644 --- a/ui/src/style.less +++ b/ui/src/style.less @@ -3,16 +3,44 @@ @board-length: 15; @tile-star-size: 45px; -.tray { +.tray-row { display: grid; - grid-template-columns: repeat(7, @tile-width); - grid-gap: 5px; - height: @tile-width; - width: fit-content; - background-color: #bbb59d; - margin: 10px; + grid-template-columns: 1fr 1fr 1fr; + width: @board-length*@tile-width; + + .tray { + display: grid; + grid-template-columns: repeat(7, @tile-width); + grid-gap: 5px; + height: @tile-width; + width: fit-content; + background-color: #bbb59d; + margin: 10px; + } + + .player-controls { + display: grid; + grid-template-areas: "check return" + "check pass"; + grid-template-rows: 1fr 1fr; + grid-template-columns: 1fr 1fr; + + .check { + grid-area: check; + } + + .return { + grid-area: return; + } + + .pass { + grid-area: pass; + } + } } + + .board-grid { //grid-area: grid; display: grid; diff --git a/ui/src/utils.ts b/ui/src/utils.ts index 9a825e0..045212c 100644 --- a/ui/src/utils.ts +++ b/ui/src/utils.ts @@ -1,4 +1,4 @@ -import {Letter as LetterData, Letter} from "word_grid"; +import {Letter as LetterData, Letter} from "../../pkg/word_grid"; import * as React from "react"; export enum CellType { @@ -14,6 +14,7 @@ export enum CellType { export interface Settings { trayLength: number; playerName: string; + aiName: string; } export enum LocationType {