]> git.scottworley.com Git - pluta-lesnura/blame - src/lib.rs
Hooks should not require network access
[pluta-lesnura] / src / lib.rs
CommitLineData
57f490a0
SW
1use rand::Rng;
2
3pub const NUM_RANKS: u8 = 13;
4
5#[derive(Clone, Copy, Eq, PartialEq)]
6pub struct Rank(u8);
7
8#[derive(Clone, Copy)]
9pub struct PathLength(Rank);
10
11#[derive(Clone, Copy, Default)]
12pub struct PathLengthInfo(u16);
13impl PathLengthInfo {
14 #[must_use]
15 pub fn is_showing(&self, i: Rank) -> bool {
16 (self.0 >> i.0) & 1 == 1
17 }
18 fn reveal(&mut self, i: Rank) {
19 self.0 |= 1 << i.0;
20 }
21 pub fn reveal_random(&mut self, true_length: PathLength) -> Option<Rank> {
22 let showing = u8::try_from(self.0.count_ones()).expect("There aren't that many bits");
23 let not_showing = NUM_RANKS - showing;
24 if not_showing <= 1 {
25 return None;
26 }
27
28 let mut show = rand::thread_rng().gen_range(0..not_showing - 1);
29 for i in 0..NUM_RANKS {
30 let r = Rank(i);
31 if !self.is_showing(r) && r != true_length.0 {
32 if show == 0 {
33 self.reveal(r);
34 return Some(r);
35 }
36 show -= 1;
37 }
38 }
39 unreachable!()
40 }
754e9730
SW
41}
42
43#[cfg(test)]
44mod tests {
45 use super::*;
46
47 #[test]
57f490a0
SW
48 fn path_length_info_random_reveal() {
49 let length = PathLength(Rank(7));
50 let mut pli = PathLengthInfo::default();
51 for _ in 0..12 {
52 let old_pli = PathLengthInfo::clone(&pli);
53 match pli.reveal_random(length) {
54 None => panic!("Nothing revealed?"),
55 Some(r) => {
56 assert!(!old_pli.is_showing(r));
57 assert!(pli.is_showing(r));
58 }
59 }
60 assert_eq!(pli.0.count_ones(), 1 + old_pli.0.count_ones());
61 }
62 assert!(pli.reveal_random(length).is_none());
754e9730
SW
63 }
64}