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