context_weaver/core/processors/
rng.rs

1use std::sync::Arc;
2
3use rand::Rng;
4
5use crate::{types::Number, WorldInfoNode, WorldInfoProcessor};
6
7use super::{PluginBridge, WorldInfoProcessorFactory};
8
9#[derive(Debug, Clone)]
10pub struct RngProcessor {
11    min: Number,
12    max: Number,
13    decimals: bool
14}
15
16impl WorldInfoNode for RngProcessor {
17    fn content(&self) -> Result<String, crate::WorldInfoError> {
18        self.process()
19    }
20
21    fn name(&self) -> String {
22        "weaver.core.rng".to_string()
23    }
24
25    fn cloned(&self) -> Box<dyn WorldInfoNode> {
26        Box::new(self.to_owned())
27    }
28}
29
30impl WorldInfoProcessor for RngProcessor {
31    fn process(&self) -> Result<String, crate::WorldInfoError> {
32        let mut rng = rand::rng();
33
34        if self.decimals {
35            Ok(rng.random_range(self.min.as_f64()..self.max.as_f64()).to_string())
36        } else {
37            let min = self.min.as_f64().round() as i64;
38            let max = self.max.as_f64().round() as i64;
39            Ok(rng.random_range(min..max).to_string())
40        }
41    }
42}
43
44pub struct RngProcessorFactory;
45
46impl<P: PluginBridge + 'static> WorldInfoProcessorFactory<P> for RngProcessorFactory {
47    fn create(&self, properties: &serde_json::Value, _bridge: &Arc<P>) -> Box<dyn WorldInfoProcessor> {
48        let raw_min: crate::WorldInfoType = properties["min"].clone().into();
49        let raw_max: crate::WorldInfoType = properties["max"].clone().into();
50        let raw_decimal: crate::WorldInfoType = properties["decimal"].clone().into();
51
52        let min = match raw_min {
53            crate::WorldInfoType::Number(n) => n,
54            crate::WorldInfoType::String(s) => parse_number(&s).unwrap_or(Number::Int(0)),
55            _ => Number::Int(0),
56        };
57
58        let max = match raw_max {
59            crate::WorldInfoType::Number(n) => n,
60            crate::WorldInfoType::String(s) => parse_number(&s).unwrap_or(Number::Int(100)),
61            _ => Number::Int(100),
62        };
63
64        let decimals = match raw_decimal {
65            crate::WorldInfoType::Boolean(b) => b,
66            _ => false,
67        };
68
69        Box::new(RngProcessor { min, max, decimals })
70    }
71}
72
73fn parse_number(s: &str) -> Option<Number> {
74    if let Ok(i) = s.parse::<i64>() {
75        Some(Number::Int(i))
76    } else if let Ok(u) = s.parse::<u64>() {
77        Some(Number::UInt(u))
78    } else if let Ok(f) = s.parse::<f64>() {
79        Some(Number::Float(f))
80    } else {
81        None
82    }
83}