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
84
85
86
87
88
89
90
91
92
93
use std::fmt;

/// Data which describes the turn that can be played.
///
/// In case of a castling turn, king's source and destination squares will be
/// provided.
///
/// Exact turn written in the algebraic chess notation format contains spoilers,
/// so it should be fetched via `get_turn` function.
pub struct AvailableTurn {
    /// Source square
    pub src: String,

    /// Destination square
    pub dst: String,

    /// Piece making the move
    pub piece: String,

    /// Captured piece
    pub captured: Option<String>,

    /// Chess notation format of the turn
    turn: String,
}

impl fmt::Display for AvailableTurn {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "AvailableTurn (src: {}, dst: {}, piece: {}, captured: {:?}, \
             turn: {}",
            self.src, self.dst, self.piece, self.captured, self.turn
        )
    }
}

impl AvailableTurn {
    /// Create `AvailableTurn`
    pub fn new(
        src: String,
        dst: String,
        piece: String,
        captured: Option<String>,
        turn: String,
    ) -> AvailableTurn {
        Self {
            src,
            dst,
            piece,
            captured,
            turn,
        }
    }

    /// Fetch turn written in chess notation format
    ///
    /// Turn info contains spoilers about the turn (checkmate or check),
    /// that's why the `turn` string is not publicly provided in the struct
    pub fn get_turn(&self) -> &str {
        self.turn.as_str()
    }
}

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

    #[test]
    fn print() {
        let src = String::from("a2");
        let dst = String::from("a3");
        let turn = String::from("a3");
        let piece = String::from("Pawn");
        let captured: Option<String> = None;

        assert_eq!(
            format!(
                "AvailableTurn (src: {}, dst: {}, piece: {}, captured: {:?}, \
                 turn: {}",
                src, dst, piece, captured, turn
            ),
            AvailableTurn::new(
                src.clone(),
                dst.clone(),
                piece,
                captured,
                turn.clone()
            )
            .to_string()
        );
    }
}