Skip to main content

server/domain/phase/state/
starting.rs

1use serde::{Deserialize, Serialize};
2
3use crate::{
4    display::format_vec,
5    domain::{CutsForDeal, Deck, HasCutsForDeal, HasDeck, HasPending, Pending, Roles},
6};
7
8/// Represents the state of the game during the *starting* phase,
9/// before the deal is assigned and initial hands are dealt.
10///
11/// `cuts_for_deal` entries will be `None` until a player has made a cut.
12/// `pending` reflects player's acknowledgements of the cuts.
13#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
14pub struct Starting {
15    cuts_for_deal: CutsForDeal,
16    deck: Deck,
17    pending: Pending,
18}
19
20impl Starting {
21    /// Creates a new `Starting` state with the provided cut information,
22    /// deck, and pending actions.
23    ///
24    /// The caller is responsible for ensuring that the inputs are valid for
25    /// the beginning of the current starting state of the game.
26    pub fn new(cuts_for_deal: CutsForDeal, deck: Deck, pending: Pending) -> Self {
27        Self {
28            cuts_for_deal,
29            deck,
30            pending,
31        }
32    }
33
34    /// Computes and returns the player roles based on the completed cuts.
35    ///
36    /// If the cuts are incomplete or have the same face value then the
37    /// function returns `None`.
38    #[must_use]
39    pub fn roles(&self) -> Option<Roles> {
40        Roles::from_cuts(&self.cuts_for_deal)
41    }
42}
43
44impl HasCutsForDeal for Starting {
45    fn cuts_for_deal(&self) -> &CutsForDeal {
46        &self.cuts_for_deal
47    }
48
49    fn cuts_for_deal_mut(&mut self) -> &mut CutsForDeal {
50        &mut self.cuts_for_deal
51    }
52}
53
54impl HasDeck for Starting {
55    fn deck(&self) -> &Deck {
56        &self.deck
57    }
58
59    fn deck_mut(&mut self) -> &mut Deck {
60        &mut self.deck
61    }
62}
63
64impl HasPending for Starting {
65    fn pending(&self) -> &Pending {
66        &self.pending
67    }
68
69    fn pending_mut(&mut self) -> &mut Pending {
70        &mut self.pending
71    }
72}
73
74impl Default for Starting {
75    fn default() -> Self {
76        let cuts = [None, None];
77        let deck = Deck::shuffled_pack();
78        let pending = Pending::default();
79        Starting {
80            cuts_for_deal: cuts,
81            deck,
82            pending,
83        }
84    }
85}
86
87impl std::fmt::Display for Starting {
88    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
89        let Self {
90            cuts_for_deal: cuts,
91            deck,
92            pending,
93        } = self;
94        let cuts = cuts
95            .iter()
96            .map(|c| c.map_or(String::from("--"), |c| c.to_string()))
97            .collect::<Vec<_>>();
98        let cuts = format_vec(&cuts);
99
100        write!(
101            f,
102            r#"Starting(
103    cuts: {cuts}
104    deck: {deck}
105    pending: {pending}
106)"#
107        )
108    }
109}