schnapsen_rs/
lib.rs

1use core::fmt;
2use std::collections::HashMap;
3use std::hash::Hash;
4use std::ops::Index;
5use std::sync::{Arc, RwLock};
6
7use models::{contains_card_comb, has_announcable, Announcement};
8use models::{Card, Player};
9use rand::prelude::*;
10use rand::thread_rng;
11use serde::Deserialize;
12use serde::Serialize;
13
14pub mod client;
15pub mod models;
16
17#[cfg(test)]
18mod tests;
19
20#[derive(Debug)]
21pub enum PlayerError {
22    CantPlay40,
23    CantPlay20,
24    CantTakeCardDeckEmpty,
25    CantPlayCard(Card),
26    PlayerNotActive,
27    CardNotTrump,
28    CantTakeCardRoundNotFinished,
29    NoPlayerActive,
30    CantTakeAllDeckCards,
31    NotAllPlayersHaveTakenCards,
32    CantSetActivePlayer,
33    CantSwapTrump,
34    CantTakeCardPlayerNotActive,
35    CantTakeCardHaveAlreadyFive,
36    TalonAlreadyClosed,
37}
38
39impl PlayerError {
40    pub const fn get_message(&self) -> &str {
41        match self {
42            PlayerError::CantPlay40 => "Player can't play 40 right now",
43            PlayerError::CantPlay20 => "Player can't play 20 right now",
44            PlayerError::CantTakeCardDeckEmpty => "Player can't take card from empty card deck",
45            PlayerError::CantPlayCard(_) => "Player can't play this card",
46            PlayerError::PlayerNotActive => "Player is not active",
47            PlayerError::CardNotTrump => "Player can't play card because it's not trump",
48            PlayerError::CantTakeCardRoundNotFinished => {
49                "Player can't take card because round is not finished"
50            },
51            PlayerError::NoPlayerActive => {
52                "No player is active"
53            },
54            PlayerError::CantTakeAllDeckCards => {
55                "Can't take so much deck cards because there are not enough cards or the opponent would have any cards left to pick"
56            },
57            PlayerError::NotAllPlayersHaveTakenCards => {
58                "Not all players have taken cards"
59            },
60            PlayerError::CantSetActivePlayer => {
61                "Can't set active player because some player is already active"
62            },
63            PlayerError::CantSwapTrump => {
64                "Can't swap trump because player has no jack of trump in his hand"
65            },
66            PlayerError::CantTakeCardPlayerNotActive => {
67                "Can't take card because player is not active"
68            },
69            PlayerError::CantTakeCardHaveAlreadyFive => {
70                "Can't take card because player already has five cards"
71            },
72            PlayerError::TalonAlreadyClosed => {
73                "Talon is already closed"
74            }
75        }
76    }
77}
78
79#[derive(Debug, Clone)]
80pub struct PlayerPoint {
81    pub player: Arc<RwLock<Player>>,
82    pub points: u8,
83}
84
85#[derive(Debug, Clone)]
86pub struct CardComparisonResult {
87    pub winner: PlayerPoint,
88    pub loser: PlayerPoint,
89}
90
91impl fmt::Display for PlayerError {
92    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93        write!(f, "PlayerError: {}", self.get_message())
94    }
95}
96impl std::error::Error for PlayerError {}
97
98#[derive(Debug, Clone, Serialize, Deserialize)]
99#[serde(tag = "event", content = "data")]
100pub enum PrivateEvent {
101    CanAnnounce(Announcement),
102    CannotAnnounce(Announcement),
103    CardAvailabe(Card),
104    CardUnavailabe(Card),
105    CardPlayable(Card),
106    CardNotPlayable(Card),
107    TrumpChangePossible(Card),
108    TrumpChangeImpossible(Card),
109    AllowPlayCard,
110    AllowDrawCard,
111    AllowAnnounce,
112    AllowCloseTalon,
113    AllowSwapTrump,
114}
115
116// TODO: Alle user_ids are currently serialized as the write-tokens. This has to be changed. SECURITY RISK
117#[derive(Debug, Clone, Serialize, Deserialize)]
118#[serde(tag = "event", content = "data")]
119pub enum PublicEvent {
120    Score {
121        user_id: String,
122        points: u8,
123    },
124    PlayCard {
125        user_id: String,
126        card: Card,
127    },
128    Trick {
129        user_id: String,
130        cards: [Card; 2],
131    },
132    Announce {
133        user_id: String,
134        announcement: Announcement,
135    },
136    Result {
137        winner: String,
138        points: u8,
139        ranked: HashMap<String, u8>,
140    },
141    FinalResult {
142        ranked: HashMap<String, u8>,
143        winner: String,
144    },
145    CloseTalon {
146        user_id: String,
147    },
148    TrumpChange(Option<Card>),
149    // TrumpSwap(String, Card)
150    Active {
151        user_id: String,
152    },
153    Inactive {
154        user_id: String,
155    },
156    DeckCardCount(usize),
157    ReceiveCard {
158        user_id: String,
159    },
160    FinishedDistribution,
161}
162
163type FPub = Arc<dyn Fn(PublicEvent) -> () + Send + Sync + 'static>;
164type FPriv = Arc<dyn Fn(PrivateEvent) -> () + Send + Sync + 'static>;
165
166pub struct SchnapsenDuo {
167    players: [Arc<RwLock<Player>>; 2],
168    deck: Vec<Card>,
169    active: Option<Arc<RwLock<Player>>>,
170    trump: Option<models::Card>,
171    taken_trump: Option<(Arc<RwLock<Player>>, models::Card)>,
172    closed_talon: Option<Arc<RwLock<Player>>>,
173    stack: Vec<Card>,
174    pub_callbacks: Vec<FPub>,
175    priv_callbacks: HashMap<String, Vec<FPriv>>,
176}
177
178unsafe impl Send for SchnapsenDuo {}
179unsafe impl Sync for SchnapsenDuo {}
180
181impl Hash for SchnapsenDuo {
182    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
183        self.players
184            .iter()
185            .for_each(|player| player.read().unwrap().hash(state));
186        let now = chrono::Utc::now();
187        state.write(now.timestamp().to_le_bytes().as_slice().into());
188    }
189}
190
191impl SchnapsenDuo {
192    pub fn new(player_ids: &[String; 2]) -> Self {
193        let deck = Self::populate_deck();
194        let players = [
195            Arc::new(RwLock::new(Player::new(player_ids[0].clone()))),
196            Arc::new(RwLock::new(Player::new(player_ids[1].clone()))),
197        ];
198
199        Self {
200            active: None,
201            players,
202            deck: deck.into(),
203            trump: None,
204            stack: Vec::new(),
205            pub_callbacks: Vec::new(),
206            priv_callbacks: HashMap::new(),
207            taken_trump: None,
208            closed_talon: None,
209        }
210    }
211
212    #[inline]
213    pub fn on_priv_event(
214        &mut self,
215        player: Arc<RwLock<Player>>,
216        callback: impl Fn(PrivateEvent) -> () + Send + Sync + 'static,
217    ) {
218        self.priv_callbacks
219            .entry(player.read().unwrap().id.clone())
220            .or_insert_with(Vec::new)
221            .push(Arc::new(callback));
222    }
223
224    #[inline]
225    pub fn on_pub_event(&mut self, callback: impl Fn(PublicEvent) -> () + Send + Sync + 'static) {
226        self.pub_callbacks.push(Arc::new(callback));
227    }
228
229    #[inline]
230    pub fn off_pub_event(&mut self, callback: impl Fn(PublicEvent) -> () + Send + Sync + 'static) {
231        let callback = Arc::new(callback) as Arc<dyn Fn(PublicEvent) -> () + Send + Sync + 'static>;
232        self.pub_callbacks.retain(|x| !Arc::ptr_eq(x, &callback));
233    }
234
235    #[inline]
236    pub fn off_priv_event(
237        &mut self,
238        player: &Player,
239        callback: impl Fn(PrivateEvent) -> () + Send + Sync + 'static,
240    ) {
241        let callback =
242            Arc::new(callback) as Arc<dyn Fn(PrivateEvent) -> () + Send + Sync + 'static>;
243        if let Some(callbacks) = self.priv_callbacks.get_mut(&player.id) {
244            callbacks.retain(|x| !Arc::ptr_eq(x, &callback));
245        }
246    }
247
248    pub fn get_player(&self, player_id: &str) -> Option<Arc<RwLock<Player>>> {
249        self.players
250            .iter()
251            .find(|player| player.read().unwrap().id == player_id)
252            .cloned()
253    }
254
255    #[inline]
256    pub fn get_other_player(&self, other: Arc<RwLock<Player>>) -> Option<Arc<RwLock<Player>>> {
257        self.players
258            .iter()
259            .find(|player| !Arc::ptr_eq(*player, &other))
260            .cloned()
261    }
262
263    #[inline]
264    fn get_active_player(&self) -> Option<Arc<RwLock<Player>>> {
265        self.active.clone()
266    }
267
268    #[inline]
269    pub fn get_non_active_player(&self) -> Option<Arc<RwLock<Player>>> {
270        self.players
271            .iter()
272            .find(|player| !Arc::ptr_eq(*player, self.active.as_ref().unwrap()))
273            .cloned()
274    }
275
276    pub fn cutt_deck(
277        &mut self,
278        player: Arc<RwLock<Player>>,
279        mut cards_to_take: usize,
280    ) -> Result<(), PlayerError> {
281        let player = &player.read().unwrap();
282        if player.id != self.active.as_ref().unwrap().read().unwrap().id {
283            return Err(PlayerError::CantTakeCardRoundNotFinished);
284        }
285        if cards_to_take > self.deck.len() {
286            cards_to_take = self.deck.len();
287        }
288        let (back, front) = self.deck.split_at(cards_to_take);
289        self.deck = front.into_iter().chain(back.into_iter()).cloned().collect();
290        Ok(())
291    }
292
293    pub fn is_active(&self, player: &Player) -> bool {
294        self.active.as_ref().unwrap().read().unwrap().id == player.id
295    }
296
297    fn draw_card_after_trick(&mut self, player: Arc<RwLock<Player>>) -> Result<Card, PlayerError> {
298        let card = {
299            let player = &player.read().unwrap();
300            if !self.stack.is_empty() {}
301
302            if player.cards.len() == 5 {
303                return Err(PlayerError::CantTakeCardHaveAlreadyFive);
304            }
305
306            if self.trump.is_none() {
307                return Err(PlayerError::CantTakeCardDeckEmpty);
308            }
309
310            if self.closed_talon.is_some() {
311                return Err(PlayerError::TalonAlreadyClosed);
312            }
313
314            match self.draw_card(player) {
315                Ok(card) => card,
316                Err(PlayerError::CantTakeCardDeckEmpty) => self.take_trump(player),
317                Err(e) => return Err(e),
318            }
319        };
320
321        player.write().unwrap().cards.push(card.clone());
322
323        let new = self.get_other_player(player).unwrap();
324        let new_id = new.try_read().unwrap().id.clone();
325        let card_len = new.try_read().unwrap().cards.len();
326
327        if card_len < 5 && self.trump.is_some() {
328            self.draw_card_after_trick(new.clone())?;
329        } else {
330            self.swap_to(new.clone());
331            if new.read().unwrap().announcable.len() > 0 {
332                self.notify_priv(new_id.clone(), PrivateEvent::AllowAnnounce);
333            }
334            self.notify_priv(new_id.clone(), PrivateEvent::AllowCloseTalon);
335            self.notify_priv(new_id.clone(), PrivateEvent::AllowPlayCard);
336        }
337        Ok(card)
338    }
339
340    fn draw_card(&mut self, player: &Player) -> Result<Card, PlayerError> {
341        if self.deck.is_empty() {
342            return Err(PlayerError::CantTakeCardDeckEmpty);
343        }
344
345        let card = self.deck.pop().unwrap();
346
347        self.notify_pub(PublicEvent::DeckCardCount(self.deck.len()));
348
349        self.notify_priv(player.id.clone(), PrivateEvent::CardAvailabe(card.clone()));
350        self.notify_pub(PublicEvent::ReceiveCard {
351            user_id: player.id.clone(),
352        });
353
354        Ok(card)
355    }
356
357    pub fn close_talon(&mut self, player: Arc<RwLock<Player>>) -> Result<(), PlayerError> {
358        let player = &player.read().unwrap();
359        if self.active.is_none()
360            || !self.is_active(player)
361            || self.deck.is_empty()
362            || !self.stack.is_empty()
363        {
364            return Err(PlayerError::PlayerNotActive);
365        }
366
367        if self.closed_talon.is_some() {
368            return Err(PlayerError::TalonAlreadyClosed);
369        }
370
371        self.closed_talon = Some(self.get_owned_player(player));
372        self.notify_pub(PublicEvent::CloseTalon {
373            user_id: player.id.clone(),
374        });
375
376        Ok(())
377    }
378
379    #[inline]
380    pub fn take_cards_til(
381        &mut self,
382        player: Arc<RwLock<Player>>,
383        idx: usize,
384    ) -> Result<Vec<Card>, PlayerError> {
385        let player = &player.read().unwrap();
386        if idx >= self.deck.len() - 1 {
387            return Err(PlayerError::CantTakeAllDeckCards);
388        }
389        if self.deck.is_empty() {
390            return Err(PlayerError::CantTakeCardDeckEmpty);
391        }
392
393        let cards = self.deck.drain(..idx).collect::<Vec<_>>();
394
395        for card in &cards {
396            self.notify_priv(player.id.clone(), PrivateEvent::CardAvailabe(card.clone()));
397            self.notify_pub(PublicEvent::ReceiveCard {
398                user_id: player.id.clone(),
399            });
400        }
401
402        self.notify_pub(PublicEvent::DeckCardCount(self.deck.len()));
403        Ok(cards)
404    }
405
406    #[inline]
407    pub fn get_player_with_greatest_card(&self) -> Result<Arc<RwLock<Player>>, PlayerError> {
408        if self
409            .players
410            .iter()
411            .any(|player| player.read().unwrap().cards.is_empty())
412        {
413            return Err(PlayerError::NotAllPlayersHaveTakenCards);
414        }
415        Ok(self
416            .players
417            .iter()
418            .max_by_key(|player| player.read().unwrap().cards.last().unwrap().value.clone() as u8)
419            .unwrap()
420            .clone())
421    }
422
423    pub fn recreate_deck(&mut self) {
424        self.deck = Self::populate_deck().into();
425        self.players.iter().for_each(|player| {
426            player.write().unwrap().reset();
427        });
428    }
429
430    pub fn distribute_cards(&mut self) -> Result<(), PlayerError> {
431        if self.active.is_none() {
432            return Err(PlayerError::NoPlayerActive);
433        }
434        let mut player_order: Vec<Arc<RwLock<Player>>> = self.players.iter().cloned().collect();
435
436        if !Arc::ptr_eq(self.players.index(0), &self.active.clone().unwrap()) {
437            player_order = self.players.iter().cloned().rev().collect();
438        }
439
440        let mut callbacks = Vec::new();
441        for player in player_order.clone() {
442            for _ in 0..3 {
443                callbacks.extend(self.do_cards(&mut player.write().unwrap()));
444            }
445        }
446        let trump = self.deck.pop().unwrap();
447        self.notify_pub(PublicEvent::TrumpChange(Some(trump.clone())));
448        let _ = self.trump.insert(trump);
449
450        for player in player_order.clone() {
451            for _ in 0..2 {
452                callbacks.extend(self.do_cards(&mut player.write().unwrap()));
453            }
454        }
455
456        callbacks.extend(
457            player_order
458                .into_iter()
459                .map(|player| {
460                    self.update_playable_cards(player.clone())
461                        .into_iter()
462                        .chain(self.update_swap_trump(player.clone()).into_iter())
463                        .chain(self.update_announcable_props(player.clone()).into_iter())
464                })
465                .flatten(),
466        );
467
468        let player_id = self.active.as_ref().unwrap().read().unwrap().id.clone();
469
470        let priv_calls: Vec<Arc<dyn Fn(PrivateEvent) + Send + Sync>> = self
471            .priv_callbacks
472            .get(&player_id)
473            .unwrap_or(&vec![])
474            .clone();
475
476        std::thread::spawn(move || {
477            callbacks.into_iter().for_each(|callback| {
478                callback.join().unwrap();
479            });
480
481            Self::notify(priv_calls.clone(), PrivateEvent::AllowPlayCard)
482                .into_iter()
483                .for_each(|handle| handle.join().unwrap());
484
485            Self::notify(priv_calls, PrivateEvent::AllowCloseTalon)
486                .into_iter()
487                .for_each(|handle| handle.join().unwrap());
488        });
489
490        Ok(())
491    }
492
493    #[inline]
494    pub fn set_active_player(&mut self, player: Arc<RwLock<Player>>) -> Result<(), PlayerError> {
495        if self.active.is_some() {
496            return Err(PlayerError::CantSetActivePlayer);
497        }
498        self.make_active(player);
499        Ok(())
500    }
501
502    pub fn play_card(
503        &mut self,
504        player: Arc<RwLock<Player>>,
505        card: Card,
506    ) -> Result<(), PlayerError> {
507        if self.active.is_none() || !self.is_active(&player.read().unwrap()) {
508            return Err(PlayerError::PlayerNotActive);
509        }
510
511        if !player.read().unwrap().playable_cards.contains(&card) {
512            return Err(PlayerError::CantPlayCard(card));
513        }
514
515        player.write().unwrap().cards.retain(|x| *x != card);
516        player
517            .write()
518            .unwrap()
519            .playable_cards
520            .retain(|x| *x != card);
521
522        self.stack.push(card.clone());
523
524        let player_id = player.read().unwrap().id.clone();
525        self.notify_priv(
526            player_id.clone(),
527            PrivateEvent::CardUnavailabe(card.clone()),
528        );
529
530        self.notify_priv(
531            player_id.clone(),
532            PrivateEvent::CardNotPlayable(card.clone()),
533        );
534
535        self.notify_pub(PublicEvent::PlayCard {
536            user_id: player_id,
537            card,
538        });
539
540        if self.stack.len() == 2 {
541            return self.handle_trick();
542        } else {
543            self.swap_to(self.get_non_active_player().unwrap());
544            self.notify_priv(
545                self.active.as_ref().unwrap().read().unwrap().id.clone(),
546                PrivateEvent::AllowPlayCard,
547            );
548        }
549        Ok(())
550    }
551
552    pub fn swap_trump(
553        &mut self,
554        player: Arc<RwLock<Player>>,
555        card: Card,
556    ) -> Result<Card, PlayerError> {
557        let player = &player.read().unwrap();
558        if self.active.is_none() || !self.is_active(player) {
559            return Err(PlayerError::PlayerNotActive);
560        }
561        if let Some(swap) = self.can_swap_trump(player) {
562            if *swap != card {
563                return Err(PlayerError::CantSwapTrump);
564            }
565            let trump = self.trump.take().unwrap();
566
567            self.trump = Some(card.clone());
568
569            self.notify_priv(player.id.clone(), PrivateEvent::CardAvailabe(trump.clone()));
570            self.notify_priv(player.id.clone(), PrivateEvent::CardUnavailabe(card));
571
572            self.notify_pub(PublicEvent::TrumpChange(Some(
573                self.trump.as_ref().unwrap().clone(),
574            )));
575            return Ok(trump);
576        }
577        Err(PlayerError::CantSwapTrump)
578    }
579
580    pub fn announce_40(&mut self, player: &Player) -> Result<Announcement, PlayerError> {
581        let cards_to_announce = self.can_announce_40(player);
582        if cards_to_announce.is_none() {
583            return Err(PlayerError::CantPlay40);
584        }
585
586        let announcement = models::Announcement {
587            cards: cards_to_announce.unwrap(),
588            announce_type: models::AnnounceType::Forty,
589        };
590
591        self.notify_pub(PublicEvent::Announce {
592            user_id: player.id.clone(),
593            announcement: announcement.clone(),
594        });
595
596        Ok(announcement)
597    }
598
599    pub fn announce_20(
600        &mut self,
601        player: &Player,
602        cards: [Card; 2],
603    ) -> Result<Announcement, PlayerError> {
604        let announce = self.can_announce_20(player);
605        if announce.is_empty() || !contains_card_comb(&announce, cards.clone()) {
606            return Err(PlayerError::CantPlay20);
607        }
608
609        let announcement = models::Announcement {
610            cards,
611            announce_type: models::AnnounceType::Twenty,
612        };
613
614        self.notify_pub(PublicEvent::Announce {
615            user_id: player.id.clone(),
616            announcement: announcement.clone(),
617        });
618
619        Ok(announcement)
620    }
621
622    #[inline]
623    fn get_owned_player(&self, find: &Player) -> Arc<RwLock<Player>> {
624        self.players
625            .iter()
626            .find(|player| player.read().unwrap().id == find.id)
627            .unwrap()
628            .clone()
629    }
630
631    #[inline]
632    fn can_announce_20(&self, player: &Player) -> Vec<[Card; 2]> {
633        if self.active.is_none() || !self.is_active(player) {
634            return Vec::new();
635        }
636
637        (0..4)
638            .filter_map(move |suit: u8| {
639                let mut cards_iter = player.cards.iter().filter(|card| {
640                    card.suit == suit.into()
641                        && (card.value == models::CardVal::Queen
642                            || card.value == models::CardVal::King)
643                });
644                if let (Some(card1), Some(card2)) = (cards_iter.next(), cards_iter.next()) {
645                    Some([card1.clone(), card2.clone()])
646                } else {
647                    None
648                }
649            })
650            .collect()
651    }
652
653    fn can_announce_40(&self, player: &Player) -> Option<[Card; 2]> {
654        let cards_to_announce = self.can_announce_20(player);
655        if cards_to_announce.is_empty() {
656            return None;
657        }
658
659        for pretender in cards_to_announce {
660            // TODO: As this is needed more often, move this into it's own function
661            let trump = match self.trump {
662                Some(ref trump) => trump,
663                None => &self.taken_trump.as_ref().unwrap().1,
664            };
665
666            if pretender.first().unwrap().suit == trump.suit {
667                return Some(pretender);
668            }
669        }
670        None
671    }
672
673    fn populate_deck() -> [Card; 20] {
674        let mut deck = (0..4)
675            .map(|suit: u8| {
676                (10..12).chain(2..5).map(move |value: u8| Card {
677                    value: value.into(),
678                    suit: suit.into(),
679                })
680            })
681            .flatten()
682            .collect::<Vec<Card>>();
683
684        let mut rng = thread_rng();
685        deck.shuffle(&mut rng);
686        deck.try_into()
687            .expect("Programming error. Populated deck is not of length 20")
688    }
689
690    // TODO: Change the return type to one simple JoinHandle
691    fn notify_pub(&self, event: PublicEvent) -> Vec<std::thread::JoinHandle<()>> {
692        Self::notify(self.pub_callbacks.clone(), event)
693    }
694
695    fn notify<T: Clone + Send + Sync + 'static>(
696        callbacks: Vec<Arc<dyn Fn(T) -> () + Send + Sync + 'static>>,
697        event: T,
698    ) -> Vec<std::thread::JoinHandle<()>> {
699        let mut handles = Vec::new();
700        for callback in callbacks.iter().cloned() {
701            let clone = event.clone();
702            handles.push(std::thread::spawn(move || callback(clone)));
703        }
704        handles
705    }
706
707    fn notify_priv(
708        &self,
709        user_id: String,
710        event: PrivateEvent,
711    ) -> Vec<std::thread::JoinHandle<()>> {
712        let mut handles = Vec::new();
713        if let Some(callbacks) = self.priv_callbacks.get(&user_id).cloned() {
714            for callback in callbacks {
715                let clone = event.clone();
716                handles.push(std::thread::spawn(move || callback(clone)));
717            }
718        }
719        handles
720    }
721
722    fn update_announcable_props(
723        &self,
724        player: Arc<RwLock<Player>>,
725    ) -> Vec<std::thread::JoinHandle<()>> {
726        let (callbacks, announcable) = self.notify_announcable_props(&player.read().unwrap());
727        player.write().unwrap().announcable = announcable;
728        callbacks
729    }
730
731    fn notify_announcable_props(
732        &self,
733        player: &Player,
734    ) -> (Vec<std::thread::JoinHandle<()>>, Vec<Announcement>) {
735        let id = player.id.clone();
736
737        let announcable_cards = self.can_announce_20(player);
738        let mut announcements = announcable_cards
739            .iter()
740            .map(|card| Announcement {
741                cards: card.clone(),
742                announce_type: models::AnnounceType::Twenty,
743            })
744            .collect::<Vec<_>>();
745
746        if let Some(announcement_cards) = self.can_announce_40(player) {
747            let forty_announcement = Announcement {
748                cards: announcement_cards,
749                announce_type: models::AnnounceType::Forty,
750            };
751
752            announcements.push(forty_announcement.clone());
753        }
754
755        let player_announcements = player.announcable.clone();
756
757        let mut callbacks = Vec::new();
758
759        let mut announcable = player.announcable.clone();
760
761        for announcement in player_announcements.iter() {
762            if !has_announcable(&announcements, announcement) {
763                announcable.retain(|x| {
764                    x.announce_type != announcement.announce_type
765                        && x.cards.first().unwrap().suit != announcement.cards.first().unwrap().suit
766                });
767
768                callbacks.extend(self.notify_priv(
769                    id.clone(),
770                    PrivateEvent::CannotAnnounce(announcement.clone()),
771                ));
772            }
773        }
774
775        for announcement in announcements {
776            if player
777                .announcements
778                .iter()
779                .any(|x| x.cards.first().unwrap().suit == announcement.cards.first().unwrap().suit)
780            {
781                announcable.retain(|x| {
782                    x.cards.first().unwrap().suit != announcement.cards.first().unwrap().suit
783                });
784                continue;
785            }
786
787            if !player.has_announcable(&announcement) {
788                announcable.push(announcement.clone());
789                callbacks
790                    .extend(self.notify_priv(id.clone(), PrivateEvent::CanAnnounce(announcement)));
791            }
792        }
793        (callbacks, announcable)
794    }
795
796    fn update_swap_trump(&self, player: Arc<RwLock<Player>>) -> Vec<std::thread::JoinHandle<()>> {
797        let (callbacks, can_swap) = self.notify_swap_trump_check(&player.read().unwrap());
798
799        player.write().unwrap().possible_trump_swap = can_swap;
800
801        let player_read = player.read().unwrap();
802        if player_read.possible_trump_swap.is_some() {
803            self.notify_priv(player_read.id.clone(), PrivateEvent::AllowSwapTrump);
804        }
805        callbacks
806    }
807
808    fn notify_swap_trump_check(
809        &self,
810        player: &Player,
811    ) -> (Vec<std::thread::JoinHandle<()>>, Option<Card>) {
812        let mut callbacks = Vec::new();
813        let can_swap = player.possible_trump_swap.is_some();
814        let id = player.id.clone();
815        if let Some(swap) = self.can_swap_trump(player) {
816            let card = swap.clone();
817            if can_swap {
818                return (callbacks, Some(card));
819            }
820            callbacks.extend(self.notify_priv(id, PrivateEvent::TrumpChangePossible(card.clone())));
821            return (callbacks, Some(card));
822        }
823        if can_swap {
824            callbacks.extend(self.notify_priv(
825                id,
826                PrivateEvent::TrumpChangeImpossible(
827                    player.possible_trump_swap.as_ref().unwrap().clone(),
828                ),
829            ));
830        }
831        (callbacks, None)
832    }
833
834    fn swap_to(&mut self, player: Arc<RwLock<Player>>) {
835        self.update_announcable_props(player.clone());
836        self.update_swap_trump(player.clone());
837        self.update_playable_cards(player.clone());
838        if self.active.is_some() && Arc::ptr_eq(&player, self.active.as_ref().unwrap()) {
839            return;
840        }
841
842        if let Some(active) = &self.active {
843            let user_id = active.read().unwrap().id.clone();
844            self.notify_pub(PublicEvent::Inactive {
845                user_id: user_id.clone(),
846            });
847        }
848
849        self.make_active(player.clone());
850    }
851
852    fn make_active(&mut self, player: Arc<RwLock<Player>>) -> Vec<std::thread::JoinHandle<()>> {
853        let user_id = self.active.insert(player).read().unwrap().id.clone();
854
855        self.notify_pub(PublicEvent::Active { user_id })
856    }
857
858    // First player in the array is the player who first played the card (first card on the stack)
859    fn get_winner<'a>(
860        &self,
861        players: [&'a (Arc<RwLock<Player>>, Card); 2],
862    ) -> &'a (Arc<RwLock<Player>>, Card) {
863        let enemy = players.first().unwrap();
864        let active = players.last().unwrap();
865
866        let enemy_suit = enemy.1.suit.clone();
867        let active_suit = active.1.suit.clone();
868        let enemy_is_trump = {
869            if self.trump.is_some() {
870                enemy_suit == self.trump.as_ref().unwrap().suit
871            } else {
872                enemy_suit == self.taken_trump.as_ref().unwrap().1.suit
873            }
874        };
875
876        let active_is_trump = {
877            if self.trump.is_some() {
878                active_suit == self.trump.as_ref().unwrap().suit
879            } else {
880                active_suit == self.taken_trump.as_ref().unwrap().1.suit
881            }
882        };
883
884        if !active_is_trump && enemy_is_trump {
885            enemy
886        } else if active_is_trump && !enemy_is_trump {
887            active
888        } else if self.stack.last().unwrap().suit != self.stack.first().unwrap().suit {
889            enemy
890        } else if self.stack.last().unwrap().value.clone() as u8
891            > self.stack.first().unwrap().value.clone() as u8
892        {
893            active
894        } else {
895            enemy
896        }
897    }
898
899    fn update_finish_round(
900        &mut self,
901        last_trick: Arc<RwLock<Player>>,
902    ) -> Result<bool, PlayerError> {
903        let comparison_result = self.notfiy_points().unwrap();
904
905        let mut winner = comparison_result.winner;
906        let mut loser = comparison_result.loser;
907
908        if winner.points < 66 {
909            if self
910                .players
911                .iter()
912                .any(|player| player.read().unwrap().cards.is_empty())
913            {
914                if let Some(ref player) = self.closed_talon {
915                    if Arc::ptr_eq(&player, &winner.player) {
916                        std::mem::swap(&mut winner.player, &mut loser.player);
917                    }
918                } else if !Arc::ptr_eq(&last_trick, &winner.player) {
919                    std::mem::swap(&mut winner.player, &mut loser.player);
920                }
921            } else {
922                return Ok(false);
923            }
924        }
925
926        self.active = None;
927
928        let points;
929        if loser.points == 0 {
930            points = 3;
931        } else if loser.points <= 33 {
932            points = 2;
933        } else {
934            points = 1;
935        }
936
937        winner.player.write().unwrap().points += points;
938
939        let mut ranked = HashMap::new();
940        {
941            let winner = winner.player.read().unwrap();
942            let loser = loser.player.read().unwrap();
943            ranked.insert(winner.id.clone(), winner.points);
944            ranked.insert(loser.id.clone(), loser.points);
945        }
946
947        self.notify_pub(PublicEvent::Result {
948            winner: winner.player.read().unwrap().id.clone(),
949            points,
950            ranked,
951        });
952
953        if self
954            .players
955            .iter()
956            .find(|player| player.read().unwrap().points >= 7)
957            .is_none()
958        {
959            return Ok(true);
960        }
961
962        let mut res = HashMap::new();
963        res.insert(
964            winner.player.read().unwrap().id.clone(),
965            winner.player.read().unwrap().points,
966        );
967        res.insert(
968            loser.player.read().unwrap().id.clone(),
969            loser.player.read().unwrap().points,
970        );
971
972        self.notify_pub(PublicEvent::FinalResult {
973            ranked: res,
974            winner: winner.player.read().unwrap().id.clone(),
975        });
976        Ok(true)
977    }
978
979    pub fn calc_points(&self) -> Result<CardComparisonResult, PlayerError> {
980        let points = self
981            .players
982            .iter()
983            .map(|player| {
984                let player = player.read().unwrap();
985                player.tricks.iter().flatten().fold(
986                    player
987                        .announcements
988                        .iter()
989                        .map(|a| {
990                            if !player.tricks.is_empty() {
991                                a.announce_type.clone() as u8
992                            } else {
993                                0 as u8
994                            }
995                        })
996                        .sum(),
997                    |acc, card| acc + card.value.clone() as u8,
998                )
999            })
1000            .zip(self.players.iter());
1001
1002        let (max_points, winner) = points.clone().max_by_key(|(points, _)| *points).unwrap();
1003        let (min_points, loser) = points.min_by_key(|(points, _)| *points).unwrap();
1004
1005        Ok(CardComparisonResult {
1006            winner: PlayerPoint {
1007                player: winner.clone(),
1008                points: max_points,
1009            },
1010            loser: PlayerPoint {
1011                player: loser.clone(),
1012                points: min_points,
1013            },
1014        })
1015    }
1016
1017    fn notfiy_points(&mut self) -> Result<CardComparisonResult, PlayerError> {
1018        let comparison = self.calc_points()?;
1019        self.notify_pub(PublicEvent::Score {
1020            user_id: comparison.winner.player.read().unwrap().id.clone(),
1021            points: comparison.winner.points,
1022        });
1023
1024        self.notify_pub(PublicEvent::Score {
1025            user_id: comparison.loser.player.read().unwrap().id.clone(),
1026            points: comparison.loser.points,
1027        });
1028
1029        Ok(comparison)
1030    }
1031
1032    fn handle_trick(&mut self) -> Result<(), PlayerError> {
1033        let won = self
1034            .get_winner([
1035                &(
1036                    self.get_non_active_player().unwrap(),
1037                    self.stack.first().unwrap().clone(),
1038                ),
1039                &(
1040                    self.get_active_player().unwrap(),
1041                    self.stack.last().unwrap().clone(),
1042                ),
1043            ])
1044            .0
1045            .clone();
1046
1047        let won_id = won.read().unwrap().id.clone();
1048        self.notify_pub(PublicEvent::Trick {
1049            user_id: won_id.clone(),
1050            cards: self.stack.clone().try_into().unwrap(),
1051        });
1052
1053        let cards = [self.stack.pop().unwrap(), self.stack.pop().unwrap()];
1054
1055        won.write().unwrap().tricks.push(cards);
1056
1057        let exited = self.update_finish_round(won.clone())?;
1058
1059        if exited {
1060            return Ok(());
1061        }
1062
1063        if !self.deck.is_empty() && self.closed_talon.is_none() {
1064            self.draw_card_after_trick(won.clone())?;
1065        } else {
1066            self.swap_to(won.clone());
1067            if won.read().unwrap().announcable.len() > 0 {
1068                self.notify_priv(won_id.clone(), PrivateEvent::AllowAnnounce);
1069            }
1070            self.notify_priv(won_id, PrivateEvent::AllowPlayCard);
1071        }
1072
1073        Ok(())
1074    }
1075
1076    fn do_cards(&mut self, player: &mut Player) -> Vec<std::thread::JoinHandle<()>> {
1077        let card = self.deck.pop().unwrap();
1078        let mut callbacks =
1079            self.notify_priv(player.id.clone(), PrivateEvent::CardAvailabe(card.clone()));
1080        callbacks.extend(self.notify_pub(PublicEvent::ReceiveCard {
1081            user_id: player.id.clone(),
1082        }));
1083        player.cards.push(card);
1084        callbacks
1085    }
1086
1087    pub fn next_round(&mut self, winner: Arc<RwLock<Player>>) {
1088        self.active.replace(winner.clone());
1089        self.closed_talon = None;
1090        self.taken_trump = None;
1091        self.stack.clear();
1092
1093        for player in &self.players {
1094            let mut player_lock = player.write().unwrap();
1095
1096            for card in player_lock.cards.iter() {
1097                self.notify_priv(
1098                    player_lock.id.clone(),
1099                    PrivateEvent::CardUnavailabe(card.clone()),
1100                )
1101                .into_iter()
1102                .for_each(|handle| handle.join().unwrap());
1103            }
1104
1105            player_lock.cards.clear();
1106        }
1107
1108        self.notify_pub(PublicEvent::DeckCardCount(9));
1109
1110        self.recreate_deck();
1111
1112        self.distribute_cards().unwrap();
1113
1114        self.active = None;
1115        self.swap_to(winner.clone());
1116    }
1117
1118    fn can_swap_trump<'a>(&self, player: &'a Player) -> Option<&'a Card> {
1119        if self.trump.is_none() || !self.stack.is_empty() || self.closed_talon.is_some() {
1120            return None;
1121        }
1122
1123        player.cards.iter().find(|card| {
1124            card.suit == self.trump.as_ref().unwrap().suit && card.value == models::CardVal::Jack
1125        })
1126    }
1127
1128    fn notify_changes_playable_cards(
1129        &self,
1130        player: &Player,
1131        playable: &[Card],
1132    ) -> Vec<std::thread::JoinHandle<()>> {
1133        let mut callbacks: Vec<_> = playable
1134            .iter()
1135            .filter_map(|card| {
1136                if player
1137                    .playable_cards
1138                    .iter()
1139                    .any(|x| x.to_owned() == card.to_owned())
1140                {
1141                    return None;
1142                }
1143                Some(self.notify_priv(player.id.clone(), PrivateEvent::CardPlayable(card.clone())))
1144            })
1145            .into_iter()
1146            .collect();
1147
1148        callbacks.extend(player.playable_cards.iter().filter_map(|card| {
1149            if !playable.iter().any(|x| x.to_owned() == card.to_owned()) {
1150                return Some(self.notify_priv(
1151                    player.id.clone(),
1152                    PrivateEvent::CardNotPlayable(card.clone()),
1153                ));
1154            }
1155            None
1156        }));
1157
1158        callbacks.into_iter().flatten().collect()
1159    }
1160
1161    fn update_playable_cards(
1162        &self,
1163        player: Arc<RwLock<Player>>,
1164    ) -> Vec<std::thread::JoinHandle<()>> {
1165        let playable_cards = self.find_playable_cards(player.clone());
1166
1167        let callbacks =
1168            self.notify_changes_playable_cards(&player.read().unwrap(), &playable_cards);
1169
1170        player.write().unwrap().playable_cards = playable_cards.to_vec();
1171
1172        callbacks
1173    }
1174
1175    fn find_playable_cards(&self, player: Arc<RwLock<Player>>) -> Vec<Card> {
1176        let mut playable = {
1177            if !self.stack.is_empty() && (self.taken_trump.is_some() || self.closed_talon.is_some())
1178            {
1179                let trump = match self.trump {
1180                    Some(ref trump) => trump,
1181                    None => &self.taken_trump.as_ref().unwrap().1,
1182                };
1183
1184                // Force color
1185                let forcing_color: Vec<_> = player
1186                    .read()
1187                    .unwrap()
1188                    .cards
1189                    .iter()
1190                    .filter(|card| card.suit == self.stack.first().unwrap().suit.clone())
1191                    .cloned()
1192                    .collect();
1193
1194                if forcing_color.is_empty() {
1195                    player
1196                        .read()
1197                        .unwrap()
1198                        .cards
1199                        .iter()
1200                        .filter(|card| card.suit == trump.suit)
1201                        .cloned()
1202                        .collect()
1203                } else {
1204                    forcing_color
1205                }
1206            } else {
1207                player.read().unwrap().cards.clone()
1208            }
1209        };
1210
1211        if playable.is_empty() {
1212            playable = player.read().unwrap().cards.clone();
1213        }
1214
1215        if self.closed_talon.is_some() && !self.stack.is_empty() {
1216            // Force trick
1217            let gonna_win: Vec<_> = playable
1218                .clone()
1219                .into_iter()
1220                .filter(|card| {
1221                    self.get_winner([
1222                        &(
1223                            self.get_non_active_player().unwrap().clone(),
1224                            self.stack.first().unwrap().clone(),
1225                        ),
1226                        &(self.get_active_player().unwrap(), card.clone()),
1227                    ])
1228                    .0
1229                    .read()
1230                    .unwrap()
1231                    .id == player.read().unwrap().id
1232                })
1233                .collect();
1234
1235            if !gonna_win.is_empty() {
1236                playable = gonna_win;
1237            }
1238        }
1239
1240        playable
1241    }
1242
1243    fn take_trump(&mut self, player: &Player) -> Card {
1244        let taken_trump = self
1245            .taken_trump
1246            .insert((self.get_owned_player(player), self.trump.take().unwrap()))
1247            .clone();
1248
1249        self.notify_pub(PublicEvent::TrumpChange(None));
1250        // TODO: Everything after this line should be consolidated into a function, as it is also needed in self.draw_card
1251        self.notify_pub(PublicEvent::DeckCardCount(self.deck.len()));
1252        self.notify_priv(
1253            player.id.clone(),
1254            PrivateEvent::CardAvailabe(taken_trump.1.clone()),
1255        );
1256        self.notify_pub(PublicEvent::ReceiveCard {
1257            user_id: player.id.clone(),
1258        });
1259
1260        return taken_trump.1.clone();
1261    }
1262}