module Data.Geo.Route.Waypoint( Waypoint(..) , Waypoints , HasWaypoint(..) , HasWaypoints(..) , HasMaybeDateTime(..) , mkWaypoint , gpxWaypoint , (.<.>) , (~<.>) , (<%>) , (<.?>) , (-.-) ) where import Prelude(Show(show), Double) import Data.Eq(Eq) import Data.Foldable(Foldable(foldMap)) import Data.Function(id, (.)) import Data.Functor(Functor(fmap)) import Data.Maybe(Maybe(Nothing, Just)) import Data.Ord(Ord) import Data.String(String) import Control.Lens(Lens', lens, ( # ), (^.), over, (?~)) import Data.Geo.Coordinate.Latitude(HasLatitude(latitude), fracLatitude) import Data.Geo.Coordinate.Longitude(HasLongitude(longitude), fracLongitude) import Data.Geo.Coordinate.Coordinate(Coordinate, HasCoordinate(coordinate), (..#..)) import Data.Geo.Route.Comment(Comment, HasMaybeComment(mcomment), commentIso) import Data.Geo.Route.Description(Description, HasMaybeDescription(mdescription), descriptionIso) import Data.Geo.Route.Elevation(Elevation, HasMaybeElevation(melevation)) import Data.Geo.Route.Gpx(Gpx(gpx)) import Data.Geo.Route.Name(Name, HasMaybeName(mname), nameIso) import Data.Geo.Route.Symbol(Symbol, HasMaybeSymbol(msymbol)) import Text.Printf(printf) import Text.XML.XSD.DateTime(DateTime) data Waypoint = Waypoint Coordinate (Maybe Elevation) (Maybe DateTime) (Maybe Name) (Maybe Comment) (Maybe Description) (Maybe Symbol) deriving (Eq, Ord, Show) type Waypoints = [Waypoint] mkWaypoint :: HasCoordinate c => c -> Waypoint mkWaypoint c = Waypoint (c ^. coordinate) Nothing Nothing Nothing Nothing Nothing Nothing instance HasCoordinate Waypoint where coordinate = lens (\(Waypoint c _ _ _ _ _ _) -> c) (\(Waypoint _ e d n m s y) c -> Waypoint c e d n m s y) instance HasLatitude Waypoint where latitude = coordinate . latitude instance HasLongitude Waypoint where longitude = coordinate . longitude instance HasMaybeElevation Waypoint where melevation = lens (\(Waypoint _ e _ _ _ _ _) -> e) (\(Waypoint c _ d n m s y) e -> Waypoint c e d n m s y) class HasMaybeDateTime t where mdateTime :: Lens' t (Maybe DateTime) instance HasMaybeDateTime Waypoint where mdateTime = lens (\(Waypoint _ _ d _ _ _ _) -> d) (\(Waypoint c e _ n m s y) d -> Waypoint c e d n m s y) (<%>) :: HasMaybeDateTime t => DateTime -> t -> t (<%>) = (?~) mdateTime infixr 5 <%> instance HasMaybeName Waypoint where mname = lens (\(Waypoint _ _ _ n _ _ _) -> n) (\(Waypoint c e d _ m s y) n -> Waypoint c e d n m s y) instance HasMaybeComment Waypoint where mcomment = lens (\(Waypoint _ _ _ _ m _ _) -> m) (\(Waypoint c e d n _ s y) m -> Waypoint c e d n m s y) instance HasMaybeDescription Waypoint where mdescription = lens (\(Waypoint _ _ _ _ _ s _) -> s) (\(Waypoint c e d n m _ y) s -> Waypoint c e d n m s y) instance HasMaybeSymbol Waypoint where msymbol = lens (\(Waypoint _ _ _ _ _ _ y) -> y) (\(Waypoint c e d n m s _) y -> Waypoint c e d n m s y) class HasWaypoint t where waypoint :: Lens' t Waypoint instance HasWaypoint Waypoint where waypoint = id class HasWaypoints t where waypoints :: Lens' t Waypoints gpxWaypoint :: (HasMaybeName s, HasMaybeComment s, HasMaybeSymbol s, HasMaybeElevation s, HasMaybeDescription s, HasLatitude s, HasLongitude s, HasMaybeDateTime s) => String -> s -> String gpxWaypoint element w = let lat = fracLatitude # (w ^. latitude) lon = fracLongitude # (w ^. longitude) e = w ^. melevation d = w ^. mdateTime n = w ^. mname m = w ^. mcomment s = w ^. mdescription y = w ^. msymbol gpx' :: (Foldable t, Gpx a) => t a -> String gpx' = foldMap gpx in printf "<%s lat=\"%0.6f\" lon=\"%0.6f\">%s%s%s%s%s%s" element lat lon (gpx' e) (gpx' d) (gpx' n) (gpx' m) (gpx' s) (gpx' y) element instance Gpx Waypoint where gpx = gpxWaypoint "wpt" (.<.>) :: String -> Coordinate -> Waypoint s .<.> c = let ups i = Just (s ^. i) in Waypoint c Nothing Nothing (ups nameIso) (ups commentIso) (ups descriptionIso) Nothing infixr 5 .<.> (~<.>) :: Name -> Coordinate -> Waypoint n ~<.> c = Waypoint c Nothing Nothing (Just n) Nothing Nothing Nothing infixr 5 ~<.> (<.?>) :: Double -> Double -> Maybe Waypoint x <.?> y = fmap mkWaypoint (x ..#.. y) infixr 6 <.?> (-.-) :: HasWaypoints t => Maybe Waypoint -> t -> t (-.-) Nothing = id (-.-) (Just w) = over waypoints (w:) infixr 6 -.-