WordGrid/src/wasm.rs
2023-09-20 18:59:32 -07:00

213 lines
No EOL
6.1 KiB
Rust

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<E: Serialize> {
response_type: ResponseType,
value: E,
game_state: Option<GameState>,
}
#[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<JsValue, Error> {
let tray = self.0.player_states.get_tray(name);
serde_wasm_bindgen::to_value(&tray)
}
pub fn get_board_cell_types(&self) -> Result<JsValue, Error> {
let board = self.0.get_board();
let cell_types: Vec<CellType> = 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<JsValue, Error> {
let board = self.0.get_board();
let letters: Vec<Option<Letter>> = board.cells.iter().map(|cell| -> Option<Letter> {
cell.value.clone()
}).collect();
serde_wasm_bindgen::to_value(&letters)
}
pub fn receive_play(&mut self, tray_tile_locations: JsValue, commit_move: bool) -> Result<JsValue, Error> {
let tray_tile_locations: Vec<Option<PlayedTile>> = 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<JsValue, JsValue> {
#[derive(Serialize, Deserialize, Tsify)]
#[tsify(from_wasm_abi)]
pub struct PlayerAndScore {
name: String,
score: u32,
}
let scores: Vec<PlayerAndScore> = 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<JsValue, Error>{
let tray_tile_locations: Vec<bool> = 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<JsValue, Error>{
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<JsValue, Error> {
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<JsValue, Error> {
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,
})?)
}
}
}
}