Skip to main content

weiss_core/state/
reveal.rs

1use serde::{Deserialize, Serialize};
2
3use crate::db::CardId;
4
5/// Max number of reveal history entries tracked per player.
6pub const REVEAL_HISTORY_LEN: usize = 8;
7
8/// Ring buffer of recently revealed cards.
9#[derive(Clone, Debug, Hash, Serialize, Deserialize)]
10pub struct RevealHistory {
11    entries: [CardId; REVEAL_HISTORY_LEN],
12    len: u8,
13    head: u8,
14}
15
16impl RevealHistory {
17    /// Create an empty reveal history.
18    pub fn new() -> Self {
19        Self {
20            entries: [0; REVEAL_HISTORY_LEN],
21            len: 0,
22            head: 0,
23        }
24    }
25
26    /// Push a newly revealed card into the history.
27    pub fn push(&mut self, card: CardId) {
28        let head = self.head as usize;
29        self.entries[head] = card;
30        if (self.len as usize) < REVEAL_HISTORY_LEN {
31            self.len = self.len.saturating_add(1);
32        }
33        self.head = ((head + 1) % REVEAL_HISTORY_LEN) as u8;
34    }
35
36    /// Write entries in chronological order into `out`.
37    pub fn write_chronological(&self, out: &mut [i32]) {
38        out.fill(0);
39        let len = self.len as usize;
40        if len == 0 {
41            return;
42        }
43        let start = if len < REVEAL_HISTORY_LEN {
44            0
45        } else {
46            self.head as usize
47        };
48        for idx in 0..len.min(out.len()) {
49            let entry_idx = if len < REVEAL_HISTORY_LEN {
50                idx
51            } else {
52                (start + idx) % REVEAL_HISTORY_LEN
53            };
54            out[idx] = self.entries[entry_idx] as i32;
55        }
56    }
57}
58
59impl Default for RevealHistory {
60    fn default() -> Self {
61        Self::new()
62    }
63}
64
65#[cfg(test)]
66mod tests {
67    use super::{RevealHistory, REVEAL_HISTORY_LEN};
68
69    #[test]
70    fn reveal_history_chronology_before_wrap() {
71        let mut history = RevealHistory::new();
72        history.push(10);
73        history.push(20);
74        history.push(30);
75        let mut out = [0i32; REVEAL_HISTORY_LEN];
76        history.write_chronological(&mut out);
77        assert_eq!(&out[..3], &[10, 20, 30]);
78        assert!(out[3..].iter().all(|entry| *entry == 0));
79    }
80
81    #[test]
82    fn reveal_history_chronology_after_wrap_keeps_latest_entries() {
83        let mut history = RevealHistory::new();
84        for card in 1..=(REVEAL_HISTORY_LEN as u32 + 3) {
85            history.push(card);
86        }
87        let mut out = [0i32; REVEAL_HISTORY_LEN];
88        history.write_chronological(&mut out);
89        let expected: Vec<i32> = (4..=(REVEAL_HISTORY_LEN as i32 + 3)).collect();
90        assert_eq!(out.as_slice(), expected.as_slice());
91    }
92}