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 = 2400 -- ft ybaf_ele = 65 -- ft ybaf_declared_density_height = ybaf_declared_density + ybaf_ele === 2465 ybaf_declared_temp = declared_temp (v ybaf_declared_density_height) === 10.07 ybaf_interpolate nw sw ne se = interpolate nw sw ne se (v ybaf_declared_density_height) (v ybaf_declared_temp) ybaf_checks = [ ybaf_declared_density_height , ybaf_declared_temp ] ---- YRED yred_declared_density = 2400 -- ft yred_ele = 7 -- ft yred_declared_density_height = yred_declared_density + yred_ele === 2407 yred_declared_temp = declared_temp (v yred_declared_density_height) === 10.186 yred_interpolate nw sw ne se = interpolate nw sw ne se (v yred_declared_density_height) (v yred_declared_temp) yred_checks = [ yred_declared_density_height , yred_declared_temp ] ---- YBSU ybsu_declared_density = 2400 -- ft ybsu_ele = 15 -- ft ybsu_declared_density_height = ybsu_declared_density + ybsu_ele === 2415 ybsu_declared_temp = declared_temp (v ybsu_declared_density_height) === 10.17 ybsu_interpolate nw sw ne se = interpolate nw sw ne se (v ybsu_declared_density_height) (v ybsu_declared_temp) ybsu_checks = [ ybsu_declared_density_height , ybsu_declared_temp ] ---- YKRY ykry_declared_density = 2600 -- ft ykry_ele = 1492 -- ft ykry_declared_density_height = ykry_declared_density + ykry_ele === 4092 ykry_declared_temp = declared_temp (v ykry_declared_density_height) === 6.816000000000001 ykry_interpolate nw sw ne se = interpolate nw sw ne se (v ykry_declared_density_height) (v ykry_declared_temp) ykry_checks = [ ykry_declared_density_height , ykry_declared_temp ] ---- YGAS ygas_declared_density = 2600 -- ft ygas_ele = 460 -- ft ygas_declared_density_height = ygas_declared_density + ygas_ele === 3060 ygas_declared_temp = declared_temp (v ygas_declared_density_height) === 8.879999999999999 ygas_interpolate nw sw ne se = interpolate nw sw ne se (v ygas_declared_density_height) (v ygas_declared_temp) ygas_checks = [ ygas_declared_density_height , ygas_declared_temp ] ---- -- TODR YBAF -- *2200lb* todr_ybaf_groundroll = ybaf_interpolate 840 925 905 995 === DistanceRequired { distance_required_ft = 879.525 , distance_required_ft_cao20_7_4 = 1011.4537499999999 , distance_required_metre = 268.07922 , distance_required_metre_cao20_7_4 = 308.291103 } todr_ybaf_50ft = ybaf_interpolate 1545 1705 1650 1835 === DistanceRequired { distance_required_ft = 1619.4 , distance_required_ft_cao20_7_4 = 1862.31 , distance_required_metre = 493.59312000000006 , distance_required_metre_cao20_7_4 = 567.6320880000001 } todr_ybaf_checks = [ todr_ybaf_groundroll , todr_ybaf_50ft ] -- LDR YRED -- *2400lb* ldr_yred_groundroll = yred_interpolate 570 590 590 615 === DistanceRequired { distance_required_ft = 578.14 , distance_required_ft_cao20_7_4 = 664.8609999999999 , distance_required_metre = 176.217072 , distance_required_metre_cao20_7_4 = 202.64963279999998 } ldr_yred_50ft = ybsu_interpolate 1330 1360 1360 1395 === DistanceRequired { distance_required_ft = 1342.45 , distance_required_ft_cao20_7_4 = 1543.8174999999999 , distance_required_metre = 409.17876 , distance_required_metre_cao20_7_4 = 470.555574 } ldr_yred_checks = [ ldr_yred_groundroll , ldr_yred_50ft ] -- TODR YRED -- *2200lb* todr_yred_groundroll = yred_interpolate 840 925 905 995 === DistanceRequired { distance_required_ft = 874.595 , distance_required_ft_cao20_7_4 = 1005.7842499999999 , distance_required_metre = 266.57655600000004 , distance_required_metre_cao20_7_4 = 306.56303940000004 } todr_yred_50ft = yred_interpolate 1545 1705 1650 1835 === DistanceRequired { distance_required_ft = 1610.12 , distance_required_ft_cao20_7_4 = 1851.6379999999997 , distance_required_metre = 490.764576 , distance_required_metre_cao20_7_4 = 564.3792623999999 } todr_yred_checks = [ todr_yred_groundroll , todr_yred_50ft ] -- LDR YBSU -- *2400lb* ldr_ybsu_groundroll = ybsu_interpolate 570 590 590 615 === DistanceRequired { distance_required_ft = 578.3 , distance_required_ft_cao20_7_4 = 665.0449999999998 , distance_required_metre = 176.26584 , distance_required_metre_cao20_7_4 = 202.70571599999997 } ldr_ybsu_50ft = ybsu_interpolate 1330 1360 1360 1395 === DistanceRequired { distance_required_ft = 1342.45 , distance_required_ft_cao20_7_4 = 1543.8174999999999 , distance_required_metre = 409.17876 , distance_required_metre_cao20_7_4 = 470.555574 } ldr_ybsu_checks = [ ldr_ybsu_groundroll , ldr_ybsu_50ft ] -- TODR YBSU -- *2200lb* todr_ybsu_groundroll = ybsu_interpolate 840 925 905 995 === DistanceRequired { distance_required_ft = 875.275 , distance_required_ft_cao20_7_4 = 1006.5662499999999 , distance_required_metre = 266.78382 , distance_required_metre_cao20_7_4 = 306.80139299999996 } todr_ybsu_50ft = ybsu_interpolate 1545 1705 1650 1835 === DistanceRequired { distance_required_ft = 1611.4 , distance_required_ft_cao20_7_4 = 1853.11 , distance_required_metre = 491.15472000000005 , distance_required_metre_cao20_7_4 = 564.827928 } todr_ybsu_checks = [ todr_ybsu_groundroll , todr_ybsu_50ft ] -- LDR YKRY -- *2400lb* ldr_ykry_groundroll = ykry_interpolate 595 615 615 640 === DistanceRequired { distance_required_ft = 611.162 , distance_required_ft_cao20_7_4 = 702.8362999999999 , distance_required_metre = 186.2821776 , distance_required_metre_cao20_7_4 = 214.22450424 } ldr_ykry_50ft = ykry_interpolate 1365 1400 1400 1435 === DistanceRequired { distance_required_ft = 1392.72 , distance_required_ft_cao20_7_4 = 1601.628 , distance_required_metre = 424.501056 , distance_required_metre_cao20_7_4 = 488.1762144 } ldr_ykry_checks = [ ldr_ykry_groundroll , ldr_ykry_50ft ] -- TODR YKRY -- *2200lb* todr_ykry_groundroll = ykry_interpolate 945 1040 1020 1125 === DistanceRequired { distance_required_ft = 1006.884 , distance_required_ft_cao20_7_4 = 1157.9166 , distance_required_metre = 306.8982432 , distance_required_metre_cao20_7_4 = 352.93297968 } todr_ykry_50ft = ykry_interpolate 1750 1945 1890 2105 === DistanceRequired { distance_required_ft = 1867.228 , distance_required_ft_cao20_7_4 = 2147.3122 , distance_required_metre = 569.1310944 , distance_required_metre_cao20_7_4 = 654.50075856 } todr_ykry_checks = [ todr_ykry_groundroll , todr_ykry_50ft ] -- LDR YGAS -- *2400lb* ldr_ygas_groundroll = ygas_interpolate 570 595 590 615 === DistanceRequired { distance_required_ft = 589.5 , distance_required_ft_cao20_7_4 = 677.925 , distance_required_metre = 179.67960000000002 , distance_required_metre_cao20_7_4 = 206.63154 } ldr_ygas_50ft = ygas_interpolate 1330 1365 1360 1400 === DistanceRequired { distance_required_ft = 1359.37 , distance_required_ft_cao20_7_4 = 1563.2754999999997 , distance_required_metre = 414.33597599999996 , distance_required_metre_cao20_7_4 = 476.48637239999994 } ldr_ygas_checks = [ ldr_ygas_groundroll , ldr_ygas_50ft ] -- TODR YGAS -- *2200lb* todr_ygas_groundroll = ygas_interpolate 855 945 925 1020 === DistanceRequired { distance_required_ft = 923.67 , distance_required_ft_cao20_7_4 = 1062.2205 , distance_required_metre = 281.534616 , distance_required_metre_cao20_7_4 = 323.7648084 } todr_ygas_50ft = ygas_interpolate 1585 1750 1705 1890 === DistanceRequired { distance_required_ft = 1703.98 , distance_required_ft_cao20_7_4 = 1959.5769999999998 , distance_required_metre = 519.373104 , distance_required_metre_cao20_7_4 = 597.2790696 } todr_ygas_checks = [ todr_ygas_groundroll , todr_ygas_50ft ] -- LDR YBAF -- *2400lb* ldr_ybaf_groundroll = ybaf_interpolate 550 570 570 590 === DistanceRequired { distance_required_ft = 559.3 , distance_required_ft_cao20_7_4 = 643.1949999999999 , distance_required_metre = 170.47464 , distance_required_metre_cao20_7_4 = 196.04583599999998 } ldr_ybaf_50ft = ybaf_interpolate 1295 1330 1330 1360 === DistanceRequired { distance_required_ft = 1311.275 , distance_required_ft_cao20_7_4 = 1507.96625 , distance_required_metre = 399.67662000000007 , distance_required_metre_cao20_7_4 = 459.62811300000004 } ldr_ybaf_checks = [ ldr_ybaf_groundroll , ldr_ybaf_50ft ] ---- checks = concat [ ybaf_checks , yred_checks , ybsu_checks , ykry_checks , ygas_checks ] todr_checks = concat [ todr_ybaf_checks , todr_yred_checks , todr_ybsu_checks , todr_ykry_checks , todr_ygas_checks ] ldr_checks = concat [ ldr_ybsu_checks , ldr_yred_checks , ldr_ykry_checks , ldr_ygas_checks , ldr_ybaf_checks ] all_checks = map check checks ++ map check todr_checks ++ map check ldr_checks failed_checks = catMaybes all_checks