{-# OPTIONS_GHC -Wall #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE FlexibleContexts #-}

module Data.Aviation.Navigation.WindComponent(
  WindComponent(..)
, HasWindComponent(..)
, calculateWindComponent
) where

import Control.Category ( Category(id, (.)) )
import Control.Lens ( view, Lens' )
import Data.Aviation.Navigation.Vector
    ( HasVector(magnitude, angle) )
import Data.Aviation.Navigation.WindParameters
    ( HasWindParameters(windParameters, trackTAS, windDirSpeed) )
import Data.Eq ( Eq )
import Data.Functor ( Functor(fmap) )
import Data.Ord ( Ord )
import GHC.Show(Show)
import Prelude(Double, Num((*), (-)), sin, cos)

data WindComponent =
  WindComponent
    Double
    Double
  deriving (WindComponent -> WindComponent -> Bool
(WindComponent -> WindComponent -> Bool)
-> (WindComponent -> WindComponent -> Bool) -> Eq WindComponent
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: WindComponent -> WindComponent -> Bool
== :: WindComponent -> WindComponent -> Bool
$c/= :: WindComponent -> WindComponent -> Bool
/= :: WindComponent -> WindComponent -> Bool
Eq, Eq WindComponent
Eq WindComponent =>
(WindComponent -> WindComponent -> Ordering)
-> (WindComponent -> WindComponent -> Bool)
-> (WindComponent -> WindComponent -> Bool)
-> (WindComponent -> WindComponent -> Bool)
-> (WindComponent -> WindComponent -> Bool)
-> (WindComponent -> WindComponent -> WindComponent)
-> (WindComponent -> WindComponent -> WindComponent)
-> Ord WindComponent
WindComponent -> WindComponent -> Bool
WindComponent -> WindComponent -> Ordering
WindComponent -> WindComponent -> WindComponent
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: WindComponent -> WindComponent -> Ordering
compare :: WindComponent -> WindComponent -> Ordering
$c< :: WindComponent -> WindComponent -> Bool
< :: WindComponent -> WindComponent -> Bool
$c<= :: WindComponent -> WindComponent -> Bool
<= :: WindComponent -> WindComponent -> Bool
$c> :: WindComponent -> WindComponent -> Bool
> :: WindComponent -> WindComponent -> Bool
$c>= :: WindComponent -> WindComponent -> Bool
>= :: WindComponent -> WindComponent -> Bool
$cmax :: WindComponent -> WindComponent -> WindComponent
max :: WindComponent -> WindComponent -> WindComponent
$cmin :: WindComponent -> WindComponent -> WindComponent
min :: WindComponent -> WindComponent -> WindComponent
Ord, Int -> WindComponent -> ShowS
[WindComponent] -> ShowS
WindComponent -> String
(Int -> WindComponent -> ShowS)
-> (WindComponent -> String)
-> ([WindComponent] -> ShowS)
-> Show WindComponent
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> WindComponent -> ShowS
showsPrec :: Int -> WindComponent -> ShowS
$cshow :: WindComponent -> String
show :: WindComponent -> String
$cshowList :: [WindComponent] -> ShowS
showList :: [WindComponent] -> ShowS
Show)

class HasWindComponent a where
  windComponent ::
    Lens' a WindComponent
  {-# INLINE crosswind #-}
  crosswind ::
    Lens' a Double
  crosswind =
    (WindComponent -> f WindComponent) -> a -> f a
forall a. HasWindComponent a => Lens' a WindComponent
Lens' a WindComponent
windComponent ((WindComponent -> f WindComponent) -> a -> f a)
-> ((Double -> f Double) -> WindComponent -> f WindComponent)
-> (Double -> f Double)
-> a
-> f a
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (Double -> f Double) -> WindComponent -> f WindComponent
forall a. HasWindComponent a => Lens' a Double
Lens' WindComponent Double
crosswind
  {-# INLINE headwind #-}
  headwind ::
    Lens' a Double
  headwind =
    (WindComponent -> f WindComponent) -> a -> f a
forall a. HasWindComponent a => Lens' a WindComponent
Lens' a WindComponent
windComponent ((WindComponent -> f WindComponent) -> a -> f a)
-> ((Double -> f Double) -> WindComponent -> f WindComponent)
-> (Double -> f Double)
-> a
-> f a
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (Double -> f Double) -> WindComponent -> f WindComponent
forall a. HasWindComponent a => Lens' a Double
Lens' WindComponent Double
headwind

instance HasWindComponent WindComponent where
  windComponent :: Lens' WindComponent WindComponent
windComponent =
    (WindComponent -> f WindComponent)
-> WindComponent -> f WindComponent
forall a. a -> a
forall {k} (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id
  {-# INLINE crosswind #-}
  crosswind :: Lens' WindComponent Double
crosswind Double -> f Double
f (WindComponent Double
c Double
h) =
    (Double -> WindComponent) -> f Double -> f WindComponent
forall a b. (a -> b) -> f a -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Double -> Double -> WindComponent
`WindComponent` Double
h) (Double -> f Double
f Double
c)
  {-# INLINE headwind #-}
  headwind :: Lens' WindComponent Double
headwind Double -> f Double
f (WindComponent Double
c Double
h) =
    (Double -> WindComponent) -> f Double -> f WindComponent
forall a b. (a -> b) -> f a -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Double -> Double -> WindComponent
WindComponent Double
c) (Double -> f Double
f Double
h)

calculateWindComponent ::
  HasWindParameters a Double =>
  a
  -> WindComponent
calculateWindComponent :: forall a. HasWindParameters a Double => a -> WindComponent
calculateWindComponent a
wp =
  let t :: Vector Double
t = Getting (Vector Double) a (Vector Double) -> a -> Vector Double
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view ((WindParameters Double
 -> Const (Vector Double) (WindParameters Double))
-> a -> Const (Vector Double) a
forall a c. HasWindParameters a c => Lens' a (WindParameters c)
Lens' a (WindParameters Double)
windParameters ((WindParameters Double
  -> Const (Vector Double) (WindParameters Double))
 -> a -> Const (Vector Double) a)
-> ((Vector Double -> Const (Vector Double) (Vector Double))
    -> WindParameters Double
    -> Const (Vector Double) (WindParameters Double))
-> Getting (Vector Double) a (Vector Double)
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (Vector Double -> Const (Vector Double) (Vector Double))
-> WindParameters Double
-> Const (Vector Double) (WindParameters Double)
forall a c. HasWindParameters a c => Lens' a (Vector c)
Lens' (WindParameters Double) (Vector Double)
trackTAS) a
wp
      w :: Vector Double
w = Getting (Vector Double) a (Vector Double) -> a -> Vector Double
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view ((WindParameters Double
 -> Const (Vector Double) (WindParameters Double))
-> a -> Const (Vector Double) a
forall a c. HasWindParameters a c => Lens' a (WindParameters c)
Lens' a (WindParameters Double)
windParameters ((WindParameters Double
  -> Const (Vector Double) (WindParameters Double))
 -> a -> Const (Vector Double) a)
-> ((Vector Double -> Const (Vector Double) (Vector Double))
    -> WindParameters Double
    -> Const (Vector Double) (WindParameters Double))
-> Getting (Vector Double) a (Vector Double)
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (Vector Double -> Const (Vector Double) (Vector Double))
-> WindParameters Double
-> Const (Vector Double) (WindParameters Double)
forall a c. HasWindParameters a c => Lens' a (Vector c)
Lens' (WindParameters Double) (Vector Double)
windDirSpeed) a
wp
      diff :: Double
diff = Getting Double (Vector Double) Double -> Vector Double -> Double
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Double (Vector Double) Double
forall a c. HasVector a c => Lens' a c
Lens' (Vector Double) Double
angle Vector Double
w Double -> Double -> Double
forall a. Num a => a -> a -> a
- Getting Double (Vector Double) Double -> Vector Double -> Double
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Double (Vector Double) Double
forall a c. HasVector a c => Lens' a c
Lens' (Vector Double) Double
angle Vector Double
t
      wm :: Double
wm = Getting Double (Vector Double) Double -> Vector Double -> Double
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Double (Vector Double) Double
forall a c. HasVector a c => Lens' a c
Lens' (Vector Double) Double
magnitude Vector Double
w
      cw :: Double
cw = Double
wm Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
sin Double
diff
      hw :: Double
hw = Double
wm Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
cos Double
diff
  in  Double -> Double -> WindComponent
WindComponent Double
cw Double
hw