otter_support/
fake-rng.rs1use crate::prelude::*;
6
7use parking_lot::Mutex;
8use rand::distributions::uniform::SampleUniform;
9
10#[derive(Deserialize,Debug,Clone,Default)]
11#[serde(transparent)]
12pub struct FakeRngSpec(Option<Vec<String>>);
13
14#[derive(Serialize,Deserialize,Error,Debug,Clone)]
15#[error("RNG is real")]
16pub struct RngIsReal;
17
18impl FakeRngSpec {
19 pub fn make_game_rng(self) -> RngWrap { RngWrap( match self.0 {
20 None => None,
21 Some(ents) => Some(Mutex::new(FakeRng {
22 i: 0,
23 ents,
24 })) }
25 )}
26}
27
28#[derive(Debug)]
29pub struct RngWrap (
30 Option<Mutex<FakeRng>>
31);
32
33#[derive(Debug)]
34struct FakeRng {
35 i: usize,
36 ents: Vec<String>,
37}
38
39impl RngWrap {
40 pub fn is_fake(&self) -> bool { self.0.is_some() }
41
42 #[throws(RngIsReal)]
43 pub fn set_fake(&self, v: Vec<String>, _: AuthorisationSuperuser) {
44 let mut fake = self.0.as_ref().ok_or(RngIsReal)?.lock();
45 fake.i = 0;
46 fake.ents = v;
47 }
48
49 #[throws(as Option)]
50 fn next_fake(&self) -> String {
51 let mut fake = self.0.as_ref()?.lock();
52 let e = fake.ents.get(fake.i)?.clone();
53 fake.i += 1;
54 fake.i %= fake.ents.len();
55 e
56 }
57
58 pub fn shuffle<T:Copy>(&self, slice: &mut [T]) { match self.next_fake() {
59 None => {
60 let mut rng = thread_rng();
61 slice.shuffle(&mut rng);
62 },
63 Some(s) => {
64 let l = slice.len();
65 let n: usize = s.parse().unwrap_or(0);
66 let front = slice[0..n].to_owned();
67 slice.copy_within(n.., 0);
68 slice[l-n..].copy_from_slice(&front);
69 },
70 } }
71
72 pub fn range<T>(&self, range: std::ops::Range<T>) -> T
73 where T: SampleUniform + FromStr + Ord + Default
74 {
75 match self.next_fake() {
76 None => {
77 let mut rng = thread_rng();
78 rng.gen_range(range)
79 },
80 Some(s) => (||{
81 let n: T = s.parse().ok()?;
82 range.contains(&n).then(|| n)
83 })().unwrap_or_default(),
84 }
85 }
86}