warlocks_cauldron/providers/
address.rs1use super::dependencies::*;
2
3
4pub enum DDType {
5 lt, lg,
6}
7
8#[derive(Debug)]
9pub enum FloatNumber {
10 DMS(String),
11 Raw(f32),
12}
13
14impl std::fmt::Display for FloatNumber {
15 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
16 write!(f, "{}", match self {
17 FloatNumber::DMS(dms) => dms.to_string(),
18 FloatNumber::Raw(raw) => raw.to_string(),
19 })
20 }
21}
22
23#[derive(Debug)]
24pub enum Coordinates {
25 DMS(String, String),
26 Raw(f32, f32),
27}
28
29impl std::fmt::Display for Coordinates {
30 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31 let coordiantes = match self {
32 Coordinates::DMS(lng, lat) => (lng.to_string(), lat.to_string()),
33 Coordinates::Raw(lng, lat) => (lng.to_string(), lat.to_string()),
34 };
35
36 write!(f, "({}, {})", coordiantes.0, coordiantes.1)
37 }
38}
39
40
41pub struct Address<'a>(pub &'a Locale);
45
46impl<'a> Address<'a> {
47 fn data(&self) -> &ParsedData { self.0.get_data() }
49
50 fn dd_to_dms(num: f32, dd_type: DDType) -> String {
56 let direction = match dd_type {
57 DDType::lg => if num < 0.0 { "W" } else { "E" },
58 DDType::lt => if num < 0.0 { "S" } else { "N" },
59 };
60
61 let num = num.abs();
62 let degrees = num.floor();
63 let part = num - degrees;
64 let minutes = (part * 60.0).floor();
65 let seconds = 3600.0 * part - 60.0 * minutes;
66 format!("{degrees}º{minutes}'{seconds:.3}\"{direction}")
67 }
68
69 fn get_fs(key: DDType, dms: bool) -> FloatNumber {
75 let rng = match key {
76 DDType::lt => (-90.0, 90.0),
77 DDType::lg => (-180.0, 180.0),
78 };
79
80 let result = uniform(rng.0, rng.1);
81
82 match dms {
83 true => FloatNumber::DMS(Self::dd_to_dms(result, key)),
84 false => FloatNumber::Raw(result),
85 }
86 }
87
88 pub fn street_number(&self) -> i32 {
92 rand::thread_rng().gen_range(0..1400)
93 }
94
95 pub fn street_name(&self) -> &str {
99 get_random_element(self.data().address.street.name.iter())
100 }
101
102 pub fn street_suffix(&self) -> &str {
106 get_random_element(self.data().address.street.suffix.iter())
107 }
108
109 #[deprecated(since = "0.0.0", note = "use .local_address()")]
112 pub fn address(&self) -> String {
113 self.local_address()
114 }
115
116 pub fn local_address(&self) -> String {
120 let data = self.data();
121
122 let format = &data.address.address_fmt;
123
124 let st_num = &self.street_number().to_string();
125 let st_name = self.street_name();
126
127 if SHORTENED_ADDRESS_FMT.contains(&data.lang_code) {
128 return format
129 .replace("{st_num}", st_num)
130 .replace("{st_name}", st_name);
131 }
132
133 if data.lang_code.eq("ja") {
134 return format
135 .replacen("{}", self.city(), 1)
136 .replacen("{}", &randint(0, 100).to_string(), 1)
137 .replacen("{}", &randint(0, 100).to_string(), 1)
138 .replacen("{}", &randint(0, 100).to_string(), 1);
139 }
140
141 format
142 .replace("{st_num}", st_num)
143 .replace("{st_name}", st_name)
144 .replace("{st_sfx}", &self.street_suffix())
145 }
146
147 pub fn full_address(&self) -> String {
151 format!("{}, {}, {}, {}", self.country(true), self.state(false), self.city(), self.local_address())
152 }
153
154 pub fn continent(&self, code: bool) -> &str {
162 get_random_element(match code {
163 true => self.data().address.continent.iter(),
164 false => CONTINENT_CODES.iter(),
165 })
166 }
167
168 pub fn country_code(&self, code: Option<CountryCode>) -> Option<&str> {
175 match COUNTRY_CODES.get(validate_enum(code, None)) {
176 Some(cc) => Some(get_random_element(cc.iter())),
177 None => None,
178 }
179 }
180
181 pub fn country(&self, current_locale: bool) -> &str {
188 match current_locale {
189 false => get_random_element(self.data().address.country.name.iter()),
190 true => &self.data().address.country.current_locale,
191 }
192 }
193
194 pub fn state(&self, abbr: bool) -> &str {
201 get_random_element(
202 match abbr {
203 true => self.data().address.state.abbr.iter(),
204 false => self.data().address.state.name.iter(),
205 }
206 )
207 }
208
209 pub fn region(&self, abbr: bool) -> &str {
216 self.state(abbr)
217 }
218
219 pub fn province(&self, abbr: bool) -> &str {
226 self.state(abbr)
227 }
228
229 pub fn federal_subject(&self, abbr: bool) -> &str {
236 self.state(abbr)
237 }
238
239 pub fn prefecture(&self, abbr: bool) -> &str {
246 self.state(abbr)
247 }
248
249 pub fn city(&self) -> &str {
253 get_random_element(self.data().address.city.iter())
254 }
255
256 pub fn postal_code(&self) -> String {
260 custom_code(&self.data().address.postal_code_fmt, '@', '#')
261 }
262
263 pub fn zip_code(&self) -> String {
267 self.postal_code()
268 }
269
270 pub fn calling_code(&self) -> &str {
274 get_random_element(CALLING_CODES.iter())
275 }
276
277 pub fn latitude(dms: bool) -> FloatNumber {
284 Self::get_fs(DDType::lt, dms)
285 }
286
287 pub fn longitude(dms: bool) -> FloatNumber {
294 Self::get_fs(DDType::lg, dms)
295 }
296
297 pub fn coordinates(dms: bool) -> Coordinates {
304 match (dms, Self::latitude(dms), Self::longitude(dms)) {
305 (true, FloatNumber::DMS(lat), FloatNumber::DMS(lng)) => Coordinates::DMS(lat, lng),
306 (false, FloatNumber::Raw(lat), FloatNumber::Raw(lng)) => Coordinates::Raw(lat, lng),
307 _ => panic!("In theory, it shouldn't break :D"),
308 }
309 }
310}