tokenomics_simulator/
engine_builder.rs1use chrono::Utc;
9#[cfg(feature = "serde")]
10use serde::{Deserialize, Serialize};
11use uuid::Uuid;
12
13use crate::{
14 Simulation, SimulationError, SimulationOptions, SimulationReport, SimulationStatus, Token,
15};
16
17#[derive(Debug, Default, PartialEq)]
19#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
20pub struct SimulationBuilder {
21 pub name: Option<String>,
24
25 pub token: Option<Token>,
28
29 pub description: Option<String>,
32
33 pub options: Option<SimulationOptions>,
36}
37
38impl SimulationBuilder {
39 pub fn new() -> Self {
45 SimulationBuilder::default()
46 }
47
48 pub fn name(mut self, name: String) -> Self {
58 self.name = Some(name);
59 self
60 }
61
62 pub fn token(mut self, token: Token) -> Self {
72 self.token = Some(token);
73 self
74 }
75
76 pub fn description(mut self, description: String) -> Self {
86 self.description = Some(description);
87 self
88 }
89
90 pub fn options(mut self, options: SimulationOptions) -> Self {
100 self.options = Some(options);
101 self
102 }
103
104 pub fn build(self) -> Result<Simulation, SimulationError> {
110 Ok(Simulation {
111 id: Uuid::new_v4(),
112 description: self.description,
113 status: SimulationStatus::Pending,
114 name: self.name.ok_or(SimulationError::MissingName)?,
115 token: self.token.ok_or(SimulationError::MissingToken)?,
116 options: self.options.ok_or(SimulationError::MissingOptions)?,
117 interval_reports: vec![],
118 report: SimulationReport::default(),
119 created_at: Utc::now(),
120 updated_at: Utc::now(),
121 })
122 }
123}
124
125#[cfg(test)]
126mod tests {
127 use rust_decimal::Decimal;
128
129 use crate::{SimulationInterval, TokenBuilder, ValuationModel};
130
131 use super::*;
132
133 #[test]
134 fn test_new_simulation_builder() {
135 let builder = SimulationBuilder::new();
136
137 assert_eq!(builder.name, None);
138 assert_eq!(builder.token, None);
139 assert_eq!(builder.description, None);
140 assert_eq!(builder.options, None);
141 }
142
143 #[test]
144 fn test_build_simulation() {
145 let token = TokenBuilder::new()
146 .name("Test Token".to_string())
147 .total_supply(1_000_000)
148 .build()
149 .unwrap();
150 let options = SimulationOptions {
151 duration: 30,
152 total_users: 100,
153 decimal_precision: 4,
154 market_volatility: Decimal::new(5, 1),
155 transaction_fee_percentage: None,
156 interval_type: SimulationInterval::Daily,
157 adoption_rate: None,
158 valuation_model: Some(ValuationModel::Exponential(1.0)),
159 };
160
161 let simulation = SimulationBuilder::default()
162 .name("Test Simulation".to_string())
163 .description("Test Simulation".to_string())
164 .token(token.clone())
165 .options(options.clone())
166 .build()
167 .unwrap();
168
169 assert_eq!(simulation.name, "Test Simulation");
170 assert_eq!(simulation.token, token);
171 assert_eq!(simulation.options, options);
172 }
173
174 #[test]
175 fn test_build_simulation_missing_name() {
176 let token = TokenBuilder::new()
177 .name("Test Token".to_string())
178 .total_supply(1_000_000)
179 .build()
180 .unwrap();
181 let options = SimulationOptions {
182 duration: 30,
183 total_users: 100,
184 decimal_precision: 4,
185 market_volatility: Decimal::new(5, 1),
186 transaction_fee_percentage: None,
187 interval_type: SimulationInterval::Daily,
188 adoption_rate: None,
189 valuation_model: Some(ValuationModel::Exponential(1.0)),
190 };
191
192 let simulation = SimulationBuilder::default()
193 .token(token)
194 .options(options)
195 .build();
196
197 assert!(simulation.is_err());
198 assert_eq!(simulation.unwrap_err(), SimulationError::MissingName);
199 }
200
201 #[test]
202 fn test_build_simulation_missing_token() {
203 let options = SimulationOptions {
204 duration: 30,
205 total_users: 100,
206 decimal_precision: 4,
207 market_volatility: Decimal::new(5, 1),
208 transaction_fee_percentage: None,
209 interval_type: SimulationInterval::Daily,
210 adoption_rate: None,
211 valuation_model: Some(ValuationModel::Exponential(1.0)),
212 };
213
214 let simulation = SimulationBuilder::default()
215 .name("Test Simulation".to_string())
216 .options(options)
217 .build();
218
219 assert!(simulation.is_err());
220 assert_eq!(simulation.unwrap_err(), SimulationError::MissingToken);
221 }
222
223 #[test]
224 fn test_build_simulation_missing_options() {
225 let token = TokenBuilder::new()
226 .name("Test Token".to_string())
227 .total_supply(1_000_000)
228 .build()
229 .unwrap();
230
231 let simulation = SimulationBuilder::default()
232 .name("Test Simulation".to_string())
233 .token(token)
234 .build();
235
236 assert!(simulation.is_err());
237 assert_eq!(simulation.unwrap_err(), SimulationError::MissingOptions);
238 }
239}