souplesse/lib/Track.hs

92 lines
2.0 KiB
Haskell
Raw Normal View History

2024-10-28 23:35:36 +00:00
{-# LANGUAGE OverloadedStrings #-}
2024-10-29 19:21:25 +00:00
module Track (
Track,
Pos(..),
pos,
elevation,
2024-10-29 19:21:25 +00:00
parse,
Track.length
) where
2024-10-27 23:13:39 +00:00
import Data.Time
import qualified Data.List
2024-10-28 23:35:36 +00:00
import Text.XML
import Text.XML.Cursor as Cursor
import qualified Data.Text
import Data.Text.Lazy as T
import Debug.Trace (trace, traceShow)
import Data.List as List
import Data.Map as Map
import Control.Exception
data Pos = Pos Float Float deriving (Show, Eq)
2024-10-28 23:35:36 +00:00
type Power = Maybe Int
type Cadence = Maybe Int
type HeartRate = Maybe Int
data Point = Point {
pos :: Pos,
elevation :: Maybe Float,
2024-10-28 23:35:36 +00:00
time :: UTCTime,
power :: Power,
cadence :: Cadence,
heartRate :: HeartRate
} deriving (Show)
2024-10-27 23:13:39 +00:00
2024-10-29 19:35:17 +00:00
-- TODO do we even need this type?
2024-10-27 23:13:39 +00:00
type Track = [Point]
2024-10-30 13:30:33 +00:00
gpxNS = "http://www.topografix.com/GPX/1/1"
2024-10-28 23:35:36 +00:00
mkPoint pos =
Point
pos
2024-10-29 21:22:49 +00:00
Nothing
2024-10-28 23:35:36 +00:00
(UTCTime (toEnum 60631) 43200)
(Just 0)
(Just 0)
(Just 0)
elToPoint :: Cursor -> Point
2024-10-29 21:22:49 +00:00
elToPoint c =
case node c of
2024-10-28 23:35:36 +00:00
NodeElement (Element _ attrs _) ->
let
2024-10-29 19:35:17 +00:00
lat = getAttr "lat"
2024-10-28 23:35:36 +00:00
lon = getAttr "lon"
2024-10-30 13:30:33 +00:00
ele = child c >>= element (Name "ele" (Just gpxNS) Nothing) >>= child >>= content
2024-10-29 21:22:49 +00:00
in Point (Pos lat lon)
(case ele of
2024-10-30 14:25:54 +00:00
[e] -> Just $ asFloat e
2024-10-29 21:22:49 +00:00
_ -> Nothing)
(UTCTime (toEnum 60631) 43200)
(Just 0)
(Just 0)
(Just 0)
where
asFloat v = (read (Data.Text.unpack v) :: Float)
getAttr name =
2024-10-30 14:25:54 +00:00
case Map.lookup name attrs of
2024-10-29 21:22:49 +00:00
Just v -> asFloat v
_ -> 0
_ -> mkPoint (Pos 0 0)
2024-10-28 23:35:36 +00:00
getPoints :: Cursor -> [Point]
getPoints c =
let
2024-10-30 13:30:33 +00:00
ns n = Name n (Just gpxNS) Nothing
2024-10-28 23:35:36 +00:00
trkpts =
2024-10-30 13:30:33 +00:00
element (ns "gpx") c >>= child >>=
element (ns "trk") >>= descendant >>=
element (ns "trkpt")
2024-10-28 23:35:36 +00:00
in
2024-10-30 14:25:54 +00:00
List.map elToPoint trkpts
2024-10-28 23:35:36 +00:00
parse :: String -> Either SomeException [Point]
parse str = do
gpx <- parseText def (T.pack str)
return (getPoints (fromDocument gpx))
2024-10-28 23:35:36 +00:00
2024-10-27 23:13:39 +00:00
length :: Track -> Int
2024-10-30 14:25:54 +00:00
length = Data.List.length