1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use strum::EnumIter;
4use variant_count::VariantCount;
5
6use super::bgs;
7use super::dec::{date_format, date_format_opt};
8use super::RootEntry;
9
10use super::util::DisplayViaSerde;
11use crate::display_via_serde;
12
13use serde;
14
15#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
18#[cfg_attr(feature = "type_hash", derive(type_hash::TypeHash))]
19#[serde(rename_all = "camelCase")]
20#[serde(deny_unknown_fields)]
21pub struct Station {
22 pub id: u64,
23 pub allegiance: Option<bgs::Allegiance>,
25 pub body: Option<StationBody>,
26 pub commodities: Option<Vec<Commodity>>,
27 pub controlling_faction: Option<bgs::ControllingFaction>,
28 pub distance_to_arrival: Option<f32>,
29 pub economy: Option<bgs::Economy>,
30 pub government: Option<bgs::Government>,
31 pub have_market: bool,
32 pub have_outfitting: bool,
33 pub have_shipyard: bool,
34 pub market_id: Option<u64>,
35 pub name: String,
36 pub other_services: Vec<OtherService>,
37 pub outfitting: Option<Vec<Outfitting>>,
38 pub second_economy: Option<bgs::Economy>,
39 pub ships: Option<Vec<Ship>>,
40 pub system_id: Option<u64>,
41 pub system_id64: Option<u64>,
42 pub system_name: Option<String>,
43 #[serde(rename = "type")]
44 pub typ: Option<StationType>,
45 pub update_time: UpdateTime,
47}
48
49impl RootEntry for Station {
50 fn entry_id(&self) -> u64 {
51 self.id
52 }
53
54 fn type_name() -> &'static str {
55 "station"
56 }
57
58 fn time(&self) -> DateTime<Utc> {
59 self.update_time.information
60 }
61}
62
63#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
66#[cfg_attr(feature = "type_hash", derive(type_hash::TypeHash))]
67#[serde(rename_all = "camelCase")]
68#[serde(deny_unknown_fields)]
69pub struct Commodity {
70 id: Option<String>,
71 name: String,
72 buy_price: u64,
74 demand: u64,
75 sell_price: u64,
76 stock: u64,
77 stock_bracket: u64,
78}
79
80#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, EnumIter, VariantCount)]
81#[cfg_attr(feature = "type_hash", derive(type_hash::TypeHash))]
82#[serde(deny_unknown_fields)]
83pub enum OtherService {
84 #[serde(rename = "Black Market")]
85 BlackMarket,
86 Contacts,
87 #[serde(rename = "Crew Lounge")]
88 CrewLounge,
89 #[serde(rename = "Interstellar Factors Contact")]
90 InterstellarFactorsContact,
91 #[serde(rename = "Material Trader")]
92 MaterialTrader,
93 Missions,
94 Refuel,
95 Repair,
96 Restock,
97 #[serde(rename = "Search and Rescue")]
98 SearchAndRescue,
99 #[serde(rename = "Technology Broker")]
100 TechnologyBroker,
101 Tuning,
102 #[serde(rename = "Universal Cartographics")]
103 UniversalCartographics,
104 #[serde(rename = "Apex Interstellar Transport")]
105 ApexInterstellarTransport,
106 #[serde(rename = "Frontline Solutions")]
107 FrontlineSolutions,
108 #[serde(rename = "Pioneer Supplies")]
109 PioneerSupplies,
110 #[serde(rename = "Vista Genomics")]
111 VistaGenomics,
112 #[serde(rename = "System colonisation")]
113 SystemColonisation,
114 #[serde(rename = "Fleet carrier administration")]
115 FleetCarrierAdministration,
116 #[serde(rename = "Fleet carrier vendor")]
117 FleetCarrierVendor,
118 Bartender,
119}
120
121display_via_serde!(OtherService);
122
123#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
124#[cfg_attr(feature = "type_hash", derive(type_hash::TypeHash))]
125#[serde(rename_all = "camelCase")]
126#[serde(deny_unknown_fields)]
127pub struct Outfitting {
128 id: Option<String>,
129 name: String,
130}
131
132#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
133#[serde(untagged)]
134#[cfg_attr(feature = "type_hash", derive(type_hash::TypeHash))]
135pub enum Name {
136 String(String),
137 Number(u64),
138}
139
140impl std::fmt::Display for Name {
141 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
142 match self {
143 Name::String(s) => write!(f, "{}", s),
144 Name::Number(n) => write!(f, "{}", n),
145 }
146 }
147}
148
149#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
150#[cfg_attr(feature = "type_hash", derive(type_hash::TypeHash))]
151#[serde(rename_all = "camelCase")]
152#[serde(deny_unknown_fields)]
153pub struct Ship {
154 id: u64,
155 name: Name,
156}
157
158#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
159#[cfg_attr(feature = "type_hash", derive(type_hash::TypeHash))]
160#[serde(rename_all = "camelCase")]
161#[serde(deny_unknown_fields)]
162pub struct StationBody {
163 pub id: u64,
164 pub latitude: Option<f32>,
166 pub longitude: Option<f32>,
167 pub name: String,
168}
169
170#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, EnumIter, VariantCount)]
171#[cfg_attr(feature = "type_hash", derive(type_hash::TypeHash))]
172#[serde(deny_unknown_fields)]
173pub enum StationType {
174 #[serde(rename = "Ocellus Starport")]
176 OcellusStarport,
177 #[serde(rename = "Orbis Starport")]
178 OrbisStarport,
179 #[serde(rename = "Coriolis Starport")]
180 CoriolisStarport,
181 #[serde(rename = "Asteroid base")]
182 AsteroidBase,
183 #[serde(rename = "Mega ship")]
184 MegaShip,
185 Outpost,
187 #[serde(rename = "Planetary Port")]
189 PlanetaryPort,
190 #[serde(rename = "Planetary Outpost")]
191 PlanetaryOutpost,
192 #[serde(rename = "Odyssey Settlement")]
193 OdysseySettlement,
194 #[serde(rename = "Fleet Carrier")]
196 FleetCarrier,
197}
198
199display_via_serde!(StationType);
200
201#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
202#[cfg_attr(feature = "type_hash", derive(type_hash::TypeHash))]
203#[serde(rename_all = "camelCase")]
204#[serde(deny_unknown_fields)]
205pub struct UpdateTime {
206 #[serde(with = "date_format")]
207 #[cfg_attr(feature = "type_hash", type_hash(foreign_type))]
208 pub information: DateTime<Utc>,
209 #[serde(with = "date_format_opt")]
210 #[serde(default = "option_none")]
211 #[cfg_attr(feature = "type_hash", type_hash(foreign_type))]
212 pub market: Option<DateTime<Utc>>,
213 #[serde(with = "date_format_opt")]
214 #[serde(default = "option_none")]
215 #[cfg_attr(feature = "type_hash", type_hash(foreign_type))]
216 pub outfitting: Option<DateTime<Utc>>,
217 #[serde(with = "date_format_opt")]
218 #[serde(default = "option_none")]
219 #[cfg_attr(feature = "type_hash", type_hash(foreign_type))]
220 pub shipyard: Option<DateTime<Utc>>,
221}
222
223fn option_none<T>() -> Option<T> {
224 None
225}