use serde::{Deserialize, Serialize}; use serde_wasm_bindgen::Error; use tsify::Tsify; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; use crate::board::{CellType, Letter}; use crate::game::{Game, GameState, PlayedTile}; use crate::player_interaction::ai::Difficulty; #[wasm_bindgen] pub struct GameWasm(Game); #[derive(Serialize, Deserialize, Tsify)] #[tsify(from_wasm_abi)] pub enum ResponseType { OK, ERR, } #[derive(Serialize, Deserialize, Tsify)] #[tsify(from_wasm_abi)] pub struct MyResult { response_type: ResponseType, value: E, game_state: Option, } #[wasm_bindgen] impl GameWasm { #[wasm_bindgen(constructor)] pub fn new(seed: u64, dictionary_text: &str, ai_difficulty: JsValue) -> GameWasm { let difficulty: Difficulty = serde_wasm_bindgen::from_value(ai_difficulty).unwrap(); GameWasm(Game::new(seed, dictionary_text, vec!["Player".to_string()], vec![difficulty])) } pub fn get_tray(&self, name: &str) -> Result { let tray = self.0.player_states.get_tray(name); serde_wasm_bindgen::to_value(&tray) } pub fn get_board_cell_types(&self) -> Result { let board = self.0.get_board(); let cell_types: Vec = board.cells.iter().map(|cell| -> CellType { cell.cell_type.clone() }).collect(); serde_wasm_bindgen::to_value(&cell_types) } pub fn get_board_letters(&self) -> Result { let board = self.0.get_board(); let letters: Vec> = board.cells.iter().map(|cell| -> Option { cell.value.clone() }).collect(); serde_wasm_bindgen::to_value(&letters) } pub fn receive_play(&mut self, tray_tile_locations: JsValue, commit_move: bool) -> Result { let tray_tile_locations: Vec> = serde_wasm_bindgen::from_value(tray_tile_locations)?; let result = self.0.receive_play(tray_tile_locations, commit_move); match result { Ok((x, game_state)) => { serde_wasm_bindgen::to_value(&MyResult { response_type: ResponseType::OK, value: x, game_state: Some(game_state) }) }, Err(e) => { serde_wasm_bindgen::to_value(&MyResult { response_type: ResponseType::ERR, value: e, game_state: None, }) } } } pub fn get_scores(&self) -> Result { #[derive(Serialize, Deserialize, Tsify)] #[tsify(from_wasm_abi)] pub struct PlayerAndScore { name: String, score: u32, } let scores: Vec = self.0.player_states.0.iter() .map(|player_state| { PlayerAndScore { name: player_state.player.get_name().to_string(), score: player_state.score, } }) .collect(); Ok(serde_wasm_bindgen::to_value(&scores)?) } pub fn exchange_tiles(&mut self, tray_tile_locations: JsValue) -> Result{ let tray_tile_locations: Vec = serde_wasm_bindgen::from_value(tray_tile_locations)?; match self.0.exchange_tiles(tray_tile_locations) { Ok((_, turn_action, state)) => { serde_wasm_bindgen::to_value(&MyResult { response_type: ResponseType::OK, value: turn_action, game_state: Some(state), }) }, Err(e) => { serde_wasm_bindgen::to_value(&MyResult { response_type: ResponseType::ERR, value: e, game_state: None, }) } } } pub fn add_word(&mut self, word: String) { self.0.add_word(word); } pub fn skip_turn(&mut self) -> Result{ let result = self.0.pass(); match result { Ok(game_state) => { Ok(serde_wasm_bindgen::to_value(&MyResult { response_type: ResponseType::OK, value: "Turn passed", game_state: Some(game_state), })?) }, Err(e) => { Ok(serde_wasm_bindgen::to_value(&MyResult { response_type: ResponseType::ERR, value: e, game_state: None, })?) } } } pub fn advance_turn(&mut self) -> Result { let result = self.0.advance_turn(); match result { Ok((turn_advance_result, game_state)) => { Ok(serde_wasm_bindgen::to_value(&MyResult { response_type: ResponseType::OK, value: turn_advance_result, game_state: Some(game_state), })?) }, Err(e) => { Ok(serde_wasm_bindgen::to_value(&MyResult { response_type: ResponseType::ERR, value: e, game_state: None, })?) } } } pub fn get_current_player(&self) -> String { 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, game_state: None, })?) }, Err(msg) => { Ok(serde_wasm_bindgen::to_value(&MyResult{ response_type: ResponseType::OK, value: msg, game_state: None, })?) } } } }