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}