1use crate::algorithm::*;
27use crate::city::*;
28use crate::err::ModuleErr;
29use crate::way::*;
30use getset::Getters;
31use std::rc::Rc;
32use wasm_bindgen::prelude::*;
33
34#[cfg(target_arch = "wasm32")]
35use js_sys::Array;
36
37#[derive(Debug, Clone, PartialEq, Eq)]
42pub enum Status {
43 Arrived(Rc<City>),
47 Waiting(Rc<City>),
51 Taking(Rc<Way>),
55}
56
57#[cfg(target_arch = "wasm32")]
58#[wasm_bindgen]
59#[derive(Debug, Copy, Clone, PartialEq, Eq)]
60pub enum StatusTsBinding {
61 Arrived,
62 Waiting,
63 Taking,
64}
65
66#[wasm_bindgen]
68#[derive(Debug, Getters, Clone)]
69pub struct Person {
70 #[getset(get = "pub")]
72 statu: Status,
73
74 #[getset(get = "pub")]
76 start_city: Rc<City>,
77
78 #[getset(get = "pub")]
80 end_city: Rc<City>,
81
82 #[getset(get = "pub")]
84 time_limit: Option<i32>,
85
86 #[getset(get = "pub")]
88 cost_time: i32,
89
90 #[getset(get = "pub")]
92 start_time: i32,
93
94 #[getset(get = "pub")]
96 total_risk: f64,
97
98 #[getset(get = "pub")]
100 road: Vec<Rc<Way>>,
101}
102
103impl Person {
104 pub fn new(
113 start_city: Rc<City>,
114 end_city: Rc<City>,
115 start_time: i32,
116 time_limit: Option<i32>,
117 ) -> Result<Person, ModuleErr> {
118 let r = calculate(start_city.clone(), end_city.clone(), start_time, time_limit)?;
119 Ok(Person {
120 start_city: start_city.clone(),
121 end_city,
122 time_limit,
123 start_time,
124 statu: Status::Waiting(start_city.clone()),
125
126 cost_time: r.end_time() - start_time,
127 total_risk: r.total_risk().clone(),
128 road: r.road().clone(),
129 })
130 }
131
132 pub fn step(&mut self, now_time: i32) {
136 match self.statu {
137 Status::Arrived(_) => return,
138 _ => {}
139 }
140 let mut pass_time = now_time - self.start_time;
141 let mut time = self.start_time;
142 for way in &self.road {
143 let waiting_time = calculate_time(&(time % 24), way.start_time());
144 if waiting_time > pass_time {
145 self.statu = Status::Waiting(way.start_city().clone());
146 return;
147 }
148 pass_time -= waiting_time;
149 if way.cost_time() > &pass_time {
150 self.statu = Status::Taking(way.clone());
151 return;
152 }
153 pass_time -= way.cost_time();
154 time += waiting_time + way.cost_time();
155 }
156 self.statu = Status::Arrived(self.end_city.clone());
157 }
158}
159
160#[cfg(target_arch = "wasm32")]
161#[wasm_bindgen]
162impl Person {
163 #[wasm_bindgen(getter = statu)]
165 pub fn get_status_ts_binding(&self) -> StatusTsBinding {
166 match self.statu {
167 Status::Arrived(_) => StatusTsBinding::Arrived,
168 Status::Taking(_) => StatusTsBinding::Taking,
169 Status::Waiting(_) => StatusTsBinding::Waiting,
170 }
171 }
172
173 #[wasm_bindgen(getter = statu_value)]
175 pub fn get_status_value_ts_binding(&self) -> JsValue {
176 match &self.statu {
177 Status::Arrived(a) => JsValue::from(unsafe { (*Rc::into_raw(a.clone())).clone() }),
178 Status::Taking(a) => JsValue::from(unsafe { (*Rc::into_raw(a.clone())).clone() }),
179 Status::Waiting(a) => JsValue::from(unsafe { (*Rc::into_raw(a.clone())).clone() }),
180 }
181 }
182
183 #[wasm_bindgen(getter = start_city)]
185 pub fn get_start_city_ts_binding(&self) -> City {
186 unsafe { (*Rc::into_raw(self.start_city.clone())).clone() }
187 }
188
189 #[wasm_bindgen(getter = end_city)]
191 pub fn get_end_city_ts_binding(&self) -> City {
192 unsafe { (*Rc::into_raw(self.end_city.clone())).clone() }
193 }
194
195 #[wasm_bindgen(getter = time_limit)]
197 pub fn get_time_limit_ts_binding(&self) -> Option<i32> {
198 self.time_limit
199 }
200
201 #[wasm_bindgen(getter = cost_time)]
203 pub fn get_cost_time_ts_binding(&self) -> i32 {
204 self.cost_time
205 }
206
207 #[wasm_bindgen(getter = start_time)]
209 pub fn get_start_time_ts_binding(&self) -> i32 {
210 self.start_time
211 }
212
213 #[wasm_bindgen(getter = total_risk)]
215 pub fn get_total_risk_ts_binding(&self) -> f64 {
216 self.total_risk
217 }
218
219 #[wasm_bindgen(getter = road)]
221 pub fn get_road_ts_binding(&self) -> Array {
222 unsafe {
223 self.road
224 .iter()
225 .map(|i| JsValue::from((*Rc::into_raw(i.clone())).clone()))
226 .collect()
227 }
228 }
229}
230
231#[cfg(test)]
232mod tests {
233 use super::*;
234 #[test]
235 fn calculate_time_from_up_to() {
236 assert_eq!(calculate_time(&20, &10), 14);
237 }
238
239 #[test]
240 fn calculate_time_from_down_to() {
241 assert_eq!(calculate_time(&10, &20), 10);
242 }
243 #[test]
244 fn new_person() {
245 let mut city_0 = Rc::new(City::new(0, String::new(), RiskLevel::Low));
246 let city_1 = Rc::new(City::new(1, String::new(), RiskLevel::Low));
247 let way_air = Rc::new(Way::new(1, Type::Air, city_0.clone(), city_1.clone(), 3, 4));
248 unsafe {
249 Rc::get_mut_unchecked(&mut city_0).add_way(way_air.clone());
250 }
251 let person = Person::new(city_0.clone(), city_1, 1, None);
252 assert!(person.is_ok());
253 let person = person.ok().unwrap();
254 assert_eq!(person.statu, Status::Waiting(city_0));
255 }
256
257 #[test]
258 fn step() {
259 let mut city_0 = Rc::new(City::new(0, String::new(), RiskLevel::Low));
260 let city_1 = Rc::new(City::new(1, String::new(), RiskLevel::Low));
261 let way_air = Rc::new(Way::new(1, Type::Air, city_0.clone(), city_1.clone(), 3, 4));
262 unsafe {
263 Rc::get_mut_unchecked(&mut city_0).add_way(way_air.clone());
264 }
265 let person = Person::new(city_0.clone(), city_1.clone(), 2, None);
266 assert!(person.is_ok());
267 let mut person = person.ok().unwrap();
268 assert_eq!(person.statu, Status::Waiting(city_0));
269 person.step(4);
270 assert_eq!(person.statu, Status::Taking(way_air.clone()));
271 person.step(7);
272 assert_eq!(person.statu, Status::Arrived(city_1));
273 }
274}
275
276#[cfg(target_arch = "wasm32")]
277#[cfg(test)]
278mod tests_ts_binding {
279 use super::*;
280 use wasm_bindgen_test::*;
281
282 #[wasm_bindgen_test]
283 fn get_status() {
284 let mut city_0 = Rc::new(City::new(0, String::new(), RiskLevel::Low));
285 let city_1 = Rc::new(City::new(1, String::new(), RiskLevel::Low));
286 let way_air = Rc::new(Way::new(1, Type::Air, city_0.clone(), city_1.clone(), 3, 4));
287 unsafe {
288 Rc::get_mut_unchecked(&mut city_0).add_way(way_air.clone());
289 }
290 let person = Person::new(city_0.clone(), city_1, 1, None);
291 assert!(person.is_ok());
292 let person = person.ok().unwrap();
293 assert_eq!(person.get_status_ts_binding(), StatusTsBinding::Waiting);
294 }
295
296 #[wasm_bindgen_test]
297 fn get_status_value() {
298 let mut city_0 = Rc::new(City::new(0, String::new(), RiskLevel::Low));
299 let city_1 = Rc::new(City::new(1, String::new(), RiskLevel::Low));
300 let way_air = Rc::new(Way::new(1, Type::Air, city_0.clone(), city_1.clone(), 3, 4));
301 unsafe {
302 Rc::get_mut_unchecked(&mut city_0).add_way(way_air.clone());
303 }
304 let person = Person::new(city_0.clone(), city_1, 1, None);
305 assert!(person.is_ok());
306 let person = person.ok().unwrap();
307 assert!(person.get_status_value_ts_binding().is_object())
308 }
309
310 #[wasm_bindgen_test]
311 fn get_time_limit_none() {
312 let mut city_0 = Rc::new(City::new(0, String::new(), RiskLevel::Low));
313 let city_1 = Rc::new(City::new(1, String::new(), RiskLevel::Low));
314 let way_air = Rc::new(Way::new(1, Type::Air, city_0.clone(), city_1.clone(), 3, 4));
315 unsafe {
316 Rc::get_mut_unchecked(&mut city_0).add_way(way_air.clone());
317 }
318 let person = Person::new(city_0.clone(), city_1, 1, None);
319 assert!(person.is_ok());
320 let person = person.ok().unwrap();
321 assert_eq!(person.get_time_limit_ts_binding(), person.time_limit);
322 }
323
324 #[wasm_bindgen_test]
325 fn get_time_limit_some() {
326 let mut city_0 = Rc::new(City::new(0, String::new(), RiskLevel::Low));
327 let city_1 = Rc::new(City::new(1, String::new(), RiskLevel::Low));
328 let way_air = Rc::new(Way::new(1, Type::Air, city_0.clone(), city_1.clone(), 3, 4));
329 unsafe {
330 Rc::get_mut_unchecked(&mut city_0).add_way(way_air.clone());
331 }
332 let person = Person::new(city_0.clone(), city_1, 1, Some(10));
333 assert!(person.is_ok());
334 let person = person.ok().unwrap();
335 assert_eq!(person.get_time_limit_ts_binding(), person.time_limit);
336 }
337
338 #[wasm_bindgen_test]
339 fn get_cost_time() {
340 let mut city_0 = Rc::new(City::new(0, String::new(), RiskLevel::Low));
341 let city_1 = Rc::new(City::new(1, String::new(), RiskLevel::Low));
342 let way_air = Rc::new(Way::new(1, Type::Air, city_0.clone(), city_1.clone(), 3, 4));
343 unsafe {
344 Rc::get_mut_unchecked(&mut city_0).add_way(way_air.clone());
345 }
346 let person = Person::new(city_0.clone(), city_1, 1, Some(10));
347 assert!(person.is_ok());
348 let person = person.ok().unwrap();
349 assert_eq!(person.get_cost_time_ts_binding(), person.cost_time);
350 }
351
352 #[wasm_bindgen_test]
353 fn get_start_city() {
354 let mut city_0 = Rc::new(City::new(0, String::new(), RiskLevel::Low));
355 let city_1 = Rc::new(City::new(1, String::new(), RiskLevel::Low));
356 let way_air = Rc::new(Way::new(1, Type::Air, city_0.clone(), city_1.clone(), 3, 4));
357 unsafe {
358 Rc::get_mut_unchecked(&mut city_0).add_way(way_air.clone());
359 }
360 let person = Person::new(city_0.clone(), city_1, 1, Some(10));
361 assert!(person.is_ok());
362 let person = person.ok().unwrap();
363 assert_eq!(
364 person.get_start_city_ts_binding().get_id_ts_binding(),
365 city_0.get_id_ts_binding()
366 );
367 }
368
369 #[wasm_bindgen_test]
370 fn get_end_city() {
371 let mut city_0 = Rc::new(City::new(0, String::new(), RiskLevel::Low));
372 let city_1 = Rc::new(City::new(1, String::new(), RiskLevel::Low));
373 let way_air = Rc::new(Way::new(1, Type::Air, city_0.clone(), city_1.clone(), 3, 4));
374 unsafe {
375 Rc::get_mut_unchecked(&mut city_0).add_way(way_air.clone());
376 }
377 let person = Person::new(city_0.clone(), city_1.clone(), 1, Some(10));
378 assert!(person.is_ok());
379 let person = person.ok().unwrap();
380 assert_eq!(
381 person.get_end_city_ts_binding().get_id_ts_binding(),
382 city_1.get_id_ts_binding()
383 );
384 }
385
386 #[wasm_bindgen_test]
387 fn get_start_time() {
388 let mut city_0 = Rc::new(City::new(0, String::new(), RiskLevel::Low));
389 let city_1 = Rc::new(City::new(1, String::new(), RiskLevel::Low));
390 let way_air = Rc::new(Way::new(1, Type::Air, city_0.clone(), city_1.clone(), 3, 4));
391 unsafe {
392 Rc::get_mut_unchecked(&mut city_0).add_way(way_air.clone());
393 }
394 let person = Person::new(city_0.clone(), city_1, 1, Some(10));
395 assert!(person.is_ok());
396 let person = person.ok().unwrap();
397 assert_eq!(person.get_start_time_ts_binding(), person.start_time);
398 }
399
400 #[wasm_bindgen_test]
401 fn get_total_risk() {
402 let mut city_0 = Rc::new(City::new(0, String::new(), RiskLevel::Low));
403 let city_1 = Rc::new(City::new(1, String::new(), RiskLevel::Low));
404 let way_air = Rc::new(Way::new(1, Type::Air, city_0.clone(), city_1.clone(), 3, 4));
405 unsafe {
406 Rc::get_mut_unchecked(&mut city_0).add_way(way_air.clone());
407 }
408 let person = Person::new(city_0.clone(), city_1, 1, Some(10));
409 assert!(person.is_ok());
410 let person = person.ok().unwrap();
411 assert_eq!(person.get_total_risk_ts_binding(), person.total_risk);
412 }
413}