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
use
{
rand :: { Rng, RngCore, thread_rng, SeedableRng, distributions::uniform::SampleUniform } ,
rand_chacha :: { ChaCha8Rng } ,
std :: { ops::Range, fmt } ,
log :: { * } ,
};
#[ derive( Debug ) ]
pub struct Dictator
{
seed: u64,
rng : ChaCha8Rng,
}
impl Dictator
{
pub fn new( seed: u64 ) -> Self
{
trace!( "Creating new dictator with seed {}", seed );
Self
{
seed,
rng: ChaCha8Rng::seed_from_u64( seed ),
}
}
pub fn please( &mut self, question: &str, prob: f64 ) -> bool
{
let answer = self.rng.gen_bool( prob );
trace!( "dictator please {}, answer: {}", question, answer );
answer
}
pub fn pick<Idx: SampleUniform + fmt::Debug + Copy + PartialOrd>( &mut self, what: &str, range: Range<Idx> ) -> Idx
{
let pick = self.rng.gen_range( range.clone() );
trace!( "dictator pick {} from {:?}, answer: {:?}", what, range, pick );
pick
}
pub fn seed() -> u64
{
thread_rng().next_u64()
}
}
#[ cfg(test) ]
mod tests
{
use super::*;
#[test]
fn predictable()
{
let mut bd = Dictator::new( 265468510 );
assert!( !bd.please( "one" , 0.4 ) );
assert!( !bd.please( "two" , 0.6 ) );
assert!( !bd.please( "three", 0.5 ) );
assert!( !bd.please( "four" , 0.3 ) );
assert!( bd.please( "five" , 0.9 ) );
assert!( !bd.please( "six" , 0.2 ) );
assert!( !bd.please( "seven", 0.5 ) );
assert!( bd.please( "eight", 0.4 ) );
assert_eq!( 1 , bd.pick( "nine" , 0..100 ) );
assert_eq!( 94, bd.pick( "ten" , 0..100 ) );
assert_eq!( 46, bd.pick( "eleven", 0..100 ) );
assert!( bd.please( "twelve" , 0.6 ) );
assert!( bd.please( "thirteen", 0.5 ) );
assert!( bd.please( "fourteen", 0.5 ) );
assert!( bd.please( "fifteen" , 0.5 ) );
assert!( !bd.please( "sixteen" , 0.5 ) );
}
}