weiss_core/state/
reveal.rs1use serde::{Deserialize, Serialize};
2
3use crate::db::CardId;
4
5pub const REVEAL_HISTORY_LEN: usize = 8;
7
8#[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 pub fn new() -> Self {
19 Self {
20 entries: [0; REVEAL_HISTORY_LEN],
21 len: 0,
22 head: 0,
23 }
24 }
25
26 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 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}