conditions/
icons.rs

1use lazy_static::lazy_static;
2use std::collections::HashMap;
3
4use crate::weather::Source;
5
6#[derive(Debug, PartialEq)]
7pub enum TimeOfDay {
8    Night,
9    Day,
10}
11
12impl From<u8> for TimeOfDay {
13    fn from(is_day: u8) -> Self {
14        match is_day {
15            1 => TimeOfDay::Day,
16            _ => TimeOfDay::Night,
17        }
18    }
19}
20
21impl TimeOfDay {
22    #[must_use]
23    pub fn icon(&self, provider: &crate::weather::Source, code: i32) -> String {
24        let icons: &HashMap<i32, &'static str> = match provider {
25            Source::WeatherAPI => match self {
26                TimeOfDay::Day => &WEATHERAPI_DAY_ICONS,
27                TimeOfDay::Night => &WEATHERAPI_NIGHT_ICONS,
28            },
29            Source::OpenMeteo => match self {
30                TimeOfDay::Day => &OPEN_METEO_DAY_ICONS,
31                TimeOfDay::Night => &OPEN_METEO_NIGHT_ICONS,
32            },
33        };
34
35        (*icons.get(&code).unwrap_or(&"?")).to_string()
36    }
37}
38
39lazy_static! {
40    static ref WEATHERAPI_DAY_ICONS: HashMap<i32, &'static str> = {
41        let mut m = HashMap::new();
42        m.insert(1000, " "); // Clear/113
43        m.insert(1003, " "); // Partly cloudy/116
44        m.insert(1006, " "); // Cloudy/119
45        m.insert(1009, " "); // Overcast/122
46        m.insert(1030, " "); // Mist/143
47        m.insert(1063, " "); // Patchy rain possible/176
48        m.insert(1066, " "); // Patchy snow possible/179
49        m.insert(1069, " "); // Patchy sleet possible/182
50        m.insert(1072, " "); // Patchy freezing drizzle possible/185
51        m.insert(1087, " "); // Thundery outbreaks possible/200
52        m.insert(1114, " "); // Blowing snow/227
53        m.insert(1117, " "); // Blizzard/230
54        m.insert(1135, " "); // Fog/248
55        m.insert(1147, " "); // Freezing fog/260
56        m.insert(1150, " "); // Patchy light drizzle/263
57        m.insert(1153, " "); // Light drizzle/266
58        m.insert(1168, " "); // Freezing drizzle/281
59        m.insert(1171, " "); // Heavy freezing drizzle/284
60        m.insert(1180, " "); // Patchy light rain/293
61        m.insert(1183, " "); // Light rain/296
62        m.insert(1186, " "); // Moderate rain at times/299
63        m.insert(1189, " "); // Moderate rain/302
64        m.insert(1192, " "); // Heavy rain at times/305
65        m.insert(1195, " "); // Heavy rain/308
66        m.insert(1198, " "); // Light freezing rain/311
67        m.insert(1201, " "); // Moderate or heavy freezing rain/314
68        m.insert(1204, " "); // Light sleet/317
69        m.insert(1207, " "); // Moderate or heavy sleet/320
70        m.insert(1210, " "); // Patchy light snow/323
71        m.insert(1213, " "); // Light snow/326
72        m.insert(1216, " "); // Patchy moderate snow/329
73        m.insert(1219, " "); // Moderate snow/332
74        m.insert(1222, " "); // Patchy heavy snow/335
75        m.insert(1225, " "); // Heavy snow/338
76        m.insert(1237, " "); // Ice pellets/350
77        m.insert(1240, " "); // Light rain shower/353
78        m.insert(1243, " "); // Moderate or heavy rain shower/356
79        m.insert(1246, " "); // Torrential rain shower/359
80        m.insert(1249, " "); // Light sleet showers/362
81        m.insert(1252, " "); // Moderate or heavy sleet showers/365
82        m.insert(1255, " "); // Light snow showers/368
83        m.insert(1258, " "); // Moderate or heavy snow showers/371
84        m.insert(1261, " "); // Light showers of ice pellets/374
85        m.insert(1264, " "); // Moderate or heavy showers of ice pellets/377
86        m.insert(1273, " "); // Patchy light rain with thunder/386
87        m.insert(1276, " "); // Moderate or heavy rain with thunder/389
88        m.insert(1279, " "); // Patchy light snow with thunder/392
89        m.insert(1282, " "); // Moderate or heavy snow with thunder/395
90        m
91    };
92
93    static ref WEATHERAPI_NIGHT_ICONS: HashMap<i32, &'static str> = {
94        let mut m = HashMap::new();
95        m.insert(1000, ""); // Clear/113
96        m.insert(1003, ""); // Partly cloudy/116
97        m.insert(1006, ""); // Cloudy/119
98        m.insert(1009, ""); // Overcast/122
99        m.insert(1030, ""); // Mist/143
100        m.insert(1063, ""); // Patchy rain possible/176
101        m.insert(1066, ""); // Patchy snow possible/179
102        m.insert(1069, ""); // Patchy sleet possible/182
103        m.insert(1072, ""); // Patchy freezing drizzle possible/185
104        m.insert(1087, ""); // Thundery outbreaks possible/200
105        m.insert(1114, ""); // Blowing snow/227
106        m.insert(1117, ""); // Blizzard/230
107        m.insert(1135, ""); // Fog/248
108        m.insert(1147, ""); // Freezing fog/260
109        m.insert(1150, ""); // Patchy light drizzle/263
110        m.insert(1153, ""); // Light drizzle/266
111        m.insert(1168, ""); // Freezing drizzle/281
112        m.insert(1171, ""); // Heavy freezing drizzle/284
113        m.insert(1180, ""); // Patchy light rain/293
114        m.insert(1183, ""); // Light rain/296
115        m.insert(1186, ""); // Moderate rain at times/299
116        m.insert(1189, ""); // Moderate rain/302
117        m.insert(1192, ""); // Heavy rain at times/305
118        m.insert(1195, ""); // Heavy rain/308
119        m.insert(1198, ""); // Light freezing rain/311
120        m.insert(1201, ""); // Moderate or heavy freezing rain/314
121        m.insert(1204, ""); // Light sleet/317
122        m.insert(1207, ""); // Moderate or heavy sleet/320
123        m.insert(1210, ""); // Patchy light snow/323
124        m.insert(1213, ""); // Light snow/326
125        m.insert(1216, ""); // Patchy moderate snow/329
126        m.insert(1219, ""); // Moderate snow/332
127        m.insert(1222, ""); // Patchy heavy snow/335
128        m.insert(1225, ""); // Heavy snow/338
129        m.insert(1237, ""); // Ice pellets/350
130        m.insert(1240, ""); // Light rain shower/353
131        m.insert(1243, ""); // Moderate or heavy rain shower/356
132        m.insert(1246, ""); // Torrential rain shower/359
133        m.insert(1249, ""); // Light sleet showers/362
134        m.insert(1252, ""); // Moderate or heavy sleet showers/365
135        m.insert(1255, ""); // Light snow showers/368
136        m.insert(1258, ""); // Moderate or heavy snow showers/371
137        m.insert(1261, ""); // Light showers of ice pellets/374
138        m.insert(1264, ""); // Moderate or heavy showers of ice pellets/377
139        m.insert(1273, ""); // Patchy light rain with thunder/386
140        m.insert(1276, ""); // Moderate or heavy rain with thunder/389
141        m.insert(1279, ""); // Patchy light snow with thunder/392
142        m.insert(1282, ""); // Moderate or heavy snow with thunder/395
143        m
144    };
145
146    static ref OPEN_METEO_DAY_ICONS: HashMap<i32, &'static str> = {
147        let mut m = HashMap::new();
148        m.insert(0, " "); // Clear sky
149        m.insert(1, " ");
150        m.insert(2, " ");
151        m.insert(3, " "); // Mainly clear, partly cloudy, and overcast
152        m.insert(45, " ");
153        m.insert(48, " "); // Fog
154        m.insert(51, " ");
155        m.insert(53, " ");
156        m.insert(55, " "); // Drizzle: Light, moderate, and dense intensity
157        m.insert(56, " ");
158        m.insert(57, " "); // Freezing Drizzle: Light and dense intensity
159        m.insert(61, " ");
160        m.insert(63, " ");
161        m.insert(65, " "); // Rain: Slight, moderate and heavy intensity
162        m.insert(66, " ");
163        m.insert(67, " "); // Freezing Rain: Light and heavy intensity
164        m.insert(71, " ");
165        m.insert(73, " ");
166        m.insert(75, " "); // Snow fall: Slight, moderate, and heavy intensity
167        m.insert(77, " "); // Snow grains
168        m.insert(80, " ");
169        m.insert(81, " ");
170        m.insert(82, " "); // Rain showers: Slight, moderate, and violent
171        m.insert(85, " ");
172        m.insert(86, " "); // Snow showers slight and heavy
173        m.insert(95, " "); // Thunderstorm: Slight or moderate
174        m.insert(96, " ");
175        m.insert(99, " "); // Thunderstorm with slight and heavy hail
176        m
177    };
178
179    static ref OPEN_METEO_NIGHT_ICONS: HashMap<i32, &'static str> = {
180        let mut m = HashMap::new();
181        m.insert(0, ""); // Clear sky
182        m.insert(1, "");
183        m.insert(2, "");
184        m.insert(3, ""); // Mainly clear, partly cloudy, and overcast
185        m.insert(45, "");
186        m.insert(48, ""); // Fog
187        m.insert(51, "");
188        m.insert(53, "");
189        m.insert(55, ""); // Drizzle: Light, moderate, and dense intensity
190        m.insert(56, "");
191        m.insert(57, ""); // Freezing Drizzle: Light and dense intensity
192        m.insert(61, "");
193        m.insert(63, "");
194        m.insert(65, ""); // Rain: Slight, moderate and heavy intensity
195        m.insert(66, "");
196        m.insert(67, ""); // Freezing Rain: Light and heavy intensity
197        m.insert(71, "");
198        m.insert(73, "");
199        m.insert(75, ""); // Snow fall: Slight, moderate, and heavy intensity
200        m.insert(77, ""); // Snow grains
201        m.insert(80, "");
202        m.insert(81, "");
203        m.insert(82, ""); // Rain showers: Slight, moderate, and violent
204        m.insert(85, "");
205        m.insert(86, ""); // Snow showers slight and heavy
206        m.insert(95, ""); // Thunderstorm: Slight or moderate
207        m.insert(96, "");
208        m.insert(99, ""); // Thunderstorm with slight and heavy hail
209        m
210    };
211}
212
213#[cfg(test)]
214mod tests {
215    use super::*;
216
217    #[test]
218    fn it_converts_1_to_day() {
219        assert_eq!(TimeOfDay::from(1), TimeOfDay::Day);
220    }
221
222    #[test]
223    fn it_converts_0_to_night() {
224        assert_eq!(TimeOfDay::from(0), TimeOfDay::Night);
225    }
226
227    #[test]
228    fn it_converts_any_other_value_to_night() {
229        assert_eq!(TimeOfDay::from(42), TimeOfDay::Night);
230    }
231
232    #[test]
233    fn valid_code_for_day() {
234        let icon =
235            TimeOfDay::Day.icon(&crate::weather::Source::WeatherAPI, 1006);
236
237        assert_eq!(icon, " ".to_string());
238    }
239
240    #[test]
241    fn valid_code_for_night() {
242        let icon =
243            TimeOfDay::Night.icon(&crate::weather::Source::OpenMeteo, 71);
244
245        assert_eq!(icon, "".to_string());
246    }
247
248    #[test]
249    fn invalid_code_for() {
250        let icon =
251            TimeOfDay::Night.icon(&crate::weather::Source::WeatherAPI, 9999);
252
253        assert_eq!(icon, "?".to_string());
254    }
255}