diff --git a/spatial-coordinate-systems/src/dd.rs b/spatial-coordinate-systems/src/dd.rs index b5b784a..c5a622e 100644 --- a/spatial-coordinate-systems/src/dd.rs +++ b/spatial-coordinate-systems/src/dd.rs @@ -1,5 +1,14 @@ -use crate::common::{optional_separator, parse_f64}; -use nom::{character::complete::space0, combinator::map_opt, sequence::tuple, IResult}; +use crate::{ + common::{optional_separator, parse_direction, parse_f64}, + Direction, +}; +use nom::{ + branch::alt, + character::complete::space0, + combinator::{map, map_opt}, + sequence::tuple, + IResult, +}; use std::{fmt, str::FromStr}; #[derive(PartialEq, Debug, Clone)] @@ -11,8 +20,65 @@ pub struct Coordinate { impl Coordinate { pub fn parse(i: &str) -> IResult<&str, Self> { let ret = map_opt( - tuple((parse_f64, optional_separator(','), space0, parse_f64)), - |(lat, _, _, lon)| { + alt(( + map_opt( + alt(( + map( + tuple(( + parse_f64, + space0, + parse_direction, + optional_separator(','), + space0, + parse_f64, + space0, + parse_direction, + )), + |(lat, _, lat_direction, _, _, lon, _, lon_direction)| { + (lat, lat_direction, lon, lon_direction) + }, + ), + map( + tuple(( + parse_direction, + space0, + parse_f64, + optional_separator(','), + space0, + parse_direction, + space0, + parse_f64, + )), + |(lat_direction, _, lat, _, _, lon_direction, _, lon)| { + (lat, lat_direction, lon, lon_direction) + }, + ), + )), + |(lat, lat_direction, lon, lon_direction)| { + if !lat_direction.is_lat() || !lon_direction.is_lon() { + return None; + } + + Some(( + if lat_direction == Direction::North { + -lat + } else { + lat + }, + if lon_direction == Direction::East { + -lon + } else { + lon + }, + )) + }, + ), + map( + tuple((parse_f64, optional_separator(','), space0, parse_f64)), + |(lat, _, _, lon)| (lat, lon), + ), + )), + |(lat, lon)| { // Ensure this is a north/south then east/west direction Self::from(lat, lon) }, @@ -51,3 +117,20 @@ impl FromStr for Coordinate { Self::parse(i).map_err(|_| ()).map(|(_, ret)| ret) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_general() { + assert!(dbg!(Coordinate::from_str( + "69.79268710495744, -108.23886036872865" + )) + .is_ok()); + assert!(dbg!(Coordinate::from_str( + "69.79268710495744 S, 108.23886036872865 E" + )) + .is_ok()); + } +} diff --git a/web-frontend/src/routes/app/Error.svelte b/web-frontend/src/routes/app/Error.svelte index e4f1fd5..e41e104 100644 --- a/web-frontend/src/routes/app/Error.svelte +++ b/web-frontend/src/routes/app/Error.svelte @@ -1,5 +1,5 @@