gamelobby.rs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. use std::collections::BTreeMap;
  2. use std::sync::Arc;
  3. use rand::thread_rng;
  4. use rand::seq::SliceRandom;
  5. use actix::prelude::*;
  6. use log::info;
  7. use crate::server::server::{GameConnection, Server};
  8. use crate::datasource;
  9. use crate::game;
  10. use crate::server::protocol::*;
  11. use crate::server::messages::*;
  12. #[derive(PartialEq)]
  13. enum LobbyState {
  14. Starting,
  15. Creating,
  16. Guessing,
  17. Revealing
  18. }
  19. pub struct GameLobby {
  20. server: Addr<Server>,
  21. connected_players: BTreeMap<String, Addr<GameConnection>>,
  22. game_id: String,
  23. game: game::Game,
  24. player_points: BTreeMap<String, i64>,
  25. waiting_players: BTreeMap<String, Addr<GameConnection>>,
  26. ready_players: Vec<String>,
  27. revealed_players: Vec<String>,
  28. round_result: Option<RoundResultData>,
  29. lobby_state: LobbyState,
  30. shuffler: datasource::Shuffler<String>,
  31. letter_distribution: datasource::LetterDistribution
  32. }
  33. impl Actor for GameLobby {
  34. type Context = Context<Self>;
  35. fn started(&mut self, _ctx: &mut Self::Context) {
  36. self.lobby_state = LobbyState::Starting;
  37. }
  38. }
  39. impl Handler<JoinRequest> for GameLobby {
  40. type Result = ();
  41. fn handle(&mut self, jr: JoinRequest, ctx: &mut Self::Context) -> Self::Result {
  42. if self.lobby_state == LobbyState::Starting {
  43. if self.connected_players.contains_key(&jr.nick) {
  44. jr.p.do_send(NickAlreadyExistsMsg {
  45. game_id: self.game_id.clone(),
  46. nick: jr.nick
  47. });
  48. }
  49. else {
  50. self.connected_players.insert(jr.nick.clone(), jr.p.clone());
  51. self.game.player_join(jr.nick.clone());
  52. jr.p.do_send(
  53. LobbyJoined {
  54. lobby: ctx.address(),
  55. game_id: self.game_id.clone(),
  56. nick: jr.nick.clone()
  57. }
  58. );
  59. self.send_game_to_all();
  60. info!("Player {} joined lobby {}", jr.nick, self.game_id);
  61. }
  62. }
  63. else {
  64. //self.waiting_players.insert(jr.nick.clone(), jr.p);
  65. jr.p.do_send(GameAlreadyStartedMsg(jr.lobby_id));
  66. }
  67. }
  68. }
  69. impl Handler<LeaveMsg> for GameLobby {
  70. type Result = ();
  71. fn handle(&mut self, lm: LeaveMsg, _ctx: &mut Self::Context) -> Self::Result {
  72. self.waiting_players.remove(&lm.0);
  73. self.connected_players.remove(&lm.0);
  74. self.ready_players.retain(|p| p != &lm.0);
  75. self.game.remove_player(&lm.0);
  76. if self.connected_players.is_empty() {
  77. self.server.do_send(LobbyFinished(self.game_id.clone()));
  78. }
  79. }
  80. }
  81. impl Handler<ReadyMsg> for GameLobby {
  82. type Result = ();
  83. fn handle(&mut self, rm: ReadyMsg, _ctx: &mut Self::Context) -> Self::Result {
  84. if !self.ready_players.contains(&rm.0) {
  85. self.ready_players.push(rm.0);
  86. }
  87. self.send_playerlist_to_all();
  88. if self.ready_players.len() >= self.connected_players.len() {
  89. self.set_state(LobbyState::Creating);
  90. self.send_game_to_all();
  91. }
  92. }
  93. }
  94. impl Handler<UnreadyMsg> for GameLobby {
  95. type Result = ();
  96. fn handle(&mut self, urm: UnreadyMsg, _ctx: &mut Self::Context) -> Self::Result {
  97. self.ready_players.retain(|p| p != &urm.0);
  98. self.send_playerlist_to_all();
  99. }
  100. }
  101. impl Handler<RevealMsg> for GameLobby {
  102. type Result = ();
  103. fn handle(&mut self, rm: RevealMsg, _ctx: &mut Self::Context) -> Self::Result {
  104. self.revealed_players.retain(|p| p != &rm.0);
  105. self.revealed_players.push(rm.0);
  106. self.send_game_to_all();
  107. if self.all_revealed() {
  108. self.set_state(LobbyState::Starting);
  109. self.send_game_to_all();
  110. }
  111. }
  112. }
  113. impl Handler<SubmitWordMsg> for GameLobby {
  114. type Result = ();
  115. fn handle(&mut self, swm: SubmitWordMsg, _ctx: &mut Self::Context) -> Self::Result {
  116. let _correct = self.game.submit_creation(&swm.nick, swm.word);
  117. if self.game.all_words_submitted() {
  118. self.set_state(LobbyState::Guessing);
  119. self.game.next_state();
  120. self.send_game_to_all();
  121. }
  122. else {
  123. self.send_playerlist_to_all();
  124. }
  125. }
  126. }
  127. impl Handler<SubmitGuessMsg> for GameLobby {
  128. type Result = ();
  129. fn handle(&mut self, sgm: SubmitGuessMsg, _ctx: &mut Self::Context) -> Self::Result {
  130. self.game.submit_guess(&sgm.nick, sgm.guesses);
  131. if self.game.all_guesses_submitted() {
  132. self.set_state(LobbyState::Revealing);
  133. let results = self.create_result_data();
  134. for (nick, pts) in &results.point_list {
  135. self.add_player_points(nick, *pts);
  136. }
  137. //self.broadcast_results(results.clone());
  138. self.round_result = Some(results);
  139. self.game.next_state();
  140. self.send_game_to_all();
  141. }
  142. else {
  143. self.send_playerlist_to_all();
  144. }
  145. }
  146. }
  147. impl GameLobby {
  148. pub fn new(gi: String, data_source: Arc<dyn datasource::DataSource<String>>, server: Addr<Server>) -> Self {
  149. GameLobby {
  150. server: server,
  151. connected_players: BTreeMap::new(),
  152. game_id: gi,
  153. game: game::Game::new(),
  154. player_points: BTreeMap::new(),
  155. waiting_players: BTreeMap::new(),
  156. round_result: None,
  157. ready_players: Vec::new(),
  158. revealed_players: Vec::new(),
  159. lobby_state: LobbyState::Starting,
  160. shuffler: datasource::Shuffler::create(data_source),
  161. letter_distribution: datasource::LetterDistribution::create()
  162. }
  163. }
  164. fn set_state(&mut self, new_state: LobbyState) {
  165. match new_state {
  166. LobbyState::Starting => {
  167. for (nick, _addr) in &self.waiting_players {
  168. self.game.player_join(nick.clone());
  169. }
  170. self.connected_players.append(&mut self.waiting_players);
  171. },
  172. LobbyState::Creating => {
  173. let s = &mut self.shuffler;
  174. let ld = &self.letter_distribution;
  175. self.game.start_round(|| s.get(), || ld.get(4, 6));
  176. },
  177. _ => {}
  178. }
  179. self.ready_players.clear();
  180. self.revealed_players.clear();
  181. self.round_result = None;
  182. self.lobby_state = new_state;
  183. }
  184. pub fn get_player_points(&self, nick: &str) -> i64 {
  185. *self.player_points.get(nick).unwrap_or(&0)
  186. }
  187. pub fn add_player_points(&mut self, nick: &str, points: i64) {
  188. let entry = self.player_points.get_mut(nick);
  189. match entry {
  190. Some(x) => *x += points,
  191. None => { self.player_points.insert(nick.to_owned(), points); },
  192. }
  193. }
  194. pub fn send_game_to_all(&self) {
  195. for (nick, player) in &self.connected_players {
  196. let game_state = self.create_opaque_message(nick);
  197. player.do_send(GameUpdate{ game_data: game_state });
  198. }
  199. }
  200. pub fn send_playerlist_to_all(&self) {
  201. let player_list = self.create_playerlist();
  202. for (_nick, player) in &self.connected_players {
  203. player.do_send(PlayerListUpdate{ player_list: player_list.clone() });
  204. }
  205. }
  206. pub fn create_result_data(&self) -> RoundResultData {
  207. let (guesses, point_list) = self.game.create_results();
  208. let words = self.game.players.iter()
  209. .map(|p| (
  210. p.nick.clone(),
  211. p.submitted_word.clone().unwrap(),
  212. self.revealed_players.iter().any(|x| x == &p.nick)
  213. )
  214. )
  215. .collect::<Vec<_>>();
  216. let questions = self.game.players.iter()
  217. .map(|x| x.creating_exercise.as_ref().unwrap().question.clone())
  218. .chain(self.game.additional_questions.clone().into_iter())
  219. .collect::<Vec<_>>();
  220. let solutions = words.iter()
  221. .map(|(_n, w, _r)| w.clone())
  222. .zip(questions.iter().map(|x| x.clone()))
  223. .collect::<Vec<_>>();
  224. let mut permutation = (0..questions.len()).collect::<Vec<_>>();
  225. permutation.shuffle(&mut thread_rng());
  226. let mut shuffled_questions: Vec<String> = Vec::new();
  227. let mut shuffled_guesses: Vec<Vec<Vec<String>>> = Vec::new();
  228. for pi in &permutation {
  229. shuffled_questions.push(questions[*pi].clone());
  230. }
  231. for guessline in guesses {
  232. let mut shuffled_line: Vec<Vec<String>> = Vec::new();
  233. for pi in &permutation {
  234. if *pi < guessline.len() {
  235. shuffled_line.push(guessline[*pi].clone());
  236. }
  237. else {
  238. shuffled_line.push(Vec::new());
  239. }
  240. }
  241. shuffled_guesses.push(shuffled_line);
  242. }
  243. RoundResultData {
  244. words,
  245. questions: shuffled_questions,
  246. solutions,
  247. guesses: shuffled_guesses,
  248. point_list
  249. }
  250. }
  251. /*pub fn broadcast_results(&self, results: RoundResultData) {
  252. let has_revealed = self.revealed_players.iter()
  253. .map(|n| (n.clone(), self.revealed_players.iter().any(|x| x == n)))
  254. .collect::<Vec<_>>();
  255. for (_nick, player) in &self.connected_players {
  256. player.do_send(ResultMsg {
  257. results: results.clone(),
  258. //has_revealed: has_revealed.clone()
  259. });
  260. }
  261. }*/
  262. ///
  263. /// determines if a player is ready to progress into the next game state
  264. ///
  265. fn player_is_ready(&self, nick: &str) -> bool {
  266. match self.lobby_state {
  267. LobbyState::Starting => self.ready_players.iter().any(|p| p == nick),
  268. LobbyState::Creating => self.game.get_player(nick)
  269. .map(|p| p.has_submitted_word())
  270. .unwrap_or(false),
  271. LobbyState::Guessing => self.game.get_player(nick)
  272. .map(|p| p.has_submitted_guess())
  273. .unwrap_or(false),
  274. LobbyState::Revealing => self.ready_players.iter().any(|p| p == nick)
  275. }
  276. }
  277. fn create_playerlist(&self) -> Vec<PlayerData> {
  278. self.game.players.iter()
  279. .map(|p|
  280. PlayerData {
  281. nick: p.nick.clone(),
  282. points: self.get_player_points(&p.nick),
  283. ready: self.player_is_ready(&p.nick),
  284. })
  285. .collect::<Vec<_>>()
  286. }
  287. pub fn create_opaque_message(&self, nick: &str) -> GameData {
  288. let player = self.game.players.iter()
  289. .find(|p| p.nick == nick);
  290. GameData {
  291. players: self.create_playerlist(),
  292. state_data:
  293. if self.lobby_state == LobbyState::Revealing {
  294. let mut round_result = self.round_result.as_ref().unwrap().clone();
  295. for (nick, _word, revealed) in &mut round_result.words {
  296. *revealed = self.revealed_players.iter().any(|x| x == nick);
  297. }
  298. GameStateData::Revealing {
  299. round_result
  300. }
  301. }
  302. else {
  303. match self.game.state {
  304. game::GameState::Starting => {
  305. GameStateData::Starting
  306. },
  307. game::GameState::Creating => {
  308. GameStateData::Creating{
  309. question: player.unwrap().creating_exercise.as_ref().unwrap().question.clone(),
  310. available_chars: player.unwrap().creating_exercise.as_ref().unwrap().letters.clone()
  311. }
  312. },
  313. game::GameState::Guessing => {
  314. self.create_guessing(nick)
  315. },
  316. }
  317. }
  318. }
  319. }
  320. pub fn check_optionals(&self) {
  321. for p in &self.game.players {
  322. println!("{:?}", p);
  323. }
  324. }
  325. pub fn all_revealed(&self) -> bool {
  326. self.connected_players.iter().all(|(nick, _p)| self.revealed_players.iter().any(|x| x == nick))
  327. }
  328. pub fn create_guessing(&self, nick: &str) -> GameStateData {
  329. self.check_optionals();
  330. let words_with_chars = self.game.players.iter()
  331. .filter(|p| p.nick != nick)
  332. .map(|p|
  333. (p.submitted_word.clone().unwrap(),
  334. p.creating_exercise.clone().unwrap().letters))
  335. .collect::<Vec<_>>();
  336. let mut questions = self.game.players.iter()
  337. .filter(|p| p.nick != nick)
  338. .map(|p| p.creating_exercise.clone().unwrap().question)
  339. .collect::<Vec<_>>();
  340. questions.append(&mut self.game.additional_questions.iter()
  341. .map(|x| x.clone())
  342. .collect::<Vec<_>>()
  343. );
  344. questions.shuffle(&mut thread_rng());
  345. GameStateData::Guessing {
  346. submitted_words: words_with_chars,
  347. questions: questions
  348. }
  349. }
  350. }