fish_lib/data/
location_data.rs1use crate::data::season_data::SeasonData;
2use crate::enums::season::Season;
3use chrono::{DateTime, Utc};
4use chrono_tz::Tz;
5use serde::{Deserialize, Serialize};
6
7const SECONDS_PER_YEAR: f64 = 31_556_925.190_8;
8
9#[derive(Debug, Default, Serialize, Deserialize, PartialEq)]
10pub struct LocationData {
11 #[serde(skip, default)]
12 pub id: i32,
13 pub name: String,
14 pub timezone: Tz,
15 pub weather_seed: u32,
16 pub spring: SeasonData,
17 pub summer: SeasonData,
18 pub autumn: SeasonData,
19 pub winter: SeasonData,
20 #[serde(default)]
21 pub required_locations_unlocked: Vec<i32>,
23 #[serde(default)]
24 pub required_species_caught: Vec<i32>,
26}
27
28impl LocationData {
29 fn season_index_and_progress(&self, time: DateTime<Tz>, time_multiplier: f32) -> (usize, f64) {
30 let year_progress = (time.timestamp() as f64 * time_multiplier as f64) % SECONDS_PER_YEAR
31 / SECONDS_PER_YEAR;
32
33 let current_season = year_progress * 4.0;
34 let season_index = current_season.floor() as usize;
35 let season_progress = current_season % 1.0;
36
37 (season_index, season_progress)
38 }
39
40 pub fn current_season_data(&self, time: DateTime<Tz>, time_multiplier: f32) -> SeasonData {
41 let (index, progress) = self.season_index_and_progress(time, time_multiplier);
42
43 let (prev_data, current_data, next_data) = match index {
44 0 => (&self.winter, &self.spring, &self.summer),
45 1 => (&self.spring, &self.summer, &self.autumn),
46 2 => (&self.summer, &self.autumn, &self.winter),
47 3 => (&self.autumn, &self.winter, &self.spring),
48 _ => unreachable!(),
49 };
50
51 if progress < 0.5 {
52 let adjusted_progress = progress * 2.0;
53 let start = prev_data.interpolate(current_data, 0.5);
54 start.interpolate(current_data, adjusted_progress as f32)
55 } else {
56 let adjusted_progress = (progress - 0.5) * 2.0;
57 let start = current_data.interpolate(next_data, 0.5);
58 current_data.interpolate(&start, adjusted_progress as f32)
59 }
60 }
61
62 pub fn current_season(&self, time: DateTime<Tz>, time_multiplier: f32) -> (Season, f64) {
63 let (index, progress) = self.season_index_and_progress(time, time_multiplier);
64 let season = Season::from_index(index);
65 (season, progress)
66 }
67
68 pub fn full_season_information(
69 &self,
70 time: DateTime<Tz>,
71 time_multiplier: f32,
72 ) -> (SeasonData, Season, f64) {
73 let data = self.current_season_data(time, time_multiplier);
74 let (season, progress) = self.current_season(time, time_multiplier);
75 (data, season, progress)
76 }
77
78 pub fn get_local_time(&self) -> DateTime<Tz> {
79 Utc::now().with_timezone(&self.timezone)
80 }
81}