summaryrefslogtreecommitdiffstats
path: root/src/client/games/manager.rs
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-10-29 17:18:34 +0100
committersalmonik <salmonik@tuta.io>2026-10-29 17:18:34 +0100
commitd9f1fe513e6f7696809d3a9b4d44ca485fe99c97 (patch)
tree9da99200fdfe004a47056d10340b3f59c7ccc52e /src/client/games/manager.rs
parentv2.0.0: reset plays audit to a generic per-game schema (diff)
downloadzagan-bet-d9f1fe513e6f7696809d3a9b4d44ca485fe99c97.tar.gz
zagan-bet-d9f1fe513e6f7696809d3a9b4d44ca485fe99c97.zip
v2.1.0: add European roulette with split bets and wheel animation
Diffstat (limited to 'src/client/games/manager.rs')
-rw-r--r--src/client/games/manager.rs131
1 files changed, 128 insertions, 3 deletions
diff --git a/src/client/games/manager.rs b/src/client/games/manager.rs
index 168c49d..02e9451 100644
--- a/src/client/games/manager.rs
+++ b/src/client/games/manager.rs
@@ -1,6 +1,8 @@
1use super::response::SpinResult; 1use super::response::{RouletteResult, SpinResult};
2use super::roulette::RouletteGame;
2use super::slots::SlotsGame; 3use super::slots::SlotsGame;
3use super::traits::{Game, GameError, GamePhase, GameState}; 4use super::traits::{Game, GameError, GamePhase, GameState};
5use crate::roulette::Bets;
4use std::collections::HashMap; 6use std::collections::HashMap;
5 7
6pub struct GameManager { 8pub struct GameManager {
@@ -12,6 +14,7 @@ impl GameManager {
12 pub fn new() -> Self { 14 pub fn new() -> Self {
13 let mut games: HashMap<String, Box<dyn Game>> = HashMap::new(); 15 let mut games: HashMap<String, Box<dyn Game>> = HashMap::new();
14 games.insert("slots".to_string(), Box::new(SlotsGame::new())); 16 games.insert("slots".to_string(), Box::new(SlotsGame::new()));
17 games.insert("roulette".to_string(), Box::new(RouletteGame::new()));
15 18
16 Self { 19 Self {
17 current_session: None, 20 current_session: None,
@@ -38,11 +41,25 @@ impl GameManager {
38 return Err(GameError::InvalidAction); 41 return Err(GameError::InvalidAction);
39 } 42 }
40 43
44 let mut data = HashMap::new();
45 let bet_amount = if game_type == "roulette" {
46 data.insert(
47 "bets".to_string(),
48 serde_json::to_string(&Bets::default()).unwrap_or_else(|_| "{}".to_string()),
49 );
50 data.insert("chip".to_string(), "10".to_string());
51 data.insert("status".to_string(), "place".to_string());
52 data.insert("number_input".to_string(), String::new());
53 0
54 } else {
55 10
56 };
57
41 self.current_session = Some(GameState { 58 self.current_session = Some(GameState {
42 game_type: game_type.to_string(), 59 game_type: game_type.to_string(),
43 bet_amount: 10, 60 bet_amount,
44 phase: GamePhase::WaitingToStart, 61 phase: GamePhase::WaitingToStart,
45 data: HashMap::new(), 62 data,
46 }); 63 });
47 64
48 Ok(()) 65 Ok(())
@@ -54,6 +71,17 @@ impl GameManager {
54 if session.phase != GamePhase::WaitingToStart && session.phase != GamePhase::Finished { 71 if session.phase != GamePhase::WaitingToStart && session.phase != GamePhase::Finished {
55 return None; 72 return None;
56 } 73 }
74 if session.game_type == "roulette" {
75 let bets = session
76 .data
77 .get("bets")
78 .cloned()
79 .unwrap_or_else(|| "{}".to_string());
80 return Some(format!(
81 "PLAY_START roulette {} {}",
82 session.bet_amount, bets
83 ));
84 }
57 Some(format!( 85 Some(format!(
58 "PLAY_START {} {}", 86 "PLAY_START {} {}",
59 session.game_type, session.bet_amount 87 session.game_type, session.bet_amount
@@ -78,6 +106,13 @@ impl GameManager {
78 session.data.remove("win_lines"); 106 session.data.remove("win_lines");
79 session.data.remove("win_cells"); 107 session.data.remove("win_cells");
80 session.data.remove("winnings"); 108 session.data.remove("winnings");
109 session.data.remove("number");
110 session.data.remove("color");
111 if session.game_type == "roulette" {
112 session
113 .data
114 .insert("status".to_string(), "spinning".to_string());
115 }
81 Ok(()) 116 Ok(())
82 } 117 }
83 118
@@ -130,6 +165,13 @@ impl GameManager {
130 session.data.remove("win_lines"); 165 session.data.remove("win_lines");
131 session.data.remove("win_cells"); 166 session.data.remove("win_cells");
132 session.data.remove("winnings"); 167 session.data.remove("winnings");
168 session.data.remove("number");
169 session.data.remove("color");
170 if session.game_type == "roulette" {
171 session
172 .data
173 .insert("status".to_string(), "place".to_string());
174 }
133 session.data.insert("error".to_string(), message.into()); 175 session.data.insert("error".to_string(), message.into());
134 } 176 }
135 177
@@ -141,6 +183,83 @@ impl GameManager {
141 } 183 }
142 } 184 }
143 185
186 pub fn roulette_bets(&self) -> Bets {
187 self.current_session
188 .as_ref()
189 .and_then(|session| session.data.get("bets"))
190 .and_then(|raw| serde_json::from_str(raw).ok())
191 .unwrap_or_default()
192 }
193
194 pub fn set_roulette_bets(&mut self, bets: &Bets) {
195 if let Some(session) = self.current_session.as_mut() {
196 session.data.insert(
197 "bets".to_string(),
198 serde_json::to_string(bets).unwrap_or_else(|_| "{}".to_string()),
199 );
200 session.bet_amount = bets.total();
201 }
202 }
203
204 pub fn roulette_chip(&self) -> u64 {
205 self.current_session
206 .as_ref()
207 .and_then(|session| session.data.get("chip"))
208 .and_then(|value| value.parse().ok())
209 .unwrap_or(10)
210 }
211
212 pub fn set_roulette_chip(&mut self, chip: u64) {
213 if let Some(session) = self.current_session.as_mut() {
214 session.data.insert("chip".to_string(), chip.to_string());
215 }
216 }
217
218 pub fn set_roulette_number_input(&mut self, value: &str) {
219 if let Some(session) = self.current_session.as_mut() {
220 session
221 .data
222 .insert("number_input".to_string(), value.to_string());
223 }
224 }
225
226 pub fn set_roulette_status(&mut self, status: &str) {
227 if let Some(session) = self.current_session.as_mut() {
228 session
229 .data
230 .insert("status".to_string(), status.to_string());
231 if status != "error" {
232 session.data.remove("error");
233 }
234 }
235 }
236
237 pub fn apply_roulette_result(&mut self, result: RouletteResult) {
238 let Some(session) = self.current_session.as_mut() else {
239 return;
240 };
241 session.phase = GamePhase::Finished;
242 session.bet_amount = result.bet_amount;
243 session.data.remove("error");
244 session.data.insert("bets".to_string(), result.bets);
245 session
246 .data
247 .insert("number".to_string(), result.number.to_string());
248 session.data.insert("color".to_string(), result.color);
249 session
250 .data
251 .insert("winnings".to_string(), result.winnings.to_string());
252 session
253 .data
254 .insert("balance".to_string(), result.balance.to_string());
255 session
256 .data
257 .insert("status".to_string(), "result".to_string());
258 session
259 .data
260 .insert("number_input".to_string(), String::new());
261 }
262
144 pub fn get_current_game(&self) -> Option<&dyn Game> { 263 pub fn get_current_game(&self) -> Option<&dyn Game> {
145 self.current_session 264 self.current_session
146 .as_ref() 265 .as_ref()
@@ -167,6 +286,12 @@ impl GameManager {
167 if session.phase != GamePhase::WaitingToStart && session.phase != GamePhase::Finished { 286 if session.phase != GamePhase::WaitingToStart && session.phase != GamePhase::Finished {
168 return Err(GameError::InvalidAction); 287 return Err(GameError::InvalidAction);
169 } 288 }
289 if session.game_type == "roulette" {
290 session
291 .data
292 .insert("chip".to_string(), bet.max(10).to_string());
293 return Ok(bet.max(10));
294 }
170 session.bet_amount = bet.max(10); 295 session.bet_amount = bet.max(10);
171 Ok(session.bet_amount) 296 Ok(session.bet_amount)
172 } 297 }