sct_reader/
sector.rs

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
use std::collections::HashMap;

use crate::{
    colour::Colour,
    error::Error,
    line::{ColouredLine, LineGroup},
    partial::{
        region::{PartialRegion, PartialRegionGroup},
        sector_info::PartialSectorInfo,
        PartialSector,
    },
    position::{Position, Valid},
    waypoint::{Airport, Fix, Ndb, Vor},
};

#[derive(Debug)]
pub struct Sector {
    pub sector_info: SectorInfo,
    pub colours: HashMap<String, Colour>,
    pub airports: Vec<Airport>,
    pub vors: Vec<Vor>,
    pub ndbs: Vec<Ndb>,
    pub fixes: Vec<Fix>,
    pub artcc_entries: Vec<LineGroup<ColouredLine>>,
    pub artcc_low_entries: Vec<LineGroup<ColouredLine>>,
    pub artcc_high_entries: Vec<LineGroup<ColouredLine>>,
    pub low_airways: Vec<LineGroup<ColouredLine>>,
    pub high_airways: Vec<LineGroup<ColouredLine>>,
    pub sid_entries: Vec<LineGroup<ColouredLine>>,
    pub star_entries: Vec<LineGroup<ColouredLine>>,
    pub geo_entries: Vec<LineGroup<ColouredLine>>,
    pub regions: Vec<RegionGroup>,
    pub labels: Vec<LabelGroup>,

    pub non_critical_errors: Vec<(usize, String, Error)>,
}

impl TryFrom<PartialSector> for Sector {
    type Error = Error;
    fn try_from(value: PartialSector) -> Result<Self, Self::Error> {
        let sector_info = SectorInfo::try_from(value.sector_info)?;
        let regions = value
            .regions
            .into_iter()
            .map(|region_group| RegionGroup::try_from(region_group))
            .collect::<Result<Vec<RegionGroup>, Error>>()?;
        Ok(Sector {
            sector_info,
            colours: value.colours,
            airports: value.airports,
            vors: value.vors,
            ndbs: value.ndbs,
            fixes: value.fixes,
            artcc_entries: value.artcc_entries,
            artcc_low_entries: value.artcc_low_entries,
            artcc_high_entries: value.artcc_high_entries,
            low_airways: value.low_airways,
            high_airways: value.high_airways,
            sid_entries: value.sid_entries,
            star_entries: value.star_entries,
            geo_entries: value.geo_entries,
            regions,
            labels: value.labels,
            non_critical_errors: vec![],
        })
    }
}

#[derive(Debug)]
pub struct RegionGroup {
    pub name: String,
    pub regions: Vec<Region>,
}
impl RegionGroup {
    pub fn new(name: String) -> RegionGroup {
        RegionGroup {
            name,
            regions: vec![],
        }
    }
}

impl TryFrom<PartialRegionGroup> for RegionGroup {
    type Error = Error;
    fn try_from(value: PartialRegionGroup) -> Result<Self, Self::Error> {
        let regions = value
            .regions
            .into_iter()
            .map(Region::try_from)
            .collect::<Result<Vec<_>, Error>>();
        if regions.is_err() {
            println!("NAME: {}", value.name);
        }
        let regions = regions?;
        Ok(RegionGroup {
            name: value.name,
            regions,
        })
    }
}

#[derive(Debug)]
pub struct Region {
    pub colour: Colour,
    pub vertices: Vec<Position<Valid>>,
}
impl TryFrom<PartialRegion> for Region {
    type Error = Error;
    fn try_from(value: PartialRegion) -> Result<Self, Self::Error> {
        Ok(Region {
            colour: value.colour.ok_or_else(|| Error::InvalidRegion)?,
            vertices: value.vertices,
        })
    }
}

#[derive(Debug)]
pub struct LabelGroup {
    pub name: String,
    pub labels: Vec<Label>,
}

#[derive(Debug)]
pub struct Label {
    pub name: String,
    pub position: Position<Valid>,
    pub colour: Colour,
}

#[derive(Debug, Clone)]
pub struct SectorInfo {
    pub name: String,
    pub default_callsign: String,
    pub default_airport: String,
    pub default_centre_pt: Position<Valid>,
    pub n_mi_per_deg_lat: f32,
    pub n_mi_per_deg_lon: f32,
    pub magnetic_variation: f32,
    pub sector_scale: f32,
}

impl TryFrom<PartialSectorInfo> for SectorInfo {
    type Error = Error;
    fn try_from(value: PartialSectorInfo) -> Result<Self, Self::Error> {
        let name = value.name.ok_or(Error::SectorInfoError)?;
        let default_callsign = value.default_callsign.ok_or(Error::SectorInfoError)?;
        let default_airport = value.default_airport.ok_or(Error::SectorInfoError)?;
        let lat = value.default_centre_pt_lat.ok_or(Error::SectorInfoError)?;
        let lon = value.default_centre_pt_lon.ok_or(Error::SectorInfoError)?;
        let default_centre_pt = Position::new(lat, lon).validate()?;
        let n_mi_per_deg_lat = value.n_mi_per_deg_lat.ok_or(Error::SectorInfoError)?;
        let n_mi_per_deg_lon = value.n_mi_per_deg_lon.ok_or(Error::SectorInfoError)?;
        let magnetic_variation = value.magnetic_variation.ok_or(Error::SectorInfoError)?;
        let sector_scale = value.sector_scale.ok_or(Error::SectorInfoError)?;

        Ok(SectorInfo {
            name,
            default_callsign,
            default_airport,
            default_centre_pt,
            n_mi_per_deg_lat,
            n_mi_per_deg_lon,
            magnetic_variation,
            sector_scale,
        })
    }
}