use std::io; use wasm_bindgen::prelude::*; use crate::{ pattern::{CharStatus, Pattern}, solver, word_list::WordList, }; static DEFAULT_VALID_WORDS: &str = include_str!("../../valid-words.txt"); static DEFAULT_ANSWERS: &str = include_str!("../../answers.txt"); #[wasm_bindgen] struct Solver(solver::Solver); #[wasm_bindgen] pub enum Color { GREY, YELLOW, GREEN, } #[wasm_bindgen] pub struct WordStats(solver::WordStats); #[allow(dead_code)] #[wasm_bindgen] impl WordStats { #[wasm_bindgen(getter)] pub fn word(&self) -> String { self.0.word.clone() } #[wasm_bindgen(getter)] pub fn solution_probability(&self) -> f64 { self.0.solution_probability } #[wasm_bindgen(getter)] pub fn expected_information_gained(&self) -> f64 { self.0.expected_information_gained } #[wasm_bindgen(getter)] pub fn expected_score_after_guess(&self) -> f64 { self.0.expected_score_after_guess } } #[allow(dead_code)] #[wasm_bindgen] impl Solver { pub fn new() -> Result { let valid_words = WordList::try_from(io::BufReader::new(io::Cursor::new(DEFAULT_VALID_WORDS)))?; let answers = WordList::try_from(io::BufReader::new(io::Cursor::new(DEFAULT_ANSWERS)))?; Ok(Solver(solver::Solver::new(valid_words, answers))) } pub fn guess(&mut self, word: &str, colors: Vec) -> Result<(), String> { let pat = Pattern::try_new( word, colors .iter() .map(|c| match c { Color::GREY => CharStatus::GREY, Color::YELLOW => CharStatus::YELLOW, Color::GREEN => CharStatus::GREEN, }) .collect(), )?; self.0.apply_guess(pat)?; Ok(()) } pub fn evaluate_words( &self, n: u32, progress: js_sys::Function, ) -> Result, String> { Ok(self .0 .evaluate_all_words_cb(move |i, n| { let _ = progress.call2(&JsValue::NULL, &JsValue::from(i), &JsValue::from(n)); })? .into_iter() .take(n as usize) .map(|ws| WordStats(ws)) .collect()) } pub fn guess_infos(&self) -> Vec { self.0 .guesses() .iter() .map(|g| g.information_gained) .collect() } pub fn solution_space(&self) -> u32 { self.0.stats().0 as u32 } pub fn solution_space_uncertainty(&self) -> f64 { self.0.stats().1 } }