Skip to main content

zekin_data_structure/
city.rs

1//! 程序的city模块,用来存储和计算城市的各种信息
2//!
3//! # examples
4//! ``` rust
5//! use data_structure::city::*;
6//!
7//! let city = city::new(1, RiskLevel::High);
8//! ```
9
10use crate::way::*;
11use getset::Getters;
12use std::rc::Rc;
13use wasm_bindgen::prelude::*;
14
15#[cfg(target_arch = "wasm32")]
16use js_sys::Array;
17
18/// 城市的风险等级,一共分万三种
19/// 1. High(高风险)
20/// 2. Medium (中风险)
21/// 3. Low (低风险)
22#[wasm_bindgen]
23#[derive(Debug, PartialEq, Clone)]
24pub enum RiskLevel {
25    /// 高风险, 风险权重为 0.9
26    High,
27    /// 中风险, 风险权重为 0.5
28    Medium,
29    /// 低风险, 风险权重为 0.2
30    Low,
31}
32
33/// 城市类, 表示城市的各种基本信息
34#[wasm_bindgen]
35#[derive(Debug, Getters, Clone)]
36pub struct City {
37    /// 返回城市的唯一id
38    #[getset(get = "pub")]
39    id: i32,
40
41    /// 返回城市名称
42    #[getset(get = "pub")]
43    name: String,
44
45    /// 返回城市的风险等级
46    #[getset(get = "pub")]
47    risk_level: RiskLevel,
48
49    /// 返回由城市出发的交通工具
50    #[getset(get = "pub")]
51    start_ways: Vec<Rc<Way>>,
52}
53
54impl PartialEq for City {
55    fn eq(&self, other: &Self) -> bool {
56        self.id == other.id
57    }
58}
59
60impl Eq for City {}
61
62impl City {
63    /// City 的构造函数,创建一个新City
64    /// # Arguments
65    /// * `id` - 城市的唯一id
66    /// * `risk_level` - 城市的风险等级
67    pub fn new(id: i32, name: String, risk_level: RiskLevel) -> City {
68        City {
69            id: id,
70            name: name,
71            risk_level: risk_level,
72            start_ways: Vec::new(),
73        }
74    }
75
76    /// 城市添加一个交通工具
77    /// # Arguments
78    /// * `way` - way的Rc指针
79    pub fn add_way(&mut self, way: Rc<Way>) {
80        self.start_ways.push(way);
81    }
82
83    /// 返回城市的风险权重系数
84    /// * 高风险 => 0.9
85    /// * 中风险 => 0.5
86    /// * 低风险 => 0.2
87    pub fn risk(&self) -> f64 {
88        match self.risk_level {
89            RiskLevel::High => 0.9,
90            RiskLevel::Medium => 0.5,
91            RiskLevel::Low => 0.2,
92        }
93    }
94}
95
96#[cfg(target_arch = "wasm32")]
97#[wasm_bindgen]
98impl City {
99    /// 返回城市的唯一id
100    #[wasm_bindgen(getter = id)]
101    pub fn get_id_ts_binding(&self) -> i32 {
102        self.id
103    }
104    
105    /// 返回城市的名称
106    #[wasm_bindgen(getter = name)]
107    pub fn get_name_ts_binding(&self) -> String {
108        self.name().clone()
109    }
110
111    /// 返回城市的风险等级
112    #[wasm_bindgen(getter = risk)]
113    pub fn get_risk_ts_binding(&self) -> f64 {
114        self.risk()
115    }
116
117    /// 返回由城市出发的交通工具
118    #[wasm_bindgen(getter = start_city)]
119    pub fn get_start_ways_ts_binding(&self) -> Array {
120        unsafe {
121            self.start_ways
122                .iter()
123                .map(|i| JsValue::from((*Rc::into_raw(i.clone())).clone()))
124                .collect()
125        }
126    }
127}
128
129#[cfg(test)]
130mod tests {
131    use super::*;
132    #[test]
133    fn get_high_risk() {
134        let city_high_risk_level = City::new(0, String::from("111"), RiskLevel::High);
135        assert_eq!(city_high_risk_level.risk(), 0.9);
136    }
137
138    #[test]
139    fn get_medium_risk() {
140        let city_medium_risk_level = City::new(0, String::from("111"), RiskLevel::Medium);
141        assert_eq!(city_medium_risk_level.risk(), 0.5);
142    }
143
144    #[test]
145    fn get_low_risk() {
146        let city_low_risk_level = City::new(0, String::from("111"), RiskLevel::Low);
147        assert_eq!(city_low_risk_level.risk(), 0.2);
148    }
149
150    #[test]
151    fn add_way() {
152        let mut city_0 = Rc::new(City::new(0, String::from("111"), RiskLevel::Low));
153        let city_1 = Rc::new(City::new(1, String::from("111"), RiskLevel::Low));
154        let way_rc = Rc::new(Way::new(1, Type::Air, city_0.clone(), city_1.clone(), 3, 4));
155
156        unsafe {
157            Rc::get_mut_unchecked(&mut city_0).add_way(way_rc.clone());
158        }
159        assert_eq!(city_0.start_ways().len(), 1);
160        assert_eq!(city_1.start_ways().len(), 0);
161    }
162}
163
164#[cfg(target_arch = "wasm32")]
165#[cfg(test)]
166mod tests_ts_binding {
167    use super::*;
168    use wasm_bindgen_test::*;
169
170    #[wasm_bindgen_test]
171    fn get_id_0() {
172        let city_0 = City::new(0, String::new(), RiskLevel::High);
173        assert_eq!(city_0.get_id_ts_binding(), 0);
174    }
175
176    #[wasm_bindgen_test]
177    fn get_id_1() {
178        let city_1 = City::new(1, String::new(), RiskLevel::High);
179        assert_eq!(city_1.get_id_ts_binding(), 1);
180    }
181
182    #[wasm_bindgen_test]
183    fn get_high_risk() {
184        let city_high_risk_level = City::new(0, String::new(), RiskLevel::High);
185        assert_eq!(city_high_risk_level.get_risk_ts_binding(), 0.9);
186    }
187
188    #[wasm_bindgen_test]
189    fn get_medium_risk() {
190        let city_medium_risk_level = City::new(0, String::new(), RiskLevel::Medium);
191        assert_eq!(city_medium_risk_level.get_risk_ts_binding(), 0.5);
192    }
193
194    #[wasm_bindgen_test]
195    fn get_low_risk() {
196        let city_low_risk_level = City::new(0, String::new(), RiskLevel::Low);
197        assert_eq!(city_low_risk_level.get_risk_ts_binding(), 0.2);
198    }
199
200    #[wasm_bindgen_test]
201    fn get_start_ways() {
202        let mut city_0 = Rc::new(City::new(0, String::new(), RiskLevel::Low));
203        let city_1 = Rc::new(City::new(1, String::new(), RiskLevel::Low));
204        let way_rc = Rc::new(Way::new(1, Type::Air, city_0.clone(), city_1.clone(), 3, 4));
205
206        unsafe {
207            Rc::get_mut_unchecked(&mut city_0).add_way(way_rc.clone());
208        }
209        assert_eq!(city_0.start_ways().len(), 1);
210        assert_eq!(city_1.start_ways().len(), 0);
211
212        let array = city_0.get_start_ways_ts_binding();
213        assert_eq!(array.length(), 1);
214    }
215}