-- | A model for defining boolean expressions for Objective prerequisites.
--
-- This model is intended to be user-facing in the .yaml files, and is
-- distinct from that in 'Data.BoolExpr'.
module Swarm.Game.Scenario.Objective.Logic where

import Control.Applicative ((<|>))
import Data.Aeson
import Data.BoolExpr
import Data.Char (toLower)
import Data.List.NonEmpty (NonEmpty)
import Data.Text (Text)
import GHC.Generics (Generic)

type ObjectiveLabel = Text

-- | In contrast with the "BoolExpr" type,
-- "And" and "Or" can have /one or more/ children
-- instead of /exactly two/.
data Prerequisite a
  = And (NonEmpty (Prerequisite a))
  | Or (NonEmpty (Prerequisite a))
  | Not (Prerequisite a)
  | Id a
  deriving (Prerequisite a -> Prerequisite a -> Bool
forall a. Eq a => Prerequisite a -> Prerequisite a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Prerequisite a -> Prerequisite a -> Bool
$c/= :: forall a. Eq a => Prerequisite a -> Prerequisite a -> Bool
== :: Prerequisite a -> Prerequisite a -> Bool
$c== :: forall a. Eq a => Prerequisite a -> Prerequisite a -> Bool
Eq, Int -> Prerequisite a -> ShowS
forall a. Show a => Int -> Prerequisite a -> ShowS
forall a. Show a => [Prerequisite a] -> ShowS
forall a. Show a => Prerequisite a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Prerequisite a] -> ShowS
$cshowList :: forall a. Show a => [Prerequisite a] -> ShowS
show :: Prerequisite a -> String
$cshow :: forall a. Show a => Prerequisite a -> String
showsPrec :: Int -> Prerequisite a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Prerequisite a -> ShowS
Show, forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (Prerequisite a) x -> Prerequisite a
forall a x. Prerequisite a -> Rep (Prerequisite a) x
$cto :: forall a x. Rep (Prerequisite a) x -> Prerequisite a
$cfrom :: forall a x. Prerequisite a -> Rep (Prerequisite a) x
Generic, forall a b. a -> Prerequisite b -> Prerequisite a
forall a b. (a -> b) -> Prerequisite a -> Prerequisite b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> Prerequisite b -> Prerequisite a
$c<$ :: forall a b. a -> Prerequisite b -> Prerequisite a
fmap :: forall a b. (a -> b) -> Prerequisite a -> Prerequisite b
$cfmap :: forall a b. (a -> b) -> Prerequisite a -> Prerequisite b
Functor, forall a. Eq a => a -> Prerequisite a -> Bool
forall a. Num a => Prerequisite a -> a
forall a. Ord a => Prerequisite a -> a
forall m. Monoid m => Prerequisite m -> m
forall a. Prerequisite a -> Bool
forall a. Prerequisite a -> Int
forall a. Prerequisite a -> [a]
forall a. (a -> a -> a) -> Prerequisite a -> a
forall m a. Monoid m => (a -> m) -> Prerequisite a -> m
forall b a. (b -> a -> b) -> b -> Prerequisite a -> b
forall a b. (a -> b -> b) -> b -> Prerequisite a -> b
forall (t :: * -> *).
(forall m. Monoid m => t m -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. t a -> [a])
-> (forall a. t a -> Bool)
-> (forall a. t a -> Int)
-> (forall a. Eq a => a -> t a -> Bool)
-> (forall a. Ord a => t a -> a)
-> (forall a. Ord a => t a -> a)
-> (forall a. Num a => t a -> a)
-> (forall a. Num a => t a -> a)
-> Foldable t
product :: forall a. Num a => Prerequisite a -> a
$cproduct :: forall a. Num a => Prerequisite a -> a
sum :: forall a. Num a => Prerequisite a -> a
$csum :: forall a. Num a => Prerequisite a -> a
minimum :: forall a. Ord a => Prerequisite a -> a
$cminimum :: forall a. Ord a => Prerequisite a -> a
maximum :: forall a. Ord a => Prerequisite a -> a
$cmaximum :: forall a. Ord a => Prerequisite a -> a
elem :: forall a. Eq a => a -> Prerequisite a -> Bool
$celem :: forall a. Eq a => a -> Prerequisite a -> Bool
length :: forall a. Prerequisite a -> Int
$clength :: forall a. Prerequisite a -> Int
null :: forall a. Prerequisite a -> Bool
$cnull :: forall a. Prerequisite a -> Bool
toList :: forall a. Prerequisite a -> [a]
$ctoList :: forall a. Prerequisite a -> [a]
foldl1 :: forall a. (a -> a -> a) -> Prerequisite a -> a
$cfoldl1 :: forall a. (a -> a -> a) -> Prerequisite a -> a
foldr1 :: forall a. (a -> a -> a) -> Prerequisite a -> a
$cfoldr1 :: forall a. (a -> a -> a) -> Prerequisite a -> a
foldl' :: forall b a. (b -> a -> b) -> b -> Prerequisite a -> b
$cfoldl' :: forall b a. (b -> a -> b) -> b -> Prerequisite a -> b
foldl :: forall b a. (b -> a -> b) -> b -> Prerequisite a -> b
$cfoldl :: forall b a. (b -> a -> b) -> b -> Prerequisite a -> b
foldr' :: forall a b. (a -> b -> b) -> b -> Prerequisite a -> b
$cfoldr' :: forall a b. (a -> b -> b) -> b -> Prerequisite a -> b
foldr :: forall a b. (a -> b -> b) -> b -> Prerequisite a -> b
$cfoldr :: forall a b. (a -> b -> b) -> b -> Prerequisite a -> b
foldMap' :: forall m a. Monoid m => (a -> m) -> Prerequisite a -> m
$cfoldMap' :: forall m a. Monoid m => (a -> m) -> Prerequisite a -> m
foldMap :: forall m a. Monoid m => (a -> m) -> Prerequisite a -> m
$cfoldMap :: forall m a. Monoid m => (a -> m) -> Prerequisite a -> m
fold :: forall m. Monoid m => Prerequisite m -> m
$cfold :: forall m. Monoid m => Prerequisite m -> m
Foldable)

prerequisiteOptions :: Options
prerequisiteOptions :: Options
prerequisiteOptions =
  Options
defaultOptions
    { sumEncoding :: SumEncoding
sumEncoding = SumEncoding
ObjectWithSingleField
    , constructorTagModifier :: ShowS
constructorTagModifier = forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower
    }

instance ToJSON (Prerequisite ObjectiveLabel) where
  toJSON :: Prerequisite ObjectiveLabel -> Value
toJSON = forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
genericToJSON Options
prerequisiteOptions

instance FromJSON (Prerequisite ObjectiveLabel) where
  parseJSON :: Value -> Parser (Prerequisite ObjectiveLabel)
parseJSON Value
x = Value -> Parser (Prerequisite ObjectiveLabel)
preString Value
x forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON Options
prerequisiteOptions Value
x
   where
    preString :: Value -> Parser (Prerequisite ObjectiveLabel)
preString = forall a.
String -> (ObjectiveLabel -> Parser a) -> Value -> Parser a
withText String
"prerequisite" forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a. Applicative f => a -> f a
pure forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> Prerequisite a
Id

toBoolExpr :: Prerequisite a -> BoolExpr a
toBoolExpr :: forall a. Prerequisite a -> BoolExpr a
toBoolExpr (And NonEmpty (Prerequisite a)
xs) = forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 forall a. BoolExpr a -> BoolExpr a -> BoolExpr a
BAnd (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. Prerequisite a -> BoolExpr a
toBoolExpr NonEmpty (Prerequisite a)
xs)
toBoolExpr (Or NonEmpty (Prerequisite a)
xs) = forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 forall a. BoolExpr a -> BoolExpr a -> BoolExpr a
BOr (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. Prerequisite a -> BoolExpr a
toBoolExpr NonEmpty (Prerequisite a)
xs)
toBoolExpr (Not Prerequisite a
x) = forall a. BoolExpr a -> BoolExpr a
BNot forall a b. (a -> b) -> a -> b
$ forall a. Prerequisite a -> BoolExpr a
toBoolExpr Prerequisite a
x
toBoolExpr (Id a
x) = forall a. Signed a -> BoolExpr a
BConst forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a. Applicative f => a -> f a
pure a
x