1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
//! The shared module contains all common structs and enums used in the API
use serde::{Serialize, Deserialize};
use std::fmt;
use std::fmt::Formatter;
use std::error::Error;
use chrono::{DateTime, Utc};

/// The various loan types
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq)]
#[cfg_attr(debug_assertions, serde(deny_unknown_fields))]
pub enum LoanType {
    /// Startup
    #[serde(rename = "STARTUP")]
    Startup,
    /// Enterprise
    #[serde(rename = "ENTERPRISE")]
    Enterprise,
}

/// The various goods in the game
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq)]
#[cfg_attr(debug_assertions, serde(deny_unknown_fields))]
pub enum Good {
    /// Fuel
    #[serde(rename = "FUEL")]
    Fuel,
    /// Chemicals
    #[serde(rename = "CHEMICALS")]
    Chemicals,
    /// Metals
    #[serde(rename = "METALS")]
    Metals,
    /// Drones
    #[serde(rename = "DRONES")]
    Drones,
    /// Food
    #[serde(rename = "FOOD")]
    Food,
    /// Consumer goods
    #[serde(rename = "CONSUMER_GOODS")]
    ConsumerGoods,
    /// Explosives
    #[serde(rename = "EXPLOSIVES")]
    Explosives,
    /// Narcotics
    #[serde(rename = "NARCOTICS")]
    Narcotics,
    /// Textiles
    #[serde(rename = "TEXTILES")]
    Textiles,
    /// Electronics
    #[serde(rename = "ELECTRONICS")]
    Electronics,
    /// Machinery
    #[serde(rename = "MACHINERY")]
    Machinery,
    /// Construction materials
    #[serde(rename = "CONSTRUCTION_MATERIALS")]
    ConstructionMaterials,
    /// Ship plating
    #[serde(rename = "SHIP_PLATING")]
    ShipPlating,
    /// Rare metals
    #[serde(rename = "RARE_METALS")]
    RareMetals,
    /// Protein Synthesizers
    #[serde(rename = "PROTEIN_SYNTHESIZERS")]
    ProteinSynthesizers,
    /// Research
    #[serde(rename = "RESEARCH")]
    Research,
    /// Precision Instruments
    #[serde(rename = "PRECISION_INSTRUMENTS")]
    PrecisionInstruments,
    /// Nanobots
    #[serde(rename = "NANOBOTS")]
    Nanobots,
    /// Biometric Firearms
    #[serde(rename = "BIOMETRIC_FIREARMS")]
    BiometricFirearms,
    /// Ship parts
    #[serde(rename = "SHIP_PARTS")]
    ShipParts,
    /// Exotic Plasma
    #[serde(rename = "EXOTIC_PLASMA")]
    ExoticPlasma,
    /// Fusion Reactors
    #[serde(rename = "FUSION_REACTORS")]
    FusionReactors,
    /// Zuco Crystals
    #[serde(rename = "ZUCO_CRYSTALS")]
    ZucoCrystals,
    /// Unstable Compounds
    #[serde(rename = "UNSTABLE_COMPOUNDS")]
    UnstableCompounds,
    /// Unknown is used when a string can't be converted to a known good
    Unknown
}

impl Good {
    /// Get the volume consumed by a good
    pub fn get_volume(&self) -> i32 {
        match *self {
            Good::Fuel => 1,
            Good::Chemicals => 1,
            Good::Metals => 1,
            Good::Drones => 1,
            Good::Food => 1,
            Good::ConsumerGoods => 1,
            Good::Explosives => 1,
            Good::Narcotics => 1,
            Good::Textiles => 1,
            Good::Electronics => 1,
            Good::Machinery => 2,
            Good::ConstructionMaterials => 1,
            Good::ShipPlating => 2,
            Good::RareMetals => 1,
            Good::ProteinSynthesizers => 1,
            Good::Research => 1,
            Good::PrecisionInstruments => 1,
            Good::Nanobots => 1,
            Good::BiometricFirearms => 1,
            Good::ShipParts => 4,
            Good::ExoticPlasma => 4,
            Good::FusionReactors => 6,
            Good::ZucoCrystals => 1,
            Good::UnstableCompounds => 3,
            Good::Unknown => 1,
        }
    }
}

impl From<String> for Good {
    fn from(good: String) -> Self {
        match good.as_str() {
            "Metals" => Good::Metals,
            "RareMetals" => Good::RareMetals,
            "Chemicals" => Good::Chemicals,
            "Fuel" => Good::Fuel,
            "Food" => Good::Food,
            "Drones" => Good::Drones,
            "Textiles" => Good::Textiles,
            "ConsumerGoods" => Good::ConsumerGoods,
            "Machinery" => Good::Machinery,
            "ConstructionMaterials" => Good::ConstructionMaterials,
            "Electronics" => Good::Electronics,
            "Research" => Good::Research,
            "ShipParts" => Good::ShipParts,
            "ShipPlating" => Good::ShipPlating,
            "FusionReactors" => Good::FusionReactors,
            "ExoticPlasma" => Good::ExoticPlasma,
            "UnstableCompounds" => Good::UnstableCompounds,
            "ProteinSynthesizers" => Good::ProteinSynthesizers,
            "BiometricFirearms" => Good::BiometricFirearms,
            "Explosives" => Good::Explosives,
            "Nanobots" => Good::Nanobots,
            "PrecisionInstruments" => Good::PrecisionInstruments,
            "Narcotics" => Good::Narcotics,
            _ => Good::Unknown
        }
    }
}

impl fmt::Display for Good {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self)
    }
}

/// The various location types
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq)]
#[cfg_attr(debug_assertions, serde(deny_unknown_fields))]
pub enum LocationType {
    /// A planet
    #[serde(rename = "PLANET")]
    Planet,
    /// A moon
    #[serde(rename = "MOON")]
    Moon,
    /// A Gas Giant
    #[serde(rename = "GAS_GIANT")]
    GasGiant,
    /// An asteroid
    #[serde(rename = "ASTEROID")]
    Asteroid,
    /// A Wormhole
    #[serde(rename = "WORMHOLE")]
    Wormhole,
    /// A nebula
    #[serde(rename = "NEBULA")]
    Nebula,
}

impl fmt::Display for LocationType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self)
    }
}

/// A representation of a users ship
#[derive(Serialize, Deserialize, Debug, Clone)]
#[cfg_attr(debug_assertions, serde(deny_unknown_fields))]
pub struct Ship {
    /// The ships id
    pub id: String,
    /// The current location of the ship or None if the ship is in transit
    pub location: Option<String>,
    /// Any cargo within the ship
    pub cargo: Vec<Cargo>,
    /// The volume available in the ships cargo
    #[serde(rename = "spaceAvailable")]
    pub space_available: i32,
    /// The type of the ship
    #[serde(rename = "type")]
    pub ship_type: String,
    /// The class of the ship
    pub class: String,
    /// The maximum cargo volume of the ship
    #[serde(rename = "maxCargo")]
    pub max_cargo: i32,
    /// The speed rating of the ship
    pub speed: i32,
    /// The manufacturer of the ship
    pub manufacturer: String,
    /// The defensive rating of the ship
    pub plating: i32,
    /// The offensive rating of the ship
    pub weapons: i32,
    /// The ships current X coordinate
    pub x: Option<i32>,
    /// The ships current Y coordinate
    pub y: Option<i32>,
    #[serde(rename = "flightPlanId")]
    /// The ships current flight plan
    pub flight_plan_id: Option<String>,
}

/// A representation of cargo within a ship
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
#[cfg_attr(debug_assertions, serde(deny_unknown_fields))]
pub struct Cargo {
    /// The good in the cargo
    pub good: Good,
    /// The quantity of the good
    pub quantity: i32,
    /// The total volume consumed by the good
    #[serde(rename = "totalVolume")]
    pub total_volume: i32,
}

/// A representation of a purchase order
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
#[cfg_attr(debug_assertions, serde(deny_unknown_fields))]
pub struct Order {
    /// The good that was purchased
    pub good: Good,
    /// The quantity of the good which was purchased
    pub quantity: i32,
    /// The price per unit of the good at the time of purchase
    #[serde(rename = "pricePerUnit")]
    pub price_per_unit: i32,
    /// The total amount of the order
    pub total: i32,
}

/// A representation of a loan
#[derive(Serialize, Deserialize, Debug, Clone)]
#[cfg_attr(debug_assertions, serde(deny_unknown_fields))]
pub struct Loan {
    /// The id of the loan
    pub id: String,
    /// The due date of the loan
    pub due: DateTime<Utc>,
    /// The repayment amount of the loan
    #[serde(rename = "repaymentAmount")]
    pub repayment_amount: i32,
    /// The current loan status
    pub status: String,
    /// The type of the loan
    #[serde(rename = "type")]
    pub loan_type: LoanType
}

/// A representation of a purchase location for a ship for sale
#[derive(Serialize, Deserialize, Debug, Clone)]
#[cfg_attr(debug_assertions, serde(deny_unknown_fields))]
pub struct PurchaseLocation {
    /// The system of the ship for sale
    pub system: String,
    /// The location of the ship for sale
    pub location: String,
    /// The price of the ship at this location
    pub price: i32,
}

/// A representation of a ship for sales
#[derive(Serialize, Deserialize, Debug, Clone)]
#[cfg_attr(debug_assertions, serde(deny_unknown_fields))]
pub struct ShipForSale {
    /// The type of the ship
    #[serde(rename = "type")]
    pub ship_type: String,
    /// The class of the ship
    pub class: String,
    /// The maximum cargo volume of the ship
    #[serde(rename = "maxCargo")]
    pub max_cargo: i32,
    /// The ships speed rating
    pub speed: i32,
    /// The manufacturer of the ship
    pub manufacturer: String,
    /// The ships defensive rating
    pub plating: i32,
    /// The weapons rating of the ship
    pub weapons: i32,
    /// The locations that this ship can be purchased at
    #[serde(rename = "purchaseLocations")]
    pub purchase_locations: Vec<PurchaseLocation>,
    /// The goods that this ship is restricted to carrying
    #[serde(rename = "restrictedGoods")]
    pub restricted_goods: Option<Vec<Good>>,
}

/// A representation of a location in a system
#[derive(Serialize, Deserialize, Debug, Clone)]
#[cfg_attr(debug_assertions, serde(deny_unknown_fields))]
pub struct Location {
    /// The system symbol for this location
    pub symbol: String,
    /// The type of this location
    #[serde(rename = "type")]
    pub location_type: String,
    /// The friendly name of this location
    pub name: String,
    /// X coordinate of the location
    pub x: i32,
    /// Y coordinate of the location
    pub y: i32,
}

/// A representation of an error message
#[derive(Serialize, Deserialize, Debug, Clone)]
#[cfg_attr(debug_assertions, serde(deny_unknown_fields))]
pub struct ErrorMessageData {
    /// The API sent error code
    pub code: i32,
    /// The message sent from the API about the error
    pub message: String,
}

/// A representation of a single flight plan
#[derive(Serialize, Deserialize, Debug, Clone)]
#[cfg_attr(debug_assertions, serde(deny_unknown_fields))]
pub struct FlightPlanData {
    /// The id of the flight plan
    pub id: String,
    /// The id of the ship on this flight plan
    #[serde(rename = "shipId")]
    pub ship_id: String,
    /// The fuel consumed by this flight plan
    #[serde(rename = "fuelConsumed")]
    pub fuel_consumed: i32,
    /// The fuel remaining after the flight plan completes
    #[serde(rename = "fuelRemaining")]
    pub fuel_remaining: i32,
    /// The time remaining until the ship arrives at the destination in seconds
    #[serde(rename = "timeRemainingInSeconds")]
    pub time_remaining_in_seconds: i32,
    /// The date time that the flight plan was created at
    #[serde(rename = "createdAt")]
    pub created_at: DateTime<Utc>,
    /// The DateTime at which the ship will arrive
    #[serde(rename = "arrivesAt")]
    pub arrives_at: DateTime<Utc>,
    /// The termination DateTime of the flight plan. I believe this could be before the arrives at
    /// date if the flight plan is cancelled mid flight (which might not be developed yet)
    #[serde(rename = "terminatedAt")]
    pub terminated_at: Option<DateTime<Utc>>,
    /// The ships destination
    pub destination: String,
    /// The ships departure location
    pub departure: String,
    /// The distance of the flight plan
    pub distance: i32,

}

/// The structures that exist at a location
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Structures {
    /// The id of the structure
    pub id: String,
    /// The structure type
    #[serde(rename = "type")]
    pub structure_type: String,
    /// The structure location
    pub location: String,
}

/// A representation of a location within a system
#[derive(Serialize, Deserialize, Debug, Clone)]
#[cfg_attr(debug_assertions, serde(deny_unknown_fields))]
pub struct SystemsInfoLocation {
    /// The system symbol of this location
    pub symbol: String,
    /// The type of this system location
    #[serde(rename = "type")]
    pub systems_info_type: LocationType,
    /// The friendly name of the system location
    pub name: String,
    /// X coordinate of the system location
    pub x: i32,
    /// Y coordinate of the system location
    pub y: i32,
    /// The current ansible progress. I believe when this gets to 1 the anomaly opens.
    #[serde(rename = "ansibleProgress")]
    pub ansible_progress: Option<f64>,
    /// The anomaly info about this sytem location
    pub anomaly: Option<String>,
    /// The structures within a system location
    pub structures: Option<Vec<Structures>>,
    /// Any messages relating to this system location
    pub messages: Option<Vec<String>>,
    /// Whether or not the system allows construction
    #[serde(rename = "allowsConstruction")]
    pub allows_construction: bool,
}

/// The representation of a system
#[derive(Serialize, Deserialize, Debug, Clone)]
#[cfg_attr(debug_assertions, serde(deny_unknown_fields))]
pub struct SystemsInfoData {
    /// The system symbol
    pub symbol: String,
    /// The friendly name of the system
    pub name: String,
    /// Locations within the system
    pub locations: Vec<SystemsInfoLocation>,
}

/// The representation of a single good within a marketplace
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
#[cfg_attr(debug_assertions, serde(deny_unknown_fields))]
pub struct MarketplaceData {
    /// The type of good for this marketplace data
    pub symbol: Good,
    /// How much volume this good consumes
    #[serde(rename = "volumePerUnit")]
    pub volume_per_unit: i32,
    /// The price per unit of the good
    #[serde(rename = "pricePerUnit")]
    pub price_per_unit: i32,
    /// The purchase price per unit of a good
    #[serde(rename = "purchasePricePerUnit")]
    pub purchase_price_per_unit: i32,
    /// The sell price per unit of a good
    #[serde(rename = "sellPricePerUnit")]
    pub sell_price_per_unit: i32,
    /// How much of the good is available at this location
    #[serde(rename = "quantityAvailable")]
    pub quantity_available: i32,
    /// DEPRECATED: Spread
    pub spread: i32,
}

/// Available structure types
#[derive(Serialize, Deserialize, Debug, Clone)]
#[cfg_attr(debug_assertions, serde(deny_unknown_fields))]
pub enum StructureType {
    /// Fuel Refinery
    #[serde(rename = "FUEL_REFINERY")]
    FuelRefinery,
    /// Warp Gate
    #[serde(rename = "WARP_GATE")]
    WarpGate,
    /// Mine
    #[serde(rename = "MINE")]
    Mine,
    /// Chemical Plant
    #[serde(rename = "CHEMICAL_PLANT")]
    ChemicalPlant,
    /// Farm
    #[serde(rename = "FARM")]
    Farm,
}

/// A representation of structure found in marketplace data
#[derive(Serialize, Deserialize, Debug, Clone)]
#[cfg_attr(debug_assertions, serde(deny_unknown_fields))]
pub struct StructureOwnedBy {
    /// The user who owns the structure
    pub username: String,
}

/// An error response returned from the API
#[derive(Serialize, Deserialize, Debug, Clone)]
#[cfg_attr(debug_assertions, serde(deny_unknown_fields))]
pub struct ErrorMessage {
    /// The data about the error
    pub error: ErrorMessageData,
}

impl fmt::Display for ErrorMessage {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        write!(f, "Error Code: {} Error Message: {}", self.error.code, self.error.message)
    }
}

impl Error for ErrorMessage {}