sct_reader/loaders/euroscope/
sector.rs1use std::collections::HashMap;
2
3use super::{
4 colour::Colour,
5 error::Error,
6 line::{ColouredLine, LineGroup},
7 partial::{
8 region::{PartialRegion, PartialRegionGroup},
9 sector_info::PartialSectorInfo,
10 PartialSector,
11 },
12 position::{Position, Valid},
13 waypoint::{Airport, Fix, Ndb, Vor},
14};
15
16#[derive(Debug)]
17pub struct Sector {
18 pub sector_info: SectorInfo,
19 pub colours: HashMap<String, Colour>,
20 pub airports: Vec<Airport>,
21 pub vors: Vec<Vor>,
22 pub ndbs: Vec<Ndb>,
23 pub fixes: Vec<Fix>,
24 pub artcc_entries: Vec<LineGroup<ColouredLine>>,
25 pub artcc_low_entries: Vec<LineGroup<ColouredLine>>,
26 pub artcc_high_entries: Vec<LineGroup<ColouredLine>>,
27 pub low_airways: Vec<LineGroup<ColouredLine>>,
28 pub high_airways: Vec<LineGroup<ColouredLine>>,
29 pub sid_entries: Vec<LineGroup<ColouredLine>>,
30 pub star_entries: Vec<LineGroup<ColouredLine>>,
31 pub geo_entries: Vec<LineGroup<ColouredLine>>,
32 pub regions: Vec<RegionGroup>,
33 pub labels: Vec<LabelGroup>,
34
35 pub non_critical_errors: Vec<(usize, String, Error)>,
36}
37
38impl TryFrom<PartialSector> for Sector {
39 type Error = Error;
40 fn try_from(value: PartialSector) -> Result<Self, Self::Error> {
41 let sector_info = SectorInfo::try_from(value.sector_info)?;
42 let regions = value
43 .region_groups
44 .into_iter()
45 .map(|region_group| RegionGroup::try_from(region_group))
46 .collect::<Result<Vec<RegionGroup>, Error>>()?;
47 Ok(Sector {
48 sector_info,
49 colours: value.colours,
50 airports: value.airports,
51 vors: value.vors,
52 ndbs: value.ndbs,
53 fixes: value.fixes,
54 artcc_entries: value.artcc_entries,
55 artcc_low_entries: value.artcc_low_entries,
56 artcc_high_entries: value.artcc_high_entries,
57 low_airways: value.low_airways,
58 high_airways: value.high_airways,
59 sid_entries: value.sid_entries,
60 star_entries: value.star_entries,
61 geo_entries: value.geo_entries,
62 regions,
63 labels: value.labels,
64 non_critical_errors: vec![],
65 })
66 }
67}
68
69#[derive(Debug)]
70pub struct RegionGroup {
71 pub name: String,
72 pub regions: Vec<Region>,
73}
74impl RegionGroup {
75 pub fn new(name: String) -> RegionGroup {
76 RegionGroup {
77 name,
78 regions: vec![],
79 }
80 }
81}
82
83impl TryFrom<PartialRegionGroup> for RegionGroup {
84 type Error = Error;
85 fn try_from(value: PartialRegionGroup) -> Result<Self, Self::Error> {
86 let regions = value
87 .regions
88 .into_iter()
89 .map(Region::try_from)
90 .collect::<Result<Vec<_>, Error>>();
91 if regions.is_err() {
92 println!("NAME: {}", value.name);
93 }
94 let regions = regions?;
95 Ok(RegionGroup {
96 name: value.name,
97 regions,
98 })
99 }
100}
101
102#[derive(Debug)]
103pub struct Region {
104 pub colour: Colour,
105 pub vertices: Vec<Position<Valid>>,
106}
107impl TryFrom<PartialRegion> for Region {
108 type Error = Error;
109 fn try_from(value: PartialRegion) -> Result<Self, Self::Error> {
110 Ok(Region {
111 colour: value.colour.ok_or_else(|| Error::InvalidRegion)?,
112 vertices: value.vertices,
113 })
114 }
115}
116
117#[derive(Debug)]
118pub struct LabelGroup {
119 pub name: String,
120 pub labels: Vec<Label>,
121}
122
123#[derive(Debug)]
124pub struct Label {
125 pub name: String,
126 pub position: Position<Valid>,
127 pub colour: Colour,
128}
129
130#[derive(Debug, Clone)]
131pub struct SectorInfo {
132 pub name: String,
133 pub default_callsign: String,
134 pub default_airport: String,
135 pub default_centre_pt: Position<Valid>,
136 pub n_mi_per_deg_lat: f32,
137 pub n_mi_per_deg_lon: f32,
138 pub magnetic_variation: f32,
139 pub sector_scale: f32,
140}
141
142impl TryFrom<PartialSectorInfo> for SectorInfo {
143 type Error = Error;
144 fn try_from(value: PartialSectorInfo) -> Result<Self, Self::Error> {
145 let name = value.name.ok_or(Error::SectorInfoError)?;
146 let default_callsign = value.default_callsign.ok_or(Error::SectorInfoError)?;
147 let default_airport = value.default_airport.ok_or(Error::SectorInfoError)?;
148 let lat = value.default_centre_pt_lat.ok_or(Error::SectorInfoError)?;
149 let lon = value.default_centre_pt_lon.ok_or(Error::SectorInfoError)?;
150 let default_centre_pt = Position::new(lat, lon).validate()?;
151 let n_mi_per_deg_lat = value.n_mi_per_deg_lat.ok_or(Error::SectorInfoError)?;
152 let n_mi_per_deg_lon = value.n_mi_per_deg_lon.ok_or(Error::SectorInfoError)?;
153 let magnetic_variation = value.magnetic_variation.ok_or(Error::SectorInfoError)?;
154 let sector_scale = value.sector_scale.ok_or(Error::SectorInfoError)?;
155
156 Ok(SectorInfo {
157 name,
158 default_callsign,
159 default_airport,
160 default_centre_pt,
161 n_mi_per_deg_lat,
162 n_mi_per_deg_lon,
163 magnetic_variation,
164 sector_scale,
165 })
166 }
167}