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#[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 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 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 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 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 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 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 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}