mons_rust/
lib.rs

1pub mod models;
2pub use models::*;
3
4use wasm_bindgen::prelude::*;
5
6#[wasm_bindgen]
7pub fn winner(fen_w: &str, fen_b: &str, flat_moves_string_w: &str, flat_moves_string_b: &str) -> String {
8    let moves_w: Vec<&str> = flat_moves_string_w.split("-").collect();
9    let moves_b: Vec<&str> = flat_moves_string_b.split("-").collect();
10
11    let game_w = MonsGame::from_fen(&fen_w);
12    let game_b = MonsGame::from_fen(&fen_b);
13
14    if game_w.is_none() || game_b.is_none() {
15        if game_w.is_none() && game_b.is_none() {
16            return "x".to_string();
17        } else if game_w.is_none() {
18            return Color::Black.fen();
19        } else {
20            return Color::White.fen();
21        }
22    }
23
24    let winner_color_game_w = game_w.unwrap().winner_color();
25    let winner_color_game_b = game_b.unwrap().winner_color();
26
27    if winner_color_game_w.is_none() && winner_color_game_b.is_none() {
28        return "".to_string()
29    } 
30
31    let mut game = MonsGame::new();
32
33    let mut w_index = 0;
34    let mut b_index = 0;
35
36    while w_index < moves_w.len() || b_index < moves_b.len() {
37        if game.active_color == Color::White {
38            if w_index >= moves_w.len() { return "x".to_string(); }
39            let inputs = Input::array_from_fen(moves_w[w_index]);
40            _ = game.process_input(inputs, false, false);
41            w_index += 1;
42        } else {
43            if b_index >= moves_b.len() { return "x".to_string(); }
44            let inputs = Input::array_from_fen(moves_b[b_index]);
45            _ = game.process_input(inputs, false, false);
46            b_index += 1;
47        }
48
49        if let Some(winner) = game.winner_color() {
50            if winner == Color::White {
51                if w_index == moves_w.len() && fen_w == game.fen() {
52                    return winner.fen();
53                } else {
54                    return "x".to_string();
55                }
56            } else {
57                if b_index == moves_b.len() && fen_b == game.fen() {
58                    return winner.fen();
59                } else {
60                    return "x".to_string();
61                }
62            }
63        }
64    }
65
66    return "x".to_string();
67}
68
69#[cfg(test)]
70mod tests {
71    use super::*;
72    use std::fs::{self, File};
73    use std::io::{self, Read};
74    use std::path::Path;
75
76    #[derive(Hash, PartialEq, Eq, Clone, Debug)]
77    struct TestCase {
78        fen_before: String,
79        input_fen: String,
80        output_fen: String,
81        fen_after: String,
82    }
83
84    #[test]
85    fn test_from_test_data() -> io::Result<()> {
86        let test_data_dir = Path::new("test-data");
87        let mut count = 0;
88        let mut oks = 0;
89        for entry in fs::read_dir(test_data_dir)? {
90            let entry = entry?;
91            let path = entry.path();
92            if path.is_file() && path.file_name().and_then(|f| f.to_str()).map_or(false, |s| !s.starts_with('.')) {
93                let mut file = File::open(&path)?;
94                let mut contents = String::new();
95                file.read_to_string(&mut contents)?;
96                let parts: Vec<&str> = contents.split("\"").collect();
97                let mut test_case = TestCase {
98                    fen_before: String::new(),
99                    input_fen: String::new(),
100                    output_fen: String::new(),
101                    fen_after: String::new(),
102                };
103
104                for i in 0..parts.len() {
105                    match parts[i] {
106                        "fenBefore" => test_case.fen_before = parts[i + 2].replace('\\', ""),
107                        "inputFen" => test_case.input_fen = parts[i + 2].replace('\\', ""),
108                        "outputFen" => test_case.output_fen = parts[i + 2].replace('\\', ""),
109                        "fenAfter" => test_case.fen_after = parts[i + 2].replace('\\', ""),
110                        _ => {}
111                    }
112                }
113
114                let inputs = Input::array_from_fen(&test_case.input_fen);
115                let recreated_inputs_fen = Input::fen_from_array(&inputs);
116                assert!(recreated_inputs_fen == test_case.input_fen);
117
118                let game_after = MonsGame::from_fen(&test_case.fen_after);
119                let recreated_game_after_fen = game_after.unwrap().fen();
120                assert!(recreated_game_after_fen == test_case.fen_after);
121
122                let mut game_before = MonsGame::from_fen(&test_case.fen_before).unwrap();
123                let recreated_game_before_fen = game_before.fen();
124                assert!(recreated_game_before_fen == test_case.fen_before);
125
126                let output = Output::from_fen(&test_case.output_fen);
127                let recreated_output_fen = output.unwrap().fen();
128                assert!(recreated_output_fen == test_case.output_fen);
129
130                assert!(!test_case.fen_before.is_empty() && !test_case.fen_after.is_empty() && !test_case.output_fen.is_empty(), "test data must not be empty");
131
132                let actual_output = game_before.process_input(inputs, false, false);
133
134                if game_before.fen() != test_case.fen_after || actual_output.fen() != test_case.output_fen {
135                    println!("expected {}", test_case.output_fen);
136                    println!("received {}", actual_output.fen());
137                    println!("forinput {}", test_case.input_fen);
138                    println!("forboard {}", test_case.fen_before);
139                    println!("expected fen after {}", test_case.fen_after);
140                    println!("received fen after {}\n\n\n\n\n", game_before.fen());
141                    count += 1;
142                } else {
143                    oks += 1;
144                    println!("ok {}", oks);
145                }
146
147                assert!(game_before.fen() == test_case.fen_after);
148                assert!(actual_output.fen() == test_case.output_fen);
149            }
150        }
151        println!("\n\n\n\n\n TOTAL ERRORS {}", count);
152        println!("TOTAL OKS {}", oks);
153        Ok(())
154    }
155}