poke_data/models/
location.rs

1use crate::data::link_context::LinkContext;
2use crate::data::linkable::Linkable;
3use crate::models::generation::GenerationId;
4use crate::models::language::LanguageId;
5use crate::models::region::{Region, RegionId};
6use crate::traits::has_identifier::HasIdentifier;
7use crate::types::language::Language;
8use serde::{Deserialize, Serialize};
9use std::collections::HashMap;
10use std::sync::Arc;
11
12pub type LocationId = u16;
13
14#[derive(Debug)]
15pub struct Location {
16    pub id: LocationId,
17    pub identifier: String,
18    pub region: Option<Arc<Region>>,
19    pub names: LocalizedLocationNames,
20    pub game_indices: LocationGameIndices,
21}
22
23#[derive(Debug, Clone, Serialize, Deserialize)]
24pub struct LocationGameIndices(HashMap<GenerationId, u16>);
25
26impl LocationGameIndices {
27    pub fn new(indices: HashMap<GenerationId, u16>) -> Self {
28        Self(indices)
29    }
30}
31
32#[derive(Debug, Clone, Serialize, Deserialize)]
33pub struct LocalizedLocationNames(HashMap<LanguageId, LocalizedLocationName>);
34
35impl LocalizedLocationNames {
36    pub fn new(localizations: HashMap<LanguageId, LocalizedLocationName>) -> Self {
37        Self(localizations)
38    }
39
40    pub fn get_by_language(&self, language: Language) -> Option<&LocalizedLocationName> {
41        let language_id = language as LanguageId;
42        if let Some(target) = self.0.get(&language_id) {
43            return Some(target);
44        }
45
46        let default_language_id = Language::default() as LanguageId;
47        if let Some(default) = self.0.get(&default_language_id) {
48            return Some(default);
49        }
50
51        None
52    }
53}
54
55#[derive(Debug, Clone, Serialize, Deserialize)]
56pub struct LocalizedLocationName {
57    pub name: String,
58    pub subtitle: String,
59}
60
61#[derive(Debug, Clone, Serialize, Deserialize)]
62pub struct UnlinkedLocation {
63    pub id: LocationId,
64    pub identifier: String,
65    pub region_id: Option<RegionId>,
66    pub names: LocalizedLocationNames,
67    pub game_indices: LocationGameIndices,
68}
69
70impl Linkable for UnlinkedLocation {
71    type Linked = Arc<Location>;
72
73    fn link(&self, context: &LinkContext) -> Self::Linked {
74        let region = self.region_id.map(|region_id| {
75            context
76                .regions
77                .get(&region_id)
78                .unwrap_or_else(|| {
79                    panic!("No region '{}' found for location '{}'", region_id, self.id)
80                })
81                .clone()
82        });
83
84        let location = Location {
85            id: self.id,
86            identifier: self.identifier.clone(),
87            region,
88            names: self.names.clone(),
89            game_indices: self.game_indices.clone(),
90        };
91
92        Arc::new(location)
93    }
94}
95
96impl HasIdentifier for Location {
97    fn identifier(&self) -> &str {
98        &self.identifier
99    }
100}