{-# LANGUAGE ScopedTypeVariables, DeriveDataTypeable, NamedFieldPuns, GADTs#-} module Language.Nomyx.Test where import Language.Nomyx.Rule import Language.Nomyx.Expression import Language.Nomyx.Evaluation import Control.Monad import Control.Monad.State.Lazy import Data.Typeable import Data.Time import Data.Maybe (fromJust) date1 = parse822Time "Tue, 02 Sep 1997 09:00:00 -0400" date2 = parse822Time "Tue, 02 Sep 1997 10:00:00 -0400" testGame = Game { gameName = "test", gameDesc = "test", rules = [], players = [PlayerInfo 1 "coco"], variables = [], events = [], outputs = [], victory = [], currentTime = date1} testRule = Rule { rNumber = 0, rName = "test", rDescription = "test", rProposedBy = 0, rRuleCode = "", rRuleFunc = VoidRule $ return (), rStatus = Pending, rAssessedBy = Nothing} evalRuleFunc (VoidRule f) = evalState (evalExp f 0) testGame execRuleFuncEvent (VoidRule f) e d = execState (evalExp f 0 >> (triggerEvent e d)) testGame execRuleFuncGame (VoidRule f) g = execState (evalExp f 0) g execRuleFuncEventGame (VoidRule f) e d g = execState (evalExp f 0 >> (triggerEvent e d)) g execRuleFunc f = execRuleFuncGame f testGame tests = [("test var 1", testVarEx1), ("test var 2", testVarEx2), ("test var 3", testVarEx3), ("test var 4", testVarEx4), ("test var 5", testVarEx5), ("test single input", testSingleInputEx), ("test input string", testInputStringEx), ("test send messsage", testSendMessageEx), ("test send message 2", testSendMessageEx2), ("test user input write", testUserInputWriteEx), ("test activate rule", testActivateRuleEx), ("test auto activate", testAutoActivateEx), ("test unanimity vote", testUnanimityVoteEx), ("test time event", testTimeEventEx), ("test time event 2", testTimeEventEx2)] allTests = and $ map snd tests --Test variable creation testVar1 :: RuleFunc testVar1 = VoidRule $ do NewVar "toto" (1::Integer) return () testVarEx1 = variables (execRuleFunc testVar1) == [(Var 0 "toto" (1::Integer))] --Test variable deleting testVar2 :: RuleFunc testVar2 = VoidRule $ do var <- newVar_ "toto" (1::Int) delVar var return () testVarEx2 = variables (execRuleFunc testVar2) == [] --Test variable reading testVar3 :: RuleFunc testVar3 = VoidRule $ do var <- newVar_ "toto" (1::Int) a <- readVar var case a of Just (1::Int) -> output "ok" 1 Nothing -> output "nok" 1 testVarEx3 = outputs (execRuleFunc testVar3) == [(1,"ok")] --Test variable writing testVar4 :: RuleFunc testVar4 = VoidRule $ do var <- newVar_ "toto" (1::Int) writeVar var (2::Int) a <- readVar var case a of Just (2::Int) -> output "ok" 1 Nothing -> output "nok" 1 testVarEx4 = outputs (execRuleFunc testVar4) == [(1,"ok")] --Test variable writing testVar5 :: RuleFunc testVar5 = VoidRule $ do var <- newVar_ "toto" ([]::[Int]) writeVar var ([1]::[Int]) a <- readVar var case a of Just (a::[Int]) -> do writeVar var (2:a) return () Nothing -> output "nok" 1 testVarEx5 = variables (execRuleFunc testVar5) == [(Var 0 "toto" ([2,1]::[Int]))] data Choice = Holland | Sarkozy deriving (Enum, Typeable, Show, Eq, Bounded) --mkInputChoiceEnum_ :: forall a. (Enum a, Bounded a, Typeable a, Eq a, Show a) => String -> a -> PlayerNumber -> (a -> Exp ()) -> Exp EventNumber testSingleInput :: RuleFunc testSingleInput = VoidRule $ do onInputChoiceEnum_ "Vote for Holland or Sarkozy" Holland h 1 where h a = output ("voted for " ++ (show a)) 1 testSingleInputEx = (outputs $ execRuleFuncEvent testSingleInput (inputChoiceEnum 1 "Vote for Holland or Sarkozy" Holland) (InputChoiceData Holland)) == [(1, "voted for Holland")] testInputString :: RuleFunc testInputString = VoidRule $ do onInputString_ "Enter a number:" h 1 where h a = output ("You entered: " ++ a) 1 testInputStringEx = (outputs $ execRuleFuncEvent testInputString (inputString 1 "Enter a number:") (InputStringData "1")) == [(1, "You entered: 1")] testSendMessage :: RuleFunc testSendMessage = VoidRule $ do let msg = Message "msg" :: Event(Message String) onEvent_ msg f sendMessage msg "toto" where f (MessageData a :: EventData(Message String)) = output a 1 testSendMessageEx = outputs (execRuleFunc testSendMessage) == [(1,"toto")] testSendMessage2 :: RuleFunc testSendMessage2 = VoidRule $ do onEvent_ (Message "msg":: Event(Message ())) f sendMessage_ (Message "msg") where f (MessageData a) = output "Received" 1 testSendMessageEx2 = outputs (execRuleFunc testSendMessage2) == [(1,"Received")] data Choice2 = Me | You deriving (Enum, Typeable, Show, Eq, Bounded) testUserInputWrite :: RuleFunc testUserInputWrite = VoidRule $ do var <- newVar_ "vote" (Nothing::Maybe Choice2) onEvent_ (Message "voted" :: Event (Message ())) h2 onEvent_ (InputChoice 1 "Vote for" [Me, You] Me) h1 where h1 (InputChoiceData a :: EventData (InputChoice Choice2)) = do writeVar (V "vote") (Just a) SendMessage (Message "voted") () h2 (MessageData _) = do a <- readVar (V "vote") case a of Just (Just Me) -> output "voted Me" 1 Nothing -> output "problem" 1 testUserInputWriteEx = (outputs $ execRuleFuncEvent testUserInputWrite (InputChoice 1 "Vote for" [Me, You] Me) (InputChoiceData Me)) == [(1,"voted Me")] testActivateRule :: RuleFunc testActivateRule = VoidRule $ do a <- GetRules if (rStatus (head a) == Pending) then do ActivateRule $ rNumber (head a) return () else return () testActivateRuleEx = rStatus (head $ rules (execRuleFuncGame testActivateRule testGame {rules=[testRule]})) == Active testAutoActivateEx = rStatus (head $ rules (execRuleFuncEventGame autoActivate (RuleEv Proposed) (RuleData testRule) (testGame {rules=[testRule]}))) == Active unanimityRule = testRule {rName = "unanimityRule", rRuleFunc = RuleRule $ voteWith unanimity, rNumber = 2, rStatus = Active} applicationMetaRuleRule = testRule {rName = "onRuleProposedUseMetaRules", rRuleFunc = onRuleProposed checkWithMetarules, rNumber = 3, rStatus = Active} gameUnanimity = testGame {rules=[unanimityRule]} testUnanimityVote :: Game testUnanimityVote = flip execState testGame $ do addPlayer (PlayerInfo 1 "coco") addPlayer (PlayerInfo 2 "jean paul") evAddRule unanimityRule evActivateRule (rNumber unanimityRule) 0 evAddRule applicationMetaRuleRule evActivateRule (rNumber applicationMetaRuleRule) 0 evProposeRule testRule evInputChoice (InputChoice 1 "Vote for rule 0" [For, Against] For) For evInputChoice (InputChoice 2 "Vote for rule 0" [For, Against] For) For testUnanimityVoteEx = (rStatus $ head $ rules testUnanimityVote) == Active testTimeEvent :: RuleFunc testTimeEvent = VoidRule $ do onEvent_ (Time date1) f where f t = outputAll $ show date1 testTimeEventEx = (outputs $ execRuleFuncEvent testTimeEvent (Time date1) (TimeData date1)) == [(1,show date1)] testTimeEvent2 :: Exp () testTimeEvent2 = schedule' [date1, date2] (outputAll . show) testTimeEventEx2 = (outputs $ flip execState testGame (evalExp testTimeEvent2 0 >> gameEvs)) == [(1,show date2), (1,show date1)] where gameEvs = do evTriggerTime date1 evTriggerTime date2 timedUnanimityRule = testRule {rName = "unanimityRule", rRuleFunc = voteWithTimeLimit unanimity date1, rNumber = 2, rStatus = Active} gameTimedUnanimity = testGame {rules=[timedUnanimityRule]} testTimedUnanimityVote :: Game testTimedUnanimityVote = flip execState testGame $ do addPlayer (PlayerInfo 1 "coco") addPlayer (PlayerInfo 2 "jean paul") evAddRule timedUnanimityRule evActivateRule (rNumber timedUnanimityRule) 0 evAddRule applicationMetaRuleRule evActivateRule (rNumber applicationMetaRuleRule) 0 evProposeRule testRule evInputChoice (InputChoice 1 "Vote for rule 0" [For, Against] For) Against evTriggerTime date1 testTimedUnanimityVoteEx = (rStatus $ head $ rules testTimedUnanimityVote) == Reject -- now <- Rule.getCurrentTime -- let oneDay = 24 * 60 * 60 :: NominalDiffTime {-autoMetarulesR = testRule {rName = "autoMetaRules", rRuleFunc = autoMetarules, rNumber = 2, rStatus = Active} gameautoMetarules = testGame {rules=[autoMetarulesR]} testAutoMetarules :: Game testAutoMetarules = flip execState testGame $ do evAddRule unanimityRule evActivateRule (rNumber unanimityRule) 0 evProposeRule testRule evInputChoice (InputChoice 1 "Vote for rule test") For evInputChoice (InputChoice 2 "Vote for rule test") For testAutoMetarulesEx = (rStatus $ head $ rules testUnanimityVote) == Active -}