poke_data/models/
location_area.rs1use crate::data::link_context::LinkContext;
2use crate::data::linkable::Linkable;
3use crate::models::encounter::Encounter;
4use crate::models::encounter_method::EncounterMethodId;
5use crate::models::localized_names::LocalizedStrings;
6use crate::models::location::{Location, LocationId};
7use crate::models::version::VersionId;
8use crate::traits::has_localized_names::HasLocalizedNames;
9use serde::{Deserialize, Serialize};
10use std::collections::HashMap;
11use std::sync::Arc;
12
13pub type LocationAreaId = u16;
14
15#[derive(Debug)]
16pub struct LocationArea {
17 pub id: LocationAreaId,
18 pub identifier: Option<String>,
19 pub names: LocalizedStrings,
20 pub location: Arc<Location>,
21 pub game_index: u16,
22 pub encounter_rates: LocationAreaEncounterRates,
23 pub encounters: HashMap<VersionId, Vec<Arc<Encounter>>>,
24}
25
26#[derive(Debug, Clone, Serialize, Deserialize)]
27pub struct LocationAreaEncounterRates(Vec<LocationAreaEncounterRate>);
28
29impl LocationAreaEncounterRates {
30 pub fn new(rates: Vec<LocationAreaEncounterRate>) -> Self {
31 Self(rates)
32 }
33}
34
35#[derive(Debug, Clone, Serialize, Deserialize)]
36pub struct LocationAreaEncounterRate {
37 pub encounter_method_id: EncounterMethodId,
38 pub version_id: VersionId,
39 pub rate: u8,
40}
41
42#[derive(Debug, Clone, Serialize, Deserialize)]
43pub struct UnlinkedLocationArea {
44 pub id: LocationAreaId,
45 pub identifier: Option<String>,
46 pub names: LocalizedStrings,
47 pub location_id: LocationId,
48 pub game_index: u16,
49 pub encounter_rates: LocationAreaEncounterRates,
50}
51
52impl Linkable for UnlinkedLocationArea {
53 type Linked = Arc<LocationArea>;
54
55 fn link(&self, context: &LinkContext) -> Self::Linked {
56 let location = context
57 .locations
58 .get(&self.location_id)
59 .unwrap_or_else(|| {
60 panic!(
61 "No location '{}' found for location area '{}'",
62 self.location_id, self.id
63 )
64 })
65 .clone();
66
67 let relevant_encounters: Vec<Arc<Encounter>> = context
68 .encounters
69 .iter()
70 .filter_map(|(_, encounter)| {
71 if encounter.location_area_id == self.id {
72 Some(encounter.clone())
73 } else {
74 None
75 }
76 })
77 .collect();
78
79 let encounters = relevant_encounters.iter().fold(
80 HashMap::new(),
81 |mut acc: HashMap<VersionId, Vec<Arc<Encounter>>>, encounter| {
82 acc.entry(encounter.version.id)
83 .or_default()
84 .push(encounter.clone());
85 acc
86 },
87 );
88
89 let location_area = LocationArea {
90 id: self.id,
91 identifier: self.identifier.clone(),
92 names: self.names.clone(),
93 location,
94 game_index: self.game_index,
95 encounter_rates: self.encounter_rates.clone(),
96 encounters,
97 };
98
99 Arc::new(location_area)
100 }
101}
102
103impl HasLocalizedNames for LocationArea {
104 fn localized_names(&self) -> &LocalizedStrings {
105 &self.names
106 }
107}