Reindent with 2 spaces, removed continent
This commit is contained in:
126979
service/airport-codes.json
126979
service/airport-codes.json
File diff suppressed because it is too large
Load Diff
@@ -1,16 +1,14 @@
|
|||||||
CREATE EXTENSION IF NOT EXISTS postgis;
|
CREATE EXTENSION IF NOT EXISTS postgis;
|
||||||
CREATE TABLE IF NOT EXISTS airports (
|
CREATE TABLE IF NOT EXISTS airports (
|
||||||
icao TEXT PRIMARY KEY NOT NULL,
|
icao TEXT PRIMARY KEY NOT NULL,
|
||||||
id INTEGER GENERATED ALWAYS AS IDENTITY,
|
category TEXT NOT NULL,
|
||||||
category TEXT NOT NULL,
|
full_name TEXT NOT NULL,
|
||||||
full_name TEXT NOT NULL,
|
iso_country TEXT NOT NULL,
|
||||||
elevation_ft INTEGER,
|
iso_region TEXT NOT NULL,
|
||||||
continent TEXT NOT NULL,
|
municipality TEXT NOT NULL,
|
||||||
iso_country TEXT NOT NULL,
|
gps_code TEXT NOT NULL,
|
||||||
iso_region TEXT NOT NULL,
|
iata_code TEXT NOT NULL,
|
||||||
municipality TEXT NOT NULL,
|
local_code TEXT NOT NULL,
|
||||||
gps_code TEXT NOT NULL,
|
point GEOMETRY(POINT,4326) NOT NULL,
|
||||||
iata_code TEXT NOT NULL,
|
data JSONB NOT NULL
|
||||||
local_code TEXT NOT NULL,
|
|
||||||
point GEOMETRY(POINT,4326) NOT NULL
|
|
||||||
);
|
);
|
||||||
@@ -4,25 +4,71 @@ use crate::db;
|
|||||||
use crate::error_handler::ServiceError;
|
use crate::error_handler::ServiceError;
|
||||||
use crate::db::schema::airports;
|
use crate::db::schema::airports;
|
||||||
use diesel::prelude::*;
|
use diesel::prelude::*;
|
||||||
|
use log::error;
|
||||||
use postgis_diesel::types::*;
|
use postgis_diesel::types::*;
|
||||||
use postgis_diesel::functions::*;
|
use postgis_diesel::functions::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, AsChangeset, Insertable)]
|
#[derive(Serialize, Deserialize)]
|
||||||
#[diesel(table_name = airports)]
|
pub struct Airport {
|
||||||
pub struct InsertAirport {
|
|
||||||
pub icao: String,
|
pub icao: String,
|
||||||
pub category: String,
|
pub category: String,
|
||||||
pub full_name: String,
|
pub full_name: String,
|
||||||
|
pub point: Point,
|
||||||
pub elevation_ft: Option<i32>,
|
pub elevation_ft: Option<i32>,
|
||||||
pub continent: String,
|
|
||||||
pub iso_country: String,
|
pub iso_country: String,
|
||||||
pub iso_region: String,
|
pub iso_region: String,
|
||||||
pub municipality: String,
|
pub municipality: String,
|
||||||
pub gps_code: String,
|
pub gps_code: String,
|
||||||
pub iata_code: String,
|
pub iata_code: String,
|
||||||
pub local_code: String,
|
pub local_code: String,
|
||||||
pub point: Point
|
pub tower: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<QueryAirport> for Airport {
|
||||||
|
fn into(self) -> QueryAirport {
|
||||||
|
return QueryAirport {
|
||||||
|
icao: self.icao.clone(),
|
||||||
|
category: self.category.clone(),
|
||||||
|
full_name: self.full_name.clone(),
|
||||||
|
point: self.point.clone(),
|
||||||
|
iso_country: self.iso_country.clone(),
|
||||||
|
iso_region: self.iso_region.clone(),
|
||||||
|
municipality: self.municipality.clone(),
|
||||||
|
gps_code: self.gps_code.clone(),
|
||||||
|
iata_code: self.iata_code.clone(),
|
||||||
|
local_code: self.local_code.clone(),
|
||||||
|
data: match serde_json::to_value(&self) {
|
||||||
|
Ok(d) => d,
|
||||||
|
Err(err) => {
|
||||||
|
error!("{}", err);
|
||||||
|
serde_json::Value::Null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<QueryAirport> for Airport {
|
||||||
|
fn from(airport: QueryAirport) -> Self {
|
||||||
|
serde_json::from_value(airport.data).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, AsChangeset, Insertable, Queryable, QueryableByName)]
|
||||||
|
#[diesel(table_name = airports)]
|
||||||
|
pub struct QueryAirport {
|
||||||
|
pub icao: String,
|
||||||
|
pub category: String,
|
||||||
|
pub full_name: String,
|
||||||
|
pub iso_country: String,
|
||||||
|
pub iso_region: String,
|
||||||
|
pub municipality: String,
|
||||||
|
pub gps_code: String,
|
||||||
|
pub iata_code: String,
|
||||||
|
pub local_code: String,
|
||||||
|
pub point: Point,
|
||||||
|
pub data: serde_json::Value
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -68,7 +114,6 @@ pub enum QueryOrderField {
|
|||||||
Icao,
|
Icao,
|
||||||
Name,
|
Name,
|
||||||
Category,
|
Category,
|
||||||
Continent,
|
|
||||||
Country,
|
Country,
|
||||||
Region,
|
Region,
|
||||||
Municipality,
|
Municipality,
|
||||||
@@ -84,7 +129,6 @@ impl FromStr for QueryOrderField {
|
|||||||
"icao" => Ok(QueryOrderField::Icao),
|
"icao" => Ok(QueryOrderField::Icao),
|
||||||
"name" => Ok(QueryOrderField::Name),
|
"name" => Ok(QueryOrderField::Name),
|
||||||
"category" => Ok(QueryOrderField::Category),
|
"category" => Ok(QueryOrderField::Category),
|
||||||
"continent" => Ok(QueryOrderField::Continent),
|
|
||||||
"iso_country" => Ok(QueryOrderField::Country),
|
"iso_country" => Ok(QueryOrderField::Country),
|
||||||
"iso_region" => Ok(QueryOrderField::Region),
|
"iso_region" => Ok(QueryOrderField::Region),
|
||||||
"municipality" => Ok(QueryOrderField::Municipality),
|
"municipality" => Ok(QueryOrderField::Municipality),
|
||||||
@@ -96,24 +140,6 @@ impl FromStr for QueryOrderField {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Queryable, QueryableByName)]
|
|
||||||
#[diesel(table_name = airports)]
|
|
||||||
pub struct QueryAirport {
|
|
||||||
pub icao: String,
|
|
||||||
pub id: i32,
|
|
||||||
pub category: String,
|
|
||||||
pub full_name: String,
|
|
||||||
pub elevation_ft: Option<i32>,
|
|
||||||
pub continent: String,
|
|
||||||
pub iso_country: String,
|
|
||||||
pub iso_region: String,
|
|
||||||
pub municipality: String,
|
|
||||||
pub gps_code: String,
|
|
||||||
pub iata_code: String,
|
|
||||||
pub local_code: String,
|
|
||||||
pub point: Point
|
|
||||||
}
|
|
||||||
|
|
||||||
impl QueryAirport {
|
impl QueryAirport {
|
||||||
pub fn get_all(filters: &QueryFilters, limit: i32, page: i32) -> Result<Vec<Self>, ServiceError> {
|
pub fn get_all(filters: &QueryFilters, limit: i32, page: i32) -> Result<Vec<Self>, ServiceError> {
|
||||||
let mut conn = db::connection()?;
|
let mut conn = db::connection()?;
|
||||||
@@ -150,7 +176,6 @@ impl QueryAirport {
|
|||||||
QueryOrderField::Icao => query.order(airports::icao.asc()),
|
QueryOrderField::Icao => query.order(airports::icao.asc()),
|
||||||
QueryOrderField::Name => query.order(airports::full_name.asc()),
|
QueryOrderField::Name => query.order(airports::full_name.asc()),
|
||||||
QueryOrderField::Category => query.order(airports::category.asc()),
|
QueryOrderField::Category => query.order(airports::category.asc()),
|
||||||
QueryOrderField::Continent => query.order(airports::continent.asc()),
|
|
||||||
QueryOrderField::Country => query.order(airports::iso_country.asc()),
|
QueryOrderField::Country => query.order(airports::iso_country.asc()),
|
||||||
QueryOrderField::Region => query.order(airports::iso_region.asc()),
|
QueryOrderField::Region => query.order(airports::iso_region.asc()),
|
||||||
QueryOrderField::Municipality => query.order(airports::municipality.asc()),
|
QueryOrderField::Municipality => query.order(airports::municipality.asc()),
|
||||||
@@ -166,7 +191,6 @@ impl QueryAirport {
|
|||||||
QueryOrderField::Icao => query.order(airports::icao.desc()),
|
QueryOrderField::Icao => query.order(airports::icao.desc()),
|
||||||
QueryOrderField::Name => query.order(airports::full_name.desc()),
|
QueryOrderField::Name => query.order(airports::full_name.desc()),
|
||||||
QueryOrderField::Category => query.order(airports::category.desc()),
|
QueryOrderField::Category => query.order(airports::category.desc()),
|
||||||
QueryOrderField::Continent => query.order(airports::continent.desc()),
|
|
||||||
QueryOrderField::Country => query.order(airports::iso_country.desc()),
|
QueryOrderField::Country => query.order(airports::iso_country.desc()),
|
||||||
QueryOrderField::Region => query.order(airports::iso_region.desc()),
|
QueryOrderField::Region => query.order(airports::iso_region.desc()),
|
||||||
QueryOrderField::Municipality => query.order(airports::municipality.desc()),
|
QueryOrderField::Municipality => query.order(airports::municipality.desc()),
|
||||||
@@ -215,16 +239,16 @@ impl QueryAirport {
|
|||||||
Ok(airport)
|
Ok(airport)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create(airport: InsertAirport) -> Result<Self, ServiceError> {
|
pub fn insert(airport: Self) -> Result<Self, ServiceError> {
|
||||||
let mut conn = db::connection()?;
|
let mut conn: r2d2::PooledConnection<diesel::r2d2::ConnectionManager<PgConnection>> = db::connection()?;
|
||||||
let airport = InsertAirport::from(airport);
|
let airport = Self::from(airport);
|
||||||
let airport = diesel::insert_into(airports::table)
|
let airport = diesel::insert_into(airports::table)
|
||||||
.values(airport)
|
.values(airport)
|
||||||
.get_result(&mut conn)?;
|
.get_result(&mut conn)?;
|
||||||
Ok(airport)
|
Ok(airport)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(icao: String, airport: InsertAirport) -> Result<Self, ServiceError> {
|
pub fn update(icao: String, airport: Self) -> Result<Self, ServiceError> {
|
||||||
let mut conn = db::connection()?;
|
let mut conn = db::connection()?;
|
||||||
let airport = diesel::update(airports::table)
|
let airport = diesel::update(airports::table)
|
||||||
.filter(airports::icao.eq(icao))
|
.filter(airports::icao.eq(icao))
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::{airports::{InsertAirport, QueryAirport, QueryFilters, QueryOrderField, QueryOrderBy}, db::{self, Response, Metadata}, auth::{JwtAuth, verify_role}};
|
use crate::{airports::{QueryAirport, QueryFilters, QueryOrderField, QueryOrderBy, Airport}, db::{self, Response, Metadata}, auth::{JwtAuth, verify_role}};
|
||||||
use actix_web::{delete, get, post, put, web, HttpResponse, HttpRequest, ResponseError};
|
use actix_web::{delete, get, post, put, web, HttpResponse, HttpRequest, ResponseError};
|
||||||
use log::{error, warn};
|
use log::{error, warn};
|
||||||
use postgis_diesel::types::{Polygon, Point};
|
use postgis_diesel::types::{Polygon, Point};
|
||||||
@@ -132,12 +132,13 @@ async fn get(icao: web::Path<String>) -> HttpResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[post("")]
|
#[post("")]
|
||||||
async fn create(airport: web::Json<InsertAirport>, auth: JwtAuth) -> HttpResponse {
|
async fn create(airport: web::Json<Airport>, auth: JwtAuth) -> HttpResponse {
|
||||||
let _ = match verify_role(&auth, "admin") {
|
let _ = match verify_role(&auth, "admin") {
|
||||||
Ok(_) => {},
|
Ok(_) => {},
|
||||||
Err(err) => return ResponseError::error_response(&err)
|
Err(err) => return ResponseError::error_response(&err)
|
||||||
};
|
};
|
||||||
match QueryAirport::create(airport.into_inner()) {
|
let query_airport: QueryAirport = airport.into_inner().into();
|
||||||
|
match QueryAirport::insert(query_airport) {
|
||||||
Ok(a) => HttpResponse::Created().json(a),
|
Ok(a) => HttpResponse::Created().json(a),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("{}", err);
|
error!("{}", err);
|
||||||
@@ -147,12 +148,13 @@ async fn create(airport: web::Json<InsertAirport>, auth: JwtAuth) -> HttpRespons
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[put("/{icao}")]
|
#[put("/{icao}")]
|
||||||
async fn update(icao: web::Path<String>, airport: web::Json<InsertAirport>, auth: JwtAuth) -> HttpResponse {
|
async fn update(icao: web::Path<String>, airport: web::Json<Airport>, auth: JwtAuth) -> HttpResponse {
|
||||||
let _ = match verify_role(&auth, "admin") {
|
let _ = match verify_role(&auth, "admin") {
|
||||||
Ok(_) => {},
|
Ok(_) => {},
|
||||||
Err(err) => return ResponseError::error_response(&err)
|
Err(err) => return ResponseError::error_response(&err)
|
||||||
};
|
};
|
||||||
match QueryAirport::update(icao.into_inner(), airport.into_inner()) {
|
let query_airport: QueryAirport = airport.into_inner().into();
|
||||||
|
match QueryAirport::update(icao.into_inner(), query_airport) {
|
||||||
Ok(a) => HttpResponse::Ok().json(a),
|
Ok(a) => HttpResponse::Ok().json(a),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("{}", err);
|
error!("{}", err);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::{error_handler::ServiceError, airports::{InsertAirport, QueryAirport}};
|
use crate::{error_handler::ServiceError, airports::QueryAirport};
|
||||||
use diesel::{r2d2::ConnectionManager, PgConnection};
|
use diesel::{r2d2::ConnectionManager, PgConnection};
|
||||||
use redis::{Client as RedisClient, aio::Connection as RedisConnection};
|
use redis::{Client as RedisClient, aio::Connection as RedisConnection};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -63,10 +63,10 @@ pub fn import_data() -> i32 {
|
|||||||
let path = "airport-codes.json";
|
let path = "airport-codes.json";
|
||||||
debug!("Importing data from {}", path);
|
debug!("Importing data from {}", path);
|
||||||
let contents: String = std::fs::read_to_string(path).expect("Failed to read file");
|
let contents: String = std::fs::read_to_string(path).expect("Failed to read file");
|
||||||
let airports: Vec<InsertAirport> = serde_json::from_str(&contents).expect("JSON was not well formed.");
|
let airports: Vec<QueryAirport> = serde_json::from_str(&contents).expect("JSON was not well formed.");
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
for airport in airports {
|
for airport in airports {
|
||||||
match QueryAirport::create(airport) {
|
match QueryAirport::insert(airport) {
|
||||||
Ok(_) => count += 1,
|
Ok(_) => count += 1,
|
||||||
Err(err) => error!("Error inserting airport; {}", err)
|
Err(err) => error!("Error inserting airport; {}", err)
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,11 +3,8 @@ diesel::table! {
|
|||||||
use postgis_diesel::sql_types::*;
|
use postgis_diesel::sql_types::*;
|
||||||
airports (icao) {
|
airports (icao) {
|
||||||
icao -> Text,
|
icao -> Text,
|
||||||
id -> Integer,
|
|
||||||
category -> Text,
|
category -> Text,
|
||||||
full_name -> Text,
|
full_name -> Text,
|
||||||
elevation_ft -> Nullable<Integer>,
|
|
||||||
continent -> Text,
|
|
||||||
iso_country -> Text,
|
iso_country -> Text,
|
||||||
iso_region -> Text,
|
iso_region -> Text,
|
||||||
municipality -> Text,
|
municipality -> Text,
|
||||||
@@ -15,6 +12,7 @@ diesel::table! {
|
|||||||
iata_code -> Text,
|
iata_code -> Text,
|
||||||
local_code -> Text,
|
local_code -> Text,
|
||||||
point -> Geometry,
|
point -> Geometry,
|
||||||
|
data -> Jsonb
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ use serde::{Deserialize, Serialize};
|
|||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
pub struct QualityControlFlags {
|
pub struct QualityControlFlags {
|
||||||
pub auto: Option<bool>,
|
pub auto: Option<bool>,
|
||||||
pub auto_station: Option<bool>,
|
pub auto_station_without_precipication: Option<bool>,
|
||||||
|
pub auto_station_with_precipication: Option<bool>,
|
||||||
pub maintenance_indicator_on: Option<bool>,
|
pub maintenance_indicator_on: Option<bool>,
|
||||||
pub corrected: Option<bool>
|
pub corrected: Option<bool>
|
||||||
}
|
}
|
||||||
@@ -18,7 +19,8 @@ impl Default for QualityControlFlags {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
QualityControlFlags {
|
QualityControlFlags {
|
||||||
auto: None,
|
auto: None,
|
||||||
auto_station: None,
|
auto_station_without_precipication: None,
|
||||||
|
auto_station_with_precipication: None,
|
||||||
maintenance_indicator_on: None,
|
maintenance_indicator_on: None,
|
||||||
corrected: None,
|
corrected: None,
|
||||||
}
|
}
|
||||||
@@ -123,7 +125,6 @@ impl Default for Metar {
|
|||||||
|
|
||||||
impl Metar {
|
impl Metar {
|
||||||
fn parse(metar_strings: Vec<&str>) -> Result<Vec<Self>, ServiceError> {
|
fn parse(metar_strings: Vec<&str>) -> Result<Vec<Self>, ServiceError> {
|
||||||
// Parse a metar in the format of: KSMF 211653Z 01004KT 10SM BKN250 11/06 A3041 RMK AO2 SLP296 T01060061
|
|
||||||
let mut metars: Vec<Self> = vec![];
|
let mut metars: Vec<Self> = vec![];
|
||||||
for metar_string in metar_strings {
|
for metar_string in metar_strings {
|
||||||
trace!("Parsing METAR data: {}", metar_string);
|
trace!("Parsing METAR data: {}", metar_string);
|
||||||
@@ -347,15 +348,42 @@ impl Metar {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let slp_re = regex::Regex::new(r"^SLP([0-9]{3})$").unwrap();
|
let slp_re = regex::Regex::new(r"^SLP([0-9]{3})$").unwrap();
|
||||||
|
let hourly_temp_re = regex::Regex::new(r"^T[01][0-9]{3}[01][0-9]{3}$").unwrap();
|
||||||
let remark = metar_parts[0];
|
let remark = metar_parts[0];
|
||||||
metar_parts.remove(0);
|
metar_parts.remove(0);
|
||||||
if remark == "AO2" {
|
if remark == "AO1" {
|
||||||
metar.quality_control_flags.auto_station = Some(true);
|
metar.quality_control_flags.auto_station_without_precipication = Some(true);
|
||||||
|
} else if remark == "AO2" {
|
||||||
|
metar.quality_control_flags.auto_station_with_precipication = Some(true);
|
||||||
} else if remark == "$" {
|
} else if remark == "$" {
|
||||||
metar.quality_control_flags.maintenance_indicator_on = Some(true);
|
metar.quality_control_flags.maintenance_indicator_on = Some(true);
|
||||||
} else if slp_re.is_match(remark) {
|
} else if slp_re.is_match(remark) {
|
||||||
let slp = slp_re.captures(remark).unwrap();
|
let slp = slp_re.captures(remark).unwrap();
|
||||||
metar.sea_level_pressure_mb = Some(slp[1].parse::<f64>().unwrap());
|
let sea_level_pressure = slp[1].parse::<f64>().unwrap();
|
||||||
|
if sea_level_pressure > 500.0 {
|
||||||
|
metar.sea_level_pressure_mb = Some((sea_level_pressure / 10.0) + 900.0);
|
||||||
|
} else {
|
||||||
|
metar.sea_level_pressure_mb = Some((sea_level_pressure / 10.0) + 1000.0);
|
||||||
|
}
|
||||||
|
} else if hourly_temp_re.is_match(remark) {
|
||||||
|
let temp_negation = &remark[1..2];
|
||||||
|
let temp = &remark[2..5];
|
||||||
|
if let Ok(t) = temp.parse::<f64>() {
|
||||||
|
if temp_negation == "0" {
|
||||||
|
metar.temp_c = Some(t / 10.0);
|
||||||
|
} else {
|
||||||
|
metar.temp_c = Some(t / 10.0 * -1.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let dewpoint_negation = &remark[6..7];
|
||||||
|
let dewpoint = &remark[6..9];
|
||||||
|
if let Ok(d) = dewpoint.parse::<f64>() {
|
||||||
|
if dewpoint_negation == "0" {
|
||||||
|
metar.dewpoint_c = Some(d / 10.0);
|
||||||
|
} else {
|
||||||
|
metar.dewpoint_c = Some(d / 10.0 * -1.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user