bowling_rs/
score_provider.rs1use crate::{Frame, Game, Score};
2
3pub trait ScoreProvider: Clone + Copy {
5 fn computed(&self, game: &Game) -> Vec<usize>;
7
8 fn score(&self, game: &Game) -> usize {
10 let computed = self.computed(game);
11
12 if let Some(score) = computed.last() {
13 return *score;
14 }
15
16 0
17 }
18
19 fn max(&self, game: &Game, provider: &impl ScoreProvider) -> usize;
21}
22
23#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
25pub struct TenPinScoreProvider;
26
27impl ScoreProvider for TenPinScoreProvider {
28 fn computed(&self, game: &Game) -> Vec<usize> {
29 let mut frames = vec![];
30 let mut score = 0;
31
32 for i in 0..game.frame_count {
33 if let Some(frame) = game.frame(i) {
34 score += frame.value();
36
37 if i < game.frame_count - 1 {
39 if let Some(next) = game.frame(i + 1) {
40 if frame.is_spare() {
41 score += next.first.value();
42 } else if frame.is_strike() {
43 score += next.first.value();
44
45 if next.is_strike() {
46 if i == game.frame_count - 2 {
47 score += next.second.value();
48 } else {
49 if let Some(next2) = game.frame(i + 2) {
50 score += next2.first.value();
51 }
52 }
53 } else if next.is_spare() {
54 score += 10 - next.first.value();
55 } else {
56 score += next.second.value();
57 }
58 }
59 }
60 }
61
62 println!("({}): {} -> {}", i, frame, score);
63
64 frames.push(score);
65 }
66 }
67
68 frames
69 }
70
71 fn max(&self, game: &Game, provider: &impl ScoreProvider) -> usize {
72 let mut frames = vec![];
73
74 for i in 0..game.frame_count {
75 if let Some(frame) = game.frame(i) {
76 if i == game.frame_count - 1 {
77 let mut f = frame.clone();
78
79 if f.first == Score::EMPTY {
80 f.first = Score::STRIKE;
81 }
82
83 if f.second == Score::EMPTY {
84 if f.first == Score::STRIKE {
85 f.second = Score::STRIKE;
86 } else {
87 f.second = Score::SPARE;
88 }
89 }
90
91 if let Some(bonus) = frame.bonus {
92 if bonus == Score::EMPTY {
93 if f.second.is_strike() {
94 f.bonus = Some(Score::STRIKE);
95 } else {
96 f.bonus = Some(Score::SPARE);
97 }
98 }
99 } else {
100 if f.second.is_strike() {
101 f.bonus = Some(Score::STRIKE);
102 } else {
103 f.bonus = Some(Score::SPARE);
104 }
105 }
106
107 frames.push(f);
108 } else {
109 if frame.first.is_strike() {
110 frames.push(Frame::strike());
111 } else if frame.second == Score::EMPTY {
112 frames.push(Frame::spare(frame.first.value()))
113 } else {
114 frames.push(frame.clone());
115 }
116 }
117 } else {
118 if i == game.frame_count - 1 {
119 frames.push(Frame::triple_strike());
120 } else {
121 frames.push(Frame::strike());
122 }
123 }
124 }
125
126 Game::with_frame_count(game.frame_count, frames).score_with_provider(*provider)
127 }
128}