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 let Some(swap) = self.can_swap_trump(player) {
559            if *swap != card {
560                return Err(PlayerError::CantSwapTrump);
561            }
562            let trump = self.trump.take().unwrap();
563
564            self.trump = Some(card.clone());
565
566            self.notify_priv(player.id.clone(), PrivateEvent::CardAvailabe(trump.clone()));
567            self.notify_priv(player.id.clone(), PrivateEvent::CardUnavailabe(card));
568
569            self.notify_pub(PublicEvent::TrumpChange(Some(
570                self.trump.as_ref().unwrap().clone(),
571            )));
572            return Ok(trump);
573        }
574        Err(PlayerError::CantSwapTrump)
575    }
576
577    pub fn announce_40(&mut self, player: &Player) -> Result<Announcement, PlayerError> {
578        let cards_to_announce = self.can_announce_40(player);
579        if cards_to_announce.is_none() {
580            return Err(PlayerError::CantPlay40);
581        }
582
583        let announcement = models::Announcement {
584            cards: cards_to_announce.unwrap(),
585            announce_type: models::AnnounceType::Forty,
586        };
587
588        self.notify_pub(PublicEvent::Announce {
589            user_id: player.id.clone(),
590            announcement: announcement.clone(),
591        });
592
593        Ok(announcement)
594    }
595
596    pub fn announce_20(
597        &mut self,
598        player: &Player,
599        cards: [Card; 2],
600    ) -> Result<Announcement, PlayerError> {
601        let announce = self.can_announce_20(player);
602        if announce.is_empty() || !contains_card_comb(&announce, cards.clone()) {
603            return Err(PlayerError::CantPlay20);
604        }
605
606        let announcement = models::Announcement {
607            cards,
608            announce_type: models::AnnounceType::Twenty,
609        };
610
611        self.notify_pub(PublicEvent::Announce {
612            user_id: player.id.clone(),
613            announcement: announcement.clone(),
614        });
615
616        Ok(announcement)
617    }
618
619    #[inline]
620    fn get_owned_player(&self, find: &Player) -> Arc<RwLock<Player>> {
621        self.players
622            .iter()
623            .find(|player| player.read().unwrap().id == find.id)
624            .unwrap()
625            .clone()
626    }
627
628    #[inline]
629    fn can_announce_20(&self, player: &Player) -> Vec<[Card; 2]> {
630        if self.active.is_none() || !self.is_active(player) {
631            return Vec::new();
632        }
633
634        (0..4)
635            .filter_map(move |suit: u8| {
636                let mut cards_iter = player.cards.iter().filter(|card| {
637                    card.suit == suit.into()
638                        && (card.value == models::CardVal::Queen
639                            || card.value == models::CardVal::King)
640                });
641                if let (Some(card1), Some(card2)) = (cards_iter.next(), cards_iter.next()) {
642                    Some([card1.clone(), card2.clone()])
643                } else {
644                    None
645                }
646            })
647            .collect()
648    }
649
650    fn can_announce_40(&self, player: &Player) -> Option<[Card; 2]> {
651        let cards_to_announce = self.can_announce_20(player);
652        if cards_to_announce.is_empty() {
653            return None;
654        }
655
656        for pretender in cards_to_announce {
657            // TODO: As this is needed more often, move this into it's own function
658            let trump = match self.trump {
659                Some(ref trump) => trump,
660                None => &self.taken_trump.as_ref().unwrap().1,
661            };
662
663            if pretender.first().unwrap().suit == trump.suit {
664                return Some(pretender);
665            }
666        }
667        None
668    }
669
670    fn populate_deck() -> [Card; 20] {
671        let mut deck = (0..4)
672            .map(|suit: u8| {
673                (10..12).chain(2..5).map(move |value: u8| Card {
674                    value: value.into(),
675                    suit: suit.into(),
676                })
677            })
678            .flatten()
679            .collect::<Vec<Card>>();
680
681        let mut rng = thread_rng();
682        deck.shuffle(&mut rng);
683        deck.try_into()
684            .expect("Programming error. Populated deck is not of length 20")
685    }
686
687    // TODO: Change the return type to one simple JoinHandle
688    fn notify_pub(&self, event: PublicEvent) -> Vec<std::thread::JoinHandle<()>> {
689        Self::notify(self.pub_callbacks.clone(), event)
690    }
691
692    fn notify<T: Clone + Send + Sync + 'static>(
693        callbacks: Vec<Arc<dyn Fn(T) -> () + Send + Sync + 'static>>,
694        event: T,
695    ) -> Vec<std::thread::JoinHandle<()>> {
696        let mut handles = Vec::new();
697        for callback in callbacks.iter().cloned() {
698            let clone = event.clone();
699            handles.push(std::thread::spawn(move || callback(clone)));
700        }
701        handles
702    }
703
704    fn notify_priv(
705        &self,
706        user_id: String,
707        event: PrivateEvent,
708    ) -> Vec<std::thread::JoinHandle<()>> {
709        let mut handles = Vec::new();
710        if let Some(callbacks) = self.priv_callbacks.get(&user_id).cloned() {
711            for callback in callbacks {
712                let clone = event.clone();
713                handles.push(std::thread::spawn(move || callback(clone)));
714            }
715        }
716        handles
717    }
718
719    fn update_announcable_props(
720        &self,
721        player: Arc<RwLock<Player>>,
722    ) -> Vec<std::thread::JoinHandle<()>> {
723        let (callbacks, announcable) = self.notify_announcable_props(&player.read().unwrap());
724        player.write().unwrap().announcable = announcable;
725        callbacks
726    }
727
728    fn notify_announcable_props(
729        &self,
730        player: &Player,
731    ) -> (Vec<std::thread::JoinHandle<()>>, Vec<Announcement>) {
732        let id = player.id.clone();
733
734        let announcable_cards = self.can_announce_20(player);
735        let mut announcements = announcable_cards
736            .iter()
737            .map(|card| Announcement {
738                cards: card.clone(),
739                announce_type: models::AnnounceType::Twenty,
740            })
741            .collect::<Vec<_>>();
742
743        if let Some(announcement_cards) = self.can_announce_40(player) {
744            let forty_announcement = Announcement {
745                cards: announcement_cards,
746                announce_type: models::AnnounceType::Forty,
747            };
748
749            announcements.push(forty_announcement.clone());
750        }
751
752        let player_announcements = player.announcable.clone();
753
754        let mut callbacks = Vec::new();
755
756        let mut announcable = player.announcable.clone();
757
758        for announcement in player_announcements.iter() {
759            if !has_announcable(&announcements, announcement) {
760                announcable.retain(|x| {
761                    x.announce_type != announcement.announce_type
762                        && x.cards.first().unwrap().suit != announcement.cards.first().unwrap().suit
763                });
764
765                callbacks.extend(self.notify_priv(
766                    id.clone(),
767                    PrivateEvent::CannotAnnounce(announcement.clone()),
768                ));
769            }
770        }
771
772        for announcement in announcements {
773            if player
774                .announcements
775                .iter()
776                .any(|x| x.cards.first().unwrap().suit == announcement.cards.first().unwrap().suit)
777            {
778                announcable.retain(|x| {
779                    x.cards.first().unwrap().suit != announcement.cards.first().unwrap().suit
780                });
781                continue;
782            }
783
784            if !player.has_announcable(&announcement) {
785                announcable.push(announcement.clone());
786                callbacks
787                    .extend(self.notify_priv(id.clone(), PrivateEvent::CanAnnounce(announcement)));
788            }
789        }
790        (callbacks, announcable)
791    }
792
793    fn update_swap_trump(&self, player: Arc<RwLock<Player>>) -> Vec<std::thread::JoinHandle<()>> {
794        let (callbacks, can_swap) = self.notify_swap_trump_check(&player.read().unwrap());
795
796        player.write().unwrap().possible_trump_swap = can_swap;
797
798        let player_read = player.read().unwrap();
799        if player_read.possible_trump_swap.is_some() {
800            self.notify_priv(player_read.id.clone(), PrivateEvent::AllowSwapTrump);
801        }
802        callbacks
803    }
804
805    fn notify_swap_trump_check(
806        &self,
807        player: &Player,
808    ) -> (Vec<std::thread::JoinHandle<()>>, Option<Card>) {
809        let mut callbacks = Vec::new();
810        let can_swap = player.possible_trump_swap.is_some();
811        let id = player.id.clone();
812        if let Some(swap) = self.can_swap_trump(player) {
813            let card = swap.clone();
814            if can_swap {
815                return (callbacks, Some(card));
816            }
817            callbacks.extend(self.notify_priv(id, PrivateEvent::TrumpChangePossible(card.clone())));
818            return (callbacks, Some(card));
819        }
820        if can_swap {
821            callbacks.extend(self.notify_priv(
822                id,
823                PrivateEvent::TrumpChangeImpossible(
824                    player.possible_trump_swap.as_ref().unwrap().clone(),
825                ),
826            ));
827        }
828        (callbacks, None)
829    }
830
831    fn swap_to(&mut self, player: Arc<RwLock<Player>>) {
832        self.update_announcable_props(player.clone());
833        self.update_swap_trump(player.clone());
834        self.update_playable_cards(player.clone());
835        if self.active.is_some() && Arc::ptr_eq(&player, self.active.as_ref().unwrap()) {
836            return;
837        }
838
839        if let Some(active) = &self.active {
840            let user_id = active.read().unwrap().id.clone();
841            self.notify_pub(PublicEvent::Inactive {
842                user_id: user_id.clone(),
843            });
844        }
845
846        self.make_active(player.clone());
847    }
848
849    fn make_active(&mut self, player: Arc<RwLock<Player>>) -> Vec<std::thread::JoinHandle<()>> {
850        let user_id = self.active.insert(player).read().unwrap().id.clone();
851
852        self.notify_pub(PublicEvent::Active { user_id })
853    }
854
855    // First player in the array is the player who first played the card (first card on the stack)
856    fn get_winner<'a>(
857        &self,
858        players: [&'a (Arc<RwLock<Player>>, Card); 2],
859    ) -> &'a (Arc<RwLock<Player>>, Card) {
860        let enemy = players.first().unwrap();
861        let active = players.last().unwrap();
862
863        let enemy_suit = enemy.1.suit.clone();
864        let active_suit = active.1.suit.clone();
865        let enemy_is_trump = {
866            if self.trump.is_some() {
867                enemy_suit == self.trump.as_ref().unwrap().suit
868            } else {
869                enemy_suit == self.taken_trump.as_ref().unwrap().1.suit
870            }
871        };
872
873        let active_is_trump = {
874            if self.trump.is_some() {
875                active_suit == self.trump.as_ref().unwrap().suit
876            } else {
877                active_suit == self.taken_trump.as_ref().unwrap().1.suit
878            }
879        };
880
881        if !active_is_trump && enemy_is_trump {
882            enemy
883        } else if active_is_trump && !enemy_is_trump {
884            active
885        } else if self.stack.last().unwrap().suit != self.stack.first().unwrap().suit {
886            enemy
887        } else if self.stack.last().unwrap().value.clone() as u8
888            > self.stack.first().unwrap().value.clone() as u8
889        {
890            active
891        } else {
892            enemy
893        }
894    }
895
896    fn update_finish_round(
897        &mut self,
898        last_trick: Arc<RwLock<Player>>,
899    ) -> Result<bool, PlayerError> {
900        let comparison_result = self.notfiy_points().unwrap();
901
902        let mut winner = comparison_result.winner;
903        let mut loser = comparison_result.loser;
904
905        if winner.points < 66 {
906            if self
907                .players
908                .iter()
909                .any(|player| player.read().unwrap().cards.is_empty())
910            {
911                if let Some(ref player) = self.closed_talon {
912                    if Arc::ptr_eq(&player, &winner.player) {
913                        std::mem::swap(&mut winner.player, &mut loser.player);
914                    }
915                } else if !Arc::ptr_eq(&last_trick, &winner.player) {
916                    std::mem::swap(&mut winner.player, &mut loser.player);
917                }
918            } else {
919                return Ok(false);
920            }
921        }
922
923        let points;
924        if loser.points == 0 {
925            points = 3;
926        } else if loser.points <= 33 {
927            points = 2;
928        } else {
929            points = 1;
930        }
931
932        winner.player.write().unwrap().points += points;
933
934        let mut ranked = HashMap::new();
935        {
936            let winner = winner.player.read().unwrap();
937            let loser = loser.player.read().unwrap();
938            ranked.insert(winner.id.clone(), winner.points);
939            ranked.insert(loser.id.clone(), loser.points);
940        }
941
942        self.notify_pub(PublicEvent::Result {
943            winner: winner.player.read().unwrap().id.clone(),
944            points,
945            ranked,
946        });
947
948        if self
949            .players
950            .iter()
951            .find(|player| player.read().unwrap().points >= 7)
952            .is_none()
953        {
954            return Ok(true);
955        }
956
957        let mut res = HashMap::new();
958        res.insert(
959            winner.player.read().unwrap().id.clone(),
960            winner.player.read().unwrap().points,
961        );
962        res.insert(
963            loser.player.read().unwrap().id.clone(),
964            loser.player.read().unwrap().points,
965        );
966
967        self.notify_pub(PublicEvent::FinalResult {
968            ranked: res,
969            winner: winner.player.read().unwrap().id.clone(),
970        });
971        Ok(true)
972    }
973
974    pub fn calc_points(&self) -> Result<CardComparisonResult, PlayerError> {
975        let points = self
976            .players
977            .iter()
978            .map(|player| {
979                let player = player.read().unwrap();
980                player.tricks.iter().flatten().fold(
981                    player
982                        .announcements
983                        .iter()
984                        .map(|a| {
985                            if !player.tricks.is_empty() {
986                                a.announce_type.clone() as u8
987                            } else {
988                                0 as u8
989                            }
990                        })
991                        .sum(),
992                    |acc, card| acc + card.value.clone() as u8,
993                )
994            })
995            .zip(self.players.iter());
996
997        let (max_points, winner) = points.clone().max_by_key(|(points, _)| *points).unwrap();
998        let (min_points, loser) = points.min_by_key(|(points, _)| *points).unwrap();
999
1000        Ok(CardComparisonResult {
1001            winner: PlayerPoint {
1002                player: winner.clone(),
1003                points: max_points,
1004            },
1005            loser: PlayerPoint {
1006                player: loser.clone(),
1007                points: min_points,
1008            },
1009        })
1010    }
1011
1012    fn notfiy_points(&mut self) -> Result<CardComparisonResult, PlayerError> {
1013        let comparison = self.calc_points()?;
1014        self.notify_pub(PublicEvent::Score {
1015            user_id: comparison.winner.player.read().unwrap().id.clone(),
1016            points: comparison.winner.points,
1017        });
1018
1019        self.notify_pub(PublicEvent::Score {
1020            user_id: comparison.loser.player.read().unwrap().id.clone(),
1021            points: comparison.loser.points,
1022        });
1023
1024        Ok(comparison)
1025    }
1026
1027    fn handle_trick(&mut self) -> Result<(), PlayerError> {
1028        let won = self
1029            .get_winner([
1030                &(
1031                    self.get_non_active_player().unwrap(),
1032                    self.stack.first().unwrap().clone(),
1033                ),
1034                &(
1035                    self.get_active_player().unwrap(),
1036                    self.stack.last().unwrap().clone(),
1037                ),
1038            ])
1039            .0
1040            .clone();
1041
1042        let won_id = won.read().unwrap().id.clone();
1043        self.notify_pub(PublicEvent::Trick {
1044            user_id: won_id.clone(),
1045            cards: self.stack.clone().try_into().unwrap(),
1046        });
1047
1048        let cards = [self.stack.pop().unwrap(), self.stack.pop().unwrap()];
1049
1050        won.write().unwrap().tricks.push(cards);
1051
1052        let exited = self.update_finish_round(won.clone())?;
1053
1054        if exited {
1055            return Ok(());
1056        }
1057
1058        if !self.deck.is_empty() && self.closed_talon.is_none() {
1059            self.draw_card_after_trick(won.clone())?;
1060        } else {
1061            self.swap_to(won.clone());
1062            if won.read().unwrap().announcable.len() > 0 {
1063                self.notify_priv(won_id.clone(), PrivateEvent::AllowAnnounce);
1064            }
1065            self.notify_priv(won_id, PrivateEvent::AllowPlayCard);
1066        }
1067
1068        Ok(())
1069    }
1070
1071    fn do_cards(&mut self, player: &mut Player) -> Vec<std::thread::JoinHandle<()>> {
1072        let card = self.deck.pop().unwrap();
1073        let mut callbacks =
1074            self.notify_priv(player.id.clone(), PrivateEvent::CardAvailabe(card.clone()));
1075        callbacks.extend(self.notify_pub(PublicEvent::ReceiveCard {
1076            user_id: player.id.clone(),
1077        }));
1078        player.cards.push(card);
1079        callbacks
1080    }
1081
1082    pub fn next_round(&mut self, winner: Arc<RwLock<Player>>) {
1083        self.active.replace(winner.clone());
1084        self.closed_talon = None;
1085        self.taken_trump = None;
1086        self.stack.clear();
1087
1088        for player in &self.players {
1089            let mut player_lock = player.write().unwrap();
1090
1091            for card in player_lock.cards.iter() {
1092                self.notify_priv(
1093                    player_lock.id.clone(),
1094                    PrivateEvent::CardUnavailabe(card.clone()),
1095                ).into_iter().for_each(|handle| handle.join().unwrap());
1096            }
1097
1098            player_lock.cards.clear();
1099        }
1100
1101        self.notify_pub(PublicEvent::DeckCardCount(9));
1102
1103        self.recreate_deck();
1104
1105        self.distribute_cards().unwrap();
1106
1107        self.active = None;
1108        self.swap_to(winner.clone());
1109    }
1110
1111    fn can_swap_trump<'a>(&self, player: &'a Player) -> Option<&'a Card> {
1112        if self.active.is_none()
1113            || self.trump.is_none()
1114            || !self.stack.is_empty()
1115            || self.closed_talon.is_some()
1116        {
1117            return None;
1118        }
1119
1120        player.cards.iter().find(|card| {
1121            card.suit == self.trump.as_ref().unwrap().suit && card.value == models::CardVal::Jack
1122        })
1123    }
1124
1125    fn notify_changes_playable_cards(
1126        &self,
1127        player: &Player,
1128        playable: &[Card],
1129    ) -> Vec<std::thread::JoinHandle<()>> {
1130        let mut callbacks: Vec<_> = playable
1131            .iter()
1132            .filter_map(|card| {
1133                if player
1134                    .playable_cards
1135                    .iter()
1136                    .any(|x| x.to_owned() == card.to_owned())
1137                {
1138                    return None;
1139                }
1140                Some(self.notify_priv(player.id.clone(), PrivateEvent::CardPlayable(card.clone())))
1141            })
1142            .into_iter()
1143            .collect();
1144
1145        callbacks.extend(player.playable_cards.iter().filter_map(|card| {
1146            if !playable.iter().any(|x| x.to_owned() == card.to_owned()) {
1147                return Some(self.notify_priv(
1148                    player.id.clone(),
1149                    PrivateEvent::CardNotPlayable(card.clone()),
1150                ));
1151            }
1152            None
1153        }));
1154
1155        callbacks.into_iter().flatten().collect()
1156    }
1157
1158    fn update_playable_cards(
1159        &self,
1160        player: Arc<RwLock<Player>>,
1161    ) -> Vec<std::thread::JoinHandle<()>> {
1162        let playable_cards = self.find_playable_cards(player.clone());
1163
1164        let callbacks =
1165            self.notify_changes_playable_cards(&player.read().unwrap(), &playable_cards);
1166
1167        player.write().unwrap().playable_cards = playable_cards.to_vec();
1168
1169        callbacks
1170    }
1171
1172    fn find_playable_cards(&self, player: Arc<RwLock<Player>>) -> Vec<Card> {
1173        let mut playable = {
1174            if !self.stack.is_empty() && (self.taken_trump.is_some() || self.closed_talon.is_some())
1175            {
1176                let trump = match self.trump {
1177                    Some(ref trump) => trump,
1178                    None => &self.taken_trump.as_ref().unwrap().1,
1179                };
1180
1181                // Force color
1182                let forcing_color: Vec<_> = player
1183                    .read()
1184                    .unwrap()
1185                    .cards
1186                    .iter()
1187                    .filter(|card| card.suit == self.stack.first().unwrap().suit.clone())
1188                    .cloned()
1189                    .collect();
1190
1191                if forcing_color.is_empty() {
1192                    player
1193                        .read()
1194                        .unwrap()
1195                        .cards
1196                        .iter()
1197                        .filter(|card| card.suit == trump.suit)
1198                        .cloned()
1199                        .collect()
1200                } else {
1201                    forcing_color
1202                }
1203            } else {
1204                player.read().unwrap().cards.clone()
1205            }
1206        };
1207
1208        if playable.is_empty() {
1209            playable = player.read().unwrap().cards.clone();
1210        }
1211
1212        if self.closed_talon.is_some() && !self.stack.is_empty() {
1213            // Force trick
1214            let gonna_win: Vec<_> = playable
1215                .clone()
1216                .into_iter()
1217                .filter(|card| {
1218                    self.get_winner([
1219                        &(
1220                            self.get_non_active_player().unwrap().clone(),
1221                            self.stack.first().unwrap().clone(),
1222                        ),
1223                        &(self.get_active_player().unwrap(), card.clone()),
1224                    ])
1225                    .0
1226                    .read()
1227                    .unwrap()
1228                    .id == player.read().unwrap().id
1229                })
1230                .collect();
1231
1232            if !gonna_win.is_empty() {
1233                playable = gonna_win;
1234            }
1235        }
1236
1237        playable
1238    }
1239
1240    fn take_trump(&mut self, player: &Player) -> Card {
1241        let taken_trump = self
1242            .taken_trump
1243            .insert((self.get_owned_player(player), self.trump.take().unwrap()))
1244            .clone();
1245
1246        self.notify_pub(PublicEvent::TrumpChange(None));
1247        // TODO: Everything after this line should be consolidated into a function, as it is also needed in self.draw_card
1248        self.notify_pub(PublicEvent::DeckCardCount(self.deck.len()));
1249        self.notify_priv(
1250            player.id.clone(),
1251            PrivateEvent::CardAvailabe(taken_trump.1.clone()),
1252        );
1253        self.notify_pub(PublicEvent::ReceiveCard {
1254            user_id: player.id.clone(),
1255        });
1256
1257        return taken_trump.1.clone();
1258    }
1259}