packages feed

Nomyx-Core 0.7.0 → 0.7.1

raw patch · 11 files changed

+166/−106 lines, 11 filesdep ~Nomyx-Language

Dependency ranges changed: Nomyx-Language

Files

Nomyx-Core.cabal view
@@ -1,5 +1,5 @@ name: Nomyx-Core-version: 0.7.0+version: 0.7.1 cabal-version: >=1.6 build-type: Simple license: BSD3@@ -15,7 +15,7 @@ data-dir: data   library -    build-depends: Nomyx-Language         == 0.7.0,+    build-depends: Nomyx-Language         == 0.7.1,                    DebugTraceHelpers      == 0.12.*,                    MissingH               == 1.2.*,                    acid-state             == 0.12.*,
src/Data/Todo.hs view
@@ -27,7 +27,7 @@ instance Monad (Todo a) where    return = Done    Todo as >>= _ = Todo as-   Done a  >>= f = f a+   Done a >>= f = f a  toEither :: Todo a b -> Either [a] b toEither (Todo as) = Left as
src/Nomyx/Core/Engine.hs view
@@ -30,9 +30,10 @@    events,    getEventFields,    getEventInfo,-   getInput,+   getFormField,     -- * Inputs management+   FormField(..),    InputData(..),     -- * Outputs management
src/Nomyx/Core/Engine/Evaluation.hs view
@@ -24,9 +24,10 @@ import Control.Applicative import Control.Monad.Error.Class (MonadError(..)) import Language.Nomyx.Expression-import Nomyx.Core.Engine.Types+import Nomyx.Core.Engine.Types hiding (_vRuleNumber) import Nomyx.Core.Engine.EvalUtils import Nomyx.Core.Engine.Utils+import Safe  -- * Evaluation @@ -152,6 +153,7 @@          delVarsRule rn          delEventsRule rn          delOutputsRule rn+         delVictoryRule rn          return True  evAddRule :: RuleInfo -> Evaluate Bool@@ -268,41 +270,55 @@  -- * Events ---get the fields left to be completed in an event-getEventFields :: EventInfo -> Game -> [(FieldAddress, SomeField)]-getEventFields (EventInfo _ rn e _ _ env) g = case runEvaluateNE g rn $ getEventResult e env of-   Done _ -> []-   Todo a -> a --- | Get the field at a certain address-getInput :: EventInfo -> FieldAddress -> Game -> Maybe SomeField-getInput ei fa g = runEvaluateNE g (_ruleNumber ei) (findField ei fa)  -- | Get the field at a certain address --TODO: should we check that the field is not already completed?-findField :: EventInfo -> FieldAddress -> EvaluateNE (Maybe SomeField)-findField (EventInfo _ _ e _ _ er) addr = findField' addr e er+findField :: EventInfo -> FieldAddress -> FormField -> EvaluateNE (Maybe SomeField)+findField (EventInfo _ _ e _ _ er) addr ft = findField' addr e er ft -findField' :: FieldAddress -> Event e -> [FieldResult] -> EvaluateNE (Maybe SomeField)-findField' []         (BaseEvent f)    _   = return $ Just $ SomeField f-findField' (SumL:as)  (SumEvent e1 _)  frs = findField' as e1 (filterPath SumL frs)-findField' (SumR:as)  (SumEvent _ e2)  frs = findField' as e2 (filterPath SumR frs)-findField' (AppL:as)  (AppEvent e1 _)  frs = findField' as e1 (filterPath AppL frs)-findField' (AppR:as)  (AppEvent _ e2)  frs = findField' as e2 (filterPath AppR frs)-findField' (BindL:as) (BindEvent e1 _) frs = findField' as e1 (filterPath BindL frs)-findField' ((Index i):as) (ShortcutEvents es _) frs = findField' as (es!!i) frs-findField' (BindR:as) (BindEvent e1 f) frs = do+findField' :: FieldAddress -> Event e -> [FieldResult] -> FormField -> EvaluateNE (Maybe SomeField)+findField' []         (BaseEvent f)    _   ft = return $ do+   ft' <- getFormField (SomeField f)+   guard (ft' == ft)+   return $ SomeField f+findField' (SumL:as)  (SumEvent e1 _)  frs ft = findField' as e1 (filterPath SumL frs) ft+findField' (SumR:as)  (SumEvent _ e2)  frs ft = findField' as e2 (filterPath SumR frs) ft+findField' (AppL:as)  (AppEvent e1 _)  frs ft = findField' as e1 (filterPath AppL frs) ft+findField' (AppR:as)  (AppEvent _ e2)  frs ft = findField' as e2 (filterPath AppR frs) ft+findField' (BindL:as) (BindEvent e1 _) frs ft = findField' as e1 (filterPath BindL frs) ft+findField' (BindR:as) (BindEvent e1 f) frs ft = do    er <- getEventResult e1 (filterPath BindL frs)    case er of-      Done e2 -> findField' as (f e2) (filterPath BindR frs)+      Done e2 -> findField' as (f e2) (filterPath BindR frs) ft       Todo _  -> return Nothing-findField' _ _ _ = error "findField: wrong field address"+findField' (Shortcut:as) (ShortcutEvents es _) frs ft = do+   msfs <- mapM (\e-> findField' as e frs ft) es+   return $ headMay $ catMaybes msfs  -- returning the first field that matches +findField' fa _ _ _ = error $ "findField: wrong field address: " ++ (show fa)+ filterPath :: FieldAddressElem -> [FieldResult] -> [FieldResult] filterPath fa frs = mapMaybe f frs where    f (FieldResult fe fr (Just (fa':fas))) | fa == fa' = Just $ FieldResult fe fr (Just fas)    f _ = Nothing ++getFormField :: SomeField -> Maybe FormField+getFormField (SomeField (Input pn s (Radio choices)))    = Just $ RadioField pn s (zip [0..] (snd <$> choices))+getFormField (SomeField (Input pn s Text))               = Just $ TextField pn s+getFormField (SomeField (Input pn s TextArea))           = Just $ TextAreaField pn s+getFormField (SomeField (Input pn s Button))             = Just $ ButtonField pn s+getFormField (SomeField (Input pn s (Checkbox choices))) = Just $ CheckboxField pn s (zip [0..] (snd <$> choices))+getFormField _ = Nothing+++--get the fields left to be completed in an event+getEventFields :: EventInfo -> Game -> [(FieldAddress, SomeField)]+getEventFields (EventInfo _ rn e _ _ env) g = case runEvaluateNE g rn $ getEventResult e env of+   Done _ -> []+   Todo a -> a+ -- compute the result of an event given an environment. -- in the case the event cannot be computed because some fields results are pending, return that list instead. getEventResult :: Event a -> [FieldResult] -> EvaluateNE (Todo (FieldAddress, SomeField) a)@@ -325,67 +341,60 @@    Nothing -> Todo [(fa, SomeField a)]  getEventResult' (ShortcutEvents es f) ers fa = do-  ers <- mapM (\i -> getEventResult' (es!!i) ers (fa ++ [Index i]) ) [0.. (length es -1)]-  case f (toMaybe <$> ers) of-     True  -> return $ Done $ toMaybe <$> ers-     False -> return $ Todo $ join $ lefts $ toEither <$> ers+  (ers :: [Todo (FieldAddress, SomeField) a]) <- mapM (\e -> getEventResult' e ers (fa ++ [Shortcut])) es -- get the result for each event in the list+  return $ case f (toMaybe <$> ers) of                                                                    -- apply f to the event results that we already have+     True  -> Done $ toMaybe <$> ers                                                                      -- if the result is true, we are done. Return the list of maybe results+     False -> Todo $ join $ lefts $ toEither <$> ers                                                      -- otherwise, return the list of remaining fields to complete from each event + -- trigger an event triggerEvent :: (Typeable e, Show e) => Field e -> e -> Evaluate ()-triggerEvent e dat = do-   evs <- access (eGame >>> events)-   triggerEvent' (FieldResult e dat Nothing) evs+triggerEvent e dat = access (eGame >>> events) >>= triggerEvent' (FieldResult e dat Nothing)  -- trigger some specific events triggerEvent' :: FieldResult -> [EventInfo] -> Evaluate () triggerEvent' res evs = do-   evs' <- mapM (liftEval . (updateEventInfo res)) evs-   (eGame >>> events) %= union (map fst evs')-   mapM triggerIfComplete evs'-   return ()+   evs' <- mapM (liftEval . (updateEventInfo res)) evs  -- get all the EventInfos updated with the field+   (eGame >>> events) %= union (map fst evs')           -- store them+   void $ mapM triggerIfComplete evs'                   -- trigger the handlers for completed events  -- if the event is complete, trigger its handler triggerIfComplete :: (EventInfo, Maybe SomeData) -> Evaluate ()-triggerIfComplete (EventInfo en rn _ h SActive _, Just (SomeData val)) = do-   case (cast val) of-      Just a -> do-         let exp = h (en, a)-         withRN rn $ (evalNomex exp) `catchError` (errorHandler en)-         return ()-      Nothing -> error "Bad trigger data type"+triggerIfComplete (EventInfo en rn _ h SActive _, Just (SomeData val)) = case (cast val) of+   Just a ->  void $ withRN rn $ (evalNomex $ h (en, a)) `catchError` (errorHandler en)+   Nothing -> error "Bad trigger data type" triggerIfComplete _ = return () ---- update the EventInfo with the field result+-- update the EventInfo with the field result.+-- get the event result if all fields are completed updateEventInfo :: FieldResult -> EventInfo -> EvaluateNE (EventInfo, Maybe SomeData) updateEventInfo (FieldResult field dat addr) ei@(EventInfo _ _ ev _ _ envi) = do    g <- asks _eGame    let eventRes = FieldResult field dat addr    er <- getEventResult ev (eventRes : envi)-   if (SomeField field) `elem` (map snd $ getEventFields ei g) then do   -- if the field if found among the remaining fields of the event-      case er of                                                         -- then check the event with that field result included-            Todo _ -> return $ (env ^=  (eventRes : envi) $ ei, Nothing) -- some fields are left to complete: add ours in the environment-            Done a -> return $ (env ^=  [] $ ei, Just $ SomeData a)      -- the event is now complete: empty the environment and output the result-      else return $ (ei, Nothing)                                        -- field not found: do nothin-+   return $ case er of                                                      -- check if the event will be complete+      Todo _ -> if (SomeField field) `elem` (map snd $ getEventFields ei g) -- is yes, check if our field is really a missing field of the event+         then (env ^=  (eventRes : envi) $ ei, Nothing)                     -- some fields are left to complete: add ours in the environment+         else (ei, Nothing)                                                 -- field not found: do nothing+      Done a -> (env ^=  [] $ ei, Just $ SomeData a)                        -- the event is complete: empty the environment and output the result  -- * input triggers  -- trigger the input event with the input data-triggerInput :: EventNumber -> FieldAddress -> InputData -> Evaluate ()-triggerInput en fa ir = do+triggerInput :: EventNumber -> FieldAddress -> FormField -> InputData -> Evaluate ()+triggerInput en fa ft ir = do    evs <- access (eGame >>> events)    let mei = find ((== en) . getL eventNumber) evs-   when (isJust mei) $ execInputHandler ir fa (fromJust mei)+   when (isJust mei) $ execInputHandler ir fa ft (fromJust mei)  -- execute the corresponding handler-execInputHandler :: InputData -> FieldAddress -> EventInfo -> Evaluate ()-execInputHandler ir fa ei@(EventInfo _ _ _ _ SActive _) = do-   i <- liftEval $ findField ei fa+execInputHandler :: InputData -> FieldAddress -> FormField -> EventInfo -> Evaluate ()+execInputHandler ir fa ft ei@(EventInfo _ _ _ _ SActive _) = do+   i <- liftEval $ findField ei fa ft    case i of       Just sf -> execInputHandler' ir sf fa ei       Nothing -> logAll "Input not found"-execInputHandler _ _ _ = return ()+execInputHandler _ _ _ _ = return ()  -- execute the event handler using the data received from user execInputHandler' :: InputData -> SomeField -> FieldAddress -> EventInfo -> Evaluate ()@@ -427,7 +436,13 @@    let toDelete = filter ((== rn) . getL oRuleNumber) os    mapM_ (evDelOutput . _outputNumber) toDelete +--delete victory of a rule+delVictoryRule :: RuleNumber -> Evaluate ()+delVictoryRule rn = do+   vic <- access (eGame >>> victory)+   when (isJust vic && _vRuleNumber (fromJust vic) == rn) $ void $ (eGame >>> victory) ~= Nothing + -- | Show instance for Game -- showing a game involves evaluating some parts (such as victory and outputs) instance Show Game where@@ -446,8 +461,11 @@ displayEvent g ei@(EventInfo en rn _ _ s env) =    "event num: " ++ (show en) ++    ", rule num: " ++ (show rn) ++-   ", event fields: " ++ (show $ getEventFields ei g) +++   ", event fields: " ++ (show $ getEventFields ei g) ++ --TODO: display also event result?    ", envs: " ++ (show env) ++    ", status: " ++ (show s) -+displayEvent' :: EventInfo -> EvaluateNE String+displayEvent' ei = do+   (EvalEnv _ g) <- ask+   return $ displayEvent g ei
src/Nomyx/Core/Engine/GameEvents.hs view
@@ -24,7 +24,7 @@                | JoinGame          PlayerNumber PlayerName                | LeaveGame         PlayerNumber                | ProposeRuleEv     PlayerNumber SubmitRule-               | InputResult       PlayerNumber EventNumber FieldAddress InputData+               | InputResult       PlayerNumber EventNumber FieldAddress FormField InputData                | GLog              (Maybe PlayerNumber) String                | TimeEvent         UTCTime                | SystemAddRule     SubmitRule@@ -51,7 +51,7 @@ enactEvent (JoinGame pn name) _               = mapStateIO $ joinGame name pn enactEvent (LeaveGame pn) _                   = mapStateIO $ leaveGame pn enactEvent (ProposeRuleEv pn sr) (Just inter) = void $ proposeRule sr pn inter-enactEvent (InputResult pn en fa ir) _        = mapStateIO $ inputResult pn en fa ir+enactEvent (InputResult pn en fa ft ir) _     = mapStateIO $ inputResult pn en fa ft ir enactEvent (GLog mpn s) _                     = mapStateIO $ logGame s mpn enactEvent (TimeEvent t) _                    = mapStateIO $ runSystemEval' $ evTriggerTime t enactEvent (SystemAddRule r) (Just inter)     = systemAddRule r inter@@ -136,10 +136,10 @@    void $ logs %= (Log mpn time s : )  -- | the user has provided an input result-inputResult :: PlayerNumber -> EventNumber -> FieldAddress -> InputData -> State Game ()-inputResult pn en fa ir = do-   tracePN pn $ "input result: EventNumber " ++ show en ++ ", FieldAddress " ++ show fa ++ ", choice " ++ show ir-   runSystemEval pn $ triggerInput en fa ir+inputResult :: PlayerNumber -> EventNumber -> FieldAddress -> FormField -> InputData -> State Game ()+inputResult pn en fa ft ir = do+   tracePN pn $ "input result: EventNumber " ++ show en ++ ", FieldAddress " ++ show fa ++ ", Form " ++ show ft ++ ", choice " ++ show ir+   runSystemEval pn $ triggerInput en fa ft ir  getGameTimes :: Game -> [UTCTime] getGameTimes g = concatMap (\ei -> getTimes ei g) (_events g)
src/Nomyx/Core/Engine/Test.hs view
@@ -55,11 +55,11 @@ execRuleEvents :: (Show e, Typeable e) => Nomex a -> [(Field e, e)] -> Game execRuleEvents f eds = execState (runSystemEval' $ evalNomex f >> mapM (\(a,b) -> triggerEvent a b) eds) testGame -execRuleInput :: Nomex a -> EventNumber -> FieldAddress -> InputData -> Game-execRuleInput r en fa d = execState (runSystemEval' $ evalNomex r >> triggerInput en fa d) testGame+execRuleInput :: Nomex a -> EventNumber -> FieldAddress -> FormField -> InputData -> Game+execRuleInput r en fa ft d = execState (runSystemEval' $ evalNomex r >> triggerInput en fa ft d) testGame -execRuleInputs :: Nomex a -> EventNumber -> [(FieldAddress, InputData)] -> Game-execRuleInputs r en fads = execState (runSystemEval' $ evalNomex r >> mapM (\(fa, d) -> triggerInput en fa d) fads) testGame+execRuleInputs :: Nomex a -> EventNumber -> [(FieldAddress, FormField, InputData)] -> Game+execRuleInputs r en fads = execState (runSystemEval' $ evalNomex r >> mapM (\(fa, ft, d) -> triggerInput en fa ft d) fads) testGame  execRuleGame :: Nomex a -> Game -> Game execRuleGame r g = execState (runSystemEval' $ void $ evalNomex r) g@@ -90,7 +90,6 @@          ("test user input write", testUserInputWriteEx),          ("test activate rule", testActivateRuleEx),          ("test auto activate", testAutoActivateEx),-         --("test meta rules vote", testApplicationMetaRuleEx),          ("test time event", testTimeEventEx),          ("test time event 2", testTimeEventEx2),          ("test delete rule", testDeleteRuleEx1),@@ -102,13 +101,15 @@          ("test assess on every vote 3", testVoteAssessOnEveryVote3),          ("test assess on every vote 4", testVoteAssessOnEveryVote4),          ("test majority with", testVoteMajorityWith),---         ("test number positive votes", testVoteNumberPositiveVotes),+         ("test number positive votes", testVoteNumberPositiveVotes),          ("test vote with quorum 1", testVoteWithQuorum1),          ("test assess on time limit 1", testVoteAssessOnTimeLimit1),          ("test assess on time limit 2", testVoteAssessOnTimeLimit2),          ("test assess on time limit 3", testVoteAssessOnTimeLimit3),          ("test assess on time limit 4", testVoteAssessOnTimeLimit4),          ("test assess on time limit 5", testVoteAssessOnTimeLimit5),+         ("test vote player arrives", testVotePlayerArriveEx),+         ("test vote player leaves", testVotePlayerLeaveEx),          ("test composed event sum", testSumComposeEx),          ("test composed event prod 1", testProdComposeEx1),          ("test composed event prod 2", testProdComposeEx2),@@ -296,12 +297,14 @@     actions     evProposeRule testRule     evs <- lift getChoiceEvents-    let pos = take positives evs-    let neg = take negatives $ drop positives evs-    mapM_ (\(en, fa) -> triggerInput en fa (RadioData 0)) pos --issuing positive votes-    mapM_ (\(en, fa) -> triggerInput en fa (RadioData 1)) neg --issuing negative votes+    mapM_ (triggerVote 0) (take positives evs)                  --issuing positive votes+    mapM_ (triggerVote 1) (take negatives $ drop positives evs) --issuing negative votes     when timeEvent $ evTriggerTime date2 +--Trigger a vote event (0 for positive, 1 for negative), using event details+triggerVote :: Int -> (EventNumber, FieldAddress, PlayerNumber, String) -> Evaluate ()+triggerVote res (en, fa, pn, t) = triggerInput en fa (RadioField pn t [(0,"For"),(1,"Against")]) (RadioData res)+ voteGame' :: Int -> Int -> Int -> Bool -> Rule -> Game voteGame' positives negatives notVoted timeEvent rf  = voteGameActions positives negatives notVoted timeEvent $ addActivateRule rf 1 @@ -329,6 +332,34 @@  testVoteRule s g = (_rStatus $ head $ _rules g) == s +--Test with a player arriving in the middle of a vote (he should be able to vote)+testVotePlayerArrive :: Game+testVotePlayerArrive = flip execState testGame {_players = []} $ runSystemEval' $ do+    addPlayer (PlayerInfo 1 "coco 1" Nothing)+    addActivateRule  (onRuleProposed $ callVoteRule (unanimity `withQuorum` 2) oneDay) 1+    evProposeRule testRule+    evs <- lift getChoiceEvents+    mapM_ (triggerVote 0) evs                 --issuing positive vote player 1+    addPlayer (PlayerInfo 2 "coco 2" Nothing) --new player+    evs <- lift getChoiceEvents+    mapM_ (triggerVote 0) evs                 --issuing positive vote player 2++testVotePlayerArriveEx = testVoteRule Active testVotePlayerArrive++--Test with a player leaving in the middle of a vote+--in some cases a player leaving can trigger the end of the vote (i.e when everybody voted except him)+testVotePlayerLeave :: Game+testVotePlayerLeave = flip execState testGame {_players = []} $ runSystemEval' $ do+    addPlayer (PlayerInfo 1 "coco 1" Nothing)+    addPlayer (PlayerInfo 2 "coco 2" Nothing)+    addActivateRule  (onRuleProposed $ callVoteRule unanimity oneDay) 1+    evProposeRule testRule+    evs <- lift getChoiceEvents+    triggerVote 0 (last evs)  -- issuing positive vote player 1+    evDelPlayer 2             -- player 2 leaving++testVotePlayerLeaveEx = testVoteRule Active testVotePlayerLeave+ -- Event composition  testSumCompose :: Rule@@ -336,7 +367,7 @@    f a = outputAll_ $ show a  testSumComposeEx = isOutput "True" g where-   g = execRuleInput testSumCompose 1 [SumL, AppR] ButtonData+   g = execRuleInput testSumCompose 1 [SumL, AppR] (ButtonField 1 "click here:") ButtonData   testProdCompose :: Rule@@ -344,10 +375,10 @@    f a = outputAll_ $ show a  testProdComposeEx1 = null $ allOutputs g where-   g = execRuleInput testProdCompose 1 [AppR] (TextData "toto")+   g = execRuleInput testProdCompose 1 [AppR] (TextField 1 "") (TextData "toto")  testProdComposeEx2 = isOutput "(\"toto\",\"tata\")" g where-   g = execRuleInputs testProdCompose 1 [([AppL, AppR], TextData "toto"), ([AppR], TextData "tata")]+   g = execRuleInputs testProdCompose 1 [([AppL, AppR], (TextField 1 ""), TextData "toto"), ([AppR], (TextField 1 ""), TextData "tata")]  testTwoEvents :: Rule testTwoEvents = do@@ -356,7 +387,7 @@    f a = outputAll_ $ show a  testTwoEventsEx = (length $ allOutputs g) == 1 where-   g = execRuleInput testTwoEvents 1 [] (TextData "toto")+   g = execRuleInput testTwoEvents 1 [] (TextField 1 "") (TextData "toto")  testMonadicEvent :: Rule testMonadicEvent = do@@ -367,31 +398,32 @@    void $ onEvent_ e displayMsg  testMonadicEventEx = isOutput "coco2" g where-   g = execRuleInputs testMonadicEvent 1 [([BindL], TextData "coco1"), ([BindR, BindR], TextData "coco2")]+   g = execRuleInputs testMonadicEvent 1 [([BindL], (TextField 1 ""), TextData "coco1"), ([BindR, BindR], (TextField 1 ""), TextData "coco2")]  testShorcutEvent :: Rule testShorcutEvent = do    let displayMsg a = void $ newOutput_ Nothing (concat $ catMaybes a)    let e = do-       let a = inputText 1 ""-       shortcut [a,a] (\as -> length (filter isJust as) == 1)+       let a = inputText 1 "a"+       let b = inputText 1 "b"+       shortcut [a,b] (\as -> length (filter isJust as) >= 1)    void $ onEvent_ e displayMsg  testShorcutEventEx = isOutput "coco1" g where-   g = execRuleInputs testShorcutEvent 1 [([Index 0], TextData "coco1")]+   g = execRuleInputs testShorcutEvent 1 [([Shortcut], (TextField 1 "a"), TextData "coco1")]   --Get all event numbers of type choice (radio button)-getChoiceEvents :: State EvalEnv [(EventNumber, FieldAddress)]+getChoiceEvents :: State EvalEnv [(EventNumber, FieldAddress, PlayerNumber, String)] getChoiceEvents = do    evs <- access (eGame >>> events)    g <- access eGame-   return $ [(_eventNumber ev, inum) | ev <- evs, inum <- getInputChoices ev g]+   return $ [(_eventNumber ev, fa, pn, t) | ev <- evs, (fa, pn, t) <- getInputChoices ev g] -getInputChoices :: EventInfo -> Game -> [FieldAddress]+getInputChoices :: EventInfo -> Game -> [(FieldAddress, PlayerNumber, String)] getInputChoices ei g = mapMaybe isInput (getEventFields ei g) where-   isInput :: (t, SomeField) -> Maybe t-   isInput (fa, (SomeField (Input _ _ (Radio _)))) = Just fa+   isInput :: (FieldAddress, SomeField) -> Maybe (FieldAddress, PlayerNumber, String)+   isInput (fa, (SomeField (Input pn t (Radio _)))) = Just (fa, pn, t)    isInput _ = Nothing  --Get all event numbers of type text (text field)
src/Nomyx/Core/Engine/Types.hs view
@@ -4,6 +4,7 @@ {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE DeriveGeneric #-}  -- | Types for the engine module Nomyx.Core.Engine.Types where@@ -17,6 +18,7 @@ import Control.Monad.Error (ErrorT(..)) import Control.Monad.State import Control.Monad.Reader+import GHC.Generics  -- * Evaluation @@ -79,7 +81,15 @@  -- * Events --- data sent back by the forms+-- a form field+data FormField = RadioField PlayerNumber String [(Int, String)]+               | TextField PlayerNumber String+               | TextAreaField PlayerNumber String+               | ButtonField PlayerNumber String+               | CheckboxField PlayerNumber String [(Int, String)]+                 deriving (Show, Read, Ord, Eq, Generic)++-- data sent back by the form fields data InputData = RadioData Int                | CheckboxData [Int]                | TextData String
src/Nomyx/Core/Engine/Utils.hs view
@@ -22,7 +22,7 @@         -> [a] -- ^ Output list
 replaceWith f y = map (\z -> if f z then y else z)
 -tracePN :: (Monad m ) => Int -> String -> m ()+tracePN :: (Monad m) => Int -> String -> m () tracePN pn s = traceM $ "Player " ++ (show pn) ++ " " ++ s  traceData :: (Show a) => String -> a -> a
src/Nomyx/Core/Serialize.hs view
@@ -79,6 +79,7 @@ $(deriveJSON defaultOptions ''GameInfo) $(deriveJSON defaultOptions ''TimedEvent) $(deriveJSON defaultOptions ''FieldAddressElem)+$(deriveJSON defaultOptions ''FormField) $(deriveJSON defaultOptions ''GameEvent) $(deriveJSON defaultOptions ''InputData) $(deriveJSON defaultOptions ''SubmitRule)
src/Nomyx/Core/Session.hs view
@@ -40,7 +40,7 @@ newGame' name desc pn isPublic sh = do       gs <- access gameInfos       if not $ any ((== name) . getL gameNameLens) gs then do-         tracePN pn $ "Creating a new game of name: " ++ name+         tracePN pn $ "Creating a new game with name: " ++ name          t <- lift T.getCurrentTime          -- create a game with zero players          lg <- lift $ initialGameInfo name desc isPublic (Just pn) t sh@@ -119,8 +119,8 @@          tracePN pn ("Error in submitted rule: " ++ errorMsg)          modifyProfile pn (pLastRule ^= Just (sr, errorMsg)) -inputResult :: PlayerNumber -> EventNumber -> FieldAddress -> InputData -> GameName -> StateT Session IO ()-inputResult pn en fa ir gn = inGameDo gn $ execGameEvent $ InputResult pn en fa ir+inputResult :: PlayerNumber -> EventNumber -> FieldAddress -> FormField -> InputData -> GameName -> StateT Session IO ()+inputResult pn en fa ft ir gn = inGameDo gn $ execGameEvent $ InputResult pn en fa ft ir  -- | upload a rule file, given a player number, the full path of the file, the file name and the server handle inputUpload :: PlayerNumber -> FilePath -> FilePath -> ServerHandle -> StateT Session IO Bool
src/Nomyx/Core/Test.hs view
@@ -136,7 +136,7 @@    onePlayerOneGame    sh <- access sh    submitRule (SubmitRule "" "" r) 1 "test" sh-   inputAllRadios 0 1+   inputAllRadios 0  testFile' :: FilePath -> FilePath -> String -> StateT Session IO Bool testFile' path name func = do@@ -144,7 +144,7 @@    dataDir <- lift PNC.getDataDir    res <- inputUpload 1 (dataDir </> testDir </> path) name sh    submitRule (SubmitRule "" "" func) 1 "test" sh-   inputAllRadios 0 1+   inputAllRadios 0    return res  testFile :: FilePath -> String -> StateT Session IO Bool@@ -165,8 +165,7 @@    twoPlayersOneGame    sh <- access sh    submitRule (SubmitRule "" "" [cr|helloWorld|]) 1 "test" sh-   inputAllRadios 0 1-   inputAllRadios 0 2+   inputAllRadios 0  condHelloWorld2Players :: Multi -> Bool condHelloWorld2Players = isOutput' "hello, world!"@@ -180,8 +179,7 @@    submitRule (SubmitRule "" "" [cr|createBankAccount|]) 1 "test" sh    submitRule (SubmitRule "" "" [cr|winXEcuOnRuleAccepted 100|]) 1 "test" sh    submitRule (SubmitRule "" "" [cr|moneyTransfer|]) 2 "test" sh-   inputAllRadios 0 1-   inputAllRadios 0 2+   inputAllRadios 0    inputAllTexts "50" 1  condMoneyTransfer :: Multi -> Bool@@ -312,19 +310,19 @@ isOutput' :: String -> Multi -> Bool isOutput' s m = any (isOutput s . _game . _loggedGame) (_gameInfos m) --- select first choice for all radio buttons-inputAllRadios :: Int -> PlayerNumber -> StateT Session IO ()-inputAllRadios choice pn = do+-- select a choice for all radio buttons+inputAllRadios :: Int -> StateT Session IO ()+inputAllRadios choice = do    s <- get    let evs = evalState getChoiceEvents (EvalEnv 0 (firstGame $ _multi s))-   mapM_ (\(en, inum) -> inputResult pn en inum (RadioData choice) "test") evs+   mapM_ (\(en, fa, pn, t) -> inputResult pn en fa (RadioField pn t [(0,"For"),(1,"Against")]) (RadioData choice) "test") evs  -- input text for all text fields inputAllTexts :: String -> PlayerNumber -> StateT Session IO () inputAllTexts a pn = do    s <- get    let evs = evalState getTextEvents (firstGame $ _multi s)-   mapM_ (\(en, fa) -> inputResult pn en fa (TextData a) "test") evs+   mapM_ (\(en, fa) -> inputResult pn en fa (TextField 1 "") (TextData a) "test") evs  firstGame :: Multi -> Game firstGame = G._game . _loggedGame . head . _gameInfos