Basic tray retrieval

This commit is contained in:
Joel Therrien 2023-08-05 18:59:30 -07:00
parent efeb2d4d0b
commit cb69ada00d
11 changed files with 141 additions and 13 deletions

View file

@ -10,4 +10,8 @@ crate-type = ["cdylib"]
csv = "1.2.2" csv = "1.2.2"
rand = {version = "0.8.5", features = ["small_rng"]} rand = {version = "0.8.5", features = ["small_rng"]}
getrandom = {version = "0.2", features = ["js"]} getrandom = {version = "0.2", features = ["js"]}
wasm-bindgen = "0.2.87" wasm-bindgen = { version = "0.2.87", features = ["serde-serialize"] }
serde_json = "1.0"
serde = { version = "1.0.181", features = ["derive"] }
serde-wasm-bindgen = "0.4"

View file

@ -1,6 +1,7 @@
use std::collections::HashSet; use std::collections::HashSet;
use std::fmt; use std::fmt;
use std::fmt::{Formatter, Write}; use std::fmt::{Formatter, Write};
use serde::{Deserialize, Serialize};
use crate::constants::{ALL_LETTERS_BONUS, GRID_LENGTH, TRAY_LENGTH}; use crate::constants::{ALL_LETTERS_BONUS, GRID_LENGTH, TRAY_LENGTH};
use crate::dictionary::DictionaryImpl; use crate::dictionary::DictionaryImpl;
@ -48,7 +49,7 @@ impl Coordinates {
} }
} }
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone, Serialize, Deserialize)]
pub struct Letter { pub struct Letter {
pub text: char, pub text: char,
pub points: u32, pub points: u32,

67
src/game.rs Normal file
View file

@ -0,0 +1,67 @@
use rand::rngs::SmallRng;
use rand::SeedableRng;
use wasm_bindgen::prelude::wasm_bindgen;
use crate::board::Letter;
use crate::constants::{standard_tile_pool, TRAY_LENGTH};
use crate::player_interaction::ai::Difficulty;
use crate::player_interaction::Tray;
pub enum Player {
Human(String),
AI{
name: String,
difficulty: Difficulty,
}
}
pub struct PlayerState {
player: Player,
score: u32,
tray: Tray
}
pub struct Game {
tiles: Vec<Letter>,
player: PlayerState,
}
// Problem - I want to provide a UI to the player
// Ideally they would get some kind of 'tray' object with methods to use and run
// However I want the main game state to live in Rust, not in JS.
// Does this mean I provide Rc<RefCell<Tray>>?
// Other option - what if I just have one Game object that exposes all methods.
// At no point do they get a Tray reference that auto-updates, they need to handle that
// I just provide read-only JSON of everything, and they call the methods for updates
// This will later work out well when I build it out as an API for multiplayer.
impl Game {
pub fn new(seed: u64) -> Self {
let mut rng = SmallRng::seed_from_u64(seed);
let mut letters = standard_tile_pool(Some(&mut rng));
let mut tray = Tray::new(TRAY_LENGTH);
tray.fill(&mut letters);
let player = PlayerState {
player: Player::Human("Joel".to_string()),
score: 0,
tray,
};
Game {
tiles: letters,
player,
}
}
pub fn get_tray(&self) -> &Tray {
&self.player.tray
}
pub fn get_tray_mut(&mut self) -> &mut Tray {
&mut self.player.tray
}
}

View file

@ -4,6 +4,8 @@ pub mod constants;
pub mod board; pub mod board;
pub mod dictionary; pub mod dictionary;
pub mod player_interaction; pub mod player_interaction;
pub mod game;
pub mod wasm;
#[wasm_bindgen] #[wasm_bindgen]
@ -16,3 +18,4 @@ extern {
pub fn greet(name: &str) { pub fn greet(name: &str) {
alert(&format!("Hello, {}!", name)); alert(&format!("Hello, {}!", name));
} }

View file

@ -1,8 +1,10 @@
use serde::{Deserialize, Serialize};
use crate::board::Letter; use crate::board::Letter;
pub mod ai; pub mod ai;
#[derive(Debug)] #[derive(Debug, Serialize, Deserialize)]
pub struct Tray { pub struct Tray {
pub letters: Vec<Option<Letter>> pub letters: Vec<Option<Letter>>
} }

View file

@ -0,0 +1,5 @@
pub struct Difficulty {
proportion: f64,
randomness: f64,
}

22
src/wasm.rs Normal file
View file

@ -0,0 +1,22 @@
use serde_wasm_bindgen::Error;
use wasm_bindgen::JsValue;
use wasm_bindgen::prelude::wasm_bindgen;
use crate::game::Game;
#[wasm_bindgen]
pub struct GameWasm(Game);
#[wasm_bindgen]
impl GameWasm {
#[wasm_bindgen(constructor)]
pub fn new(seed: u64) -> GameWasm {
GameWasm(Game::new(seed))
}
pub fn get_tray(&self) -> Result<JsValue, Error> {
let tray = self.0.get_tray();
serde_wasm_bindgen::to_value(tray)
}
}

27
ui/package-lock.json generated
View file

@ -5,14 +5,15 @@
"packages": { "packages": {
"": { "": {
"dependencies": { "dependencies": {
"@types/react": "^18.2.18",
"@types/react-dom": "^18.2.7",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"word_grid": "file:../pkg" "word_grid": "file:../pkg"
}, },
"devDependencies": { "devDependencies": {
"parcel": "^2.9.3" "@types/react": "^18.2.18",
"@types/react-dom": "^18.2.7",
"parcel": "^2.9.3",
"process": "^0.11.10"
} }
}, },
"../pkg": { "../pkg": {
@ -1961,12 +1962,14 @@
"node_modules/@types/prop-types": { "node_modules/@types/prop-types": {
"version": "15.7.5", "version": "15.7.5",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
"integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==",
"dev": true
}, },
"node_modules/@types/react": { "node_modules/@types/react": {
"version": "18.2.18", "version": "18.2.18",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.18.tgz", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.18.tgz",
"integrity": "sha512-da4NTSeBv/P34xoZPhtcLkmZuJ+oYaCxHmyHzwaDQo9RQPBeXV+06gEk2FpqEcsX9XrnNLvRpVh6bdavDSjtiQ==", "integrity": "sha512-da4NTSeBv/P34xoZPhtcLkmZuJ+oYaCxHmyHzwaDQo9RQPBeXV+06gEk2FpqEcsX9XrnNLvRpVh6bdavDSjtiQ==",
"dev": true,
"dependencies": { "dependencies": {
"@types/prop-types": "*", "@types/prop-types": "*",
"@types/scheduler": "*", "@types/scheduler": "*",
@ -1977,6 +1980,7 @@
"version": "18.2.7", "version": "18.2.7",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.7.tgz", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.7.tgz",
"integrity": "sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA==", "integrity": "sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA==",
"dev": true,
"dependencies": { "dependencies": {
"@types/react": "*" "@types/react": "*"
} }
@ -1984,7 +1988,8 @@
"node_modules/@types/scheduler": { "node_modules/@types/scheduler": {
"version": "0.16.3", "version": "0.16.3",
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz",
"integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==" "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==",
"dev": true
}, },
"node_modules/abortcontroller-polyfill": { "node_modules/abortcontroller-polyfill": {
"version": "1.7.5", "version": "1.7.5",
@ -2330,7 +2335,8 @@
"node_modules/csstype": { "node_modules/csstype": {
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
"integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==",
"dev": true
}, },
"node_modules/detect-libc": { "node_modules/detect-libc": {
"version": "1.0.3", "version": "1.0.3",
@ -3182,6 +3188,15 @@
"node": ">=12" "node": ">=12"
} }
}, },
"node_modules/process": {
"version": "0.11.10",
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
"integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
"dev": true,
"engines": {
"node": ">= 0.6.0"
}
},
"node_modules/react": { "node_modules/react": {
"version": "18.2.0", "version": "18.2.0",
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",

View file

@ -5,8 +5,9 @@
"word_grid": "file:../pkg" "word_grid": "file:../pkg"
}, },
"devDependencies": { "devDependencies": {
"parcel": "^2.9.3",
"@types/react": "^18.2.18", "@types/react": "^18.2.18",
"@types/react-dom": "^18.2.7" "@types/react-dom": "^18.2.7",
"parcel": "^2.9.3",
"process": "^0.11.10"
} }
} }

View file

@ -6,6 +6,7 @@
</head> </head>
<body> <body>
<script src="./index.js" type="module"></script> <script src="./index.js" type="module"></script>
</body> </body>
</html> </html>

View file

@ -5,7 +5,7 @@
// will "boot" the module and make it ready to use. Currently browsers // will "boot" the module and make it ready to use. Currently browsers
// don't support natively imported WebAssembly as an ES module, but // don't support natively imported WebAssembly as an ES module, but
// eventually the manual initialization won't be required! // eventually the manual initialization won't be required!
import init, { greet } from '../node_modules/word_grid/word_grid.js'; import init, { greet, GameWasm } from '../node_modules/word_grid/word_grid.js';
async function run() { async function run() {
// First up we need to actually load the wasm file, so we use the // First up we need to actually load the wasm file, so we use the
@ -36,8 +36,15 @@
// modes // modes
await init(); await init();
greet("Heyo!");
let game = new GameWasm(1234n);
let tray = game.get_tray();
console.log({tray});
// And afterwards we can use all the functionality defined in wasm. // And afterwards we can use all the functionality defined in wasm.
greet("Heyo!");
} }
run(); run();