schnapsen_rs/models/
mod.rs

1use std::hash::Hash;
2
3use num_enum::FromPrimitive;
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
7pub struct Card {
8    pub value: CardVal,
9    pub suit: CardSuit,
10}
11
12impl PartialOrd for Card {
13    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
14        Some(self.value.cmp(&other.value))
15    }
16}
17
18impl Ord for Card {
19    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
20        self.value.cmp(&other.value)
21    }
22}
23
24#[derive(Debug, Serialize, Deserialize, Clone, FromPrimitive, PartialEq, Eq, PartialOrd, Ord)]
25#[repr(u8)]
26pub enum CardVal {
27    Ten = 10,
28    Jack = 2,
29    Queen = 3,
30    King = 4,
31    #[default]
32    Ace = 11,
33}
34
35#[derive(Debug, Serialize, Deserialize, Clone, FromPrimitive, PartialEq, Eq)]
36#[repr(u8)]
37pub enum CardSuit {
38    #[default]
39    Hearts = 0,
40    Diamonds = 1,
41    Clubs = 2,
42    Spades = 3,
43}
44
45#[derive(Debug, Clone)]
46pub struct Player {
47    pub id: String,
48    pub cards: Vec<Card>,
49    pub playable_cards: Vec<Card>,
50    pub tricks: Vec<[Card; 2]>,
51    pub announcements: Vec<Announcement>,
52    pub announcable: Vec<Announcement>,
53    pub possible_trump_swap: Option<Card>,
54    pub points: u8,
55}
56
57impl Player {
58    pub fn reset(&mut self) {
59        self.tricks.clear();
60        self.announcements.clear();
61    }
62
63    pub fn new(id: String) -> Self {
64        Player {
65            id,
66            cards: Vec::new(),
67            playable_cards: Vec::new(),
68            tricks: Vec::new(),
69            announcements: Vec::new(),
70            announcable: Vec::new(),
71            points: 0,
72            possible_trump_swap: None,
73        }
74    }
75
76    pub fn has_announced(&self, mut cards: [Card; 2]) -> bool {
77        cards.sort();
78        let announced = self
79            .announcements
80            .iter()
81            .map(|x| {
82                let mut a = x.cards.clone();
83                a.sort();
84                a
85            })
86            .collect::<Vec<_>>();
87        announced.into_iter().any(|x| x == cards)
88    }
89
90    pub fn has_announcable(&self, announcement: &Announcement) -> bool {
91        has_announcable(&self.announcable, announcement)
92    }
93}
94
95pub fn has_announcable(data: &[Announcement], check: &Announcement) -> bool {
96    data.iter().any(|proposed| 
97        proposed.announce_type == check.announce_type
98            && proposed.cards.first().unwrap().suit == check.cards.first().unwrap().suit
99    )
100}
101
102pub fn contains_card_comb(data: &[[Card; 2]], mut check: [Card; 2]) -> bool {
103    check.sort();
104    let announced = data
105        .iter()
106        .map(|x| {
107            let mut clone = x.clone();
108            clone.sort();
109            clone
110        })
111        .collect::<Vec<_>>();
112    announced.into_iter().any(|x| x == check)
113}
114
115impl Hash for Player {
116    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
117        state.write(self.id.as_bytes());
118    }
119}
120
121
122#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
123pub struct Announcement {
124    pub cards: [Card; 2],
125    pub announce_type: AnnounceType,
126}
127
128#[derive(Debug, Serialize, Deserialize, Clone, FromPrimitive, PartialEq, Eq)]
129#[repr(u8)]
130pub enum AnnounceType {
131    Forty = 40,
132    #[default]
133    Twenty = 20,
134}
135