Compare commits

...

2 Commits

Author SHA1 Message Date
e15c42ff4a handle bad data
where by "handle" we mean that Track.parse now returns an Either
instead of making up data points that lie on the equator
2024-10-31 00:35:19 +00:00
a3d48100ae replace case expressions with listToMaybe 2024-10-30 23:32:13 +00:00
2 changed files with 28 additions and 39 deletions

View File

@ -17,6 +17,7 @@ import Control.Exception
import Data.List as List import Data.List as List
import Data.List qualified import Data.List qualified
import Data.Map as Map import Data.Map as Map
import Data.Maybe
import Data.Text qualified import Data.Text qualified
import Data.Text.Lazy as T import Data.Text.Lazy as T
import Data.Time import Data.Time
@ -52,16 +53,12 @@ gpxNS localName =
tpxNS localName = tpxNS localName =
Name localName (Just "http://www.garmin.com/xmlschemas/TrackPointExtension/v2") Nothing Name localName (Just "http://www.garmin.com/xmlschemas/TrackPointExtension/v2") Nothing
mkPoint pos =
Point
pos
Nothing
(UTCTime (toEnum 60631) 43200)
Nothing
Nothing
Nothing
elToPoint :: Cursor -> Point data BadFile = BadFile deriving (Show)
instance Exception BadFile
elToPoint :: Cursor -> Either SomeException Point
elToPoint c = elToPoint c =
case node c of case node c of
NodeElement (Element _ attrs _) -> NodeElement (Element _ attrs _) ->
@ -85,37 +82,27 @@ elToPoint c =
>>= element (Name "PowerInWatts" (Just "http://www.garmin.com/xmlschemas/PowerExtension/v1") Nothing) >>= element (Name "PowerInWatts" (Just "http://www.garmin.com/xmlschemas/PowerExtension/v1") Nothing)
>>= child >>= child
>>= content >>= content
in Point parsedTime =
listToMaybe ts
>>= (Data.Time.ISO8601.parseISO8601 . Data.Text.unpack)
in case parsedTime of
Nothing -> Left (toException BadFile)
Just utime ->
Right $
Point
(Pos lat lon) (Pos lat lon)
( case ele of (listToMaybe ele >>= return . asFloat)
[e] -> Just $ asFloat e utime
_ -> Nothing (listToMaybe cadence >>= return . asInt)
) (listToMaybe power >>= return . asInt)
( case ts of
[e] -> case Data.Time.ISO8601.parseISO8601 (Data.Text.unpack e) of
Just utime -> utime
_ -> UTCTime (toEnum 0) 0
_ -> UTCTime (toEnum 0) 0
)
( case cadence of
[e] -> Just (asInt e)
_ -> Nothing
)
( case power of
[e] -> Just (asInt e)
_ -> Nothing
)
Nothing Nothing
where where
asFloat v = (read (Data.Text.unpack v) :: Float) asFloat v = (read (Data.Text.unpack v) :: Float)
asInt v = (read (Data.Text.unpack v) :: Int) asInt v = (read (Data.Text.unpack v) :: Int)
getAttr name = getAttr name = maybe 0 asFloat (Map.lookup name attrs)
case Map.lookup name attrs of _ -> Left (toException BadFile)
Just v -> asFloat v
_ -> 0
_ -> mkPoint (Pos 0 0)
getPoints :: Cursor -> [Point] getPoints :: Cursor -> Either SomeException [Point]
getPoints c = getPoints c =
let trkpts = let trkpts =
element (gpxNS "gpx") c element (gpxNS "gpx") c
@ -123,12 +110,12 @@ getPoints c =
>>= element (gpxNS "trk") >>= element (gpxNS "trk")
>>= descendant >>= descendant
>>= element (gpxNS "trkpt") >>= element (gpxNS "trkpt")
in List.map elToPoint trkpts in traverse elToPoint trkpts
parse :: String -> Either SomeException [Point] parse :: String -> Either SomeException [Point]
parse str = do parse str = do
gpx <- parseText def (T.pack str) gpx <- parseText def (T.pack str)
return (getPoints (fromDocument gpx)) getPoints (fromDocument gpx)
length :: Track -> Int length :: Track -> Int
length = Data.List.length length = Data.List.length

View File

@ -34,7 +34,9 @@ onepoint =
wrap wrap
[r| [r|
<trk> <trkseg> <trk> <trkseg>
<trkpt lat="51" lon="-0.1"> </trkpt> <trkpt lat="51" lon="-0.1">
<time>2024-10-23T08:34:59.779+01:00</time>
</trkpt>
</trkseg> </trk> </trkseg> </trk>
|] |]