module Scientist.Result.Evaluate
  ( evaluateResult
  ) where

import Prelude

import Data.List.NonEmpty (NonEmpty)
import Data.Text (Text)
import Scientist.Candidate
import Scientist.Control
import Scientist.Experiment
import Scientist.Result

evaluateResult
  :: Experiment m c a b
  -> ResultControl a
  -> NonEmpty (ResultCandidate b)
  -> [Text]
  -> Result c a b
evaluateResult :: Experiment m c a b
-> ResultControl a
-> NonEmpty (ResultCandidate b)
-> [Text]
-> Result c a b
evaluateResult Experiment m c a b
ex ResultControl a
control NonEmpty (ResultCandidate b)
candidates [Text]
order
  | (ResultCandidate b -> Bool) -> NonEmpty (ResultCandidate b) -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (ResultControl a -> ResultCandidate b -> Bool
ignore ResultControl a
control) NonEmpty (ResultCandidate b)
candidates = ResultDetails c a b -> Result c a b
forall c a b. ResultDetails c a b -> Result c a b
ResultIgnored ResultDetails c a b
details
  | (ResultCandidate b -> Bool) -> NonEmpty (ResultCandidate b) -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (ResultControl a -> ResultCandidate b -> Bool
match ResultControl a
control) NonEmpty (ResultCandidate b)
candidates = ResultDetails c a b -> Result c a b
forall c a b. ResultDetails c a b -> Result c a b
ResultMatched ResultDetails c a b
details
  | Bool
otherwise = ResultDetails c a b -> Result c a b
forall c a b. ResultDetails c a b -> Result c a b
ResultMismatched ResultDetails c a b
details
 where
  ignore :: ResultControl a -> ResultCandidate b -> Bool
ignore ResultControl a
a ResultCandidate b
b = Experiment m c a b
-> Control a -> Either SomeException (Candidate b) -> Bool
forall (m :: * -> *) c a b.
Experiment m c a b
-> Control a -> Either SomeException (Candidate b) -> Bool
getExperimentIgnore
    Experiment m c a b
ex
    (a -> Control a
forall a. a -> Control a
Control (a -> Control a) -> a -> Control a
forall a b. (a -> b) -> a -> b
$ ResultControl a -> a
forall a. ResultControl a -> a
resultControlValue ResultControl a
a)
    (b -> Candidate b
forall a. a -> Candidate a
Candidate (b -> Candidate b)
-> Either SomeException b -> Either SomeException (Candidate b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ResultCandidate b -> Either SomeException b
forall a. ResultCandidate a -> Either SomeException a
resultCandidateValue ResultCandidate b
b)

  match :: ResultControl a -> ResultCandidate b -> Bool
match ResultControl a
a ResultCandidate b
b = Experiment m c a b
-> Control a -> Either SomeException (Candidate b) -> Bool
forall (m :: * -> *) c a b.
Experiment m c a b
-> Control a -> Either SomeException (Candidate b) -> Bool
getExperimentCompare
    Experiment m c a b
ex
    (a -> Control a
forall a. a -> Control a
Control (a -> Control a) -> a -> Control a
forall a b. (a -> b) -> a -> b
$ ResultControl a -> a
forall a. ResultControl a -> a
resultControlValue ResultControl a
a)
    (b -> Candidate b
forall a. a -> Candidate a
Candidate (b -> Candidate b)
-> Either SomeException b -> Either SomeException (Candidate b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ResultCandidate b -> Either SomeException b
forall a. ResultCandidate a -> Either SomeException a
resultCandidateValue ResultCandidate b
b)

  details :: ResultDetails c a b
details = ResultDetails :: forall c a b.
Text
-> Maybe c
-> ResultControl a
-> NonEmpty (ResultCandidate b)
-> [Text]
-> ResultDetails c a b
ResultDetails
    { resultDetailsExperimentName :: Text
resultDetailsExperimentName = Experiment m c a b -> Text
forall (m :: * -> *) c a b. Experiment m c a b -> Text
getExperimentName Experiment m c a b
ex
    , resultDetailsExperimentContext :: Maybe c
resultDetailsExperimentContext = Experiment m c a b -> Maybe c
forall (m :: * -> *) c a b. Experiment m c a b -> Maybe c
getExperimentContext Experiment m c a b
ex
    , resultDetailsControl :: ResultControl a
resultDetailsControl = ResultControl a
control
    , resultDetailsCandidates :: NonEmpty (ResultCandidate b)
resultDetailsCandidates = NonEmpty (ResultCandidate b)
candidates
    , resultDetailsExecutionOrder :: [Text]
resultDetailsExecutionOrder = [Text]
order
    }