1use lazy_static::lazy_static;
2use rand::rngs::SmallRng;
3use rand::Rng;
4use rand::SeedableRng;
5use std::ops::Add;
6use std::ops::Range;
7use std::ops::Sub;
8use std::sync::Mutex;
9
10use crate::geom::Line;
11use crate::geom::Point;
12
13lazy_static! {
14 static ref GLOBAL_RNG: Mutex<SmallRng> = {
15 let rng = SmallRng::seed_from_u64(100);
16 Mutex::new(rng)
17 };
18}
19
20#[derive(Copy, Clone)]
21pub struct Random {
22 min: f32,
23 max: f32,
24}
25
26impl Random {
27 pub fn new(range: Range<f32>) -> Self {
28 let min = range.start.min(range.end);
29 let max = range.start.max(range.end);
30
31 Self { min, max }
32 }
33
34 pub fn random(&self) -> f32 {
35 random_range(self.min..self.max)
36 }
37}
38
39pub fn random(range: Range<f32>) -> f32 {
40 let min = range.start.min(range.end);
41 let max = range.start.max(range.end);
42
43 random_range(min..max)
44}
45
46fn random_range(range: Range<f32>) -> f32 {
47 GLOBAL_RNG.lock().unwrap().gen_range(range)
48}
49
50impl Add<f32> for Random {
51 type Output = f32;
52
53 fn add(self, other: f32) -> f32 {
54 other + self.random()
55 }
56}
57
58impl Add<Point<f32>> for Random {
59 type Output = Point;
60
61 fn add(self, Point(x, y): Point) -> Point {
62 Point(self + x, self + y)
63 }
64}
65
66impl Add<Line<f32>> for Random {
67 type Output = Line;
68
69 fn add(self, Line(start, end): Line) -> Line {
70 Line(self + start, self + end)
71 }
72}
73
74impl Sub<f32> for Random {
75 type Output = f32;
76
77 fn sub(self, other: f32) -> f32 {
78 other - self.random()
79 }
80}
81
82impl Sub<Point<f32>> for Random {
83 type Output = Point;
84
85 fn sub(self, Point(x, y): Point) -> Point {
86 Point(self - x, self - y)
87 }
88}
89
90impl Sub<Line<f32>> for Random {
91 type Output = Line;
92
93 fn sub(self, Line(start, end): Line) -> Line {
94 Line(self - start, self - end)
95 }
96}