balanced_direction/
balance.rs

1/// Represents a position within a 3x3 grid, with each variant corresponding to a specific point.
2///
3/// The `Balance` enum is used to model a balanced ternary direction or position
4/// within a 2D grid. Each variant represents one of the nine possible positions
5/// in the grid, where the center (`Balance::Center`) is `(0, 0)` and the
6/// surrounding positions are offsets from this central point.
7///
8/// # Variants
9///
10/// - `TopLeft`: The position at `(-1, -1)`
11/// - `Top`: The position at `(0, -1)`
12/// - `TopRight`: The position at `(1, -1)`
13/// - `Left`: The position at `(-1, 0)`
14/// - `Center`: The central position `(0, 0)`
15/// - `Right`: The position at `(1, 0)`
16/// - `BottomLeft`: The position at `(-1, 1)`
17/// - `Bottom`: The position at `(0, 1)`
18/// - `BottomRight`: The position at `(1, 1)`
19///
20/// # Examples
21///
22/// ```
23/// use balanced_direction::Balance;
24///
25/// let position = Balance::TopLeft;
26/// assert_eq!(position.to_vector(), (-1, -1));
27///
28/// let center = Balance::Center;
29/// assert_eq!(center.to_vector(), (0, 0));
30/// ```
31#[derive(Debug, PartialEq, Clone, Copy, Eq, Hash)]
32pub enum Balance {
33    /// `TopLeft`: The position at `(-1, -1)`
34    TopLeft,
35    /// `Top`: The position at `(0, -1)`
36    Top,
37    /// `TopRight`: The position at `(1, -1)`
38    TopRight,
39    /// `Left`: The position at `(-1, 0)`
40    Left,
41    /// `Center`: The central position `(0, 0)`
42    Center,
43    /// `Right`: The position at `(1, 0)`
44    Right,
45    /// `BottomLeft`: The position at `(-1, 1)`
46    BottomLeft,
47    /// `Bottom`: The position at `(0, 1)`
48    Bottom,
49    /// `BottomRight`: The position at `(1, 1)`
50    BottomRight,
51}
52
53impl Balance {
54    /// Returns the x-coordinate of the current `Balance` position in the 3x3 grid.
55    ///
56    /// # Returns
57    ///
58    /// An `i8` value representing the x-coordinate of the position.
59    ///
60    /// # Examples
61    ///
62    /// ```
63    /// use balanced_direction::Balance;
64    ///
65    /// let position = Balance::Right;
66    /// assert_eq!(position.x(), 1);
67    ///
68    /// let position = Balance::Center;
69    /// assert_eq!(position.x(), 0);
70    /// ```
71    pub const fn x(self) -> i8 {
72        if self.has_left() {
73            -1
74        } else if self.has_right() {
75            1
76        } else {
77            0
78        }
79    }
80
81    /// Returns the y-coordinate of the current `Balance` position in the 3x3 grid.
82    ///
83    /// # Returns
84    ///
85    /// An `i8` value representing the y-coordinate of the position.
86    ///
87    /// # Examples
88    ///
89    /// ```
90    /// use balanced_direction::Balance;
91    ///
92    /// let position = Balance::Bottom;
93    /// assert_eq!(position.y(), 1);
94    ///
95    /// let position = Balance::Center;
96    /// assert_eq!(position.y(), 0);
97    /// ```
98    pub const fn y(self) -> i8 {
99        if self.has_top() {
100            -1
101        } else if self.has_bottom() {
102            1
103        } else {
104            0
105        }
106    }
107
108    /// (spatial) Checks if the current position has the `Balance::Top` variant or any variant
109    /// that includes the top row in the 3x3 grid.
110    pub const fn has_top(self) -> bool {
111        matches!(self, Balance::Top | Balance::TopLeft | Balance::TopRight)
112    }
113
114    /// (spatial) Checks if the current position has the `Balance::Bottom` variant or any variant
115    /// that includes the bottom row in the 3x3 grid.
116    pub const fn has_bottom(self) -> bool {
117        matches!(
118            self,
119            Balance::Bottom | Balance::BottomLeft | Balance::BottomRight
120        )
121    }
122
123    /// (spatial) Checks if the current position has the `Balance::Left` variant or any variant
124    /// that includes the left row in the 3x3 grid.
125    pub const fn has_left(self) -> bool {
126        matches!(self, Balance::Left | Balance::TopLeft | Balance::BottomLeft)
127    }
128
129    /// (spatial) Checks if the current position has the `Balance::Right` variant or any variant
130    /// that includes the right column in the 3x3 grid.
131    pub const fn has_right(self) -> bool {
132        matches!(
133            self,
134            Balance::Right | Balance::TopRight | Balance::BottomRight
135        )
136    }
137
138    /// (spatial) Checks if the current position includes the center or any direct neighbor
139    /// (top, bottom, left, or right) in the 3x3 grid.
140    pub const fn is_orthogonal(self) -> bool {
141        matches!(
142            self,
143            Balance::Center | Balance::Top | Balance::Bottom | Balance::Left | Balance::Right
144        )
145    }
146
147    /// (spatial) Checks if the current position includes the center or any indirect neighbor
148    /// (corners) in the 3x3 grid.
149    pub const fn is_diagonal(self) -> bool {
150        matches!(
151            self,
152            Balance::Center
153                | Balance::TopLeft
154                | Balance::TopRight
155                | Balance::BottomLeft
156                | Balance::BottomRight
157        )
158    }
159
160    /// (spatial) Determines whether the current position is one of the edge positions
161    /// (top, bottom, left, or right) in the 3x3 grid.
162    pub const fn is_edge(self) -> bool {
163        matches!(
164            self,
165            Balance::Top | Balance::Bottom | Balance::Left | Balance::Right
166        )
167    }
168
169    /// (spatial) Checks if the current position is one of the corner positions
170    /// (top-left, top-right, bottom-left, or bottom-right) in the 3x3 grid.
171    pub const fn is_corner(self) -> bool {
172        matches!(
173            self,
174            Balance::TopLeft | Balance::TopRight | Balance::BottomLeft | Balance::BottomRight
175        )
176    }
177
178
179    /// Converts the current `Balance` position into a symbol representation.
180    ///
181    /// # Returns
182    ///
183    /// A `&'static str` that visually represents the position using an emoji.
184    /// Each position in the 3x3 grid is mapped to a unique symbol:
185    ///
186    /// - `TopLeft`: "↖️"
187    /// - `Top`: "⬆️"
188    /// - `TopRight`: "↗️"
189    /// - `Left`: "⬅️"
190    /// - `Center`: "⏺️"
191    /// - `Right`: "➡️"
192    /// - `BottomLeft`: "↙️"
193    /// - `Bottom`: "⬇️"
194    /// - `BottomRight`: "↘️"
195    ///
196    /// # Examples
197    ///
198    /// ```
199    /// use balanced_direction::Balance;
200    ///
201    /// let position = Balance::Top;
202    /// assert_eq!(position.to_symbol(), "⬆️");
203    ///
204    /// let position = Balance::Center;
205    /// assert_eq!(position.to_symbol(), "⏺️");
206    /// ```
207    pub const fn to_symbol(self) -> &'static str {
208        match self {
209            Balance::TopLeft => "↖️",
210            Balance::Top => "⬆️",
211            Balance::TopRight => "↗️",
212            Balance::Left => "⬅️",
213            Balance::Center => "⏺️",
214            Balance::Right => "➡️",
215            Balance::BottomLeft => "↙️",
216            Balance::Bottom => "⬇️",
217            Balance::BottomRight => "↘️",
218        }
219    }
220}