import Data.Maybe cao_20_7_4 = (*1.15) kg_to_lb = (*2.2) ft_to_metre = (*0.3048) litre_to_kg_avgas = (*0.72) taxi_fuel_kg = 5 modrem x d = fromInteger (x `mod` d) / fromInteger d -- Calculate pressure altitude isatemp = 15 isapressure = 1013.25 pressure_altitude ele qnh = max 0 (fromIntegral ele + (isapressure - fromIntegral qnh) * 30) declared_temp da = isatemp - da / 500 -- Find the 4 numbers to interpolate -- nw ne -- sw se -- Calculate the proportion of the temperature to interpolate (0 >= temp_prop <= 1) -- Calculate the proportion of the pressure altutide to interpolate (0 >= pa_prop <= 1) data DistanceRequired = DistanceRequired { distance_required_ft :: Double , distance_required_ft_cao20_7_4 :: Double , distance_required_metre :: Double , distance_required_metre_cao20_7_4 :: Double } deriving (Eq, Show) f <<$>> DistanceRequired nw sw ne se = DistanceRequired (f nw) (f sw) (f ne) (f se) eachDistanceRequired f (DistanceRequired nw1 sw1 ne1 se1) (DistanceRequired nw2 sw2 ne2 se2) = DistanceRequired (f nw1 nw2) (f sw1 sw2) (f ne1 ne2) (f se1 se2) distanceRequired1 x = DistanceRequired x (cao_20_7_4 x) (ft_to_metre x) (cao_20_7_4 (ft_to_metre x)) grass gr clear50ft = let gr' = (*1.45) <<$>> gr t = eachDistanceRequired (+) (eachDistanceRequired (-) clear50ft gr) gr' in (gr', t) interpolate :: Double -> Double -> Double -> Double -> Double -> Double -> DistanceRequired interpolate nw sw ne se da temp = let temp_prop = modrem (round temp) 10 interpolate' a b prop = (a-b)*prop+b interpolate_temp a b = interpolate' a b temp_prop result = interpolate' (interpolate_temp se sw) (interpolate_temp ne nw) (modrem (round da) 1000) in distanceRequired1 result data Check a = Check a a deriving (Eq, Ord, Show) (===) :: a -> a -> Check a (===) = Check infixl 4 === v :: Check a -> a v (Check a _) = a check :: (Show a, Eq a) => Check a -> Maybe String check (Check a1 a2) = if a1 == a2 then Nothing else Just (concat [show a1, " /= ", show a2]) ---- ---- YBAF ybaf_declared_density = 1450 -- ft (winter) ybaf_ele = 65 -- ft ybaf_declared_density_height = ybaf_declared_density + ybaf_ele === 1515 ybaf_declared_temp = declared_temp (v ybaf_declared_density_height) === 11.97 ybaf_interpolate nw sw ne se = interpolate nw sw ne se (v ybaf_declared_density_height) (v ybaf_declared_temp) ---- YSPE yspe_declared_density = 1450 -- ft (winter) yspe_ele = 2934 -- ft yspe_declared_density_height = yspe_declared_density + yspe_ele === 4384 yspe_declared_temp = declared_temp (v yspe_declared_density_height) === 6.231999999999999 yspe_interpolate nw sw ne se = interpolate nw sw ne se (v yspe_declared_density_height) (v yspe_declared_temp) ---- -- TODR YBAF -- *2550lb* todr_ybaf_groundroll = ybaf_interpolate 1010 1110 1090 1195 === DistanceRequired { distance_required_ft = 1078.015 , distance_required_ft_cao20_7_4 = 1239.71725 , distance_required_metre = 328.578972 , distance_required_metre_cao20_7_4 = 377.8658178 } todr_ybaf_50ft = ybaf_interpolate 1720 1890 1850 2035 === DistanceRequired { distance_required_ft = 1835.095 , distance_required_ft_cao20_7_4 = 2110.35925 , distance_required_metre = 559.336956 , distance_required_metre_cao20_7_4 = 643.2374993999999 } -- LDR YSPE -- *2550lb* ldr_yspe_groundroll = yspe_interpolate 630 655 655 680 === DistanceRequired { distance_required_ft = 654.6 , distance_required_ft_cao20_7_4 = 752.79 , distance_required_metre = 199.52208000000002 , distance_required_metre_cao20_7_4 = 229.450392 } ldr_yspe_50ft = yspe_interpolate 1425 1460 1460 1500 === DistanceRequired { distance_required_ft = 1460.592 , distance_required_ft_cao20_7_4 = 1679.6808 , distance_required_metre = 445.18844160000003 , distance_required_metre_cao20_7_4 = 511.96670784 } -- TODR YSPE -- *2550lb* todr_yspe_groundroll = yspe_interpolate 1235 1355 1215 1335 === DistanceRequired { distance_required_ft = 1269.08 , distance_required_ft_cao20_7_4 = 1459.4419999999998 , distance_required_metre = 386.815584 , distance_required_metre_cao20_7_4 = 444.83792159999996 } todr_yspe_50ft = yspe_interpolate 2120 2345 2295 2545 === DistanceRequired { distance_required_ft = 2317.16 , distance_required_ft_cao20_7_4 = 2664.7339999999995 , distance_required_metre = 706.270368 , distance_required_metre_cao20_7_4 = 812.2109231999999 } -- LDR YBAF -- *2550lb* ldr_ybaf_groundroll = ybaf_interpolate 585 610 605 630 === DistanceRequired { distance_required_ft = 601.875 , distance_required_ft_cao20_7_4 = 692.15625 , distance_required_metre = 183.4515 , distance_required_metre_cao20_7_4 = 210.969225 } ldr_ybaf_50ft = ybaf_interpolate 1350 1385 1385 1420 === DistanceRequired { distance_required_ft = 1375.025 , distance_required_ft_cao20_7_4 = 1581.27875 , distance_required_metre = 419.10762000000005 , distance_required_metre_cao20_7_4 = 481.973763 } ---- ybaf_checks = [ ybaf_declared_density_height , ybaf_declared_temp ] yspe_checks = [ yspe_declared_density_height , yspe_declared_temp ] todr_ybaf_checks = [ todr_ybaf_groundroll , todr_ybaf_50ft ] ldr_yspe_checks = [ ldr_yspe_groundroll , ldr_yspe_50ft ] todr_yspe_checks = [ todr_yspe_groundroll , todr_yspe_50ft ] ldr_ybaf_checks = [ ldr_ybaf_groundroll , ldr_ybaf_50ft ] checks = concat [ ybaf_checks , yspe_checks ] todr_checks = concat [ todr_ybaf_checks , todr_yspe_checks ] ldr_checks = concat [ ldr_ybaf_checks , ldr_yspe_checks ] all_checks = map check checks ++ map check todr_checks ++ map check ldr_checks failed_checks = catMaybes all_checks