game.rs 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. use serde::{Serialize, Deserialize};
  2. use std::collections::BTreeMap;
  3. #[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
  4. pub enum GameState {
  5. Starting,
  6. Creating,
  7. Guessing
  8. }
  9. #[derive(Serialize, Deserialize, Clone, Debug)]
  10. pub struct CreatingEx {
  11. pub question: String,
  12. pub letters: Vec<char>
  13. }
  14. #[derive(Serialize, Clone, Debug)]
  15. pub struct Player {
  16. pub nick: String,
  17. pub creating_exercise: Option<CreatingEx>,
  18. pub submitted_word: Option<String>,
  19. pub submitted_guess: Option<Vec<(String, String)>>
  20. }
  21. #[derive(Serialize, Clone, Debug)]
  22. pub struct Game {
  23. pub players: Vec<Player>,
  24. pub round_number: i32,
  25. pub additional_questions: Vec<String>,
  26. pub state: GameState,
  27. }
  28. impl Player {
  29. pub fn has_submitted_word(&self) -> bool {
  30. self.submitted_word.is_some()
  31. }
  32. pub fn has_submitted_guess(&self) -> bool {
  33. self.submitted_guess.is_some()
  34. }
  35. }
  36. impl Game {
  37. pub fn new() -> Self {
  38. Self {
  39. players: Vec::new(),
  40. round_number: 0,
  41. additional_questions: Vec::new(),
  42. state: GameState::Starting
  43. }
  44. }
  45. pub fn get_player_mut(&mut self, nick: &str) -> Option<&mut Player> {
  46. self.players.iter_mut().find(|x| x.nick == nick)
  47. }
  48. pub fn get_player(&self, nick: &str) -> Option<&Player> {
  49. self.players.iter().find(|x| x.nick == nick)
  50. }
  51. pub fn check_letters(word: &str, letters: &Vec<char>) -> bool {
  52. let allowed_chars = [" ", "-", "'"];
  53. if word.len() == 0 {
  54. return false;
  55. }
  56. let mut countmap: BTreeMap<String, isize> = BTreeMap::new();
  57. for c in letters {
  58. let upper: String = c.to_uppercase().collect();
  59. let val = countmap.get(&upper).unwrap_or(&0) + 1;
  60. countmap.insert(upper, val);
  61. }
  62. for c in word.to_uppercase().chars() {
  63. let upper = String::from(c);
  64. let count = countmap.get(&upper);
  65. if allowed_chars.iter().any(|x| &upper == *x) {
  66. continue;
  67. }
  68. if let Some(&v) = count {
  69. if v <= 0 {
  70. return false;
  71. }
  72. countmap.insert(upper, v - 1);
  73. }
  74. else {
  75. return false;
  76. }
  77. }
  78. true
  79. }
  80. pub fn submit_creation(&mut self, player_nick: &str, word: String) -> bool {
  81. match self.state {
  82. GameState::Creating => {
  83. if let Some(player) = self.get_player_mut(player_nick) {
  84. if let Some(ex) = &player.creating_exercise {
  85. if Self::check_letters(&word, &ex.letters) {
  86. player.submitted_word = Some(word);
  87. return true;
  88. }
  89. }
  90. }
  91. },
  92. _ => {}
  93. }
  94. false
  95. }
  96. pub fn submit_guess(&mut self, player_nick: &str, guess: Vec<(String, String)>) -> bool {
  97. match self.state {
  98. GameState::Guessing => {
  99. if let Some(player) = self.get_player_mut(player_nick) {
  100. player.submitted_guess = Some(guess);
  101. true
  102. }
  103. else {
  104. false
  105. }
  106. },
  107. _ => false
  108. }
  109. }
  110. pub fn all_words_submitted(&self) -> bool {
  111. self.state == GameState::Creating &&
  112. self.players.iter().map(|p| p.submitted_word.is_some()).fold(true, |a, b| a && b)
  113. }
  114. pub fn all_guesses_submitted(&self) -> bool {
  115. self.state == GameState::Guessing &&
  116. self.players.iter().map(|p| p.submitted_guess.is_some()).fold(true, |a, b| a && b)
  117. }
  118. pub fn next_state(&mut self) {
  119. if self.state == GameState::Guessing {
  120. self.clear_submissions();
  121. }
  122. self.state = match self.state {
  123. GameState::Starting => GameState::Creating,
  124. GameState::Creating => GameState::Guessing,
  125. GameState::Guessing => GameState::Starting
  126. }
  127. }
  128. pub fn start_round<F, G>(&mut self, mut word_generator: F, mut char_generator: G)
  129. where F: FnMut() -> String,
  130. G: FnMut() -> Vec<char> {
  131. self.clear_submissions();
  132. /*let mut exes = vec![
  133. CreatingEx{ question: "Delikatessfutter für Hunde".to_owned(), letters: vec!['a', 'b', 'c'] },
  134. CreatingEx{ question: "Ein Hotel für die ganze Familie".to_owned(), letters: vec!['b', 'c', 'd'] },
  135. CreatingEx{ question: "Brasilianischer Superstar".to_owned(), letters: vec!['c', 'd', 'e'] },
  136. CreatingEx{ question: "Buchstabe des griechischen Alphabets".to_owned(), letters: vec!['d', 'e', 'f'] },
  137. ];*/
  138. for p in &mut self.players {
  139. p.creating_exercise = Some(
  140. CreatingEx{
  141. question: word_generator(),
  142. letters: char_generator()
  143. }
  144. );
  145. }
  146. self.additional_questions.clear();
  147. self.additional_questions.push(word_generator());
  148. self.additional_questions.push(word_generator());
  149. self.state = GameState::Creating;
  150. }
  151. pub fn clear_submissions(&mut self) {
  152. for p in &mut self.players {
  153. p.submitted_word = None;
  154. p.submitted_guess = None;
  155. p.creating_exercise = None;
  156. }
  157. }
  158. pub fn player_join(&mut self, nick: String) {
  159. self.players.push(Player{
  160. nick: nick,
  161. creating_exercise: None,
  162. submitted_word: None,
  163. submitted_guess: None
  164. });
  165. }
  166. pub fn remove_player(&mut self, nick: &str) {
  167. self.players.retain(|p| p.nick != nick);
  168. }
  169. pub fn create_results(&self) -> (Vec<Vec<Vec<String>>>, Vec<(String, i64)>) {
  170. let mut result: Vec<Vec<Vec<String>>> = Vec::new();
  171. let mut questions = self.players.iter()
  172. .map(|p| p.creating_exercise.clone().unwrap().question)
  173. .collect::<Vec<_>>();
  174. questions.append(&mut self.additional_questions.iter()
  175. .map(|x| x.clone())
  176. .collect::<Vec<_>>()
  177. );
  178. let mut player_points: Vec<i64> = vec![0; self.players.len()];
  179. for (player, p_id) in self.players.iter().zip(0..) {
  180. let mut line: Vec<Vec<String>> = Vec::new();
  181. let word = player.submitted_word.as_ref().unwrap();
  182. for (question, q_id) in questions.iter().zip(0..) {
  183. let mut cell: Vec<String> = Vec::new();
  184. for (p, inner_p) in self.players.iter().zip(0..) {
  185. if let Some(guess) = &p.submitted_guess {
  186. if let Some(_corr) = guess.iter().find(|(w, q)| w == word && q == question) {
  187. cell.push(p.nick.clone());
  188. // if solution is correct and not its own
  189. if p_id == q_id && p_id != inner_p {
  190. player_points[p_id] += 1;
  191. player_points[inner_p] += 1;
  192. }
  193. }
  194. }
  195. }
  196. line.push(cell);
  197. }
  198. result.push(line);
  199. }
  200. let point_list = self.players.iter()
  201. .map(|p| p.nick.clone())
  202. .zip(player_points)
  203. .collect::<Vec<_>>();
  204. return (result, point_list);
  205. }
  206. }