1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
use crate::PlayerFlag;
#[derive(Debug)]
pub struct Win;
impl Win {
pub const FIRST: PlayerFlag = 0b0000_0001;
pub const SECOND: PlayerFlag = 0b0000_0010;
pub const THIRD: PlayerFlag = 0b0000_0100;
pub const FORTH: PlayerFlag = 0b0000_1000;
pub const FIFTH: PlayerFlag = 0b0001_0000;
pub const SIXTH: PlayerFlag = 0b0010_0000;
pub const SEVENTH: PlayerFlag = 0b0100_0000;
pub const EIGHT: PlayerFlag = 0b1000_0000;
pub const NINTH: PlayerFlag = 0b1_0000_0000;
pub const TENTH: PlayerFlag = 0b10_0000_0000;
pub const ELEVENTH: PlayerFlag = 0b100_0000_0000;
pub const TWELFTH: PlayerFlag = 0b1000_0000_0000;
pub const THIRTEENTH: PlayerFlag = 0b1_0000_0000_0000;
pub const FOURTEENTH: PlayerFlag = 0b10_0000_0000_0000;
pub const FIFTEENTH: PlayerFlag = 0b100_0000_0000_0000;
pub const SIXTEENTH: PlayerFlag = 0b1000_0000_0000_0000;
/// `CaseEval` win count Test #2: TAKE TWO detour.
///
/// Our heroic system has been sidelined. Our heroes need a way to translate a zero based
/// index position of a vector into a bit flag representation of that index. So, in other words,
/// the index for the first position in a vector is 0:
///
/// ```
/// let v: Vec<usize> = vec![10, 9, 8, 7, 6];
///
/// assert_eq!(*v.get(0).unwrap(), 10);
/// ```
/// [rust playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=6cf71e83aa0d16dba23fd310d07efc3c)
///
/// So we need a function that will return the bit flag for the specific position in the vector:
/// `0` returns `0b0000_0001`... `1` returns `0b0000_0010`, etc...
///
/// Now I suppose the smart way to write this function would be to create some logic that will
/// convert the index into a bit flag. The problem is, that I don't want to think about that
/// right now, and, as the founder of the dumb coder movement, I am going to write this function
/// in the stupidest way I can think of, proud of the fact that later on, someone smarter than
/// me will offer a cooler, more awesomer way of coding this, and will send me a pull request
/// with their solution just to prove how much smarter they are than me.
///
/// ASIDE: _When you think about it, how much of the shit we do boils down to basic primate
/// behavior? Lord knows that's true with software developers. If only there was a way to
/// harness this dick measuring energy into getting them to write this book for me 🤔_
///
/// Me, I'm going to code a good ol' fashioned match statement:
///
/// ```
/// use wincounter::PlayerFlag;
/// use wincounter::win::Win;
/// fn from_index(i: usize) -> PlayerFlag {
/// match i {
/// 0 => Win::FIRST,
/// 1 => Win::SECOND,
/// 2 => Win::THIRD,
/// _ => PlayerFlag::default()
/// }
/// }
/// assert_eq!(Win::FIRST, from_index(0));
/// assert_eq!(Win::SECOND, from_index(1));
/// ```
///
/// For now, the contract of `wincounter` is to support up to 16 players. The idea behind
/// this library was to have an easy way to deal winning percentages for situations where
/// more than only person in a game could win. Granted, the maximum number of players in a
/// single deck poker game is generally less than that. I've heard numbers of
/// [9, 10, 11,](https://poker.stackexchange.com/questions/4413/what-is-the-maximum-number-of-players-in-texas-holdem)
/// and even [22](https://www.betfirm.com/max-number-of-players-in-texas-hold-em/). Me, I'm
/// doing 16 so I don't have to think about it for a while.
///
/// You will have to forgive me if I don't test drive through this function too much. I've got
/// one failing `todo!()` test, and I'm going to just implement the match as seems write,
/// write tests to verify all of the boundary conditions, and call it a day.
///
/// So what are the boundary conditions?
///
/// * Positive: unsigned integer between 0 and 15.
/// * Negative: unsigned integer greater than 15.
///
/// I'll be honest with you. This wincounter library isn't wowing me. My desire to avoid
/// the hassle of wrapping an u16 `Count` in a struct is making me bend over backwards to
/// deal with the fact that I can't write methods against `Count` because it isn't a struct
/// or an enum. I feel a major refactoring coming on for this code. I'll hold off for now,
/// but it's in my backlog.
///
/// Adding a technical debt not to my code as a reminder.
///
/// *NOTE:* This isn't the first time I've had to do this sort of refactoring. The initial
/// version of the `Card` struct was a
/// [simple type alias](https://github.com/ContractBridge/ckc-rs/blob/5f301f182eb579c9f8df4e243b6ebecd310b1b24/src/lib.rs#L33).
/// For the instance in this book, I decided to write it as a struct to make the code cleaner
/// and easier to manage. It's only a matter of time before I do the same thing to
/// `wincounter::Count`. Not doing things right in order to save you some time will always
/// end up taking more time in the long run. Count on it.
///
#[must_use]
pub fn from_index(i: usize) -> PlayerFlag {
match i {
0 => Win::FIRST,
1 => Win::SECOND,
2 => Win::THIRD,
3 => Win::FORTH,
4 => Win::FIFTH,
5 => Win::SIXTH,
6 => Win::SEVENTH,
7 => Win::EIGHT,
8 => Win::NINTH,
9 => Win::TENTH,
10 => Win::ELEVENTH,
11 => Win::TWELFTH,
12 => Win::THIRTEENTH,
13 => Win::FOURTEENTH,
14 => Win::FIFTEENTH,
15 => Win::SIXTEENTH,
_ => PlayerFlag::default(),
}
}
/// This is probably a needless function, and a pair partner stronger than the voice in my head
/// would probably just tell me to do a simple OR operation. The truth is, that I have to
/// duckduckgo these bitwise operators every time I start to use them, so this is a way for me
/// to separate out the logic, write some tests to make sure I'm getting it right, and move on
/// comfortable with the knowledge that I am doing what I set out to do. Don't be too hard on
/// yourself for writing stupid code. Be hard on yourself for writing untested code.
#[must_use]
pub fn or(a: PlayerFlag, b: PlayerFlag) -> PlayerFlag {
a | b
}
}
#[cfg(test)]
#[allow(non_snake_case)]
mod util__wincounter__win__tests {
use super::*;
#[test]
fn from_index() {
assert_eq!(Win::FIRST, Win::from_index(0));
assert_eq!(Win::SECOND, Win::from_index(1));
assert_eq!(Win::THIRD, Win::from_index(2));
assert_eq!(Win::FORTH, Win::from_index(3));
assert_eq!(Win::FIFTH, Win::from_index(4));
assert_eq!(Win::SIXTH, Win::from_index(5));
assert_eq!(Win::SEVENTH, Win::from_index(6));
assert_eq!(Win::EIGHT, Win::from_index(7));
assert_eq!(Win::NINTH, Win::from_index(8));
assert_eq!(Win::TENTH, Win::from_index(9));
assert_eq!(Win::ELEVENTH, Win::from_index(10));
assert_eq!(Win::TWELFTH, Win::from_index(11));
assert_eq!(Win::THIRTEENTH, Win::from_index(12));
assert_eq!(Win::FOURTEENTH, Win::from_index(13));
assert_eq!(Win::FIFTEENTH, Win::from_index(14));
assert_eq!(Win::SIXTEENTH, Win::from_index(15));
assert_eq!(PlayerFlag::default(), Win::from_index(16));
}
#[test]
fn or() {
assert_eq!(0b0000_0110, Win::or(Win::SECOND, Win::THIRD));
}
#[test]
fn or__overlapping_bits() {
// | and ^ differ when operands share set bits; this catches the | -> ^ mutant
let combined = Win::FIRST | Win::SECOND;
assert_eq!(combined, Win::or(combined, Win::SECOND));
}
}