summaryrefslogtreecommitdiffstats
path: root/src/client/games/roulette.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/games/roulette.rs')
-rw-r--r--src/client/games/roulette.rs157
1 files changed, 157 insertions, 0 deletions
diff --git a/src/client/games/roulette.rs b/src/client/games/roulette.rs
new file mode 100644
index 0000000..3379317
--- /dev/null
+++ b/src/client/games/roulette.rs
@@ -0,0 +1,157 @@
1use super::traits::{Game, GameState};
2use crate::roulette::{is_even, is_odd, Bets};
3
4pub const ROULETTE_BOARD_LINES: usize = 8;
5
6pub struct RouletteGame;
7
8impl RouletteGame {
9 pub fn new() -> Self {
10 Self
11 }
12
13 fn bets(state: &GameState) -> Bets {
14 state
15 .data
16 .get("bets")
17 .and_then(|raw| serde_json::from_str(raw).ok())
18 .unwrap_or_default()
19 }
20
21 fn bets_line(bets: &Bets) -> String {
22 let mut parts = Vec::new();
23 if bets.red > 0 {
24 parts.push(format!("RED {}", bets.red));
25 }
26 if bets.black > 0 {
27 parts.push(format!("BLACK {}", bets.black));
28 }
29 if bets.even > 0 {
30 parts.push(format!("EVEN {}", bets.even));
31 }
32 if bets.odd > 0 {
33 parts.push(format!("ODD {}", bets.odd));
34 }
35 for bet in &bets.numbers {
36 parts.push(format!("#{} {}", bet.number, bet.amount));
37 }
38
39 let list = if parts.is_empty() {
40 "(none)".to_string()
41 } else {
42 parts.join(" ")
43 };
44 format!("Bets: {} Total: {} PLN", list, bets.total())
45 }
46
47 fn result_lines(state: &GameState) -> (String, String) {
48 if let Some(error) = state.data.get("error") {
49 if !error.is_empty() {
50 return (format!("ERROR: {error}"), String::new());
51 }
52 }
53
54 match state.data.get("status").map(String::as_str) {
55 Some("result") => {
56 let number = state
57 .data
58 .get("number")
59 .map(String::as_str)
60 .unwrap_or("?");
61 let color = state
62 .data
63 .get("color")
64 .map(|value| value.to_uppercase())
65 .unwrap_or_default();
66 let parity = number
67 .parse::<u8>()
68 .ok()
69 .map(|number| {
70 if is_even(number) {
71 " EVEN"
72 } else if is_odd(number) {
73 " ODD"
74 } else {
75 ""
76 }
77 })
78 .unwrap_or("");
79 let winnings = state
80 .data
81 .get("winnings")
82 .map(String::as_str)
83 .unwrap_or("0");
84 let result = if winnings == "0" {
85 "No win.".to_string()
86 } else {
87 format!("Won {winnings} PLN")
88 };
89 (format!("Winning: {number} {color}{parity}"), result)
90 }
91 Some("spinning") => ("Spinning...".to_string(), String::new()),
92 _ => ("Place bets, then SPACE to spin.".to_string(), String::new()),
93 }
94 }
95}
96
97impl Game for RouletteGame {
98 fn get_name(&self) -> &'static str {
99 "Roulette"
100 }
101
102 fn render(&self, state: &GameState) -> String {
103 let bets = Self::bets(state);
104 let chip = state.data.get("chip").map(String::as_str).unwrap_or("10");
105 let balance = state
106 .data
107 .get("balance")
108 .map(String::as_str)
109 .unwrap_or("?");
110 let input = state
111 .data
112 .get("number_input")
113 .map(String::as_str)
114 .unwrap_or("");
115 let input_line = if input.is_empty() {
116 String::new()
117 } else {
118 format!("Number: {input}_")
119 };
120 let (status, result) = Self::result_lines(state);
121
122 format!(
123 "=== ROULETTE ===\r\nBalance: {} PLN Chip: {} PLN\r\n{}\r\n{}\r\n{}\r\n{}\r\n[R]ed [B]lack [E]ven [O]dd [#]Number [C]lear\r\n[+/-] Chip [SPACE] Spin [Q] Quit",
124 balance,
125 chip,
126 Self::bets_line(&bets),
127 input_line,
128 status,
129 result
130 )
131 }
132
133 fn render_lines(&self, _state: &GameState) -> usize {
134 ROULETTE_BOARD_LINES
135 }
136
137 fn get_help(&self) -> String {
138 "ROULETTE (European)\n\
139 ==================\n\
140 37 pockets: 0 plus 1-36. 0 is green and loses all outside bets.\n\
141 \n\
142 Betting:\n\
143 R / B / E / O - add the current chip to red/black/even/odd\n\
144 digits + Enter - add the current chip to that number\n\
145 C - clear all bets\n\
146 + or = / - - change the chip size\n\
147 SPACE - spin when at least one bet is placed\n\
148 Q - exit\n\
149 \n\
150 Payouts:\n\
151 straight number: 35:1 (36x returned)\n\
152 red/black: 1:1 (2x returned)\n\
153 even/odd: 1:1 (2x returned)\n\
154 Multiple bets are settled independently and added together."
155 .to_string()
156 }
157}