use crate::prelude::*;
use airac::AIRAC;
#[derive(Debug, Default, Clone, PartialEq)]
pub struct NavAid {
pub(crate) id: String,
pub(crate) name: String,
pub(crate) kind: NavAidKind,
pub(crate) frequency_khz: usize,
pub(crate) latitude: f64,
pub(crate) longitude: f64,
pub(crate) elevation: usize,
}
impl NavAid {
pub fn id(&self) -> &String {
&self.id
}
pub fn name(&self) -> &String {
&self.name
}
pub fn kind(&self) -> NavAidKind {
self.kind
}
pub fn frequency_khz(&self) -> usize {
self.frequency_khz
}
pub fn frequency(&self) -> f32 {
self.frequency_khz as f32 / 1000f32
}
pub fn latitude(&self) -> f64 {
self.latitude
}
pub fn longitude(&self) -> f64 {
self.longitude
}
pub fn elevation(&self) -> usize {
self.elevation
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum NavAidKind {
VOR,
DME,
VORDME,
NDB,
TACAN,
}
impl Default for NavAidKind {
fn default() -> Self {
Self::VOR
}
}
#[derive(Debug, Default, Clone, PartialEq)]
pub struct Intersection {
pub(crate) designator: String,
pub(crate) latitude: f64,
pub(crate) longitude: f64,
}
impl Intersection {
pub fn designator(&self) -> &String {
&self.designator
}
pub fn latitude(&self) -> f64 {
self.latitude
}
pub fn longitude(&self) -> f64 {
self.longitude
}
}
#[derive(Debug, Default, Clone, PartialEq)]
pub struct Airway {
pub(crate) designator: String,
pub(crate) waypoints: Vec<AirwayWaypoint>,
}
impl Airway {
pub fn designator(&self) -> &String {
&self.designator
}
pub fn waypoints(&self) -> &Vec<AirwayWaypoint> {
&self.waypoints
}
}
#[derive(Debug, Default, Clone, PartialEq)]
pub struct AirwayWaypoint {
pub(crate) designator: String,
pub(crate) lower_limit: String,
pub(crate) upper_limit: String,
}
impl AirwayWaypoint {
pub fn designator(&self) -> &String {
&self.designator
}
pub fn is_navaid(&self) -> bool {
self.designator.len() == 3
}
pub fn is_intersection(&self) -> bool {
self.designator.len() == 5
}
pub fn lower_limit(&self) -> &String {
&self.lower_limit
}
pub fn upper_limit(&self) -> &String {
&self.upper_limit
}
}
#[derive(Debug, Default, Clone, PartialEq)]
pub struct Airport {
pub(crate) icao: String,
pub(crate) name: String,
pub(crate) latitude: f64,
pub(crate) longitude: f64,
pub(crate) elevation: usize,
pub(crate) charts: Vec<Chart>,
}
impl Airport {
pub async fn from_eaip(eaip: &EAIP, airac: AIRAC, aerodrome: String) -> Result<Self> {
let egbo = Part::Aerodromes(AD::Aerodromes(aerodrome));
let data = eaip.get_current_page(egbo.clone(), EAIPType::HTML).await?;
let mut airport = Airport::parse(&data)?;
airport.canonicalise_chart_urls(eaip, airac, egbo)?;
Ok(airport)
}
pub async fn from_current_eaip(eaip: &EAIP, aerodrome: String) -> Result<Self> {
Self::from_eaip(eaip, AIRAC::current(), aerodrome).await
}
pub fn canonicalise_chart_urls(&mut self, eaip: &EAIP, airac: AIRAC, part: Part) -> Result<()> {
let base_url = url::Url::parse(&eaip.generate_url(airac, part, EAIPType::HTML));
if let Err(err) = base_url {
return Err(Error::EAIPInvalidBaseURL(err));
}
let base_url = base_url.unwrap();
for chart in &mut self.charts {
if url::Url::parse(&chart.url) == Err(url::ParseError::RelativeUrlWithoutBase) {
if let Ok(joined_url) = base_url.join(&chart.url) {
chart.url = joined_url.to_string();
} else {
return Err(Error::ChartURLMalformed(chart.url.clone()));
}
}
}
Ok(())
}
pub fn icao(&self) -> &String {
&self.icao
}
pub fn name(&self) -> &String {
&self.name
}
pub fn latitude(&self) -> f64 {
self.latitude
}
pub fn longitude(&self) -> f64 {
self.longitude
}
pub fn elevation(&self) -> usize {
self.elevation
}
pub fn charts(&self) -> &Vec<Chart> {
&self.charts
}
}
#[derive(Debug, Default, Clone, PartialEq)]
pub struct Chart {
pub(crate) title: String,
pub(crate) url: String,
}
impl Chart {
pub fn title(&self) -> &String {
&self.title
}
pub fn url(&self) -> &String {
&self.url
}
}