179 lines
No EOL
5.4 KiB
Rust
179 lines
No EOL
5.4 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::{Board, CellType, Coordinates, Letter};
|
|
use crate::game::Game;
|
|
|
|
#[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> {
|
|
response_type: ResponseType,
|
|
value: E,
|
|
}
|
|
|
|
#[derive(Deserialize, Tsify, Copy, Clone)]
|
|
#[tsify(from_wasm_abi)]
|
|
pub struct PlayedTile {
|
|
index: usize,
|
|
character: Option<char>,
|
|
}
|
|
|
|
#[wasm_bindgen]
|
|
impl GameWasm {
|
|
|
|
#[wasm_bindgen(constructor)]
|
|
pub fn new(seed: u64, dictionary_text: &str) -> GameWasm {
|
|
GameWasm(Game::new(seed, dictionary_text, vec!["Player".to_string(), "AI".to_string()]))
|
|
}
|
|
|
|
pub fn get_tray(&self, name: &str) -> Result<JsValue, Error> {
|
|
let tray = self.0.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, player: &str, tray_tile_locations: JsValue, commit_move: bool) -> Result<JsValue, JsValue> {
|
|
let tray_tile_locations: Vec<Option<PlayedTile>> = serde_wasm_bindgen::from_value(tray_tile_locations)?;
|
|
|
|
let mut board_instance = self.0.get_board().clone();
|
|
let mut tray = self.0.get_tray(player).unwrap().clone();
|
|
|
|
let mut played_letters: Vec<(Letter, Coordinates)> = Vec::new();
|
|
for (i, played_tile) in tray_tile_locations.iter().enumerate() {
|
|
if played_tile.is_some() {
|
|
let played_tile = played_tile.unwrap();
|
|
let mut letter: Letter = tray.letters.get(i).unwrap().unwrap();
|
|
*tray.letters.get_mut(i).unwrap() = None;
|
|
|
|
let coord = Coordinates::new_from_index(played_tile.index);
|
|
if letter.is_blank {
|
|
match played_tile.character {
|
|
None => {
|
|
panic!("You can't play a blank character without providing a letter value")
|
|
}
|
|
Some(x) => {
|
|
// TODO - I should check that the character is a valid letter
|
|
letter.text = x;
|
|
}
|
|
}
|
|
}
|
|
played_letters.push((letter, coord));
|
|
|
|
}
|
|
}
|
|
|
|
match board_instance.receive_play(played_letters) {
|
|
Err(e) => {
|
|
return Ok(serde_wasm_bindgen::to_value(
|
|
&MyResult {
|
|
response_type: ResponseType::ERR,
|
|
value: e
|
|
}).unwrap());
|
|
},
|
|
Ok(_) => {}
|
|
}
|
|
|
|
#[derive(Debug, Serialize, Deserialize, Tsify)]
|
|
#[tsify(from_wasm_abi)]
|
|
struct WordResult {
|
|
word: String,
|
|
score: u32,
|
|
}
|
|
|
|
let result = board_instance.calculate_scores(self.0.get_dictionary());
|
|
let result = match result {
|
|
Ok(x) => {
|
|
let words: Vec<WordResult> = x.0.iter()
|
|
.map(|(word, score)| {
|
|
WordResult {
|
|
word: word.to_string(),
|
|
score: *score
|
|
}
|
|
|
|
})
|
|
.collect();
|
|
|
|
if commit_move {
|
|
let mut player_state = self.0.get_player_state_mut(player).unwrap();
|
|
player_state.score += x.1;
|
|
player_state.tray = tray;
|
|
|
|
board_instance.fix_tiles();
|
|
self.0.set_board(board_instance);
|
|
self.0.fill_trays()
|
|
}
|
|
|
|
serde_wasm_bindgen::to_value(
|
|
&MyResult {
|
|
response_type: ResponseType::OK,
|
|
value: words
|
|
}).unwrap()
|
|
|
|
},
|
|
Err(e) => {
|
|
serde_wasm_bindgen::to_value(
|
|
&MyResult {
|
|
response_type: ResponseType::ERR,
|
|
value: e
|
|
}).unwrap()
|
|
}
|
|
};
|
|
|
|
Ok(result)
|
|
|
|
}
|
|
|
|
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.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)?)
|
|
|
|
}
|
|
} |