1use crate::battle::BattleRules;
4use crate::error::{WeaselError, WeaselResult};
5use crate::team::TeamId;
6
7pub type PlayerId = u64;
15
16pub(crate) struct Rights<R: BattleRules> {
18 data: Vec<(PlayerId, Vec<TeamId<R>>)>,
19}
20
21impl<R: BattleRules> Rights<R> {
22 pub(crate) fn new() -> Self {
23 Self { data: Vec::new() }
24 }
25
26 fn cleanup_players(&mut self) {
28 self.data.retain(|(_, rights)| !rights.is_empty());
29 }
30
31 fn add(&mut self, player: PlayerId, team: &TeamId<R>) {
33 if let Some((_, rights)) = self.data.iter_mut().find(|(e, _)| *e == player) {
34 if rights.iter_mut().find(|e| *e == team).is_none() {
35 rights.push(team.clone());
36 }
37 } else {
38 self.data.push((player, vec![team.clone()]));
39 }
40 }
41
42 fn remove(&mut self, player: PlayerId, team: &TeamId<R>) {
44 if let Some((_, rights)) = self.data.iter_mut().find(|(e, _)| *e == player) {
45 let index = rights.iter().position(|e| e == team);
46 if let Some(index) = index {
47 rights.remove(index);
48 }
49 }
50 self.cleanup_players();
51 }
52
53 fn clear(&mut self) {
55 self.data.clear();
56 }
57
58 fn get(&self) -> impl Iterator<Item = (PlayerId, &[TeamId<R>])> {
60 self.data.iter().map(|(player, vec)| (*player, &vec[..]))
61 }
62
63 fn check(&self, player: PlayerId, team: &TeamId<R>) -> bool {
65 if let Some((_, rights)) = self.data.iter().find(|(e, _)| *e == player) {
66 return rights.iter().any(|e| e == team);
67 }
68 false
69 }
70
71 fn remove_team(&mut self, team: &TeamId<R>) {
73 for (_, rights) in &mut self.data {
74 let index = rights.iter().position(|e| e == team);
75 if let Some(index) = index {
76 rights.remove(index);
77 }
78 }
79 self.cleanup_players();
80 }
81
82 fn remove_player(&mut self, player: PlayerId) {
84 let index = self.data.iter().position(|(e, _)| *e == player);
85 if let Some(index) = index {
86 self.data.remove(index);
87 }
88 }
89}
90
91pub struct RightsHandle<'a, R>
94where
95 R: BattleRules,
96{
97 rights: &'a Rights<R>,
98}
99
100impl<'a, R> RightsHandle<'a, R>
101where
102 R: BattleRules,
103{
104 pub(crate) fn new(rights: &'a Rights<R>) -> Self {
105 Self { rights }
106 }
107
108 pub fn get(&self) -> impl Iterator<Item = (PlayerId, &[TeamId<R>])> {
110 self.rights.get()
111 }
112
113 pub fn check(&self, player: PlayerId, team: &TeamId<R>) -> bool {
115 self.rights.check(player, team)
116 }
117}
118
119pub struct RightsHandleMut<'a, R, I>
122where
123 R: BattleRules,
124 I: Iterator<Item = &'a TeamId<R>>,
125{
126 rights: &'a mut Rights<R>,
127 teams: I,
128}
129
130impl<'a, R, I> RightsHandleMut<'a, R, I>
131where
132 R: BattleRules,
133 I: Iterator<Item = &'a TeamId<R>>,
134{
135 pub(crate) fn new(rights: &'a mut Rights<R>, teams: I) -> Self {
136 Self { rights, teams }
137 }
138
139 pub fn add(&mut self, player: PlayerId, team: &TeamId<R>) -> WeaselResult<(), R> {
141 if !self.teams.any(|x| x == team) {
142 return Err(WeaselError::TeamNotFound(team.clone()));
143 }
144 self.rights.add(player, team);
145 Ok(())
146 }
147
148 pub fn remove(&mut self, player: PlayerId, team: &TeamId<R>) {
150 self.rights.remove(player, team);
151 }
152
153 pub fn clear(&mut self) {
155 self.rights.clear();
156 }
157
158 pub fn remove_team(&mut self, team: &TeamId<R>) {
160 self.rights.remove_team(team);
161 }
162
163 pub fn remove_player(&mut self, player: PlayerId) {
165 self.rights.remove_player(player);
166 }
167
168 pub fn get(&self) -> impl Iterator<Item = (PlayerId, &[TeamId<R>])> {
170 self.rights.get()
171 }
172
173 pub fn check(&self, player: PlayerId, team: &TeamId<R>) -> bool {
175 self.rights.check(player, team)
176 }
177}
178
179#[cfg(test)]
180mod tests {
181 use super::*;
182 use crate::battle::Battle;
183 use crate::{battle_rules, rules::empty::*};
184
185 const PLAYER_1_ID: PlayerId = 1;
186 const PLAYER_2_ID: PlayerId = 2;
187 const TEAM_1_ID: u32 = 1;
188 const TEAM_2_ID: u32 = 2;
189
190 battle_rules! {}
191
192 #[test]
193 fn change_rights() {
194 let mut rights: Rights<CustomRules> = Rights::new();
195 rights.add(PLAYER_1_ID, &TEAM_1_ID);
197 assert_eq!(rights.data.len(), 1);
198 rights.add(PLAYER_1_ID, &TEAM_2_ID);
200 assert_eq!(rights.data.len(), 1);
201 rights.add(PLAYER_2_ID, &TEAM_1_ID);
203 assert_eq!(rights.data.len(), 2);
204 assert_eq!(rights.check(PLAYER_1_ID, &TEAM_1_ID), true);
205 assert_eq!(rights.check(PLAYER_1_ID, &TEAM_2_ID), true);
206 assert_eq!(rights.check(PLAYER_2_ID, &TEAM_1_ID), true);
207 assert_eq!(rights.check(PLAYER_2_ID, &TEAM_2_ID), false);
208 rights.remove(PLAYER_1_ID, &TEAM_2_ID);
210 assert_eq!(rights.check(PLAYER_1_ID, &TEAM_2_ID), false);
211 rights.remove(PLAYER_2_ID, &TEAM_1_ID);
213 assert_eq!(rights.check(PLAYER_2_ID, &TEAM_1_ID), false);
214 assert_eq!(rights.data.len(), 1);
215 assert_eq!(rights.check(PLAYER_1_ID, &TEAM_1_ID), true);
217 rights.clear();
218 assert_eq!(rights.data.len(), 0);
219 assert_eq!(rights.check(PLAYER_1_ID, &TEAM_1_ID), false);
220 }
221
222 #[test]
223 fn remove_team() {
224 let mut rights: Rights<CustomRules> = Rights::new();
225 rights.add(PLAYER_1_ID, &TEAM_1_ID);
227 rights.add(PLAYER_2_ID, &TEAM_1_ID);
228 assert_eq!(rights.check(PLAYER_1_ID, &TEAM_1_ID), true);
229 assert_eq!(rights.check(PLAYER_2_ID, &TEAM_1_ID), true);
230 rights.add(PLAYER_1_ID, &TEAM_2_ID);
232 assert_eq!(rights.check(PLAYER_1_ID, &TEAM_2_ID), true);
233 assert_eq!(rights.data.len(), 2);
234 rights.remove_team(&TEAM_1_ID);
236 assert_eq!(rights.check(PLAYER_1_ID, &TEAM_1_ID), false);
237 assert_eq!(rights.check(PLAYER_2_ID, &TEAM_1_ID), false);
238 assert_eq!(rights.data.len(), 1);
239 }
240
241 #[test]
242 fn remove_player() {
243 let mut rights: Rights<CustomRules> = Rights::new();
244 rights.add(PLAYER_1_ID, &TEAM_1_ID);
246 rights.add(PLAYER_2_ID, &TEAM_1_ID);
247 assert_eq!(rights.check(PLAYER_1_ID, &TEAM_1_ID), true);
248 assert_eq!(rights.check(PLAYER_2_ID, &TEAM_1_ID), true);
249 assert_eq!(rights.data.len(), 2);
250 rights.remove_player(PLAYER_1_ID);
252 assert_eq!(rights.check(PLAYER_1_ID, &TEAM_1_ID), false);
253 assert_eq!(rights.data.len(), 1);
254 }
255
256 #[test]
257 fn handle() {
258 let mut battle = Battle::builder(CustomRules::new()).build();
259 assert_eq!(
261 battle.rights_mut().add(PLAYER_1_ID, &TEAM_1_ID).err(),
262 Some(WeaselError::TeamNotFound(TEAM_1_ID))
263 );
264 assert_eq!(battle.rights().get().count(), 0);
265 }
266}