{-# LANGUAGE DefaultSignatures         #-}
{-# LANGUAGE DeriveAnyClass            #-}
{-# LANGUAGE DeriveGeneric             #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE FlexibleInstances         #-}
{-# LANGUAGE TemplateHaskell           #-}
{-# LANGUAGE UndecidableInstances      #-}
module Experimenter.Parameter.Type where

import           Control.DeepSeq
import           Control.Lens
import qualified Data.ByteString as BS
import           Data.Serialize  as S
import qualified Data.Text       as T
import           GHC.Generics


data ExperimentDesign
  = FullFactory
  | SingleInstance
  deriving (ExperimentDesign
ExperimentDesign -> ExperimentDesign -> Bounded ExperimentDesign
forall a. a -> a -> Bounded a
maxBound :: ExperimentDesign
$cmaxBound :: ExperimentDesign
minBound :: ExperimentDesign
$cminBound :: ExperimentDesign
Bounded, Int -> ExperimentDesign
ExperimentDesign -> Int
ExperimentDesign -> [ExperimentDesign]
ExperimentDesign -> ExperimentDesign
ExperimentDesign -> ExperimentDesign -> [ExperimentDesign]
ExperimentDesign
-> ExperimentDesign -> ExperimentDesign -> [ExperimentDesign]
(ExperimentDesign -> ExperimentDesign)
-> (ExperimentDesign -> ExperimentDesign)
-> (Int -> ExperimentDesign)
-> (ExperimentDesign -> Int)
-> (ExperimentDesign -> [ExperimentDesign])
-> (ExperimentDesign -> ExperimentDesign -> [ExperimentDesign])
-> (ExperimentDesign -> ExperimentDesign -> [ExperimentDesign])
-> (ExperimentDesign
    -> ExperimentDesign -> ExperimentDesign -> [ExperimentDesign])
-> Enum ExperimentDesign
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: ExperimentDesign
-> ExperimentDesign -> ExperimentDesign -> [ExperimentDesign]
$cenumFromThenTo :: ExperimentDesign
-> ExperimentDesign -> ExperimentDesign -> [ExperimentDesign]
enumFromTo :: ExperimentDesign -> ExperimentDesign -> [ExperimentDesign]
$cenumFromTo :: ExperimentDesign -> ExperimentDesign -> [ExperimentDesign]
enumFromThen :: ExperimentDesign -> ExperimentDesign -> [ExperimentDesign]
$cenumFromThen :: ExperimentDesign -> ExperimentDesign -> [ExperimentDesign]
enumFrom :: ExperimentDesign -> [ExperimentDesign]
$cenumFrom :: ExperimentDesign -> [ExperimentDesign]
fromEnum :: ExperimentDesign -> Int
$cfromEnum :: ExperimentDesign -> Int
toEnum :: Int -> ExperimentDesign
$ctoEnum :: Int -> ExperimentDesign
pred :: ExperimentDesign -> ExperimentDesign
$cpred :: ExperimentDesign -> ExperimentDesign
succ :: ExperimentDesign -> ExperimentDesign
$csucc :: ExperimentDesign -> ExperimentDesign
Enum, ExperimentDesign -> ExperimentDesign -> Bool
(ExperimentDesign -> ExperimentDesign -> Bool)
-> (ExperimentDesign -> ExperimentDesign -> Bool)
-> Eq ExperimentDesign
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ExperimentDesign -> ExperimentDesign -> Bool
$c/= :: ExperimentDesign -> ExperimentDesign -> Bool
== :: ExperimentDesign -> ExperimentDesign -> Bool
$c== :: ExperimentDesign -> ExperimentDesign -> Bool
Eq, Eq ExperimentDesign
Eq ExperimentDesign
-> (ExperimentDesign -> ExperimentDesign -> Ordering)
-> (ExperimentDesign -> ExperimentDesign -> Bool)
-> (ExperimentDesign -> ExperimentDesign -> Bool)
-> (ExperimentDesign -> ExperimentDesign -> Bool)
-> (ExperimentDesign -> ExperimentDesign -> Bool)
-> (ExperimentDesign -> ExperimentDesign -> ExperimentDesign)
-> (ExperimentDesign -> ExperimentDesign -> ExperimentDesign)
-> Ord ExperimentDesign
ExperimentDesign -> ExperimentDesign -> Bool
ExperimentDesign -> ExperimentDesign -> Ordering
ExperimentDesign -> ExperimentDesign -> ExperimentDesign
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 :: ExperimentDesign -> ExperimentDesign -> ExperimentDesign
$cmin :: ExperimentDesign -> ExperimentDesign -> ExperimentDesign
max :: ExperimentDesign -> ExperimentDesign -> ExperimentDesign
$cmax :: ExperimentDesign -> ExperimentDesign -> ExperimentDesign
>= :: ExperimentDesign -> ExperimentDesign -> Bool
$c>= :: ExperimentDesign -> ExperimentDesign -> Bool
> :: ExperimentDesign -> ExperimentDesign -> Bool
$c> :: ExperimentDesign -> ExperimentDesign -> Bool
<= :: ExperimentDesign -> ExperimentDesign -> Bool
$c<= :: ExperimentDesign -> ExperimentDesign -> Bool
< :: ExperimentDesign -> ExperimentDesign -> Bool
$c< :: ExperimentDesign -> ExperimentDesign -> Bool
compare :: ExperimentDesign -> ExperimentDesign -> Ordering
$ccompare :: ExperimentDesign -> ExperimentDesign -> Ordering
$cp1Ord :: Eq ExperimentDesign
Ord, (forall x. ExperimentDesign -> Rep ExperimentDesign x)
-> (forall x. Rep ExperimentDesign x -> ExperimentDesign)
-> Generic ExperimentDesign
forall x. Rep ExperimentDesign x -> ExperimentDesign
forall x. ExperimentDesign -> Rep ExperimentDesign x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep ExperimentDesign x -> ExperimentDesign
$cfrom :: forall x. ExperimentDesign -> Rep ExperimentDesign x
Generic, ExperimentDesign -> ()
(ExperimentDesign -> ()) -> NFData ExperimentDesign
forall a. (a -> ()) -> NFData a
rnf :: ExperimentDesign -> ()
$crnf :: ExperimentDesign -> ()
NFData)

data ParameterSetup a =
  forall b . (Show b, Ord b, Serialize b) =>
  ParameterSetup
  { ParameterSetup a -> Text
parameterName         :: !T.Text                          -- ^ Name of parameter.
  , ()
setParameter          :: !(b -> a -> a)                   -- ^ Set the parameter.
  , ()
getParameter          :: !(a -> b)                        -- ^ Get the parameter from the current state.
  , ()
modifyParameter       :: !(Maybe (b -> IO [b]))           -- ^ Either no modification or function.
  , ()
bounds                :: !(Maybe (b, b))                  -- ^ Bounds (inclusive).
  , ()
skipPreparationPhase  :: !(Maybe (b -> Bool))             -- ^ Skip the preparation phase if True (e.g. to skip learning phase). Default: False.
  , ()
alterExperimentDesign :: !(Maybe (b -> ExperimentDesign)) -- ^ Change the experiment design. Default: Full-Factory design.
  }
-- makeLenses ''ParameterSetup  -- does not work with ExistentialQuantification


data ParameterSetting a =
  ParameterSetting
  { ParameterSetting a -> Text
_parameterSettingName                 :: !T.Text
  , ParameterSetting a -> ByteString
_parameterSettingValue                :: !BS.ByteString
  , ParameterSetting a -> Bool
_parameterSettingSkipPreparationPhase :: !Bool
  , ParameterSetting a -> ExperimentDesign
_parameterSettingExperimentDesign     :: !ExperimentDesign
  } deriving (ParameterSetting a -> ParameterSetting a -> Bool
(ParameterSetting a -> ParameterSetting a -> Bool)
-> (ParameterSetting a -> ParameterSetting a -> Bool)
-> Eq (ParameterSetting a)
forall a. ParameterSetting a -> ParameterSetting a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ParameterSetting a -> ParameterSetting a -> Bool
$c/= :: forall a. ParameterSetting a -> ParameterSetting a -> Bool
== :: ParameterSetting a -> ParameterSetting a -> Bool
$c== :: forall a. ParameterSetting a -> ParameterSetting a -> Bool
Eq, (forall x. ParameterSetting a -> Rep (ParameterSetting a) x)
-> (forall x. Rep (ParameterSetting a) x -> ParameterSetting a)
-> Generic (ParameterSetting a)
forall x. Rep (ParameterSetting a) x -> ParameterSetting a
forall x. ParameterSetting a -> Rep (ParameterSetting a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (ParameterSetting a) x -> ParameterSetting a
forall a x. ParameterSetting a -> Rep (ParameterSetting a) x
$cto :: forall a x. Rep (ParameterSetting a) x -> ParameterSetting a
$cfrom :: forall a x. ParameterSetting a -> Rep (ParameterSetting a) x
Generic, ParameterSetting a -> ()
(ParameterSetting a -> ()) -> NFData (ParameterSetting a)
forall a. ParameterSetting a -> ()
forall a. (a -> ()) -> NFData a
rnf :: ParameterSetting a -> ()
$crnf :: forall a. ParameterSetting a -> ()
NFData)
makeLenses ''ParameterSetting


getParameterData :: ParameterSetup a -> a -> BS.ByteString
getParameterData :: ParameterSetup a -> a -> ByteString
getParameterData (ParameterSetup Text
_ b -> a -> a
_ a -> b
getter Maybe (b -> IO [b])
_ Maybe (b, b)
_ Maybe (b -> Bool)
_ Maybe (b -> ExperimentDesign)
_) a
a = Put -> ByteString
runPut (Put -> ByteString) -> Put -> ByteString
forall a b. (a -> b) -> a -> b
$ Putter b
forall t. Serialize t => Putter t
put Putter b -> Putter b
forall a b. (a -> b) -> a -> b
$ a -> b
getter a
a


mkParameterSetting :: ParameterSetup a -> a -> ParameterSetting a
mkParameterSetting :: ParameterSetup a -> a -> ParameterSetting a
mkParameterSetting (ParameterSetup Text
n b -> a -> a
_ a -> b
getter Maybe (b -> IO [b])
_ Maybe (b, b)
_ Maybe (b -> Bool)
drp Maybe (b -> ExperimentDesign)
design) a
a = Text
-> ByteString -> Bool -> ExperimentDesign -> ParameterSetting a
forall a.
Text
-> ByteString -> Bool -> ExperimentDesign -> ParameterSetting a
ParameterSetting Text
n (Put -> ByteString
runPut (Put -> ByteString) -> Put -> ByteString
forall a b. (a -> b) -> a -> b
$ Putter b
forall t. Serialize t => Putter t
put b
aVal) (Bool -> ((b -> Bool) -> Bool) -> Maybe (b -> Bool) -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False (\b -> Bool
x -> b -> Bool
x b
aVal) Maybe (b -> Bool)
drp) (ExperimentDesign
-> ((b -> ExperimentDesign) -> ExperimentDesign)
-> Maybe (b -> ExperimentDesign)
-> ExperimentDesign
forall b a. b -> (a -> b) -> Maybe a -> b
maybe ExperimentDesign
FullFactory (\b -> ExperimentDesign
x -> b -> ExperimentDesign
x b
aVal) Maybe (b -> ExperimentDesign)
design)
  where aVal :: b
aVal = a -> b
getter a
a