server/domain/scoreboard/
position.rs1use serde::{Deserialize, Serialize};
2
3use super::Points;
4
5#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
9pub struct Position {
10 back: Points,
11 front: Points,
12}
13
14impl Position {
15 #[cfg(test)]
16 pub(crate) fn new(points: usize) -> Self {
17 Self {
18 back: Points::from(0),
19 front: Points::from(points),
20 }
21 }
22
23 #[must_use]
25 pub const fn back(&self) -> Points {
26 self.back
27 }
28
29 #[must_use]
31 pub const fn front(&self) -> Points {
32 self.front
33 }
34
35 #[must_use]
37 pub fn points(&self) -> Points {
38 self.front
39 }
40}
41
42impl std::ops::Add<Points> for Position {
43 type Output = Self;
44
45 fn add(mut self, rhs: Points) -> Self::Output {
46 self += rhs;
47 self
48 }
49}
50
51impl std::ops::AddAssign<Points> for Position {
52 fn add_assign(&mut self, rhs: Points) {
53 self.back = self.front;
54 self.front += rhs;
55 }
56}
57
58impl std::fmt::Display for Position {
59 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
60 let Self {
61 back: back_peg,
62 front: front_peg,
63 } = self;
64 write!(f, "{back_peg:>3} -> {front_peg:>3}")
65 }
66}
67
68#[cfg(test)]
69mod test {
70 use super::*;
71
72 #[test]
73 fn scoring_will_jump_back_peg_over_front() {
74 let mut score = Position {
75 back: Points::from(21),
76 front: Points::from(42),
77 };
78 let points = Points::from(15);
79
80 score += points;
81
82 assert_eq!(score.back(), Points::from(42));
83 assert_eq!(score.front(), Points::from(57));
84 assert_eq!(score.points(), Points::from(57));
85 }
86
87 #[test]
88 fn score_can_be_displayed() {
89 let score = Position {
90 back: Points::from(21),
91 front: Points::from(42),
92 };
93
94 insta::assert_snapshot!(score.to_string(), @" 21 -> 42");
95 }
96}