1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
use anyhow::{anyhow, Result};
use check_buddy_core::*;

pub struct PgnParser;

impl PgnParser {
    pub fn parse(buffer: String) -> Result<Game> {
        let mut game = Game::default();

        #[cfg(target_family = "unix")]
        let empty_line = "\n\n";
        #[cfg(target_family = "windows")]
        let empty_line = "\r\n\r\n";

        let (info, uci) = buffer
            .split_once::<&str>(empty_line)
            .ok_or(anyhow!("Can't split info and UCI"))?;

        Self::parse_info(&mut game, info)?;
        Self::parse_uci(&mut game, uci)?;

        Ok(game)
    }

    fn parse_info(game: &mut Game, info: &str) -> Result<()> {
        info.lines()
            .map(|line| {
                let mut chars = line.chars();
                chars.next();
                chars.next_back();
                chars.as_str()
            })
            .for_each(|line| {
                let (title, content) = line.split_once(' ').expect("Couldn't parse info row");
                let content = content.trim_matches('\"');
                game.info.insert(title.to_string(), content.to_string());
            });
        Ok(())
    }

    fn parse_uci(game: &mut Game, uci: &str) -> Result<()> {
        let binding = uci.split_whitespace().collect::<Vec<&str>>();
        let mut uci_line = binding.chunks(3).collect::<Vec<&[&str]>>();
        let _winning = uci_line.pop();

        for moves in uci_line.iter() {
            println!("{moves:?}");
            let (move1, move2) = (moves[1], moves[2]);

            let uci_move1 = game.board_map.parse_uci_to_move(move1)?;
            println!("{:?}", uci_move1);
            game.board_map.uci_move_turn(uci_move1)?;
            println!("{:?}", game.board_map);
            let uci_move2 = game.board_map.parse_uci_to_move(move2)?;
            println!("{:?}", uci_move2);
            game.board_map.uci_move_turn(uci_move2)?;
            println!("{:?}", game.board_map);
        }

        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    fn get_example_pgn() -> Vec<u8> {
        let mut path = std::env::current_dir().unwrap();
        #[cfg(target_family = "unix")]
        path.push("assets/pgns/example.pgn");
        #[cfg(target_family = "windows")]
        path.push("assets\\pgns\\example.pgn");

        std::fs::read(path).unwrap()
    }

    #[test]
    fn should_return_happy_flow() {
        let pgn = String::from_utf8(get_example_pgn()).unwrap();
        let _ = PgnParser::parse(pgn).unwrap();
    }
}