#!/usr/bin/env runhaskell {-# OPTIONS_GHC -Wall #-} import Control.Monad.State import System.Environment import System.IO import System.Random main :: IO () main = do a <- getArgs case a of [] -> do q <- question when (null q) main [ele, qnh, temp] -> let Pressures pa da = density_altitude (read ele) (read qnh) (read temp) in putStrLn . concat $ [ "Pressure Altitude: " , show pa , "ft" , " " , "Density Altitude: " , show da , "ft" ] _ -> hPutStrLn stderr "Enter for PA/DA or no arguments for exercise drills" isa_pressure_msl :: Double isa_pressure_msl = 1013.25 isa_temp_msl :: Int isa_temp_msl = 15 randomtemp :: (Random a, RandomGen g, Num a) => State g a randomtemp = state (randomR (-15, 45)) randomele :: (Random a, RandomGen g, Num a) => State g a randomele = state (\g -> let (p, h) = randomR (-10, 240) g in (p * 50, h)) randomqnh :: (Random a, RandomGen g, Num a) => State g a randomqnh = state (randomR (990, 1030)) data Pressures = Pressures { pressure_alt :: Int , density_alt :: Int } deriving (Eq, Ord, Show) isa_temperature :: Fractional a => a -> a isa_temperature alt = fromIntegral isa_temp_msl - alt / 500 pressure_altitude :: (Integral a, Integral b) => a -> b -> Double pressure_altitude ele qnh = fromIntegral ele + (isa_pressure_msl - fromIntegral qnh) * 30 -- | -- -- >>> density_altitude 5000 1010 15 -- Bob Tait PPL Page 8 (Question 1) -- (5090,6290) -- -- >>> density_altitude 1800 1027 26 -- Bob Tait PPL Page 8 (Question 2) -- (1380,3060) -- -- >>> density_altitude 25000 1013 (-15) -- Bob Tait PPL Page 8 (Question 3) -- (25000,27400) -- -- >>> density_altitude 12500 1013 (-10) -- Bob Tait PPL Page 8 (Question 4) -- (12500,12500) -- -- >>> density_altitude 430 1030 2 -- Bob Tait PPL Page 8 (Question 5) -- (-80,-1640) density_altitude :: Int -- ^ elevation -> Int -- ^ QNH -> Int -- ^ temperature -> Pressures density_altitude ele qnh temp = let pa = pressure_altitude ele qnh isa_deviation = fromIntegral temp - isa_temperature pa in density_altitude' pa isa_deviation density_altitude' :: Double -- ^ pressure alt -> Double -- ^ isa deviation -> Pressures density_altitude' pa isa_deviation = Pressures (round pa) (round (isa_deviation * 120 + pa)) header_question :: String -> String header_question s = concat [ "\ESC[92m\ESC[42m" , s , "\ESC[m" ] value_question :: String -> String value_question s = concat [ "\ESC[38m\ESC[41m" , s , "\ESC[m" ] header_answer :: String -> String header_answer s = concat [ "\ESC[95m\ESC[45m" , s , "\ESC[m" ] value_answer :: String -> String value_answer s = concat [ "\ESC[38m\ESC[41m" , s , "\ESC[m" ] separator :: String -> String separator s = concat [ "\ESC[40m\ESC[37m" , s , "\ESC[m" ] showQuestion :: (Show a, Show b, Show c) => a -> b -> c -> String showQuestion e q t = concat [ header_question "Elevation: " , value_question (show e) , value_question "ft" , "\n" , header_question "QNH: " , value_question (show q) , value_question "hPa" , "\n" , header_question "Temperature: " , value_question (show t) , value_question "C" ] showAnswer :: (Show a, Show b) => a -> b -> String showAnswer pa da = concat [ "\n" , header_answer "Pressure Altitude: " , value_answer (show pa) , value_answer "ft" , "\n" , header_answer "Density Altitude: " , value_answer (show da) , value_answer "ft" , "\n" , separator "--------------------------------" ] question' :: Int -- ^ elevation -> Int -- ^ QNH -> Int -- ^ temperature -> IO String question' e q t = do let Pressures pa da = density_altitude e q t putStrLn (showQuestion e q t) l <- getLine putStrLn (showAnswer pa da) return l question :: IO String question = let eqt :: State StdGen (Int, Int, Int) eqt = (,,) <$> randomele <*> randomqnh <*> randomtemp in do g <- newStdGen let (e, q, t) = evalState eqt g question' e q t