module Data.Geo.Jord.Speed
(
Speed
, averageSpeed
, metresPerSecond
, kilometresPerHour
, milesPerHour
, knots
, feetPerSecond
, speedP
, readSpeed
, toMetresPerSecond
, toKilometresPerHour
, toMilesPerHour
, toKnots
, toFeetPerSecond
) where
import Control.Applicative ((<|>))
import Text.ParserCombinators.ReadP (ReadP, pfail, readP_to_S, skipSpaces, string)
import Text.Read (readMaybe)
import Data.Geo.Jord.Duration
import Data.Geo.Jord.Length
import Data.Geo.Jord.Parser
import Data.Geo.Jord.Quantity
newtype Speed =
Speed
{ mmPerHour :: Int
}
deriving (Eq)
instance Read Speed where
readsPrec _ = readP_to_S speedP
instance Show Speed where
show s = show (toKilometresPerHour s) ++ "km/h"
instance Ord Speed where
(<=) (Speed s1) (Speed s2) = s1 <= s2
instance Quantity Speed where
add a b = Speed (mmPerHour a + mmPerHour b)
sub a b = Speed (mmPerHour a - mmPerHour b)
zero = Speed 0
averageSpeed :: Length -> Duration -> Speed
averageSpeed d t = Speed (round (mm / h))
where
mm = toMillimetres d
h = toHours t
metresPerSecond :: Double -> Speed
metresPerSecond mps = Speed (round (mps * 3600000.0))
kilometresPerHour :: Double -> Speed
kilometresPerHour kph = Speed (round (kph * 1e+6))
milesPerHour :: Double -> Speed
milesPerHour mph = Speed (round (mph * 1609344.0))
knots :: Double -> Speed
knots kt = Speed (round (kt * 1852000.0))
feetPerSecond :: Double -> Speed
feetPerSecond fps = Speed (round (fps * 1097280.0))
readSpeed :: String -> Maybe Speed
readSpeed s = readMaybe s :: (Maybe Speed)
toMetresPerSecond :: Speed -> Double
toMetresPerSecond (Speed s) = fromIntegral s / 3600000.0
toKilometresPerHour :: Speed -> Double
toKilometresPerHour (Speed s) = fromIntegral s / 1e+6
toMilesPerHour :: Speed -> Double
toMilesPerHour (Speed s) = fromIntegral s / 1609344.0
toKnots :: Speed -> Double
toKnots (Speed s) = fromIntegral s / 1852000.0
toFeetPerSecond :: Speed -> Double
toFeetPerSecond (Speed s) = fromIntegral s / 1097280.0
speedP :: ReadP Speed
speedP = do
s <- number
skipSpaces
u <- string "m/s" <|> string "km/h" <|> string "mph" <|> string "kt" <|> string "ft/s"
case u of
"m/s" -> return (metresPerSecond s)
"km/h" -> return (kilometresPerHour s)
"mph" -> return (milesPerHour s)
"kt" -> return (knots s)
"ft/s" -> return (feetPerSecond s)
_ -> pfail