Nomyx-Language 0.2.3 → 0.3.0
raw patch · 9 files changed
+629/−333 lines, 9 filesdep +transformersPVP ok
version bump matches the API change (PVP)
Dependencies added: transformers
API changes (from Hackage documentation)
- Language.Nomyx.Definition: ArrayVar :: (Msg [(i, Maybe a)]) -> (V (Map i (Maybe a))) -> ArrayVar i a
- Language.Nomyx.Definition: data ArrayVar i a
- Language.Nomyx.Definition: delArrayVar :: (Ord i, Typeable a, Show a, Eq a, Typeable i, Show i) => (ArrayVar i a) -> Nomex ()
- Language.Nomyx.Definition: getArrayVarData :: (Ord i, Typeable a, Show a, Eq a, Typeable i, Show i) => (ArrayVar i a) -> Nomex ([(i, Maybe a)])
- Language.Nomyx.Definition: getArrayVarData' :: (Ord i, Typeable a, Show a, Eq a, Typeable i, Show i) => (ArrayVar i a) -> Nomex ([(i, a)])
- Language.Nomyx.Definition: getArrayVarMessage :: (Ord i, Typeable a, Show a, Eq a, Typeable i, Show i) => (ArrayVar i a) -> Nomex (Msg [(i, Maybe a)])
- Language.Nomyx.Definition: inputChoice :: (Eq c, Show c) => PlayerNumber -> String -> [c] -> c -> Event (InputChoice c)
- Language.Nomyx.Definition: inputChoiceEnum :: (Enum c, Bounded c, Typeable c, Eq c, Show c) => PlayerNumber -> String -> c -> Event (InputChoice c)
- Language.Nomyx.Definition: inputChoiceHead :: (Eq c, Show c) => PlayerNumber -> String -> [c] -> Event (InputChoice c)
- Language.Nomyx.Definition: inputString :: PlayerNumber -> String -> Event InputString
- Language.Nomyx.Definition: isFullArrayVar :: (Ord i, Typeable a, Show a, Eq a, Typeable i, Show i) => (ArrayVar i a) -> Nomex (Bool)
- Language.Nomyx.Definition: onInputChoice :: (Typeable a, Eq a, Show a) => String -> [a] -> (EventNumber -> a -> Nomex ()) -> PlayerNumber -> Nomex EventNumber
- Language.Nomyx.Definition: onInputChoiceEnum :: (Enum a, Bounded a, Typeable a, Eq a, Show a) => String -> a -> (EventNumber -> a -> Nomex ()) -> PlayerNumber -> Nomex EventNumber
- Language.Nomyx.Definition: onInputChoiceEnumOnce_ :: (Enum a, Bounded a, Typeable a, Eq a, Show a) => String -> a -> (a -> Nomex ()) -> PlayerNumber -> Nomex ()
- Language.Nomyx.Definition: onInputChoiceEnum_ :: (Enum a, Bounded a, Typeable a, Eq a, Show a) => String -> a -> (a -> Nomex ()) -> PlayerNumber -> Nomex ()
- Language.Nomyx.Definition: onInputChoiceOnce :: (Typeable a, Eq a, Show a) => String -> [a] -> (a -> Nomex ()) -> PlayerNumber -> Nomex EventNumber
- Language.Nomyx.Definition: onInputChoiceOnce_ :: (Typeable a, Eq a, Show a) => String -> [a] -> (a -> Nomex ()) -> PlayerNumber -> Nomex ()
- Language.Nomyx.Definition: onInputChoice_ :: (Typeable a, Eq a, Show a) => String -> [a] -> (a -> Nomex ()) -> PlayerNumber -> Nomex ()
- Language.Nomyx.Definition: onInputString :: String -> (EventNumber -> String -> Nomex ()) -> PlayerNumber -> Nomex EventNumber
- Language.Nomyx.Definition: onInputStringOnce_ :: String -> (String -> Nomex ()) -> PlayerNumber -> Nomex ()
- Language.Nomyx.Definition: onInputString_ :: String -> (String -> Nomex ()) -> PlayerNumber -> Nomex ()
- Language.Nomyx.Definition: output :: String -> PlayerNumber -> Nomex ()
- Language.Nomyx.Evaluation: evDelRule :: RuleNumber -> Evaluate Bool
- Language.Nomyx.Evaluation: evInputChoice :: (Eq d, Show d, Typeable d, Read d) => Event (InputChoice d) -> d -> Evaluate Bool
- Language.Nomyx.Evaluation: execChoiceHandler :: EventNumber -> Int -> EventHandler -> Evaluate ()
- Language.Nomyx.Evaluation: outputS :: PlayerNumber -> String -> Evaluate ()
- Language.Nomyx.Evaluation: triggerChoice :: EventNumber -> Int -> Evaluate ()
- Language.Nomyx.Expression: DelRule :: RuleNumber -> Nomex Bool
- Language.Nomyx.Expression: EvActive :: EventStatus
- Language.Nomyx.Expression: EvDeleted :: EventStatus
- Language.Nomyx.Expression: InputChoice :: PlayerNumber -> String -> [c] -> c -> Event (InputChoice c)
- Language.Nomyx.Expression: InputChoiceData :: c -> EventData (InputChoice c)
- Language.Nomyx.Expression: InputString :: PlayerNumber -> String -> Event InputString
- Language.Nomyx.Expression: InputStringData :: String -> EventData InputString
- Language.Nomyx.Expression: data EventStatus
- Language.Nomyx.Expression: data InputChoice c
- Language.Nomyx.Expression: data InputString
- Language.Nomyx.Expression: inputChoiceData :: EventData (InputChoice c) -> c
- Language.Nomyx.Expression: inputStringData :: EventData InputString -> String
- Language.Nomyx.Expression: instance Eq (InputChoice a)
- Language.Nomyx.Expression: instance Eq EventStatus
- Language.Nomyx.Expression: instance Eq InputString
- Language.Nomyx.Expression: instance Show EventStatus
- Language.Nomyx.Expression: instance Show InputString
- Language.Nomyx.Expression: instance Show a => Show (InputChoice a)
- Language.Nomyx.Expression: instance Show a => Show (Nomex a)
- Language.Nomyx.Expression: instance Typeable InputString
- Language.Nomyx.Expression: instance Typeable1 InputChoice
- Language.Nomyx.Expression: type Id a = a
- Language.Nomyx.Expression: type Output = (PlayerNumber, String)
- Language.Nomyx.Game: InputChoiceResult :: PlayerNumber -> EventNumber -> Int -> GameEvent
- Language.Nomyx.Game: InputStringResult :: PlayerNumber -> String -> String -> GameEvent
- Language.Nomyx.Game: OutputPlayer :: PlayerNumber -> String -> GameEvent
- Language.Nomyx.Game: outputAll :: String -> StateT LoggedGame IO ()
+ Language.Nomyx.Definition: MsgVar :: (Msg (VEvent a)) -> (V a) -> MsgVar a
+ Language.Nomyx.Definition: VDeleted :: VEvent a
+ Language.Nomyx.Definition: VUpdated :: a -> VEvent a
+ Language.Nomyx.Definition: cleanOnFull :: (Typeable a, Show a, Eq a, Ord i, Typeable i, Show i) => (ArrayVar i a) -> Nomex ()
+ Language.Nomyx.Definition: data MsgVar a
+ Language.Nomyx.Definition: data VEvent a
+ Language.Nomyx.Definition: delMsgVar :: (Typeable a, Show a, Eq a) => MsgVar a -> Nomex Bool
+ Language.Nomyx.Definition: delOutput :: OutputNumber -> Nomex Bool
+ Language.Nomyx.Definition: delOutput_ :: OutputNumber -> Nomex ()
+ Language.Nomyx.Definition: displayArrayVar :: (Typeable a, Show a, Eq a, Typeable i, Show i, Eq i) => PlayerNumber -> String -> ArrayVar i a -> Nomex ()
+ Language.Nomyx.Definition: displaySimpleVar :: (Typeable a, Show a, Eq a) => PlayerNumber -> String -> MsgVar a -> Nomex ()
+ Language.Nomyx.Definition: displayVar :: (Typeable a, Show a, Eq a) => PlayerNumber -> MsgVar a -> (a -> String) -> Nomex ()
+ Language.Nomyx.Definition: getMsgVarData :: (Typeable a, Show a, Eq a) => (MsgVar a) -> Nomex (Maybe a)
+ Language.Nomyx.Definition: getMsgVarData_ :: (Typeable a, Show a, Eq a) => (MsgVar a) -> Nomex a
+ Language.Nomyx.Definition: getMsgVarMessage :: (Typeable a, Show a, Eq a) => (MsgVar a) -> Nomex (Msg (VEvent a))
+ Language.Nomyx.Definition: inputButton :: PlayerNumber -> String -> Event (Input ())
+ Language.Nomyx.Definition: inputButtonData :: EventData (Input ()) -> ()
+ Language.Nomyx.Definition: inputCheckbox :: (Eq c, Show c, Typeable c) => PlayerNumber -> String -> [(c, String)] -> Event (Input c)
+ Language.Nomyx.Definition: inputCheckboxData :: Show c => EventData (Input c) -> [c]
+ Language.Nomyx.Definition: inputRadio :: (Eq c, Show c, Typeable c) => PlayerNumber -> String -> [c] -> c -> Event (Input c)
+ Language.Nomyx.Definition: inputRadioData :: Show c => EventData (Input c) -> c
+ Language.Nomyx.Definition: inputRadioEnum :: (Enum c, Bounded c, Typeable c, Eq c, Show c) => PlayerNumber -> String -> c -> Event (Input c)
+ Language.Nomyx.Definition: inputRadioHead :: (Eq c, Show c, Typeable c) => PlayerNumber -> String -> [c] -> Event (Input c)
+ Language.Nomyx.Definition: inputText :: PlayerNumber -> String -> Event (Input String)
+ Language.Nomyx.Definition: inputTextData :: EventData (Input String) -> String
+ Language.Nomyx.Definition: inputTextarea :: PlayerNumber -> String -> Event (Input String)
+ Language.Nomyx.Definition: inputTextareaData :: EventData (Input String) -> String
+ Language.Nomyx.Definition: instance Eq a => Eq (VEvent a)
+ Language.Nomyx.Definition: instance Show a => Show (VEvent a)
+ Language.Nomyx.Definition: instance Typeable1 VEvent
+ Language.Nomyx.Definition: isFullArrayVar_ :: (Ord i, Typeable a, Show a, Eq a, Typeable i, Show i) => (ArrayVar i a) -> Nomex Bool
+ Language.Nomyx.Definition: msgVar :: String -> MsgVar a
+ Language.Nomyx.Definition: newArrayVar_ :: (Typeable a, Show a, Eq a, Typeable i, Show i, Eq i) => VarName -> [i] -> Nomex (ArrayVar i a)
+ Language.Nomyx.Definition: newMsgVar :: (Typeable a, Show a, Eq a) => VarName -> a -> Nomex (Maybe (MsgVar a))
+ Language.Nomyx.Definition: newMsgVar' :: (Typeable a, Show a, Eq a) => VarName -> a -> (VEvent a -> Nomex ()) -> Nomex (Maybe (MsgVar a))
+ Language.Nomyx.Definition: newOutput :: String -> PlayerNumber -> Nomex OutputNumber
+ Language.Nomyx.Definition: newOutput_ :: String -> PlayerNumber -> Nomex ()
+ Language.Nomyx.Definition: onInputButton :: String -> (EventNumber -> () -> Nomex ()) -> PlayerNumber -> Nomex EventNumber
+ Language.Nomyx.Definition: onInputButton_ :: String -> (() -> Nomex ()) -> PlayerNumber -> Nomex ()
+ Language.Nomyx.Definition: onInputCheckbox :: (Typeable a, Eq a, Show a) => String -> [(a, String)] -> (EventNumber -> [a] -> Nomex ()) -> PlayerNumber -> Nomex EventNumber
+ Language.Nomyx.Definition: onInputCheckbox_ :: (Typeable a, Eq a, Show a) => String -> [(a, String)] -> ([a] -> Nomex ()) -> PlayerNumber -> Nomex ()
+ Language.Nomyx.Definition: onInputRadio :: (Typeable a, Eq a, Show a) => String -> [a] -> (EventNumber -> a -> Nomex ()) -> PlayerNumber -> Nomex EventNumber
+ Language.Nomyx.Definition: onInputRadioEnum :: (Enum a, Bounded a, Typeable a, Eq a, Show a) => String -> a -> (EventNumber -> a -> Nomex ()) -> PlayerNumber -> Nomex EventNumber
+ Language.Nomyx.Definition: onInputRadioEnumOnce_ :: (Enum a, Bounded a, Typeable a, Eq a, Show a) => String -> a -> (a -> Nomex ()) -> PlayerNumber -> Nomex ()
+ Language.Nomyx.Definition: onInputRadioEnum_ :: (Enum a, Bounded a, Typeable a, Eq a, Show a) => String -> a -> (a -> Nomex ()) -> PlayerNumber -> Nomex ()
+ Language.Nomyx.Definition: onInputRadioOnce :: (Typeable a, Eq a, Show a) => String -> [a] -> (a -> Nomex ()) -> PlayerNumber -> Nomex EventNumber
+ Language.Nomyx.Definition: onInputRadioOnce_ :: (Typeable a, Eq a, Show a) => String -> [a] -> (a -> Nomex ()) -> PlayerNumber -> Nomex ()
+ Language.Nomyx.Definition: onInputRadio_ :: (Typeable a, Eq a, Show a) => String -> [a] -> (a -> Nomex ()) -> PlayerNumber -> Nomex ()
+ Language.Nomyx.Definition: onInputText :: String -> (EventNumber -> String -> Nomex ()) -> PlayerNumber -> Nomex EventNumber
+ Language.Nomyx.Definition: onInputTextOnce_ :: String -> (String -> Nomex ()) -> PlayerNumber -> Nomex ()
+ Language.Nomyx.Definition: onInputText_ :: String -> (String -> Nomex ()) -> PlayerNumber -> Nomex ()
+ Language.Nomyx.Definition: onInputTextarea :: String -> (EventNumber -> String -> Nomex ()) -> PlayerNumber -> Nomex EventNumber
+ Language.Nomyx.Definition: onInputTextareaOnce_ :: String -> (String -> Nomex ()) -> PlayerNumber -> Nomex ()
+ Language.Nomyx.Definition: onInputTextarea_ :: String -> (String -> Nomex ()) -> PlayerNumber -> Nomex ()
+ Language.Nomyx.Definition: onMsgVarChange :: (Typeable a, Show a, Eq a) => MsgVar a -> (VEvent a -> Nomex ()) -> Nomex ()
+ Language.Nomyx.Definition: onMsgVarEvent :: (Typeable a, Show a, Eq a) => MsgVar a -> (a -> Nomex b) -> (a -> b -> Nomex ()) -> (b -> Nomex ()) -> Nomex ()
+ Language.Nomyx.Definition: partial :: String -> Nomex (Maybe a) -> Nomex a
+ Language.Nomyx.Definition: putArrayVar_ :: (Ord i, Typeable a, Show a, Eq a, Typeable i, Show i) => (ArrayVar i a) -> i -> a -> Nomex ()
+ Language.Nomyx.Definition: readMsgVar :: (Typeable a, Show a, Eq a) => MsgVar a -> Nomex (Maybe a)
+ Language.Nomyx.Definition: readMsgVar_ :: (Typeable a, Show a, Eq a) => MsgVar a -> Nomex a
+ Language.Nomyx.Definition: showArrayVar :: (Show a, Show i) => String -> [(i, a)] -> String
+ Language.Nomyx.Definition: type ArrayVar i a = MsgVar [(i, Maybe a)]
+ Language.Nomyx.Definition: updateOutput :: OutputNumber -> String -> Nomex Bool
+ Language.Nomyx.Definition: updateOutput_ :: OutputNumber -> String -> Nomex ()
+ Language.Nomyx.Definition: writeMsgVar :: (Typeable a, Show a, Eq a) => MsgVar a -> a -> Nomex Bool
+ Language.Nomyx.Definition: writeMsgVar_ :: (Typeable a, Show a, Eq a) => MsgVar a -> a -> Nomex ()
+ Language.Nomyx.Evaluation: evDelOutput :: OutputNumber -> Evaluate Bool
+ Language.Nomyx.Evaluation: evNewOutput :: PlayerNumber -> RuleNumber -> String -> Evaluate OutputNumber
+ Language.Nomyx.Evaluation: evUpdateOutput :: OutputNumber -> String -> Evaluate Bool
+ Language.Nomyx.Evaluation: execInputHandler :: UInputData -> EventHandler -> Evaluate ()
+ Language.Nomyx.Evaluation: log :: Maybe PlayerNumber -> String -> Evaluate ()
+ Language.Nomyx.Evaluation: logAll :: String -> Evaluate ()
+ Language.Nomyx.Evaluation: logPlayer :: PlayerNumber -> String -> Evaluate ()
+ Language.Nomyx.Evaluation: triggerHandler :: (Typeable e, Show e, Eq e) => EventData e -> EventHandler -> Evaluate ()
+ Language.Nomyx.Evaluation: triggerInput :: EventNumber -> UInputData -> Evaluate ()
+ Language.Nomyx.Examples: bravoButton :: RuleFunc
+ Language.Nomyx.Examples: enterHaiku :: RuleFunc
+ Language.Nomyx.Expression: Button :: InputForm a
+ Language.Nomyx.Expression: ButtonData :: InputData a
+ Language.Nomyx.Expression: Checkbox :: [(a, String)] -> InputForm a
+ Language.Nomyx.Expression: CheckboxData :: [a] -> InputData a
+ Language.Nomyx.Expression: DelOutput :: OutputNumber -> Nomex Bool
+ Language.Nomyx.Expression: Input :: PlayerNumber -> String -> (InputForm a) -> Input a
+ Language.Nomyx.Expression: InputData :: InputData a -> EventData (Input a)
+ Language.Nomyx.Expression: InputEv :: Input a -> Event (Input a)
+ Language.Nomyx.Expression: Log :: Maybe PlayerNumber -> UTCTime -> String -> Log
+ Language.Nomyx.Expression: NewOutput :: PlayerNumber -> String -> Nomex OutputNumber
+ Language.Nomyx.Expression: Radio :: [(a, String)] -> InputForm a
+ Language.Nomyx.Expression: RadioData :: a -> InputData a
+ Language.Nomyx.Expression: SActive :: Status
+ Language.Nomyx.Expression: SDeleted :: Status
+ Language.Nomyx.Expression: Text :: InputForm a
+ Language.Nomyx.Expression: TextArea :: InputForm a
+ Language.Nomyx.Expression: TextAreaData :: String -> InputData a
+ Language.Nomyx.Expression: TextData :: String -> InputData a
+ Language.Nomyx.Expression: UButtonData :: UInputData
+ Language.Nomyx.Expression: UCheckboxData :: [Int] -> UInputData
+ Language.Nomyx.Expression: URadioData :: Int -> UInputData
+ Language.Nomyx.Expression: UTextAreaData :: String -> UInputData
+ Language.Nomyx.Expression: UTextData :: String -> UInputData
+ Language.Nomyx.Expression: UpdateOutput :: OutputNumber -> String -> Nomex Bool
+ Language.Nomyx.Expression: _lMsg :: Log -> String
+ Language.Nomyx.Expression: _lPlayerNumber :: Log -> Maybe PlayerNumber
+ Language.Nomyx.Expression: _lTime :: Log -> UTCTime
+ Language.Nomyx.Expression: _logs :: Game -> [Log]
+ Language.Nomyx.Expression: _oPlayerNumber :: Output -> PlayerNumber
+ Language.Nomyx.Expression: _oRuleNumber :: Output -> PlayerNumber
+ Language.Nomyx.Expression: _oStatus :: Output -> Status
+ Language.Nomyx.Expression: _output :: Output -> String
+ Language.Nomyx.Expression: _outputNumber :: Output -> OutputNumber
+ Language.Nomyx.Expression: data Input a
+ Language.Nomyx.Expression: data InputData a
+ Language.Nomyx.Expression: data InputForm a
+ Language.Nomyx.Expression: data Log
+ Language.Nomyx.Expression: data Output
+ Language.Nomyx.Expression: data Status
+ Language.Nomyx.Expression: data UInputData
+ Language.Nomyx.Expression: inputData :: EventData (Input a) -> InputData a
+ Language.Nomyx.Expression: instance Eq Status
+ Language.Nomyx.Expression: instance Eq UInputData
+ Language.Nomyx.Expression: instance Eq e => Eq (Input e)
+ Language.Nomyx.Expression: instance Eq e => Eq (InputForm e)
+ Language.Nomyx.Expression: instance Ord UInputData
+ Language.Nomyx.Expression: instance Read UInputData
+ Language.Nomyx.Expression: instance Show Log
+ Language.Nomyx.Expression: instance Show Output
+ Language.Nomyx.Expression: instance Show Status
+ Language.Nomyx.Expression: instance Show UInputData
+ Language.Nomyx.Expression: instance Show a => Show (Input a)
+ Language.Nomyx.Expression: instance Show a => Show (InputData a)
+ Language.Nomyx.Expression: instance Show a => Show (InputForm a)
+ Language.Nomyx.Expression: instance Typeable a => Show (Nomex a)
+ Language.Nomyx.Expression: instance Typeable1 Input
+ Language.Nomyx.Expression: instance Typeable1 InputForm
+ Language.Nomyx.Expression: logs :: Lens Game [Log]
+ Language.Nomyx.Expression: oPlayerNumber :: Lens Output PlayerNumber
+ Language.Nomyx.Expression: oRuleNumber :: Lens Output PlayerNumber
+ Language.Nomyx.Expression: oStatus :: Lens Output Status
+ Language.Nomyx.Expression: output :: Lens Output String
+ Language.Nomyx.Expression: outputNumber :: Lens Output OutputNumber
+ Language.Nomyx.Expression: type OutputNumber = Int
+ Language.Nomyx.Game: GLog :: (Maybe PlayerNumber) -> String -> GameEvent
+ Language.Nomyx.Game: InputResult :: PlayerNumber -> EventNumber -> UInputData -> GameEvent
+ Language.Nomyx.Game: UButtonData :: UInputData
+ Language.Nomyx.Game: UCheckboxData :: [Int] -> UInputData
+ Language.Nomyx.Game: URadioData :: Int -> UInputData
+ Language.Nomyx.Game: UTextAreaData :: String -> UInputData
+ Language.Nomyx.Game: UTextData :: String -> UInputData
+ Language.Nomyx.Game: data UInputData
+ Language.Nomyx.Test: isOutput :: String -> Game -> Bool
+ Language.Nomyx.Test: testMultipleInputs :: RuleFunc
+ Language.Nomyx.Test: testMultipleInputsEx :: Bool
+ Language.Nomyx.Utils: sel :: [a] -> [Int] -> [a]
+ Language.Nomyx.Vote: displayVoteResult :: Votable a => String -> VoteData a -> Nomex ()
+ Language.Nomyx.Vote: displayVoteVar :: Votable a => PlayerNumber -> String -> ArrayVar PlayerNumber (Alts a) -> Nomex ()
+ Language.Nomyx.Vote: showChoice :: Votable a => Maybe (Alts a) -> String
+ Language.Nomyx.Vote: showChoices :: Votable a => [(Alts a)] -> String
+ Language.Nomyx.Vote: showPlayer :: Nomex (PlayerNumber -> String)
+ Language.Nomyx.Vote: showVotes :: Votable a => String -> (PlayerNumber -> String) -> [(PlayerNumber, Maybe (Alts a))] -> String
+ Language.Nomyx.Vote: showVotes' :: Votable a => (PlayerNumber -> String) -> [(PlayerNumber, Maybe (Alts a))] -> String
- Language.Nomyx.Definition: newArrayVar :: (Ord i, Typeable a, Show a, Eq a, Typeable i, Show i) => VarName -> [i] -> Nomex (ArrayVar i a)
+ Language.Nomyx.Definition: newArrayVar :: (Typeable a, Show a, Eq a, Typeable i, Show i, Eq i) => VarName -> [i] -> Nomex (Maybe (ArrayVar i a))
- Language.Nomyx.Definition: newArrayVar' :: (Ord i, Typeable a, Show a, Eq a, Typeable i, Show i) => VarName -> [i] -> ([(i, Maybe a)] -> Nomex ()) -> Nomex (ArrayVar i a)
+ Language.Nomyx.Definition: newArrayVar' :: (Typeable a, Show a, Eq a, Typeable i, Show i, Eq i) => VarName -> [i] -> (VEvent [(i, Maybe a)] -> Nomex ()) -> Nomex (Maybe (ArrayVar i a))
- Language.Nomyx.Definition: newArrayVarOnce :: (Ord i, Typeable a, Show a, Eq a, Typeable i, Show i) => VarName -> [i] -> ([(i, Maybe a)] -> Nomex ()) -> Nomex (ArrayVar i a)
+ Language.Nomyx.Definition: newArrayVarOnce :: (Ord i, Typeable a, Show a, Eq a, Typeable i, Show i) => VarName -> [i] -> (VEvent [(i, Maybe a)] -> Nomex ()) -> Nomex (Maybe (ArrayVar i a))
- Language.Nomyx.Definition: putArrayVar :: (Ord i, Typeable a, Show a, Eq a, Typeable i, Show i) => (ArrayVar i a) -> i -> a -> Nomex ()
+ Language.Nomyx.Definition: putArrayVar :: (Ord i, Typeable a, Show a, Eq a, Typeable i, Show i) => (ArrayVar i a) -> i -> a -> Nomex Bool
- Language.Nomyx.Evaluation: errorHandler :: String -> Nomex ()
+ Language.Nomyx.Evaluation: errorHandler :: RuleNumber -> EventNumber -> String -> Evaluate ()
- Language.Nomyx.Expression: EH :: EventNumber -> RuleNumber -> Event e -> ((EventNumber, EventData e) -> Nomex ()) -> EventStatus -> EventHandler
+ Language.Nomyx.Expression: EH :: EventNumber -> RuleNumber -> Event e -> ((EventNumber, EventData e) -> Nomex ()) -> Status -> EventHandler
- Language.Nomyx.Expression: Game :: GameName -> GameDesc -> [Rule] -> [PlayerInfo] -> [Var] -> [EventHandler] -> [Output] -> [PlayerNumber] -> UTCTime -> Game
+ Language.Nomyx.Expression: Game :: GameName -> GameDesc -> [Rule] -> [PlayerInfo] -> [Var] -> [EventHandler] -> [Output] -> [PlayerNumber] -> [Log] -> UTCTime -> Game
- Language.Nomyx.Expression: Output :: PlayerNumber -> String -> Nomex ()
+ Language.Nomyx.Expression: Output :: OutputNumber -> PlayerNumber -> PlayerNumber -> String -> Status -> Output
- Language.Nomyx.Expression: Var :: Int -> String -> a -> Var
+ Language.Nomyx.Expression: Var :: RuleNumber -> String -> a -> Var
- Language.Nomyx.Expression: _evStatus :: EventHandler -> EventStatus
+ Language.Nomyx.Expression: _evStatus :: EventHandler -> Status
- Language.Nomyx.Expression: _vRuleNumber :: Var -> Int
+ Language.Nomyx.Expression: _vRuleNumber :: Var -> RuleNumber
- Language.Nomyx.Expression: evStatus :: Lens EventHandler EventStatus
+ Language.Nomyx.Expression: evStatus :: Lens EventHandler Status
- Language.Nomyx.Expression: vRuleNumber :: Lens Var Int
+ Language.Nomyx.Expression: vRuleNumber :: Lens Var RuleNumber
Files
- Nomyx-Language.cabal +27/−12
- src/Language/Nomyx/Definition.hs +264/−105
- src/Language/Nomyx/Evaluation.hs +85/−57
- src/Language/Nomyx/Examples.hs +17/−8
- src/Language/Nomyx/Expression.hs +97/−61
- src/Language/Nomyx/Game.hs +32/−44
- src/Language/Nomyx/Test.hs +48/−27
- src/Language/Nomyx/Utils.hs +6/−0
- src/Language/Nomyx/Vote.hs +53/−19
Nomyx-Language.cabal view
@@ -1,5 +1,5 @@ name: Nomyx-Language-version: 0.2.3+version: 0.3.0 cabal-version: >=1.6 ---Warning: For using "cabal sdist", this patch is needed in cabal: https://github.com/haskell/cabal/pull/1110 ---To allow sdist to work with exported generated modules (Paths_Nomyx_Language)@@ -14,26 +14,41 @@ category: Language author: Corentin Dupont data-files: src/Language/Nomyx/Definition.hs- src/Language/Nomyx/Examples.hs src/Language/Nomyx/Expression.hs- src/Language/Nomyx/Rule.hs src/Language/Nomyx/Test.hs + src/Language/Nomyx/Examples.hs+ src/Language/Nomyx/Expression.hs+ src/Language/Nomyx/Rule.hs+ src/Language/Nomyx/Test.hs src/Language/Nomyx/Vote.hs data-dir: "" extra-source-files: AUTHORS README library- build-depends: base ==4.*, containers -any, ghc -any,- hint-server -any, hslogger -any, mtl -any, old-locale -any,- safe -any, stm -any, template-haskell -any, time -any,- time-recurrence -any, DebugTraceHelpers -any, data-lens -any,- data-lens-template -any, data-lens-fd -any, Boolean -any,- safecopy -any+ build-depends: base ==4.*,+ containers -any,+ ghc -any,+ hint-server -any,+ hslogger -any,+ mtl -any,+ old-locale -any,+ safe -any,+ stm -any,+ template-haskell -any,+ time -any,+ time-recurrence -any,+ DebugTraceHelpers -any,+ data-lens -any,+ data-lens-template -any,+ data-lens-fd -any,+ Boolean -any,+ safecopy -any,+ transformers -any exposed-modules: Language.Nomyx- Language.Nomyx.Expression + Language.Nomyx.Expression Language.Nomyx.Definition- Language.Nomyx.Evaluation + Language.Nomyx.Evaluation Language.Nomyx.Examples Language.Nomyx.Rule- Language.Nomyx.Vote + Language.Nomyx.Vote Language.Nomyx.Test Language.Nomyx.Game Language.Nomyx.Utils
src/Language/Nomyx/Definition.hs view
@@ -25,33 +25,21 @@ newVar = NewVar newVar_ :: (Typeable a, Show a, Eq a) => VarName -> a -> Nomex (V a) -newVar_ s a = do - mv <- NewVar s a - case mv of - Just var -> return var - Nothing -> throwError "newVar_: Variable existing" +newVar_ s a = partial "newVar_: Variable existing" (newVar s a) -- | variable reading readVar :: (Typeable a, Show a, Eq a) => (V a) -> Nomex (Maybe a) readVar = ReadVar readVar_ :: forall a. (Typeable a, Show a, Eq a) => (V a) -> Nomex a -readVar_ v@(V a) = do - ma <- ReadVar v - case ma of - Just (val:: a) -> return val - Nothing -> throwError $ "readVar_: Variable \"" ++ a ++ "\" with type \"" ++ (show $ typeOf v) ++ "\" not existing" +readVar_ v@(V a) = partial ("readVar_: Variable \"" ++ a ++ "\" with type \"" ++ (show $ typeOf v) ++ "\" not existing") (readVar v) -- | variable writing writeVar :: (Typeable a, Show a, Eq a) => (V a) -> a -> Nomex Bool writeVar = WriteVar writeVar_ :: (Typeable a, Show a, Eq a) => (V a) -> a -> Nomex () -writeVar_ var val = do - ma <- WriteVar var val - case ma of - True -> return () - False -> throwError "writeVar_: Variable not existing" +writeVar_ var val = void $ writeVar var val -- | modify a variable using the provided function modifyVar :: (Typeable a, Show a, Eq a) => (V a) -> (a -> a) -> Nomex () @@ -62,69 +50,141 @@ delVar = DelVar delVar_ :: (V a) -> Nomex () -delVar_ v = DelVar v >> return () +delVar_ v = void $ delVar v +++data VEvent a = VUpdated a | VDeleted deriving (Typeable, Show, Eq)+data MsgVar a = MsgVar (Msg (VEvent a)) (V a)++msgVar :: String -> MsgVar a+msgVar a = MsgVar (Message a) (V a)++newMsgVar :: (Typeable a, Show a, Eq a) => VarName -> a -> Nomex (Maybe (MsgVar a)) +newMsgVar name a = do + mv <- newVar name a+ return $ mv >>= Just . MsgVar (Message name) ++newMsgVar' :: (Typeable a, Show a, Eq a) => VarName -> a -> (VEvent a -> Nomex()) -> Nomex (Maybe (MsgVar a)) +newMsgVar' name a f = do + mv <- newMsgVar name a+ case mv of+ Just (MsgVar m _) -> do+ onMessage m $ f . messageData + return mv+ Nothing -> return Nothing ++writeMsgVar :: (Typeable a, Show a, Eq a) => MsgVar a -> a -> Nomex Bool +writeMsgVar (MsgVar m v) a = do + r <- writeVar v a+ sendMessage m (VUpdated a)+ return r++writeMsgVar_ :: (Typeable a, Show a, Eq a) => MsgVar a -> a -> Nomex ()+writeMsgVar_ mv a = void $ writeMsgVar mv a++readMsgVar :: (Typeable a, Show a, Eq a) => MsgVar a -> Nomex (Maybe a) +readMsgVar (MsgVar _ v) = readVar v++readMsgVar_ :: (Typeable a, Show a, Eq a) => MsgVar a -> Nomex a +readMsgVar_ mv = partial "readMsgVar_: variable not existing" (readMsgVar mv)++delMsgVar :: (Typeable a, Show a, Eq a) => MsgVar a -> Nomex Bool +delMsgVar (MsgVar m v) = do+ sendMessage m VDeleted+ delAllEvents m+ delVar v++onMsgVarChange :: (Typeable a, Show a, Eq a) => MsgVar a -> (VEvent a -> Nomex()) -> Nomex ()+onMsgVarChange mv f = do+ m <- getMsgVarMessage mv+ onMessage m $ \(MessageData v) -> f v++onMsgVarEvent :: (Typeable a, Show a, Eq a)+ => MsgVar a+ -> (a -> Nomex b)+ -> (a -> b -> Nomex())+ -> (b -> Nomex())+ -> Nomex ()+onMsgVarEvent mv create update delete = do+ val <- readMsgVar_ mv+ c <- create val+ onMsgVarChange mv $ f c where+ f c' (VUpdated v) = update v c'+ f c' VDeleted = delete c'+++-- | get the messsage triggered when the array is filled +getMsgVarMessage :: (Typeable a, Show a, Eq a) => (MsgVar a) -> Nomex (Msg (VEvent a)) +getMsgVarMessage (MsgVar m _) = return m ++-- | get the association array +getMsgVarData :: (Typeable a, Show a, Eq a) => (MsgVar a) -> Nomex (Maybe a) +getMsgVarData (MsgVar _ v) = readVar v ++getMsgVarData_ :: (Typeable a, Show a, Eq a) => (MsgVar a) -> Nomex a +getMsgVarData_ (MsgVar _ v) = readVar_ v++ -- * Variable arrays --- | ArrayVar is an indexed array with a signal attached to warn when the array is filled. --- | each indexed elements starts empty (value=Nothing), and when the array is full, the signal is triggered. --- | This is useful to wait for a serie of events to happen, and trigger a computation on the collected results. -data ArrayVar i a = ArrayVar (Msg [(i, Maybe a)]) (V (Map i (Maybe a))) +-- | ArrayVar is an indexed array with a signal attached triggered at every change. +-- | each indexed elements starts empty (value=Nothing). +type ArrayVar i a = MsgVar [(i, Maybe a)] -- | initialize an empty ArrayVar -newArrayVar :: (Ord i, Typeable a, Show a, Eq a, Typeable i, Show i) => VarName -> [i] -> Nomex (ArrayVar i a) +newArrayVar :: (Typeable a, Show a, Eq a, Typeable i, Show i, Eq i) => VarName -> [i] -> Nomex (Maybe (ArrayVar i a)) newArrayVar name l = do let list = map (\i -> (i, Nothing)) l - v <- newVar_ name (fromList list) - return $ ArrayVar (Message name) v + newMsgVar name list++newArrayVar_ :: (Typeable a, Show a, Eq a, Typeable i, Show i, Eq i) => VarName -> [i] -> Nomex (ArrayVar i a) +newArrayVar_ name l = partial "newArrayVar_: Variable existing" (newArrayVar name l) --- | initialize an empty ArrayVar, registering a callback that will be triggered when the array is filled -newArrayVar' :: (Ord i, Typeable a, Show a, Eq a, Typeable i, Show i) => VarName -> [i] -> ([(i,Maybe a)] -> Nomex ()) -> Nomex (ArrayVar i a) -newArrayVar' name l f = do - av@(ArrayVar m _) <- newArrayVar name l - onMessage m $ f . messageData - return av +-- | initialize an empty ArrayVar, registering a callback that will be triggered at every change +newArrayVar' :: (Typeable a, Show a, Eq a, Typeable i, Show i, Eq i) => VarName -> [i] -> (VEvent [(i,Maybe a)] -> Nomex ()) -> Nomex (Maybe (ArrayVar i a)) +newArrayVar' name l f = do+ let list = map (\i -> (i, Nothing)) l + newMsgVar' name list f -- | initialize an empty ArrayVar, registering a callback. ---the callback will be triggered when the array is filled, and then the ArrayVar will be deleted -newArrayVarOnce :: (Ord i, Typeable a, Show a, Eq a, Typeable i, Show i) => VarName -> [i] -> ([(i, Maybe a)] -> Nomex ()) -> Nomex (ArrayVar i a) +-- the ArrayVar will be deleted when full +newArrayVarOnce :: (Ord i, Typeable a, Show a, Eq a, Typeable i, Show i) => VarName -> [i] -> (VEvent [(i, Maybe a)] -> Nomex ()) -> Nomex (Maybe (ArrayVar i a)) newArrayVarOnce name l f = do - av@(ArrayVar m _) <- newArrayVar name l - onMessage m $ \a -> do - f $ messageData a - full <- (isFullArrayVar av) - when full $ delArrayVar av - return av where - + mv <- newArrayVar' name l f+ when (isJust mv) $ cleanOnFull $ fromJust mv + return mv++cleanOnFull :: (Typeable a, Show a, Eq a, Ord i, Typeable i, Show i) => (ArrayVar i a) -> Nomex ()+cleanOnFull ar = do+ m <- getMsgVarMessage ar + onMessage m $ \_ -> do + full <- (isFullArrayVar_ ar) + when full $ void $ delMsgVar ar+ return ()+ return () -isFullArrayVar :: (Ord i, Typeable a, Show a, Eq a, Typeable i, Show i) => (ArrayVar i a) -> Nomex (Bool) -isFullArrayVar av = do - d <- getArrayVarData av - let full = and $ map isJust $ map snd d - return full +isFullArrayVar_ :: (Ord i, Typeable a, Show a, Eq a, Typeable i, Show i) => (ArrayVar i a) -> Nomex Bool +isFullArrayVar_ av = do + md <- getMsgVarData av+ return $ and $ map isJust $ map snd $ fromJust md + -- | store one value and the given index. If this is the last filled element, the registered callbacks are triggered. -putArrayVar :: (Ord i, Typeable a, Show a, Eq a, Typeable i, Show i) => (ArrayVar i a) -> i -> a -> Nomex () -putArrayVar (ArrayVar m v) i a = do - ar <- readVar_ v - let ar2 = M.insert i (Just a) ar - writeVar_ v ar2 - sendMessage m (toList ar2) +putArrayVar :: (Ord i, Typeable a, Show a, Eq a, Typeable i, Show i) => (ArrayVar i a) -> i -> a -> Nomex Bool +putArrayVar mv i a = do + ma <- readMsgVar mv+ case ma of+ Just ar -> do+ let ar2 = M.insert i (Just a) (fromList ar) + writeMsgVar mv (toList ar2)+ Nothing -> return False++putArrayVar_ :: (Ord i, Typeable a, Show a, Eq a, Typeable i, Show i) => (ArrayVar i a) -> i -> a -> Nomex () +putArrayVar_ mv i a = void $ putArrayVar mv i a --- | get the messsage triggered when the array is filled -getArrayVarMessage :: (Ord i, Typeable a, Show a, Eq a, Typeable i, Show i) => (ArrayVar i a) -> Nomex (Msg [(i, Maybe a)]) -getArrayVarMessage (ArrayVar m _) = return m + --- | get the association array -getArrayVarData :: (Ord i, Typeable a, Show a, Eq a, Typeable i, Show i) => (ArrayVar i a) -> Nomex ([(i, Maybe a)]) -getArrayVarData (ArrayVar _ v) = toList <$> (readVar_ v) --- | get the association array with only the filled values -getArrayVarData' :: (Ord i, Typeable a, Show a, Eq a, Typeable i, Show i) => (ArrayVar i a) -> Nomex ([(i, a)]) -getArrayVarData' v = catMaybes . map sndMaybe <$> (getArrayVarData v) - -delArrayVar :: (Ord i, Typeable a, Show a, Eq a, Typeable i, Show i) => (ArrayVar i a) -> Nomex () -delArrayVar (ArrayVar m v) = delAllEvents m >> delVar_ v - -- * Events -- | register a callback on an event @@ -287,62 +347,122 @@ -- * Inputs - -inputChoice :: (Eq c, Show c) => PlayerNumber -> String -> [c] -> c -> Event (InputChoice c) -inputChoice = InputChoice +++-- ** Radio inputs -inputChoiceHead :: (Eq c, Show c) => PlayerNumber -> String -> [c] -> Event (InputChoice c) -inputChoiceHead pn title choices = inputChoice pn title choices (head choices) +inputRadio :: (Eq c, Show c, Typeable c) => PlayerNumber -> String -> [c] -> c -> Event (Input c) +inputRadio pn title cs _ = InputEv (Input pn title (Radio (zip cs (show <$> cs)))) -inputChoiceEnum :: forall c. (Enum c, Bounded c, Typeable c, Eq c, Show c) => PlayerNumber -> String -> c -> Event (InputChoice c) -inputChoiceEnum pn title defaultChoice = inputChoice pn title (enumFrom (minBound::c)) defaultChoice +inputRadioHead :: (Eq c, Show c, Typeable c) => PlayerNumber -> String -> [c] -> Event (Input c) +inputRadioHead pn title choices = inputRadio pn title choices (head choices) -inputString :: PlayerNumber -> String -> Event InputString -inputString = InputString +inputRadioEnum :: forall c. (Enum c, Bounded c, Typeable c, Eq c, Show c) => PlayerNumber -> String -> c -> Event (Input c) +inputRadioEnum pn title defaultChoice = inputRadio pn title (enumFrom (minBound::c)) defaultChoice ++inputRadioData :: (Show c) => EventData (Input c) -> c+inputRadioData (InputData (RadioData a)) = a+inputRadioData a = error $ "Not a Radio Data: " ++ (show a) -- | triggers a choice input to the user. The result will be sent to the callback -onInputChoice :: (Typeable a, Eq a, Show a) => String -> [a] -> (EventNumber -> a -> Nomex ()) -> PlayerNumber -> Nomex EventNumber -onInputChoice title choices handler pn = onEvent (inputChoiceHead pn title choices) (\(en, a) -> handler en (inputChoiceData a)) +onInputRadio :: (Typeable a, Eq a, Show a) => String -> [a] -> (EventNumber -> a -> Nomex ()) -> PlayerNumber -> Nomex EventNumber +onInputRadio title choices handler pn = onEvent (inputRadioHead pn title choices) (\(en, InputData (RadioData a)) -> handler en a) -- | the same, disregard the event number -onInputChoice_ :: (Typeable a, Eq a, Show a) => String -> [a] -> (a -> Nomex ()) -> PlayerNumber -> Nomex () -onInputChoice_ title choices handler pn = onEvent_ (inputChoiceHead pn title choices) (handler . inputChoiceData) +onInputRadio_ :: (Typeable a, Eq a, Show a) => String -> [a] -> (a -> Nomex ()) -> PlayerNumber -> Nomex () +onInputRadio_ title choices handler pn = onEvent_ (inputRadioHead pn title choices) (handler . inputRadioData) -- | the same, suppress the event after first trigger -onInputChoiceOnce :: (Typeable a, Eq a, Show a) => String -> [a] -> (a -> Nomex ()) -> PlayerNumber -> Nomex EventNumber -onInputChoiceOnce title choices handler pn = onEventOnce (inputChoiceHead pn title choices) (handler . inputChoiceData) +onInputRadioOnce :: (Typeable a, Eq a, Show a) => String -> [a] -> (a -> Nomex ()) -> PlayerNumber -> Nomex EventNumber +onInputRadioOnce title choices handler pn = onEventOnce (inputRadioHead pn title choices) (handler . inputRadioData) -- | the same, disregard the event number -onInputChoiceOnce_ :: (Typeable a, Eq a, Show a) => String -> [a] -> (a -> Nomex ()) -> PlayerNumber -> Nomex () -onInputChoiceOnce_ title choices handler pn = onEventOnce_ (inputChoiceHead pn title choices) (handler . inputChoiceData) +onInputRadioOnce_ :: (Typeable a, Eq a, Show a) => String -> [a] -> (a -> Nomex ()) -> PlayerNumber -> Nomex () +onInputRadioOnce_ title choices handler pn = onEventOnce_ (inputRadioHead pn title choices) (handler . inputRadioData) -- | triggers a choice input to the user, using an enumerate as input -onInputChoiceEnum :: forall a. (Enum a, Bounded a, Typeable a, Eq a, Show a) => String -> a -> (EventNumber -> a -> Nomex ()) -> PlayerNumber -> Nomex EventNumber -onInputChoiceEnum title defaultChoice handler pn = onEvent (inputChoiceEnum pn title defaultChoice) (\(en, a) -> handler en (inputChoiceData a)) +onInputRadioEnum :: forall a. (Enum a, Bounded a, Typeable a, Eq a, Show a) => String -> a -> (EventNumber -> a -> Nomex ()) -> PlayerNumber -> Nomex EventNumber +onInputRadioEnum title defaultChoice handler pn = onEvent (inputRadioEnum pn title defaultChoice) (\(en, a) -> handler en (inputRadioData a)) -- | the same, disregard the event number -onInputChoiceEnum_ :: forall a. (Enum a, Bounded a, Typeable a, Eq a, Show a) => String -> a -> (a -> Nomex ()) -> PlayerNumber -> Nomex () -onInputChoiceEnum_ title defaultChoice handler pn = onEvent_ (inputChoiceEnum pn title defaultChoice) (handler . inputChoiceData) +onInputRadioEnum_ :: forall a. (Enum a, Bounded a, Typeable a, Eq a, Show a) => String -> a -> (a -> Nomex ()) -> PlayerNumber -> Nomex () +onInputRadioEnum_ title defaultChoice handler pn = onEvent_ (inputRadioEnum pn title defaultChoice) (handler . inputRadioData) -- | the same, suppress the event after first trigger -onInputChoiceEnumOnce_ :: forall a. (Enum a, Bounded a, Typeable a, Eq a, Show a) => String -> a -> (a -> Nomex ()) -> PlayerNumber -> Nomex () -onInputChoiceEnumOnce_ title defaultChoice handler pn = onEventOnce_ (inputChoiceEnum pn title defaultChoice) (handler . inputChoiceData) +onInputRadioEnumOnce_ :: forall a. (Enum a, Bounded a, Typeable a, Eq a, Show a) => String -> a -> (a -> Nomex ()) -> PlayerNumber -> Nomex () +onInputRadioEnumOnce_ title defaultChoice handler pn = onEventOnce_ (inputRadioEnum pn title defaultChoice) (handler . inputRadioData) +-- ** Text inputs +inputText :: PlayerNumber -> String -> Event (Input String) +inputText pn title = InputEv (Input pn title Text)++inputTextData :: EventData (Input String) -> String+inputTextData (InputData (TextData a)) = a+inputTextData a = error $ "Not a Text Data: " ++ (show a)+ -- | triggers a string input to the user. The result will be sent to the callback -onInputString :: String -> (EventNumber -> String -> Nomex ()) -> PlayerNumber -> Nomex EventNumber -onInputString title handler pn = onEvent (inputString pn title) (\(en, a) -> handler en (inputStringData a)) +onInputText :: String -> (EventNumber -> String -> Nomex ()) -> PlayerNumber -> Nomex EventNumber +onInputText title handler pn = onEvent (inputText pn title) (\(en, a) -> handler en (inputTextData a)) -- | asks the player pn to answer a question, and feed the callback with this data. -onInputString_ :: String -> (String -> Nomex ()) -> PlayerNumber -> Nomex () -onInputString_ title handler pn = onEvent_ (inputString pn title) (handler . inputStringData) +onInputText_ :: String -> (String -> Nomex ()) -> PlayerNumber -> Nomex () +onInputText_ title handler pn = onEvent_ (inputText pn title) (handler . inputTextData) -- | asks the player pn to answer a question, and feed the callback with this data. -onInputStringOnce_ :: String -> (String -> Nomex ()) -> PlayerNumber -> Nomex () -onInputStringOnce_ title handler pn = onEventOnce_ (inputString pn title) (handler . inputStringData) +onInputTextOnce_ :: String -> (String -> Nomex ()) -> PlayerNumber -> Nomex () +onInputTextOnce_ title handler pn = onEventOnce_ (inputText pn title) (handler . inputTextData) ++-- ** Checkbox inputs++inputCheckboxData :: (Show c) => EventData (Input c) -> [c]+inputCheckboxData (InputData (CheckboxData a)) = a+inputCheckboxData a = error $ "Not a Checkbox Data: " ++ (show a)++inputCheckbox :: (Eq c, Show c, Typeable c) => PlayerNumber -> String -> [(c, String)] -> Event (Input c) +inputCheckbox pn title cs = InputEv (Input pn title (Checkbox cs))++onInputCheckbox :: (Typeable a, Eq a, Show a) => String -> [(a, String)] -> (EventNumber -> [a] -> Nomex ()) -> PlayerNumber -> Nomex EventNumber +onInputCheckbox title choices handler pn = onEvent (inputCheckbox pn title choices) (\(en, InputData (CheckboxData a)) -> handler en a)++onInputCheckbox_ :: (Typeable a, Eq a, Show a) => String -> [(a, String)] -> ([a] -> Nomex ()) -> PlayerNumber -> Nomex () +onInputCheckbox_ title choices handler pn = onEvent_ (inputCheckbox pn title choices) (handler . inputCheckboxData)++-- ** Button inputs++inputButtonData :: EventData (Input ()) -> ()+inputButtonData (InputData ButtonData) = ()+inputButtonData a = error $ "Not a Button Data: " ++ (show a)++inputButton :: PlayerNumber -> String -> Event (Input ()) +inputButton pn title = InputEv (Input pn title Button)++onInputButton :: String -> (EventNumber -> () -> Nomex ()) -> PlayerNumber -> Nomex EventNumber +onInputButton title handler pn = onEvent (inputButton pn title) (\(en, InputData ButtonData) -> handler en ())++onInputButton_ :: String -> (() -> Nomex ()) -> PlayerNumber -> Nomex () +onInputButton_ title handler pn = onEvent_ (inputButton pn title) (handler . inputButtonData)++-- ** Textarea inputs++inputTextareaData :: EventData (Input String) -> String+inputTextareaData (InputData (TextAreaData a)) = a+inputTextareaData a = error $ "Not a Textarea Data: " ++ (show a)++inputTextarea :: PlayerNumber -> String -> Event (Input String) +inputTextarea pn title = InputEv (Input pn title TextArea)++onInputTextarea :: String -> (EventNumber -> String -> Nomex ()) -> PlayerNumber -> Nomex EventNumber +onInputTextarea title handler pn = onEvent (inputTextarea pn title) (\(en, a) -> handler en (inputTextareaData a)) --- * Victory, players+onInputTextarea_ :: String -> (String -> Nomex ()) -> PlayerNumber -> Nomex () +onInputTextarea_ title handler pn = onEvent_ (inputTextarea pn title) (handler . inputTextareaData) +onInputTextareaOnce_ :: String -> (String -> Nomex ()) -> PlayerNumber -> Nomex () +onInputTextareaOnce_ title handler pn = onEventOnce_ (inputTextarea pn title) (handler . inputTextareaData)+ +-- * Players+ -- | get all the players getPlayers :: Nomex [PlayerInfo] getPlayers = GetPlayers @@ -382,10 +502,50 @@ delPlayer :: PlayerNumber -> Nomex Bool delPlayer = DelPlayer +-- * Outputs+ +-- | outputs a message to one player +newOutput :: String -> PlayerNumber -> Nomex OutputNumber +newOutput s pn = NewOutput pn s +newOutput_ :: String -> PlayerNumber -> Nomex () +newOutput_ s pn = void $ NewOutput pn s --- * Victory, output, time and self-number +outputAll :: String -> Nomex () +outputAll s = getPlayers >>= mapM_ ((newOutput s) . _playerNumber) ++updateOutput :: OutputNumber -> String -> Nomex Bool+updateOutput = UpdateOutput++updateOutput_ :: OutputNumber -> String -> Nomex ()+updateOutput_ on s = void $ updateOutput on s++delOutput :: OutputNumber -> Nomex Bool+delOutput = DelOutput++delOutput_ :: OutputNumber -> Nomex ()+delOutput_ on = void $ delOutput on++-- permanently display a variable (update display when variable is updated)+displayVar :: (Typeable a, Show a, Eq a) => PlayerNumber -> MsgVar a -> (a -> String) -> Nomex ()+displayVar pn mv dis = onMsgVarEvent+ mv+ (\a -> newOutput (dis a) pn)+ (\a n -> updateOutput_ n (dis a))+ delOutput_++displaySimpleVar :: (Typeable a, Show a, Eq a) => PlayerNumber -> String -> MsgVar a -> Nomex ()+displaySimpleVar pn title mv = displayVar pn mv (\a -> title ++ ": " ++ (show a) ++ "\n")++displayArrayVar :: (Typeable a, Show a, Eq a, Typeable i, Show i, Eq i) => PlayerNumber -> String -> ArrayVar i a -> Nomex ()+displayArrayVar pn title mv = displayVar pn mv (showArrayVar title)++showArrayVar :: (Show a, Show i) => String -> [(i,a)] -> String+showArrayVar title l = title ++ "\n" +++ concatMap (\(i,a) -> (show i) ++ "\t" ++ (show a) ++ "\n") l +-- * Victory, time and self-number + -- | set victory to a list of players setVictory :: [PlayerNumber] -> Nomex () setVictory = SetVictory @@ -394,17 +554,10 @@ giveVictory :: PlayerNumber -> Nomex () giveVictory pn = SetVictory [pn] --- | outputs a message to one player -output :: String -> PlayerNumber -> Nomex () -output s pn = Output pn s - -outputAll :: String -> Nomex () -outputAll s = getPlayers >>= mapM_ ((output s) . _playerNumber) - getCurrentTime :: Nomex UTCTime getCurrentTime = CurrentTime --- | allows a rule to retrieve its self number (for auto-deleting for example) +-- | allows a rule to retrieve its own number (for auto-deleting for example) getSelfRuleNumber :: Nomex RuleNumber getSelfRuleNumber = SelfRuleNumber @@ -416,11 +569,9 @@ getSelfProposedByPlayer :: Nomex PlayerNumber getSelfProposedByPlayer = getSelfRule >>= return . _rProposedBy - + -- * Miscellaneous - - voidRule :: Nomex a -> Nomex RuleResp voidRule e = e >> return Void @@ -453,8 +604,16 @@ let m = Message ((show a) ++ " &&* " ++ (show b)) newArrayVarOnce ((show a) ++ ", " ++ (show b)) [1::Integer, 2] (f m) return m where - f m ((_, Just a):(_, Just b):[]) = sendMessage m $ a && b+ f m (VUpdated ((_, Just a):(_, Just b):[])) = sendMessage m $ a && b f _ _ = return ()+++partial :: String -> Nomex (Maybe a) -> Nomex a+partial s nm = do+ m <- nm+ case m of+ Just a -> return a+ Nothing -> throwError s -- | a default rule
src/Language/Nomyx/Evaluation.hs view
@@ -2,7 +2,7 @@ module Language.Nomyx.Evaluation where -import Prelude hiding ((.))+import Prelude hiding ((.), log) import Language.Nomyx.Utils import Control.Monad import Control.Monad.State.Lazy@@ -14,11 +14,9 @@ import Control.Category import Control.Monad.Error (ErrorT(..)) import Control.Monad.Error.Class (MonadError(..))-import Language.Nomyx.Definition (outputAll) import Control.Applicative ((<$>)) import Language.Nomyx.Expression - type Evaluate a = ErrorT String (State Game) a -- | evaluate an expression.@@ -32,7 +30,6 @@ return $ Just (V name) Just _ -> return Nothing - evalExp (DelVar (V name)) _ = do vars <- access variables case find ((== name) . getL vName) vars of@@ -50,19 +47,18 @@ Just v -> return $ Just v Nothing -> return Nothing -evalExp (WriteVar (V name) val) rn = do+evalExp (WriteVar (V name) val) _ = do vars <- access variables- let newVars = replaceWith ((== name) . getL vName) (Var rn name val) vars case find (\(Var _ myName _) -> myName == name) vars of Nothing -> return False- Just _ -> do- variables ~= newVars+ Just (Var rn myName _) -> do+ variables %= replaceWith ((== name) . getL vName) (Var rn myName val) return True evalExp (OnEvent event handler) rn = do evs <- access events let en = getFreeNumber (map _eventNumber evs)- events %= ((EH en rn event handler EvActive) : )+ events %= ((EH en rn event handler SActive) : ) return en evalExp (DelEvent en) _ = evDelEvent en@@ -70,17 +66,17 @@ evalExp (DelAllEvents e) _ = do evs <- access events let filtered = filter (\EH {event} -> event === e) evs- --traceM ("DelAllEvents: deleting " ++ show filtered) mapM_ (\e -> evDelEvent e) (_eventNumber <$> filtered) evalExp (SendMessage (Message id) myData) _ = triggerEvent_ (Message id) (MessageData myData) -evalExp (Output pn string) _ = outputS pn string >> return ()+evalExp (NewOutput pn s) rn = evNewOutput pn rn s+evalExp (UpdateOutput on s) _ = evUpdateOutput on s+evalExp (DelOutput on) _ = evDelOutput on evalExp (ProposeRule rule) _ = evProposeRule rule evalExp (ActivateRule rule) rn = evActivateRule rule rn evalExp (RejectRule rule) rn = evRejectRule rule rn evalExp (AddRule rule) _ = evAddRule rule-evalExp (DelRule del) _ = evDelRule del evalExp (ModifyRule mod rule) _ = evModifyRule mod rule evalExp GetRules _ = access rules evalExp GetPlayers _ = access players@@ -97,8 +93,6 @@ let victorious = filter (\pl -> _playerNumber pl `elem` ps) pls triggerEvent_ Victory (VictoryData victorious) -- evalExp (Bind exp f) rn = do a <- evalExp exp rn evalExp (f a) rn@@ -108,36 +102,42 @@ triggerEvent :: (Typeable e, Show e, Eq e) => Event e -> EventData e -> Evaluate Bool triggerEvent e dat = do evs <- access events- let filtered = filter (\(EH {event, _evStatus}) -> e === event && _evStatus == EvActive) evs+ let filtered = filter (\(EH {event, _evStatus}) -> e === event && _evStatus == SActive) (reverse evs) case filtered of- [] -> do- --traceM $ "triggerEvent: Event not found:" ++ (show e)- return False+ [] -> return False xs -> do- mapM_ f xs- return True where- f (EH {_ruleNumber, _eventNumber, handler}) = case cast handler of- Just castedH -> do- let (exp :: Nomex ()) = castedH (_eventNumber, dat)- evalExp (exp `catchError` errorHandler) _ruleNumber- Nothing -> outputS 1 ("failed " ++ (show $ typeOf handler))+ mapM_ (triggerHandler dat) xs+ return True ++triggerHandler :: (Typeable e, Show e, Eq e) => EventData e -> EventHandler -> Evaluate ()+triggerHandler dat (EH {_ruleNumber, _eventNumber, handler}) = case cast handler of+ Just castedH -> do+ let (exp :: Nomex ()) = castedH (_eventNumber, dat)+ (evalExp exp _ruleNumber) `catchError` (errorHandler _ruleNumber _eventNumber)+ Nothing -> logAll ("failed " ++ (show $ typeOf handler))+ triggerEvent_ :: (Typeable e, Show e, Eq e) => Event e -> EventData e -> Evaluate () triggerEvent_ e ed = void $ triggerEvent e ed -errorHandler :: String -> Nomex ()-errorHandler s = outputAll $ "Error: " ++ s+errorHandler :: RuleNumber -> EventNumber -> String -> Evaluate ()+errorHandler rn en s = logAll $ "Error in rule " ++ (show rn) ++ " (triggered by event " ++ (show en) ++ "): " ++ s -triggerChoice :: EventNumber -> Int -> Evaluate ()-triggerChoice en choiceIndex = do+-- trigger the input event with the input data+triggerInput :: EventNumber -> UInputData -> Evaluate ()+triggerInput en ir = do evs <- access events let filtered = filter ((== en) . getL eventNumber) evs- mapM_ (execChoiceHandler en choiceIndex) filtered--execChoiceHandler :: EventNumber -> Int -> EventHandler -> Evaluate ()-execChoiceHandler eventNumber choiceIndex (EH _ rn (InputChoice _ _ cs _) handler _) = evalExp (handler (eventNumber, InputChoiceData (cs!!choiceIndex))) rn-execChoiceHandler _ _ _ = return ()+ mapM_ (execInputHandler ir) filtered +-- execute the event handler using the data received from user+execInputHandler :: UInputData -> EventHandler -> Evaluate ()+execInputHandler (UTextData s) (EH en rn (InputEv (Input _ _ Text)) h SActive) = evalExp (h (en, InputData $ TextData s)) rn+execInputHandler (UTextAreaData s) (EH en rn (InputEv (Input _ _ TextArea)) h SActive) = evalExp (h (en, InputData $ TextAreaData s)) rn+execInputHandler (UButtonData) (EH en rn (InputEv (Input _ _ Button)) h SActive) = evalExp (h (en, InputData $ ButtonData)) rn+execInputHandler (URadioData i) (EH en rn (InputEv (Input _ _ (Radio cs))) h SActive) = evalExp (h (en, InputData $ RadioData $ fst $ cs!!i)) rn+execInputHandler (UCheckboxData is) (EH en rn (InputEv (Input _ _ (Checkbox cs))) h SActive) = evalExp (h (en, InputData $ CheckboxData $ fst <$> cs `sel` is)) rn+execInputHandler _ _ = return () findEvent :: EventNumber -> [EventHandler] -> Maybe (EventHandler) findEvent en evs = find ((== en) . getL eventNumber) evs@@ -146,11 +146,9 @@ getChoiceEvents = do evs <- access events return $ map _eventNumber $ filter choiceEvent evs- where choiceEvent (EH _ _ (InputChoice _ _ _ _) _ _) = True+ where choiceEvent (EH _ _ (InputEv (Input _ _ (Radio _))) _ _) = True choiceEvent _ = False -outputS :: PlayerNumber -> String -> Evaluate ()-outputS pn s = void $ outputs %= ((pn, s) : ) evProposeRule :: Rule -> Evaluate Bool evProposeRule rule = do@@ -166,7 +164,7 @@ evActivateRule :: RuleNumber -> RuleNumber -> Evaluate Bool evActivateRule rn by = do rs <- access rules- case find ((== rn) . getL rNumber) rs of+ case find (\r -> _rNumber r == rn && _rStatus r /= Active) rs of Nothing -> return False Just r -> do let newrules = replaceWith ((== rn) . getL rNumber) r{_rStatus = Active, _rAssessedBy = Just by} rs@@ -179,7 +177,7 @@ evRejectRule :: RuleNumber -> RuleNumber -> Evaluate Bool evRejectRule rn by = do rs <- access rules- case find ((== rn) . getL rNumber) rs of+ case find (\r -> _rNumber r == rn && _rStatus r /= Reject) rs of Nothing -> return False Just r -> do let newrules = replaceWith ((== rn) . getL rNumber) r{_rStatus = Reject, _rAssessedBy = Just by} rs@@ -199,18 +197,6 @@ return True Just _ -> return False -evDelRule :: RuleNumber -> Evaluate Bool-evDelRule del = do- rs <- access rules- case find ((== del) . getL rNumber) rs of- Nothing -> return False- Just r -> do- let newRules = filter ((/= del) . getL rNumber) rs- rules ~= newRules- delVarsRule del- delEventsRule del- triggerEvent_ (RuleEv Deleted) (RuleData r)- return True --TODO: clean and execute new rule evModifyRule :: RuleNumber -> Rule -> Evaluate Bool@@ -265,17 +251,15 @@ return False Just eh -> do case (_evStatus eh) of- EvActive -> do+ SActive -> do --traceM ("DelEvent: deleting event en=" ++ (show en) ++ " rn=" ++ (show rn))- let newEvents = replaceWith ((== en) . getL eventNumber) eh{_evStatus = EvDeleted} evs+ let newEvents = replaceWith ((== en) . getL eventNumber) eh{_evStatus = SDeleted} evs events ~= newEvents return True- EvDeleted -> do+ SDeleted -> do --traceM ("DelEvent: Event already deleted! en=" ++ (show en) ++ "rn event=" ++ (show $ _ruleNumber eh) ++ " rn=" ++ (show rn)) return False -evInputChoice :: (Eq d, Show d, Typeable d, Read d) => Event(InputChoice d) -> d -> Evaluate Bool-evInputChoice ic d = triggerEvent ic (InputChoiceData d) evTriggerTime :: UTCTime -> Evaluate Bool evTriggerTime t = triggerEvent (Time t) (TimeData t)@@ -292,6 +276,50 @@ let toDelete = filter ((== rn) . getL ruleNumber) evs mapM_ (evDelEvent . _eventNumber) toDelete ++evNewOutput :: PlayerNumber -> RuleNumber -> String -> Evaluate OutputNumber+evNewOutput pn rn s = do+ ops <- access outputs+ let on = getFreeNumber (map _outputNumber ops)+ outputs %= ((Output on rn pn s SActive) : )+ return on++evUpdateOutput :: OutputNumber -> String -> Evaluate Bool+evUpdateOutput on s = do+ ops <- access outputs+ case find (\(Output myOn _ _ _ s) -> myOn == on && s == SActive) ops of+ Nothing -> return False+ Just (Output _ rn pn _ _) -> do+ outputs %= replaceWith ((== on) . getL outputNumber) (Output on rn pn s SActive)+ return True++evDelOutput :: OutputNumber -> Evaluate Bool+evDelOutput on = do+ ops <- access outputs+ case find ((== on) . getL outputNumber) ops of+ Nothing -> do+ return False+ Just o -> do+ case (_oStatus o) of+ SActive -> do+ let newOutputs = replaceWith ((== on) . getL outputNumber) o{_oStatus = SDeleted} ops+ outputs ~= newOutputs+ return True+ SDeleted -> do+ return False++logPlayer :: PlayerNumber -> String -> Evaluate ()+logPlayer pn s = log (Just pn) s++logAll :: String -> Evaluate ()+logAll s = log Nothing s++log :: Maybe PlayerNumber -> String -> Evaluate ()+log mpn s = do+ time <- access currentTime+ void $ logs %= (Log mpn time s : )++ runEvalError :: PlayerNumber -> Evaluate () -> State Game () runEvalError pn egs = do e <- runErrorT egs@@ -299,4 +327,4 @@ Right gs -> return gs Left e -> do tracePN pn $ "Error: " ++ e- void $ outputs %= ((pn, "Error: " ++ e) : )+ void $ runErrorT (logPlayer pn "Error: ")
src/Language/Nomyx/Examples.hs view
@@ -7,7 +7,8 @@ module Language.Nomyx.Examples(nothing, helloWorld, accounts, createBankAccount, winXEcuPerDay, winXEcuOnRuleAccepted, moneyTransfer, delRule, voteWithMajority, king, makeKing, monarchy, revolution, victoryXRules, victoryXEcu, displayTime, noGroupVictory, iWin, returnToDemocracy,- banPlayer, referendum, referendumOnKickPlayer, gameMasterElections, gameMaster,+ banPlayer, referendum, referendumOnKickPlayer, gameMasterElections, gameMaster, bravoButton,+ enterHaiku, module Data.Time.Recurrence, module Control.Monad, module Data.List, module Data.Time.Clock) where import Language.Nomyx.Definition@@ -22,6 +23,7 @@ import Language.Nomyx.Vote (elections, referendum, assessOnTimeDelay, assessOnEveryVote, withQuorum, majority, voteWith_) import Language.Nomyx.Utils (oneDay)+import Safe (readDef) -- | A rule that does nothing nothing :: RuleFunc@@ -54,13 +56,13 @@ moneyTransfer = voidRule $ do pls <- getAllPlayerNumbers when (length pls >= 2) $ forEachPlayer_ (selPlayer pls) where- selPlayer pls src = onInputChoice_ "Transfer money to player: " (delete src $ sort pls) (selAmount src) src- selAmount src dst = onInputStringOnce_ ("Select Amount to transfert to player: " ++ show dst) (transfer src dst) src+ selPlayer pls src = onInputRadio_ "Transfer money to player: " (delete src $ sort pls) (selAmount src) src+ selAmount src dst = onInputTextOnce_ ("Select Amount to transfert to player: " ++ show dst) (transfer src dst) src transfer src dst amount = do- modifyValueOfPlayer dst accounts (\a -> a + (read amount))- modifyValueOfPlayer src accounts (\a -> a - (read amount))- output ("You gave " ++ amount ++ " to " ++ show dst) src- output (show src ++ " gaved you " ++ amount ++ " Ecus") dst+ modifyValueOfPlayer dst accounts (\a -> a + (readDef 0 amount))+ modifyValueOfPlayer src accounts (\a -> a - (readDef 0 amount))+ newOutput_ ("You gave " ++ amount ++ " to " ++ show dst) src+ newOutput_ (show src ++ " gaved you " ++ amount ++ " Ecus") dst -- | delete a rule@@ -81,7 +83,7 @@ monarchy :: RuleFunc monarchy = voidRule $ onEvent_ (RuleEv Proposed) $ \(RuleData rule) -> do k <- readVar_ king- onInputChoiceEnumOnce_ ("Your Royal Highness, do you accept rule " ++ (show $ _rNumber rule) ++ "?") True (activateOrReject rule) k+ onInputRadioEnumOnce_ ("Your Royal Highness, do you accept rule " ++ (show $ _rNumber rule) ++ "?") True (activateOrReject rule) k -- | Revolution! Hail to the king!@@ -165,3 +167,10 @@ gameMaster :: V PlayerNumber gameMaster = V "GameMaster"++-- | display a button and greets you when pressed (for player 1)+bravoButton :: RuleFunc+bravoButton = voidRule $ voidRule $ onInputButton_ "Click here:" (const $ outputAll "Bravo!") 1++enterHaiku :: RuleFunc+enterHaiku = voidRule $ onInputTextarea_ "Enter a haiku:" outputAll 1
src/Language/Nomyx/Expression.hs view
@@ -34,8 +34,10 @@ type EventName = String type VarName = String type GameName = String -type Code = String +type Code = String+type OutputNumber = Int + -- * Nomyx Expression -- | A Nomex (Nomyx Expression) allows the players to write rules.@@ -57,16 +59,18 @@ ActivateRule :: RuleNumber -> Nomex Bool RejectRule :: RuleNumber -> Nomex Bool AddRule :: Rule -> Nomex Bool - DelRule :: RuleNumber -> Nomex Bool ModifyRule :: RuleNumber -> Rule -> Nomex Bool GetRules :: Nomex [Rule] --Players management GetPlayers :: Nomex [PlayerInfo] SetPlayerName:: PlayerNumber -> PlayerName -> Nomex Bool DelPlayer :: PlayerNumber -> Nomex Bool+ --Output+ NewOutput :: PlayerNumber -> String -> Nomex OutputNumber+ UpdateOutput :: OutputNumber -> String -> Nomex Bool+ DelOutput :: OutputNumber -> Nomex Bool --Mileacenous SetVictory :: [PlayerNumber] -> Nomex () - Output :: PlayerNumber -> String -> Nomex () CurrentTime :: Nomex UTCTime SelfRuleNumber :: Nomex RuleNumber --Monadic bindings@@ -75,7 +79,6 @@ ThrowError :: String -> Nomex a CatchError :: Nomex a -> (String -> Nomex a) -> Nomex a deriving (Typeable) - instance Monad Nomex where return = Return @@ -95,10 +98,10 @@ throwError = ThrowError catchError = CatchError -instance Show a => Show (Nomex a) where - show _ = "Nomex" -- ++ (show a) +instance Typeable a => Show (Nomex a) where + show e = '<' : (show . typeOf) e ++ ">" - + -- * Variables -- | a container for a variable name and type @@ -106,19 +109,16 @@ -- | stores the variable's data data Var = forall a . (Typeable a, Show a, Eq a) => - Var { _vRuleNumber :: Int, - _vName :: String, - vData :: a} + Var { _vRuleNumber :: RuleNumber, + _vName :: String, + vData :: a} instance Show Var where - show (Var a b c) = (show a) ++ " " ++ (show b) ++ " " ++ (show c) + show (Var a b c) = "Rule number = " ++ (show a) ++ ", Name = " ++ (show b) ++ ", Value = " ++ (show c) ++ "\n" instance Eq Var where Var a b c == Var d e f = (a,b,c) === (d,e,f) -type Output = (PlayerNumber, String) - -type Id a = a -- * Events -- | events types @@ -127,48 +127,67 @@ data Time deriving Typeable data EvRule deriving Typeable data Message m deriving Typeable -data InputChoice c deriving Typeable -data InputString deriving Typeable -data Victory deriving Typeable +data Victory deriving Typeable+data Input a = Input PlayerNumber String (InputForm a)+data InputForm a = Radio [(a, String)]+ | Text+ | TextArea+ | Button+ | Checkbox [(a, String)] -- | events names data Event a where - Player :: Player -> Event Player - RuleEv :: RuleEvent -> Event RuleEvent - Time :: UTCTime -> Event Time - Message :: String -> Event (Message m) - InputChoice :: (Eq c, Show c) => PlayerNumber -> String -> [c] -> c -> Event (InputChoice c) - InputString :: PlayerNumber -> String -> Event InputString - Victory :: Event Victory - + Player :: Player -> Event Player + RuleEv :: RuleEvent -> Event RuleEvent + Time :: UTCTime -> Event Time + Message :: String -> Event (Message m) + InputEv :: (Eq a, Show a, Typeable a) => Input a -> Event (Input a) + Victory :: Event Victory ++-- data sent back by inputs+data InputData a = RadioData a+ | CheckboxData [a]+ | TextData String+ | TextAreaData String+ | ButtonData+-- an untyped version of InputData for serialization+data UInputData = URadioData Int+ | UCheckboxData [Int]+ | UTextData String+ | UTextAreaData String+ | UButtonData+ deriving (Show, Read, Eq, Ord)+ -- | data associated with each events data EventData a where - PlayerData :: {playerData :: PlayerInfo} -> EventData Player - RuleData :: {ruleData :: Rule} -> EventData RuleEvent - TimeData :: {timeData :: UTCTime} -> EventData Time - MessageData :: (Show m) => {messageData :: m} -> EventData (Message m) - InputChoiceData :: (Show c) => {inputChoiceData :: c} -> EventData (InputChoice c) - InputStringData :: {inputStringData :: String} -> EventData InputString - VictoryData :: {victoryData :: [PlayerInfo]} -> EventData Victory + PlayerData :: {playerData :: PlayerInfo} -> EventData Player + RuleData :: {ruleData :: Rule} -> EventData RuleEvent + TimeData :: {timeData :: UTCTime} -> EventData Time + MessageData :: (Show m) => {messageData :: m} -> EventData (Message m) + InputData :: (Show a) => {inputData :: InputData a} -> EventData (Input a) + VictoryData :: {victoryData :: [PlayerInfo]} -> EventData Victory deriving instance Typeable1 EventData -deriving instance Typeable1 Event -deriving instance (Show a) => Show (Event a) +deriving instance Typeable1 Event+deriving instance Typeable1 Input+deriving instance Typeable1 InputForm +deriving instance (Show a) => Show (Event a)+deriving instance (Show a) => Show (InputForm a)+deriving instance (Show a) => Show (Input a) deriving instance (Show a) => Show (EventData a)+deriving instance (Show a) => Show (InputData a) deriving instance (Show a) => Show (Message a) -deriving instance (Show a) => Show (InputChoice a) deriving instance Show Time -deriving instance Show InputString deriving instance Show Victory deriving instance Eq Time deriving instance Eq Victory deriving instance Eq EvRule -deriving instance Eq (InputChoice a) -deriving instance Eq InputString deriving instance Eq (Message m) -deriving instance (Eq e) => Eq (Event e) +deriving instance (Eq e) => Eq (Event e)+deriving instance (Eq e) => Eq (Input e)+deriving instance (Eq e) => Eq (InputForm e) -data EventStatus = EvActive | EvDeleted deriving (Eq, Show)+data Status = SActive | SDeleted deriving (Eq, Show) data EventHandler where EH :: (Typeable e, Show e, Eq e) => @@ -176,7 +195,7 @@ _ruleNumber :: RuleNumber, event :: Event e, handler :: (EventNumber, EventData e) -> Nomex (),- _evStatus :: EventStatus} -> EventHandler + _evStatus :: Status} -> EventHandler instance Show EventHandler where show (EH en rn e _ _) = (show en) ++ " " ++ (show rn) ++ " (" ++ (show e) ++"),\n" @@ -189,6 +208,22 @@ type Msg a = Event (Message a) type MsgData a = EventData (Message a)++-- * Outputs++data Output = Output { _outputNumber :: OutputNumber,+ _oRuleNumber :: PlayerNumber,+ _oPlayerNumber :: PlayerNumber,+ _output :: String,+ _oStatus :: Status}+ deriving (Show)++-- * Logs++data Log = Log { _lPlayerNumber :: Maybe PlayerNumber,+ _lTime :: UTCTime,+ _lMsg :: String}+ deriving (Show) -- * Rule @@ -204,7 +239,6 @@ --An extended type for booleans supporting immediate or delayed response (through a message) data BoolResp = BoolResp Bool | MsgResp (Msg Bool) - instance Show RuleResp where show _ = "RuleResp" @@ -242,18 +276,20 @@ _playerName :: String} deriving (Eq, Typeable, Show) --- * Game +-- * Game+ -- | The state of the game: -data Game = Game { _gameName :: GameName, - _gameDesc :: GameDesc, - _rules :: [Rule], - _players :: [PlayerInfo], - _variables :: [Var], - _events :: [EventHandler], - _outputs :: [Output], - _victory :: [PlayerNumber], - _currentTime :: UTCTime+data Game = Game { _gameName :: GameName, + _gameDesc :: GameDesc, + _rules :: [Rule], + _players :: [PlayerInfo], + _variables :: [Var], + _events :: [EventHandler], + _outputs :: [Output], + _victory :: [PlayerNumber],+ _logs :: [Log], + _currentTime :: UTCTime } deriving (Typeable) @@ -272,31 +308,31 @@ Punc "{" <- lexP; Ident "_gameName" <- lexP; Punc "=" <- lexP;- a1 <- reset readPrec;+ name <- reset readPrec; Punc "," <- lexP; Ident "_gameDesc" <- lexP; Punc "=" <- lexP;- a2 <- reset readPrec;+ desc <- reset readPrec; Punc "," <- lexP; Ident "_currentTime" <- lexP; Punc "=" <- lexP;- a3 <- reset readPrec;+ time <- reset readPrec; Punc "}" <- lexP;- return $ Game a1 a2 [] [] [] [] [] [] a3+ return $ Game name desc [] [] [] [] [] [] [] time readList = readListDefault readListPrec = readListPrecDefault instance Show Game where- showsPrec p(Game b1 b2 _ _ _ _ _ _ b3) = showParen (p >= 11) $+ showsPrec p(Game name desc _ _ _ _ _ _ _ time) = showParen (p >= 11) $ showString "Game {" . showString "_gameName = " .- showsPrec 0 b1 .+ showsPrec 0 name . showString ", " . showString "_gameDesc = " .- showsPrec 0 b2 .+ showsPrec 0 desc . showString ", " . showString "_currentTime = " .- showsPrec 0 b3 .+ showsPrec 0 time . showString "}" showList = showList__ (showsPrec 0) @@ -305,5 +341,5 @@ "Game Name = " ++ (show _gameName) ++ "\n Rules = " ++ (concat $ intersperse "\n " $ map show _rules) ++ "\n Players = " ++ (show _players) ++ "\n Variables = " ++ (show _variables) ++ "\n Events = " ++ (show _events) ++ "\n Outputs = " ++ (show _outputs) ++ "\n Victory = " ++ (show _victory) ++ "\n currentTime = " ++ (show _currentTime) ++ "\n" -$( makeLenses [''Game, ''GameDesc, ''Rule, ''PlayerInfo, ''EventHandler, ''Var] ) +$( makeLenses [''Game, ''GameDesc, ''Rule, ''PlayerInfo, ''EventHandler, ''Var, ''Output] )
src/Language/Nomyx/Game.hs view
@@ -1,5 +1,5 @@ {-# LANGUAGE StandaloneDeriving, GADTs, DeriveDataTypeable,- FlexibleContexts, GeneralizedNewtypeDeriving,+ FlexibleContexts, GeneralizedNewtypeDeriving, ScopedTypeVariables, MultiParamTypeClasses, TemplateHaskell, TypeFamilies, TypeOperators, FlexibleInstances, NoMonomorphismRestriction, TypeSynonymInstances, DoAndIfThenElse, RecordWildCards #-}@@ -8,9 +8,10 @@ -- a game is a set of rules, and results of actions made by players (usually vote results) -- the module manages the effects of rules over each others. module Language.Nomyx.Game (GameEvent(..), update, update', LoggedGame(..), game, gameLog, emptyGame,- execWithGame, execWithGame', outputAll, getLoggedGame, tracePN, getTimes, activeRules, pendingRules, rejectedRules) where+ execWithGame, execWithGame', getLoggedGame, tracePN, getTimes, activeRules, pendingRules,+ rejectedRules, UInputData(..)) where -import Prelude+import Prelude hiding (log) import Control.Monad.State import Data.List import Language.Nomyx hiding (outputAll)@@ -18,7 +19,7 @@ import Control.Category ((>>>)) import Data.Lens.Template import Control.Exception-+import Control.Monad.Trans.State hiding (get) data TimedEvent = TimedEvent UTCTime GameEvent deriving (Show, Read, Eq, Ord) @@ -26,9 +27,8 @@ | JoinGame PlayerNumber PlayerName | LeaveGame PlayerNumber | ProposeRuleEv PlayerNumber SubmitRule- | InputChoiceResult PlayerNumber EventNumber Int- | InputStringResult PlayerNumber String String- | OutputPlayer PlayerNumber String+ | InputResult PlayerNumber EventNumber UInputData+ | GLog (Maybe PlayerNumber) String | TimeEvent UTCTime | SystemAddRule SubmitRule deriving (Show, Read, Eq, Ord)@@ -54,6 +54,7 @@ _events = [], _outputs = [], _victory = [],+ _logs = [], _currentTime = date} $( makeLens ''LoggedGame)@@ -64,19 +65,25 @@ 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 (InputChoiceResult pn en ci) _ = mapStateIO $ inputChoiceResult en ci pn-enactEvent (InputStringResult pn ti res) _ = mapStateIO $ inputStringResult (InputString pn ti) res pn-enactEvent (OutputPlayer pn s) _ = mapStateIO $ outputPlayer s pn+enactEvent (InputResult pn en ir) _ = mapStateIO $ inputResult pn en ir+enactEvent (GLog mpn s) _ = mapStateIO $ logGame s mpn enactEvent (TimeEvent t) _ = mapStateIO $ runEvalError 0 $ void $ evTriggerTime t enactEvent (SystemAddRule r) (Just inter) = systemAddRule r inter enactEvent (ProposeRuleEv _ _) Nothing = error "ProposeRuleEv: interpreter function needed" enactEvent (SystemAddRule _) Nothing = error "SystemAddRule: interpreter function needed" enactTimedEvent :: Maybe (RuleCode -> IO RuleFunc) -> TimedEvent -> StateT Game IO ()-enactTimedEvent inter (TimedEvent t ge) = do+enactTimedEvent inter (TimedEvent t ge) = flip stateCatch updateError $ do currentTime ~= t enactEvent ge inter+ lg <- get+ lift $ evaluate lg+ return () +updateError :: SomeException -> StateT Game IO ()+updateError e = do+ liftIO $ putStrLn $ "IO error: " ++ (show e)+ mapStateIO $ logGame ("IO error: " ++ (show e)) Nothing update :: GameEvent -> StateT LoggedGame IO () update ge = update' Nothing ge@@ -86,15 +93,7 @@ t <- access $ game >>> currentTime let te = TimedEvent t ge gameLog %= \gl -> gl ++ [te]- evalTimedEvent te inter--evalTimedEvent :: TimedEvent -> Maybe (RuleCode -> IO RuleFunc) -> StateT LoggedGame IO ()-evalTimedEvent (TimedEvent _ e) inter = focus game $ do- enactEvent e inter- lg <- get- lift $ evaluate lg- --liftIO $! putStrLn $ "evaluating " ++ (show e)- return ()+ focus game $ enactTimedEvent inter te getLoggedGame :: Game -> (RuleCode -> IO RuleFunc) -> [TimedEvent] -> IO LoggedGame getLoggedGame g mInter tes = do@@ -129,7 +128,6 @@ leaveGame :: PlayerNumber -> State Game () leaveGame pn = runEvalError pn $ void $ evDelPlayer pn - -- | insert a rule in pending rules. proposeRule :: SubmitRule -> PlayerNumber -> (RuleCode -> IO RuleFunc) -> StateT Game IO () proposeRule sr pn inter = do@@ -139,33 +137,21 @@ if r == True then tracePN pn $ "Your rule has been added to pending rules." else tracePN pn $ "Error: Rule could not be proposed" --outputPlayer :: String -> PlayerNumber -> State Game ()-outputPlayer s pn = void $ outputs %= ((pn, s) : )--outputAll :: String -> StateT LoggedGame IO () -outputAll s = do- pls <- access (game >>> players)- mapM_ (update . ((flip OutputPlayer) s)) (map _playerNumber pls)--inputChoiceResult :: EventNumber -> Int -> PlayerNumber -> State Game ()-inputChoiceResult eventNumber choiceIndex pn = do- tracePN pn $ "input choice result: Event " ++ (show eventNumber) ++ ", choice " ++ (show choiceIndex)- runEvalError pn $ triggerChoice eventNumber choiceIndex---- TODO maybe homogeneise both inputs event-inputStringResult :: Event InputString -> String -> PlayerNumber -> State Game ()-inputStringResult event input pn = do- tracePN pn $ "input String result: input " ++ input- runEvalError pn $ triggerEvent_ event (InputStringData input)+logGame :: String -> (Maybe PlayerNumber) -> State Game ()+logGame s mpn = do+ time <- access currentTime+ void $ logs %= (Log mpn time s : ) +inputResult :: PlayerNumber -> EventNumber -> UInputData -> State Game ()+inputResult pn en ir = do+ tracePN pn $ "input result: Event " ++ (show en) ++ ", choice " ++ (show ir)+ runEvalError pn $ triggerInput en ir getTimes :: EventHandler -> Maybe UTCTime-getTimes (EH _ _ (Time t) _ EvActive) = Just t+getTimes (EH _ _ (Time t) _ SActive) = Just t getTimes _ = Nothing ---- | An helper function to use the state transformer GameState.+-- | A helper function to use the state transformer GameState. -- It additionally sets the current time. execWithGame :: UTCTime -> State LoggedGame () -> LoggedGame -> LoggedGame execWithGame t gs g = execState gs $ ((game >>> currentTime) `setL` t $ g)@@ -205,6 +191,8 @@ systemAddRule :: SubmitRule -> (RuleCode -> IO RuleFunc) -> StateT Game IO () systemAddRule sr inter = do rule <- createRule sr 0 inter- let sysRule = (rStatus ^= Active).(rAssessedBy ^= Just 0)+ let sysRule = (rStatus ^= Active) >>> (rAssessedBy ^= Just 0) rules %= (sysRule rule : ) mapStateIO $ runEvalError 0 $ void $ evalExp (_rRuleFunc rule) (_rNumber rule)++stateCatch = liftCatch catch
src/Language/Nomyx/Test.hs view
@@ -24,6 +24,7 @@ _events = [], _outputs = [], _victory = [],+ _logs = [], _currentTime = date1} testRule = Rule { _rNumber = 0,@@ -47,6 +48,7 @@ ("test var 4", testVarEx4), ("test var 5", testVarEx5), ("test single input", testSingleInputEx),+ ("test multiple input", testMultipleInputsEx), ("test input string", testInputStringEx), ("test send messsage", testSendMessageEx), ("test send message 2", testSendMessageEx2),@@ -97,10 +99,10 @@ var <- newVar_ "toto" (1::Int) a <- readVar var case a of- Just (1::Int) -> output "ok" 1- _ -> output "nok" 1+ Just (1::Int) -> newOutput_ "ok" 1+ _ -> newOutput_ "nok" 1 -testVarEx3 = _outputs (execRuleFunc testVar3) == [(1,"ok")]+testVarEx3 = isOutput "ok" (execRuleFunc testVar3) --Test variable writing testVar4 :: RuleFunc@@ -109,10 +111,10 @@ writeVar var (2::Int) a <- readVar var case a of- Just (2::Int) -> output "ok" 1- _ -> output "nok" 1+ Just (2::Int) -> newOutput_ "ok" 1+ _ -> newOutput_ "nok" 1 -testVarEx4 = _outputs (execRuleFunc testVar4) == [(1,"ok")]+testVarEx4 = isOutput "ok" (execRuleFunc testVar4) --Test variable writing testVar5 :: RuleFunc@@ -124,7 +126,7 @@ Just (a::[Int]) -> do writeVar var (2:a) return ()- Nothing -> output "nok" 1+ Nothing -> newOutput_ "nok" 1 testVarEx5 = _variables (execRuleFunc testVar5) == [(Var 0 "toto" ([2,1]::[Int]))] @@ -133,17 +135,28 @@ -- Test input testSingleInput :: RuleFunc testSingleInput = voidRule $ do- onInputChoiceEnum_ "Vote for Holland or Sarkozy" Holland h 1 where- h a = output ("voted for " ++ (show a)) 1+ onInputRadioEnum_ "Vote for Holland or Sarkozy" Holland h 1 where+ h a = newOutput_ ("voted for " ++ (show a)) 1 -testSingleInputEx = (_outputs $ execRuleFuncEvent testSingleInput (inputChoiceEnum 1 "Vote for Holland or Sarkozy" Holland) (InputChoiceData Holland)) == [(1, "voted for Holland")]+testSingleInputEx = isOutput "voted for Holland" g where+ g = execRuleFuncEvent testSingleInput (inputRadioEnum 1 "Vote for Holland or Sarkozy" Holland) (InputData (RadioData Holland)) +testMultipleInputs :: RuleFunc+testMultipleInputs = voidRule $ do+ onInputCheckbox_ "Vote for Holland and Sarkozy" [(Holland, "Holland"), (Sarkozy, "Sarkozy")] h 1 where+ h a = newOutput_ ("voted for " ++ (show a)) 1++testMultipleInputsEx = isOutput "voted for [Holland,Sarkozy]" g where+ g = execRuleFuncEvent testMultipleInputs (inputCheckbox 1 "Vote for Holland and Sarkozy" [(Holland, "Holland"), (Sarkozy, "Sarkozy")]) (InputData (CheckboxData [Holland, Sarkozy]))++ testInputString :: RuleFunc testInputString = voidRule $ do- onInputString_ "Enter a number:" h 1 where- h a = output ("You entered: " ++ a) 1+ onInputText_ "Enter a number:" h 1 where+ h a = newOutput_ ("You entered: " ++ a) 1 -testInputStringEx = (_outputs $ execRuleFuncEvent testInputString (inputString 1 "Enter a number:") (InputStringData "1")) == [(1, "You entered: 1")]+testInputStringEx = isOutput "You entered: 1" g where+ g = execRuleFuncEvent testInputString (inputText 1 "Enter a number:") (InputData (TextData "1")) -- Test message testSendMessage :: RuleFunc@@ -151,17 +164,17 @@ let msg = Message "msg" :: Event(Message String) onEvent_ msg f sendMessage msg "toto" where- f (MessageData a :: EventData(Message String)) = output a 1+ f (MessageData a :: EventData(Message String)) = newOutput_ a 1 -testSendMessageEx = _outputs (execRuleFunc testSendMessage) == [(1,"toto")]+testSendMessageEx = isOutput "toto" (execRuleFunc testSendMessage) testSendMessage2 :: RuleFunc testSendMessage2 = voidRule $ do- onEvent_ (Message "msg":: Event(Message ())) $ const $ output "Received" 1+ onEvent_ (Message "msg":: Event(Message ())) $ const $ newOutput_ "Received" 1 sendMessage_ (Message "msg") -testSendMessageEx2 = _outputs (execRuleFunc testSendMessage2) == [(1,"Received")]+testSendMessageEx2 = isOutput "Received" (execRuleFunc testSendMessage2) data Choice2 = Me | You deriving (Enum, Typeable, Show, Eq, Bounded) @@ -170,18 +183,20 @@ testUserInputWrite = voidRule $ do 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+ onEvent_ (InputEv (Input 1 "Vote for" (Radio [(Me, "Me"), (You, "You")]))) h1 where+ h1 (InputData (RadioData a) :: EventData (Input Choice2)) = do writeVar (V "vote") (Just a) SendMessage (Message "voted") ()+ h1 _ = undefined h2 (MessageData _) = do a <- readVar (V "vote") case a of- Just (Just Me) -> output "voted Me" 1- _ -> output "problem" 1+ Just (Just Me) -> newOutput_ "voted Me" 1+ _ -> newOutput_ "problem" 1 h2 _ = undefined -testUserInputWriteEx = (_outputs $ execRuleFuncEvent testUserInputWrite (InputChoice 1 "Vote for" [Me, You] Me) (InputChoiceData Me)) == [(1,"voted Me")]+testUserInputWriteEx = isOutput "voted Me" g where+ g = execRuleFuncEvent testUserInputWrite (InputEv (Input 1 "Vote for" (Radio [(Me, "Me"), (You, "You")]))) (InputData (RadioData Me)) -- Test rule activation testActivateRule :: RuleFunc@@ -204,12 +219,14 @@ onEvent_ (Time date1) f where f _ = outputAll $ show date1 -testTimeEventEx = (_outputs $ execRuleFuncEvent testTimeEvent (Time date1) (TimeData date1)) == [(1,show date1)]+testTimeEventEx = isOutput (show date1) g where+ g = execRuleFuncEvent testTimeEvent (Time date1) (TimeData date1) testTimeEvent2 :: Nomex () testTimeEvent2 = schedule' [date1, date2] (outputAll . show) -testTimeEventEx2 = (_outputs $ flip execState testGame (runEvalError 0 $ evalExp testTimeEvent2 0 >> void gameEvs)) == [(1,show date2), (1,show date1)] where+testTimeEventEx2 = isOutput (show date1) g && isOutput (show date2) g where+ g = flip execState testGame (runEvalError 0 $ evalExp testTimeEvent2 0 >> void gameEvs) gameEvs = do evTriggerTime date1 evTriggerTime date2@@ -225,13 +242,13 @@ evs <- getChoiceEvents let pos = take positives evs let neg = take negatives $ drop positives evs- mapM_ (\x -> triggerChoice x (fromEnum For)) pos- mapM_ (\x -> triggerChoice x (fromEnum Against)) neg+ mapM_ (\x -> triggerInput x (URadioData $ fromEnum For)) pos+ mapM_ (\x -> triggerInput x (URadioData $ fromEnum Against)) neg when timeEvent $ void $ evTriggerTime date2 voteGame' :: Int -> Int -> Int -> Bool -> RuleFunc -> Game voteGame' positives negatives notVoted timeEvent rf = voteGameActions positives negatives notVoted timeEvent $ do- let rule = testRule {_rName = "testRule", _rRuleFunc = rf, _rNumber = 1, _rStatus = Active}+ let rule = testRule {_rName = "testRule", _rRuleFunc = rf, _rNumber = 1, _rStatus = Pending} evAddRule rule evActivateRule (_rNumber rule) 0 return ()@@ -273,4 +290,8 @@ testVoteAssessOnTimeLimit5 = testVoteRule Pending $ voteGameTimed 10 0 10 $ onRuleProposed $ voteWith_ unanimity $ assessOnTimeLimit date3 testVoteRule s g = (_rStatus $ head $ _rules g) == s++isOutput :: String -> Game -> Bool+isOutput s g = any (\(Output _ _ _ mys SActive) -> mys == s) (_outputs g)+
src/Language/Nomyx/Utils.hs view
@@ -54,3 +54,9 @@ getFreeNumber :: (Eq a, Num a, Enum a) => [a] -> a getFreeNumber l = head [a| a <- [1..], not $ a `elem` l]+++sel :: [a] -- ^ List of indices to select+ -> [Int] -- ^ List of elements+ -> [a] -- ^ List composed of elements selected from original set by indices provided+sel xs is = map (\i -> xs!!i) is
src/Language/Nomyx/Vote.hs view
@@ -13,11 +13,12 @@ import Data.Time hiding (getCurrentTime) import Control.Arrow import Control.Applicative -import Data.List (sort, group)-import Language.Nomyx.Utils (oneDay)+import Language.Nomyx.Utils+import Data.List import qualified Data.Map as M import Control.Monad.Error (MonadError(..)) + data VoteType a = ExclusiveVote (Maybe (Alts a)) | NonExclusiveVote [Alts a] @@ -50,8 +51,6 @@ assessFunction :: VoteResult a} -- function used to count the votes type Assessor a = StateT (VoteData a) Nomex () -- -- | Perform a vote. voteWith :: (Votable a) => VoteResult a -- ^ the function used to count the votes. -> Assessor a -- ^ assessors: when and how to perform the vote assessment (several assessors can be chained).@@ -63,12 +62,14 @@ let toVoteName = name toVote let msgEnd = Message ("Result of votes for " ++ toVoteName) :: Msg [Alts a] --create an array variable to store the votes. - (voteVar :: ArrayVar PlayerNumber (Alts a)) <- newArrayVar ("Votes for " ++ toVoteName) pns - let askPlayer pn = onInputChoiceOnce ("Vote for " ++ toVoteName ++ ":") als (putArrayVar voteVar pn) pn + (voteVar :: ArrayVar PlayerNumber (Alts a)) <- newArrayVar_ ("Votes for " ++ toVoteName) pns + let askPlayer pn = onInputRadioOnce ("Vote for " ++ toVoteName ++ ":") als (putArrayVar_ voteVar pn) pn inputs <- mapM askPlayer pns let voteData = VoteData msgEnd voteVar inputs countVotes - evalStateT assessors voteData - cleanVote voteData + evalStateT assessors voteData+ mapM (\n -> displayVoteVar n ("Votes for " ++ toVoteName ++ ":") voteVar) pns+ displayVoteResult toVoteName voteData+ cleanVote voteData return $ msgEnd -- | Performs a vote, all the possible alternatives are selected.@@ -81,10 +82,11 @@ assessOnEveryVote = do (VoteData msgEnd voteVar _ assess) <- get lift $ do - msgVotes <- getArrayVarMessage voteVar - onMessage msgVotes $ \(MessageData votes) -> do- let res = assess $ getVoteStats votes False- when (not $ null res) $ sendMessage msgEnd res + onMsgVarChange voteVar $ f assess msgEnd where+ f assess msgEnd (VUpdated votes) = do+ let res = assess $ getVoteStats votes False+ when (not $ null res) $ sendMessage msgEnd res+ f _ _ _ = return () -- | assess the vote with the assess function when time is reached, and sends a signal with the issue (positive of negative) @@ -93,7 +95,7 @@ (VoteData msgEnd voteVar _ assess) <- get lift $ do onEvent_ (Time time) $ \_ -> do - votes <- getArrayVarData voteVar + votes <- getMsgVarData_ voteVar sendMessage msgEnd (assess $ getVoteStats votes True) @@ -108,16 +110,16 @@ assessWhenEverybodyVoted = do (VoteData msgEnd voteVar _ assess) <- get lift $ do - msgVotes <- getArrayVarMessage voteVar - onMessage msgVotes $ \(MessageData vs) -> do- when (all isJust (map snd vs)) $ sendMessage msgEnd $ assess $ getVoteStats vs True + onMsgVarChange voteVar $ f assess msgEnd where+ f assess msgEnd (VUpdated votes) = when (all isJust (map snd votes)) $ sendMessage msgEnd $ assess $ getVoteStats votes True + f _ _ _ = return () -- | clean events and variables necessary for the vote cleanVote :: (Votable a) => VoteData a -> Nomex () -cleanVote (VoteData msgEnd voteVar inputsNumber _) = onMessage msgEnd$ \_ -> do +cleanVote (VoteData msgEnd voteVar inputsNumber _) = onMessage msgEnd $ \_ -> do delAllEvents msgEnd - delArrayVar voteVar + delMsgVar voteVar mapM_ delEvent inputsNumber @@ -179,7 +181,39 @@ counts :: (Eq a, Ord a) => [a] -> [(a, Int)] counts as = map (head &&& length) (group $ sort as)- +++displayVoteVar :: (Votable a) => PlayerNumber -> String -> ArrayVar PlayerNumber (Alts a) -> Nomex ()+displayVoteVar pn title mv = do+ sp <- showPlayer+ displayVar pn mv (showVotes title sp)++showPlayer :: Nomex (PlayerNumber -> String)+showPlayer = do+ pls <- getPlayers+ return $ (\pn -> _playerName $ fromJust $ find (\(PlayerInfo mypn _) -> mypn == pn) pls)++showChoice :: (Votable a) => Maybe (Alts a) -> String+showChoice (Just a) = show a+showChoice Nothing = "Not Voted "++showChoices :: (Votable a) => [(Alts a)] -> String+showChoices cs = concat $ intersperse ", " $ map show cs++showVotes :: (Votable a) => String -> (PlayerNumber -> String) -> [(PlayerNumber, Maybe (Alts a))] -> String+showVotes title showPlayer l = title ++ "\n" +++ concatMap (\(i,a) -> (showPlayer i) ++ "\t" ++ (showChoice a) ++ "\n") l++showVotes' :: (Votable a) => (PlayerNumber -> String) -> [(PlayerNumber, Maybe (Alts a))] -> String+showVotes' showPlayer l = concat $ intersperse ", " $ map (\(i,a) -> (showPlayer i) ++ ": " ++ (showChoice a)) voted where+ voted = filter (\(_, r) -> isJust r) l+ +displayVoteResult :: (Votable a) => String -> VoteData a -> Nomex ()+displayVoteResult toVoteName (VoteData msgEnd voteVar _ _) = onMessage msgEnd $ \(MessageData result) -> do + vs <- getMsgVarData_ voteVar+ sp <- showPlayer+ outputAll $ "Vote result for " ++ toVoteName ++ ": " ++ (showChoices result) +++ " (" ++ showVotes' sp vs ++ ")" -- * Referendum & elections