diff --git a/src/distance.rs b/src/distance.rs index 17eeefe..cb8737a 100644 --- a/src/distance.rs +++ b/src/distance.rs @@ -1,6 +1,6 @@ const EARTH_RAD_METERS: f64 = 6371e3; -type LatLon = (f64, f64); +pub type LatLon = (f64, f64); pub fn haversine(a: LatLon, b: LatLon) -> f64 { let a_latitude = a.0.to_radians(); diff --git a/src/main.rs b/src/main.rs index 3203d79..3ac62cb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,88 @@ +#![allow(dead_code)] + mod distance; mod parse; -use std::collections::HashMap; +use std::{ + collections::{hash_map::Entry, HashMap}, + rc::Rc, +}; use parse::Record; -#[derive(Debug)] +type Graph = HashMap; +type Airports = HashMap>; + +#[derive(Debug, Clone)] struct Node { - destinations: Vec, + origin: Rc, + destinations: Vec, + visited: bool, +} + +impl Node { + fn new(origin: Rc, destinations: Vec) -> Self { + Node { + destinations, + origin, + visited: false, + } + } +} + +#[derive(Debug, Clone)] +struct Airport { + id: usize, + code: String, + name: String, + city: String, + country: String, + lat: f64, + lon: f64, +} + +#[derive(Debug, Clone)] +struct Destination { + airport: Rc, + distance: f64, +} + +impl Destination { + fn new(source: &Airport, destination: Rc) -> Self { + Destination { + distance: distance::haversine( + (source.lat, source.lon), + (destination.lat, destination.lon), + ), + airport: destination, + } + } +} + +fn insert_airports_from_record(airports: &mut Airports, record: &Record) { + if let Entry::Vacant(entry) = airports.entry(record.origin_airport_id) { + entry.insert(Rc::new(Airport { + id: record.origin_airport_id, + code: record.origin_airport_code.clone(), + name: record.origin_airport.clone(), + city: record.origin_city.clone(), + country: record.origin_country.clone(), + lat: record.origin_airport_latitude, + lon: record.origin_airport_longitude, + })); + } + + if let Entry::Vacant(entry) = airports.entry(record.destination_airport_id) { + entry.insert(Rc::new(Airport { + id: record.destination_airport_id, + code: record.destination_airport_code.clone(), + name: record.destination_airport.clone(), + city: record.destination_city.clone(), + country: record.destination_country.clone(), + lat: record.destination_airport_latitude, + lon: record.destination_airport_longitude, + })); + } } fn main() { @@ -17,17 +92,25 @@ fn main() { .flatten() .collect(); - let mut graph: HashMap = HashMap::new(); + let mut airports: Airports = HashMap::new(); - for record in data.into_iter() { - use std::collections::hash_map::Entry; + for record in &data { + insert_airports_from_record(&mut airports, record); + } + let mut graph: Graph = HashMap::new(); + + for record in data { match graph.entry(record.origin_airport_code.clone()) { - Entry::Occupied(mut entry) => entry.get_mut().destinations.push(record), + Entry::Occupied(mut entry) => entry + .get_mut() + .destinations + .push(record.get_destination(&airports)), Entry::Vacant(entry) => { - entry.insert(Node { - destinations: vec![record], - }); + entry.insert(Node::new( + airports[&record.origin_airport_id].clone(), + vec![record.get_destination(&airports)], + )); } } } diff --git a/src/parse.rs b/src/parse.rs index 87719d9..aa47da3 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -1,4 +1,6 @@ -#[derive(Debug, serde::Deserialize)] +use crate::{Airports, Destination}; + +#[derive(Debug, Clone, serde::Deserialize)] pub struct Record { pub origin_airport_code: String, pub origin_airport: String, @@ -15,3 +17,12 @@ pub struct Record { pub destination_city: String, pub destination_country: String, } + +impl Record { + pub fn get_destination(&self, airports: &Airports) -> Destination { + Destination::new( + &airports[&self.origin_airport_id], + airports[&self.destination_airport_id].clone(), + ) + } +}