{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE RankNTypes #-}

module Data.Aviation.WB.Moment(
  Moment(..)
, HasMoment(..)
, HasMoments(..)
, SetMoment(..)
, HasMoment0(..)
, totalMoment
, totalMoments
, totalMoment''
, totalWeights
, momentX
) where

import Control.Applicative(Applicative((<*>)))
import Control.Category((.))
import Control.Lens(Lens', Traversal', Setter', Iso', lens, makeClassy, view, re)
import Data.Aviation.WB.Arm.ArmStatic(ArmStatic, HasArmStatic(armStatic), HasArmStatics(armStatics), SetArmStatic(setArmStatic))
import Data.Aviation.WB.Weight(Weight, HasWeight(weight), HasWeights(weights), SetWeight(setWeight))
import Data.Eq(Eq)
import Data.Foldable(Foldable, foldl, foldMap)
import Data.Functor((<$>))
import Data.Maybe(Maybe)
import Data.Ord(Ord)
import Prelude(Show, (*), (+), Rational)

data Moment =
  Moment
    Weight
    ArmStatic
  deriving (Moment -> Moment -> Bool
(Moment -> Moment -> Bool)
-> (Moment -> Moment -> Bool) -> Eq Moment
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Moment -> Moment -> Bool
$c/= :: Moment -> Moment -> Bool
== :: Moment -> Moment -> Bool
$c== :: Moment -> Moment -> Bool
Eq, Eq Moment
Eq Moment
-> (Moment -> Moment -> Ordering)
-> (Moment -> Moment -> Bool)
-> (Moment -> Moment -> Bool)
-> (Moment -> Moment -> Bool)
-> (Moment -> Moment -> Bool)
-> (Moment -> Moment -> Moment)
-> (Moment -> Moment -> Moment)
-> Ord Moment
Moment -> Moment -> Bool
Moment -> Moment -> Ordering
Moment -> Moment -> Moment
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
min :: Moment -> Moment -> Moment
$cmin :: Moment -> Moment -> Moment
max :: Moment -> Moment -> Moment
$cmax :: Moment -> Moment -> Moment
>= :: Moment -> Moment -> Bool
$c>= :: Moment -> Moment -> Bool
> :: Moment -> Moment -> Bool
$c> :: Moment -> Moment -> Bool
<= :: Moment -> Moment -> Bool
$c<= :: Moment -> Moment -> Bool
< :: Moment -> Moment -> Bool
$c< :: Moment -> Moment -> Bool
compare :: Moment -> Moment -> Ordering
$ccompare :: Moment -> Moment -> Ordering
$cp1Ord :: Eq Moment
Ord, Int -> Moment -> ShowS
[Moment] -> ShowS
Moment -> String
(Int -> Moment -> ShowS)
-> (Moment -> String) -> ([Moment] -> ShowS) -> Show Moment
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Moment] -> ShowS
$cshowList :: [Moment] -> ShowS
show :: Moment -> String
$cshow :: Moment -> String
showsPrec :: Int -> Moment -> ShowS
$cshowsPrec :: Int -> Moment -> ShowS
Show)

makeClassy ''Moment

class HasMoments a where
  moments ::
    Traversal'
      a
      Moment

instance HasMoments Moment where
  moments :: (Moment -> f Moment) -> Moment -> f Moment
moments =
    (Moment -> f Moment) -> Moment -> f Moment
forall c. HasMoment c => Lens' c Moment
moment

class SetMoment a where
  setMoment ::
    Setter'
      a
      Moment

instance SetMoment Moment where
  setMoment :: (Moment -> f Moment) -> Moment -> f Moment
setMoment =
    (Moment -> f Moment) -> Moment -> f Moment
forall c. HasMoment c => Lens' c Moment
moment

class HasMoment0 a where
  moment0 ::
    Lens'
      a
      (Maybe Moment)

instance HasWeight Moment where
  weight :: (Weight -> f Weight) -> Moment -> f Moment
weight =
    (Moment -> Weight)
-> (Moment -> Weight -> Moment) -> Lens' Moment Weight
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens
      (\(Moment Weight
w ArmStatic
_) -> Weight
w)
      (\(Moment Weight
_ ArmStatic
a) Weight
w -> Weight -> ArmStatic -> Moment
Moment Weight
w ArmStatic
a)

instance HasWeights Moment where
  weights :: (Weight -> f Weight) -> Moment -> f Moment
weights =
    (Weight -> f Weight) -> Moment -> f Moment
forall c. HasWeight c => Lens' c Weight
weight

instance SetWeight Moment where
  setWeight :: (Weight -> f Weight) -> Moment -> f Moment
setWeight =
    (Weight -> f Weight) -> Moment -> f Moment
forall c. HasWeight c => Lens' c Weight
weight

instance HasArmStatic Moment where
  armStatic :: (ArmStatic -> f ArmStatic) -> Moment -> f Moment
armStatic =
    (Moment -> ArmStatic)
-> (Moment -> ArmStatic -> Moment) -> Lens' Moment ArmStatic
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens
      (\(Moment Weight
_ ArmStatic
a) -> ArmStatic
a)
      (\(Moment Weight
w ArmStatic
_) ArmStatic
a -> Weight -> ArmStatic -> Moment
Moment Weight
w ArmStatic
a)

instance HasArmStatics Moment where
  armStatics :: (ArmStatic -> f ArmStatic) -> Moment -> f Moment
armStatics =
    (ArmStatic -> f ArmStatic) -> Moment -> f Moment
forall c. HasArmStatic c => Lens' c ArmStatic
armStatic

instance SetArmStatic Moment where
  setArmStatic :: (ArmStatic -> f ArmStatic) -> Moment -> f Moment
setArmStatic =
    (ArmStatic -> f ArmStatic) -> Moment -> f Moment
forall c. HasArmStatic c => Lens' c ArmStatic
armStatic

totalMoment ::
  HasMoment moment =>
  Iso' Rational Weight
  -> Iso' Rational ArmStatic
  -> moment
  -> Rational
totalMoment :: Iso' Rational Weight
-> Iso' Rational ArmStatic -> moment -> Rational
totalMoment Iso' Rational Weight
w Iso' Rational ArmStatic
a moment
m =
  let r :: Rational
r = Getting Rational moment Rational -> moment -> Rational
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view ((Moment -> Const Rational Moment)
-> moment -> Const Rational moment
forall c. HasMoment c => Lens' c Moment
moment ((Moment -> Const Rational Moment)
 -> moment -> Const Rational moment)
-> ((Rational -> Const Rational Rational)
    -> Moment -> Const Rational Moment)
-> Getting Rational moment Rational
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (Weight -> Const Rational Weight)
-> Moment -> Const Rational Moment
forall c. HasWeight c => Lens' c Weight
weight ((Weight -> Const Rational Weight)
 -> Moment -> Const Rational Moment)
-> ((Rational -> Const Rational Rational)
    -> Weight -> Const Rational Weight)
-> (Rational -> Const Rational Rational)
-> Moment
-> Const Rational Moment
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. AReview Rational Weight -> Getter Weight Rational
forall t b. AReview t b -> Getter b t
re AReview Rational Weight
Iso' Rational Weight
w) moment
m
      s :: Rational
s = Getting Rational moment Rational -> moment -> Rational
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view ((Moment -> Const Rational Moment)
-> moment -> Const Rational moment
forall c. HasMoment c => Lens' c Moment
moment ((Moment -> Const Rational Moment)
 -> moment -> Const Rational moment)
-> ((Rational -> Const Rational Rational)
    -> Moment -> Const Rational Moment)
-> Getting Rational moment Rational
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (ArmStatic -> Const Rational ArmStatic)
-> Moment -> Const Rational Moment
forall c. HasArmStatic c => Lens' c ArmStatic
armStatic ((ArmStatic -> Const Rational ArmStatic)
 -> Moment -> Const Rational Moment)
-> ((Rational -> Const Rational Rational)
    -> ArmStatic -> Const Rational ArmStatic)
-> (Rational -> Const Rational Rational)
-> Moment
-> Const Rational Moment
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. AReview Rational ArmStatic -> Getter ArmStatic Rational
forall t b. AReview t b -> Getter b t
re AReview Rational ArmStatic
Iso' Rational ArmStatic
a) moment
m
  in  Rational
r Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
s
  
totalMoments ::
  (HasMoment moment, Foldable f) =>
  Iso' Rational Weight
  -> Iso' Rational ArmStatic
  -> f moment
  -> Rational
totalMoments :: Iso' Rational Weight
-> Iso' Rational ArmStatic -> f moment -> Rational
totalMoments Iso' Rational Weight
w Iso' Rational ArmStatic
a =
  (Rational -> moment -> Rational)
-> Rational -> f moment -> Rational
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (\Rational
x moment
y -> Rational
x Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
+ Iso' Rational Weight
-> Iso' Rational ArmStatic -> moment -> Rational
forall moment.
HasMoment moment =>
Iso' Rational Weight
-> Iso' Rational ArmStatic -> moment -> Rational
totalMoment Iso' Rational Weight
w Iso' Rational ArmStatic
a moment
y) Rational
0


totalMoment'' ::
  (HasMoment moment, Foldable f) =>
  Iso' Rational Weight
  -> Iso' Rational ArmStatic
  -> f moment
  -> Moment
totalMoment'' :: Iso' Rational Weight
-> Iso' Rational ArmStatic -> f moment -> Moment
totalMoment'' Iso' Rational Weight
w Iso' Rational ArmStatic
a f moment
m =
  let (Rational
mw, Rational
ma) = ((Rational, Rational) -> moment -> (Rational, Rational))
-> (Rational, Rational) -> f moment -> (Rational, Rational)
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (\(Rational
w', Rational
a') moment
n ->  let w'' :: Rational
w'' = Getting Rational moment Rational -> moment -> Rational
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view ((Moment -> Const Rational Moment)
-> moment -> Const Rational moment
forall c. HasMoment c => Lens' c Moment
moment ((Moment -> Const Rational Moment)
 -> moment -> Const Rational moment)
-> ((Rational -> Const Rational Rational)
    -> Moment -> Const Rational Moment)
-> Getting Rational moment Rational
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (Weight -> Const Rational Weight)
-> Moment -> Const Rational Moment
forall c. HasWeight c => Lens' c Weight
weight ((Weight -> Const Rational Weight)
 -> Moment -> Const Rational Moment)
-> ((Rational -> Const Rational Rational)
    -> Weight -> Const Rational Weight)
-> (Rational -> Const Rational Rational)
-> Moment
-> Const Rational Moment
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. AReview Rational Weight -> Getter Weight Rational
forall t b. AReview t b -> Getter b t
re AReview Rational Weight
Iso' Rational Weight
w) moment
n
                                            a'' :: Rational
a'' = Getting Rational moment Rational -> moment -> Rational
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view ((Moment -> Const Rational Moment)
-> moment -> Const Rational moment
forall c. HasMoment c => Lens' c Moment
moment ((Moment -> Const Rational Moment)
 -> moment -> Const Rational moment)
-> ((Rational -> Const Rational Rational)
    -> Moment -> Const Rational Moment)
-> Getting Rational moment Rational
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (ArmStatic -> Const Rational ArmStatic)
-> Moment -> Const Rational Moment
forall c. HasArmStatic c => Lens' c ArmStatic
armStatic ((ArmStatic -> Const Rational ArmStatic)
 -> Moment -> Const Rational Moment)
-> ((Rational -> Const Rational Rational)
    -> ArmStatic -> Const Rational ArmStatic)
-> (Rational -> Const Rational Rational)
-> Moment
-> Const Rational Moment
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. AReview Rational ArmStatic -> Getter ArmStatic Rational
forall t b. AReview t b -> Getter b t
re AReview Rational ArmStatic
Iso' Rational ArmStatic
a) moment
n
                                        in  (Rational
w' Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
+ Rational
w'', Rational
a' Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
+ Rational
w'' Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
a'')) (Rational
0, Rational
0) f moment
m
  in  Weight -> ArmStatic -> Moment
Moment (Getting Weight Rational Weight -> Rational -> Weight
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Weight Rational Weight
Iso' Rational Weight
w Rational
mw) (Getting ArmStatic Rational ArmStatic -> Rational -> ArmStatic
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting ArmStatic Rational ArmStatic
Iso' Rational ArmStatic
a Rational
ma)

totalWeights ::
  (HasMoment moment, Foldable f) =>
  f moment
  -> Weight
totalWeights :: f moment -> Weight
totalWeights =
  (moment -> Weight) -> f moment -> Weight
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap (Getting Weight moment Weight -> moment -> Weight
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view ((Moment -> Const Weight Moment) -> moment -> Const Weight moment
forall c. HasMoment c => Lens' c Moment
moment ((Moment -> Const Weight Moment) -> moment -> Const Weight moment)
-> ((Weight -> Const Weight Weight)
    -> Moment -> Const Weight Moment)
-> Getting Weight moment Weight
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (Weight -> Const Weight Weight) -> Moment -> Const Weight Moment
forall c. HasWeight c => Lens' c Weight
weight))
    
momentX :: 
  (HasWeight w, HasArmStatic s, Applicative f) =>
  f w
  -> f s
  -> f Moment
momentX :: f w -> f s -> f Moment
momentX f w
wt f s
b =
  (\w
w -> Weight -> ArmStatic -> Moment
Moment (Getting Weight w Weight -> w -> Weight
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Weight w Weight
forall c. HasWeight c => Lens' c Weight
weight w
w) (ArmStatic -> Moment) -> (s -> ArmStatic) -> s -> Moment
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Getting ArmStatic s ArmStatic -> s -> ArmStatic
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting ArmStatic s ArmStatic
forall c. HasArmStatic c => Lens' c ArmStatic
armStatic) (w -> s -> Moment) -> f w -> f (s -> Moment)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> f w
wt f (s -> Moment) -> f s -> f Moment
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> f s
b