fish_lib/game/services/
weather_service.rs

1use crate::config::ConfigInterface;
2use crate::data::location_data::LocationData;
3use crate::game::errors::resource::GameResourceError;
4use crate::game::errors::GameResult;
5use crate::game::systems::weather_system::config::WeatherSystemConfig;
6use crate::game::systems::weather_system::weather::Weather;
7use crate::game::systems::weather_system::WeatherSystem;
8use chrono::DateTime;
9use chrono_tz::Tz;
10use std::collections::HashMap;
11use std::sync::Arc;
12
13pub trait WeatherServiceInterface: Send + Sync {
14    fn get_weather(
15        &self,
16        location_data: Arc<LocationData>,
17        time: DateTime<Tz>,
18    ) -> GameResult<Weather>;
19    fn get_current_weather(&self, location_data: Arc<LocationData>) -> GameResult<Weather>;
20}
21
22pub struct WeatherService {
23    time_multiplier: f32,
24    // Weather systems by location id
25    weather_systems: HashMap<i32, WeatherSystem>,
26}
27
28impl WeatherService {
29    pub fn new(config: Arc<dyn ConfigInterface>) -> Self {
30        let mut systems = HashMap::new();
31        config
32            .locations()
33            .iter()
34            .for_each(|(location_id, location_data)| {
35                let config = WeatherSystemConfig::builder()
36                    .with_location_data(location_data.clone())
37                    .build();
38                let system = WeatherSystem::new(config);
39                systems.insert(*location_id, system);
40            });
41
42        Self {
43            time_multiplier: config.settings().time_speed_multiplier,
44            weather_systems: systems,
45        }
46    }
47}
48
49impl WeatherServiceInterface for WeatherService {
50    fn get_weather(
51        &self,
52        location_data: Arc<LocationData>,
53        time: DateTime<Tz>,
54    ) -> GameResult<Weather> {
55        let location_id = location_data.id;
56        self.weather_systems
57            .get(&location_id)
58            .map(|system| system.get_weather(time, self.time_multiplier))
59            .ok_or_else(|| GameResourceError::location_not_found(location_id).into())
60    }
61
62    fn get_current_weather(&self, location_data: Arc<LocationData>) -> GameResult<Weather> {
63        let time_now = location_data.get_local_time();
64        self.get_weather(location_data, time_now)
65    }
66}