12 use std::{collections::HashMap, iter}; |
12 use std::{collections::HashMap, iter}; |
13 |
13 |
14 pub const MAX_TEAMS_IN_ROOM: u8 = 8; |
14 pub const MAX_TEAMS_IN_ROOM: u8 = 8; |
15 pub const MAX_HEDGEHOGS_IN_ROOM: u8 = MAX_TEAMS_IN_ROOM * MAX_HEDGEHOGS_PER_TEAM; |
15 pub const MAX_HEDGEHOGS_IN_ROOM: u8 = MAX_TEAMS_IN_ROOM * MAX_HEDGEHOGS_PER_TEAM; |
16 |
16 |
|
17 #[derive(Clone, Debug)] |
|
18 pub struct OwnedTeam { |
|
19 pub owner_id: ClientId, |
|
20 pub owner_nick: String, |
|
21 pub info: TeamInfo, |
|
22 } |
|
23 |
17 fn client_teams_impl( |
24 fn client_teams_impl( |
18 teams: &[(ClientId, TeamInfo)], |
25 teams: &[OwnedTeam], |
19 client_id: ClientId, |
26 owner_id: ClientId, |
20 ) -> impl Iterator<Item = &TeamInfo> + Clone { |
27 ) -> impl Iterator<Item = &TeamInfo> + Clone { |
21 teams |
28 teams |
22 .iter() |
29 .iter() |
23 .filter(move |(id, _)| *id == client_id) |
30 .filter(move |team| team.owner_id == owner_id) |
24 .map(|(_, t)| t) |
31 .map(|team| &team.info) |
25 } |
32 } |
26 |
33 |
27 pub struct GameInfo { |
34 pub struct GameInfo { |
28 pub original_teams: Vec<(ClientId, TeamInfo)>, |
35 pub original_teams: Vec<OwnedTeam>, |
29 pub left_teams: Vec<String>, |
36 pub left_teams: Vec<String>, |
30 pub msg_log: Vec<String>, |
37 pub msg_log: Vec<String>, |
31 pub sync_msg: Option<String>, |
38 pub sync_msg: Option<String>, |
32 pub is_paused: bool, |
39 pub is_paused: bool, |
33 original_config: RoomConfig, |
40 original_config: RoomConfig, |
34 } |
41 } |
35 |
42 |
36 impl GameInfo { |
43 impl GameInfo { |
37 fn new(teams: Vec<(ClientId, TeamInfo)>, config: RoomConfig) -> GameInfo { |
44 fn new(teams: Vec<OwnedTeam>, config: RoomConfig) -> GameInfo { |
38 GameInfo { |
45 GameInfo { |
39 left_teams: Vec::new(), |
46 left_teams: Vec::new(), |
40 msg_log: Vec::new(), |
47 msg_log: Vec::new(), |
41 sync_msg: None, |
48 sync_msg: None, |
42 is_paused: false, |
49 is_paused: false, |
43 original_teams: teams, |
50 original_teams: teams, |
44 original_config: config, |
51 original_config: config, |
45 } |
52 } |
46 } |
53 } |
47 |
54 |
48 pub fn client_teams(&self, client_id: ClientId) -> impl Iterator<Item = &TeamInfo> + Clone { |
55 pub fn client_teams(&self, owner_id: ClientId) -> impl Iterator<Item = &TeamInfo> + Clone { |
49 client_teams_impl(&self.original_teams, client_id) |
56 client_teams_impl(&self.original_teams, owner_id) |
|
57 } |
|
58 |
|
59 pub fn client_teams_by_nick<'a>( |
|
60 &'a self, |
|
61 owner_nick: &'a str, |
|
62 ) -> impl Iterator<Item = &TeamInfo> + Clone + 'a { |
|
63 self.original_teams |
|
64 .iter() |
|
65 .filter(move |team| team.owner_nick == owner_nick) |
|
66 .map(|team| &team.info) |
50 } |
67 } |
51 |
68 |
52 pub fn mark_left_teams<'a, I>(&mut self, team_names: I) |
69 pub fn mark_left_teams<'a, I>(&mut self, team_names: I) |
53 where |
70 where |
54 I: Iterator<Item = &'a String>, |
71 I: Iterator<Item = &'a String>, |
93 |
110 |
94 pub players_number: u8, |
111 pub players_number: u8, |
95 pub default_hedgehog_number: u8, |
112 pub default_hedgehog_number: u8, |
96 pub max_teams: u8, |
113 pub max_teams: u8, |
97 pub ready_players_number: u8, |
114 pub ready_players_number: u8, |
98 pub teams: Vec<(ClientId, TeamInfo)>, |
115 pub teams: Vec<OwnedTeam>, |
99 config: RoomConfig, |
116 config: RoomConfig, |
100 pub voting: Option<Voting>, |
117 pub voting: Option<Voting>, |
101 pub saves: HashMap<String, RoomSave>, |
118 pub saves: HashMap<String, RoomSave>, |
102 pub game_info: Option<GameInfo>, |
119 pub game_info: Option<GameInfo>, |
103 } |
120 } |
123 game_info: None, |
140 game_info: None, |
124 } |
141 } |
125 } |
142 } |
126 |
143 |
127 pub fn hedgehogs_number(&self) -> u8 { |
144 pub fn hedgehogs_number(&self) -> u8 { |
128 self.teams.iter().map(|(_, t)| t.hedgehogs_number).sum() |
145 self.teams |
|
146 .iter() |
|
147 .map(|team| team.info.hedgehogs_number) |
|
148 .sum() |
129 } |
149 } |
130 |
150 |
131 pub fn addable_hedgehogs(&self) -> u8 { |
151 pub fn addable_hedgehogs(&self) -> u8 { |
132 MAX_HEDGEHOGS_IN_ROOM - self.hedgehogs_number() |
152 MAX_HEDGEHOGS_IN_ROOM - self.hedgehogs_number() |
133 } |
153 } |
134 |
154 |
135 pub fn add_team( |
155 pub fn add_team( |
136 &mut self, |
156 &mut self, |
137 owner_id: ClientId, |
157 owner: &HwClient, |
138 mut team: TeamInfo, |
158 mut team: TeamInfo, |
139 preserve_color: bool, |
159 preserve_color: bool, |
140 ) -> &TeamInfo { |
160 ) -> &TeamInfo { |
141 if !preserve_color { |
161 if !preserve_color { |
142 team.color = iter::repeat(()) |
162 team.color = iter::repeat(()) |
143 .enumerate() |
163 .enumerate() |
144 .map(|(i, _)| i as u8) |
164 .map(|(i, _)| i as u8) |
145 .take(u8::max_value() as usize + 1) |
165 .take(u8::MAX as usize + 1) |
146 .find(|i| self.teams.iter().all(|(_, t)| t.color != *i)) |
166 .find(|i| self.teams.iter().all(|team| team.info.color != *i)) |
147 .unwrap_or(0u8) |
167 .unwrap_or(0u8) |
148 }; |
168 }; |
149 team.hedgehogs_number = if self.teams.is_empty() { |
169 team.hedgehogs_number = if self.teams.is_empty() { |
150 self.default_hedgehog_number |
170 self.default_hedgehog_number |
151 } else { |
171 } else { |
152 self.teams[0] |
172 self.teams[0] |
153 .1 |
173 .info |
154 .hedgehogs_number |
174 .hedgehogs_number |
155 .min(self.addable_hedgehogs()) |
175 .min(self.addable_hedgehogs()) |
156 }; |
176 }; |
157 self.teams.push((owner_id, team)); |
177 self.teams.push(OwnedTeam { |
158 &self.teams.last().unwrap().1 |
178 owner_id: owner.id, |
|
179 owner_nick: owner.nick.clone(), |
|
180 info: team, |
|
181 }); |
|
182 &self.teams.last().unwrap().info |
159 } |
183 } |
160 |
184 |
161 pub fn remove_team(&mut self, team_name: &str) { |
185 pub fn remove_team(&mut self, team_name: &str) { |
162 if let Some(index) = self.teams.iter().position(|(_, t)| t.name == team_name) { |
186 if let Some(index) = self |
|
187 .teams |
|
188 .iter() |
|
189 .position(|team| team.info.name == team_name) |
|
190 { |
163 self.teams.remove(index); |
191 self.teams.remove(index); |
164 } |
192 } |
165 } |
193 } |
166 |
194 |
167 pub fn set_hedgehogs_number(&mut self, n: u8) -> Vec<String> { |
195 pub fn set_hedgehogs_number(&mut self, n: u8) -> Vec<String> { |
168 let mut names = Vec::new(); |
196 let mut names = Vec::new(); |
169 let teams = &mut self.teams; |
197 let teams = &mut self.teams; |
170 |
198 |
171 if teams.len() as u8 * n <= MAX_HEDGEHOGS_IN_ROOM { |
199 if teams.len() as u8 * n <= MAX_HEDGEHOGS_IN_ROOM { |
172 for (_, team) in teams.iter_mut() { |
200 for team in teams.iter_mut() { |
173 team.hedgehogs_number = n; |
201 team.info.hedgehogs_number = n; |
174 names.push(team.name.clone()) |
202 names.push(team.info.name.clone()) |
175 } |
203 } |
176 self.default_hedgehog_number = n; |
204 self.default_hedgehog_number = n; |
177 } |
205 } |
178 names |
206 names |
179 } |
207 } |
188 where |
216 where |
189 F: Fn(&TeamInfo) -> bool, |
217 F: Fn(&TeamInfo) -> bool, |
190 { |
218 { |
191 self.teams |
219 self.teams |
192 .iter_mut() |
220 .iter_mut() |
193 .find(|(_, t)| f(t)) |
221 .find(|team| f(&team.info)) |
194 .map(|(id, t)| (*id, t)) |
222 .map(|team| (team.owner_id, &mut team.info)) |
195 } |
223 } |
196 |
224 |
197 pub fn find_team<F>(&self, f: F) -> Option<&TeamInfo> |
225 pub fn find_team<F>(&self, f: F) -> Option<&TeamInfo> |
198 where |
226 where |
199 F: Fn(&TeamInfo) -> bool, |
227 F: Fn(&TeamInfo) -> bool, |
200 { |
228 { |
201 self.teams |
229 self.teams |
202 .iter() |
230 .iter() |
203 .find_map(|(_, t)| Some(t).filter(|t| f(&t))) |
231 .find_map(|team| Some(&team.info).filter(|t| f(&t))) |
204 } |
232 } |
205 |
233 |
206 pub fn client_teams(&self, client_id: ClientId) -> impl Iterator<Item = &TeamInfo> { |
234 pub fn client_teams(&self, owner_id: ClientId) -> impl Iterator<Item = &TeamInfo> { |
207 client_teams_impl(&self.teams, client_id) |
235 client_teams_impl(&self.teams, owner_id) |
208 } |
236 } |
209 |
237 |
210 pub fn client_team_indices(&self, client_id: ClientId) -> Vec<u8> { |
238 pub fn client_team_indices(&self, client_id: ClientId) -> Vec<u8> { |
211 self.teams |
239 self.teams |
212 .iter() |
240 .iter() |
213 .enumerate() |
241 .enumerate() |
214 .filter(move |(_, (id, _))| *id == client_id) |
242 .filter(move |(_, team)| team.owner_id == client_id) |
215 .map(|(i, _)| i as u8) |
243 .map(|(i, _)| i as u8) |
216 .collect() |
244 .collect() |
217 } |
245 } |
218 |
246 |
219 pub fn clan_team_owners(&self, color: u8) -> impl Iterator<Item = ClientId> + '_ { |
247 pub fn clan_team_owners(&self, color: u8) -> impl Iterator<Item = ClientId> + '_ { |
220 self.teams |
248 self.teams |
221 .iter() |
249 .iter() |
222 .filter(move |(_, t)| t.color == color) |
250 .filter(move |team| team.info.color == color) |
223 .map(|(id, _)| *id) |
251 .map(|team| team.owner_id) |
224 } |
252 } |
225 |
253 |
226 pub fn find_team_owner(&self, team_name: &str) -> Option<(ClientId, &str)> { |
254 pub fn find_team_owner(&self, team_name: &str) -> Option<(ClientId, &str)> { |
227 self.teams |
255 self.teams |
228 .iter() |
256 .iter() |
229 .find(|(_, t)| t.name == team_name) |
257 .find(|team| team.info.name == team_name) |
230 .map(|(id, t)| (*id, &t.name[..])) |
258 .map(|team| (team.owner_id, &team.info.name[..])) |
231 } |
259 } |
232 |
260 |
233 pub fn find_team_color(&self, owner_id: ClientId) -> Option<u8> { |
261 pub fn find_team_color(&self, owner_id: ClientId) -> Option<u8> { |
234 self.client_teams(owner_id).nth(0).map(|t| t.color) |
262 self.client_teams(owner_id).nth(0).map(|t| t.color) |
235 } |
263 } |
236 |
264 |
237 pub fn has_multiple_clans(&self) -> bool { |
265 pub fn has_multiple_clans(&self) -> bool { |
238 self.teams.iter().min_by_key(|(_, t)| t.color) |
266 let colors = self.teams.iter().map(|team| team.info.color); |
239 != self.teams.iter().max_by_key(|(_, t)| t.color) |
267 colors.clone().min() != colors.max() |
240 } |
268 } |
241 |
269 |
242 pub fn set_config(&mut self, cfg: GameCfg) { |
270 pub fn set_config(&mut self, cfg: GameCfg) { |
243 self.config.set_config(cfg); |
271 self.config.set_config(cfg); |
244 } |
272 } |