moonpool_sim/providers/
random.rs1use moonpool_core::RandomProvider;
4use rand::distr::{Distribution, StandardUniform, uniform::SampleUniform};
5use std::ops::Range;
6
7use crate::sim::rng::{set_sim_seed, sim_random, sim_random_range};
8
9#[derive(Clone, Debug)]
18pub struct SimRandomProvider {
19 _marker: std::marker::PhantomData<()>,
21}
22
23impl SimRandomProvider {
24 pub fn new(seed: u64) -> Self {
33 set_sim_seed(seed);
35
36 Self {
37 _marker: std::marker::PhantomData,
38 }
39 }
40}
41
42impl RandomProvider for SimRandomProvider {
43 fn random<T>(&self) -> T
44 where
45 StandardUniform: Distribution<T>,
46 {
47 sim_random()
48 }
49
50 fn random_range<T>(&self, range: Range<T>) -> T
51 where
52 T: SampleUniform + PartialOrd,
53 {
54 sim_random_range(range)
55 }
56
57 fn random_ratio(&self) -> f64 {
58 sim_random::<f64>()
59 }
60
61 fn random_bool(&self, probability: f64) -> bool {
62 debug_assert!(
63 (0.0..=1.0).contains(&probability),
64 "Probability must be between 0.0 and 1.0, got {}",
65 probability
66 );
67 sim_random::<f64>() < probability
68 }
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74
75 #[test]
76 fn test_deterministic_randomness() {
77 let provider1 = SimRandomProvider::new(42);
79 let value1_1: f64 = provider1.random();
80 let value1_2: u32 = provider1.random();
81
82 let provider2 = SimRandomProvider::new(42);
83 let value2_1: f64 = provider2.random();
84 let value2_2: u32 = provider2.random();
85
86 assert_eq!(value1_1, value2_1);
87 assert_eq!(value1_2, value2_2);
88 }
89
90 #[test]
91 fn test_random_range() {
92 let provider = SimRandomProvider::new(123);
93
94 for _ in 0..100 {
96 let value = provider.random_range(10..20);
97 assert!(value >= 10);
98 assert!(value < 20);
99 }
100
101 for _ in 0..100 {
103 let value = provider.random_range(0.0..1.0);
104 assert!(value >= 0.0);
105 assert!(value < 1.0);
106 }
107 }
108
109 #[test]
110 fn test_random_ratio() {
111 let provider = SimRandomProvider::new(456);
112
113 for _ in 0..100 {
114 let ratio = provider.random_ratio();
115 assert!(ratio >= 0.0);
116 assert!(ratio < 1.0);
117 }
118 }
119
120 #[test]
121 fn test_random_bool() {
122 let provider = SimRandomProvider::new(789);
123
124 for _ in 0..10 {
126 assert!(!provider.random_bool(0.0));
127 }
128
129 for _ in 0..10 {
131 assert!(provider.random_bool(1.0));
132 }
133
134 let results: Vec<bool> = (0..100).map(|_| provider.random_bool(0.5)).collect();
136 let true_count = results.iter().filter(|&&x| x).count();
137
138 assert!(
141 true_count > 30 && true_count < 70,
142 "Got {} true values out of 100",
143 true_count
144 );
145 }
146
147 #[test]
148 #[should_panic(expected = "Probability must be between 0.0 and 1.0")]
149 fn test_random_bool_invalid_probability() {
150 let provider = SimRandomProvider::new(999);
151 provider.random_bool(1.5); }
153}