module Data.GPS.Gps2HtmlReport.JourneyStats where
import Data.GPS
import Data.Maybe
import Data.Time.LocalTime
import Data.Time.Clock
import Data.Time.Calendar
import Text.XML.XSD.DateTime
ptsElevation :: [WptType] -> [(LocalTime,Double)]
ptsElevation = map (\point -> (utcToLocalTime dfltTZ (Text.XML.XSD.DateTime.toUTCTime (fromJust $ time point)) , fromJust $ ele point))
avrSpeedOverTime :: [(LocalTime,Speed)] -> Double -> Double -> [(LocalTime,Speed)] -> [(LocalTime,Speed)]
avrSpeedOverTime [] _ _ _ = []
avrSpeedOverTime [spd] totalSpeed numPoints iteratedAvr = iteratedAvr ++ [(fst spd, (snd spd + totalSpeed) / (numPoints+1))]
avrSpeedOverTime (spd:spds) totalSpeed numPoints iteratedAvr = avrSpeedOverTime [spd] totalSpeed numPoints iteratedAvr ++ avrSpeedOverTime spds (snd spd + totalSpeed) (numPoints+1) iteratedAvr
speedAtPoints :: [WptType] -> [(LocalTime,Speed)]
speedAtPoints [] = []
speedAtPoints (point:points) = (lclTime $ fromJust (time point),0.0) : speedAtPoints' point points
speedAtPoints' :: WptType -> [WptType] -> [(LocalTime, Speed)]
speedAtPoints' _ [] = []
speedAtPoints' prev [x]
| isJust (time x) = [(lclTime $ fromJust (time x), fromJust $ speed prev x)]
| otherwise = []
speedAtPoints' prev (x:xs)
| isJust (time x) = (lclTime $ fromJust (time x), fromJust $ speed prev x) : speedAtPoints' x xs
| otherwise = [] ++ speedAtPoints' x xs
accumDistance :: [WptType] -> Double -> [(LocalTime,Distance)]
accumDistance [] _ = []
accumDistance [x] _ = [(lclTime $ fromJust (time x),0.0)]
accumDistance (x:xs) acc =
let dist = distance x (head xs)
in (lclTime $ fromJust (time x), dist + acc ) : accumDistance xs (dist + acc)
findPoint :: [WptType] -> WptType -> (WptType -> Maybe Double) -> (Double -> Double -> Bool) -> Maybe (LocalTime,Double)
findPoint [] _ _ _ = Nothing
findPoint (point:points) currSelected wayPointElement equalityF
| equalityF (fromJust $ wayPointElement point) (fromJust $ wayPointElement currSelected) = findPoint points point wayPointElement equalityF
| otherwise = if null points
then Just (lclTime (fromJust $ time currSelected), fromJust $ ele currSelected)
else findPoint points currSelected wayPointElement equalityF
journeyDistance :: (Lat a, Lon a) => [a] -> Distance
journeyDistance [] = 0.0
journeyDistance [_] = 0.0
journeyDistance (point:points) = distance point (head points) + journeyDistance points
meanJourneySpeed :: (Lat a, Lon a, Time a) => [a] -> Distance
meanJourneySpeed points = journeyDistance points / realToFrac (journeyTime points)
maxSpeed :: [WptType] -> Speed
maxSpeed points =
let speedTuple = speedAtPoints points
speedList = map snd speedTuple
maxSpeed = foldr max 0.0 speedList
in maxSpeed
meanElevation :: Ele a => [a] -> Double
meanElevation points =
let elevationVals = map (fromJust . ele) points
totalElevation = foldr (+) 0.0 elevationVals
theMean = totalElevation / fromIntegral (length points)
in theMean
journeyTime :: Time a => [a] -> NominalDiffTime
journeyTime [] = fromInteger 0
journeyTime [_] = fromInteger 0
journeyTime (point:points) =
let startTime = toUTCTime (fromJust (time point))
endTime = toUTCTime (fromJust (time $ last points))
in diffUTCTime endTime startTime
dateOfJourney :: Time a => [a] -> Maybe Day
dateOfJourney [] = Nothing
dateOfJourney (point:_) = Just $ utctDay $ toUTCTime $ fromJust (time point)
lclTime :: DateTime -> LocalTime
lclTime dteTime = utcToLocalTime dfltTZ (Text.XML.XSD.DateTime.toUTCTime dteTime)
dfltTZ :: TimeZone
dfltTZ = TimeZone {timeZoneMinutes=0,timeZoneSummerOnly=False,timeZoneName="GMT"}