packages feed

nomyx-web-1.0.0: src/Nomyx/Web/Game/Actions.hs

{-# LANGUAGE DoAndIfThenElse      #-}
{-# LANGUAGE ExtendedDefaultRules #-}
{-# LANGUAGE GADTs                #-}
{-# LANGUAGE OverloadedStrings    #-}

module Nomyx.Web.Game.Actions where

import           Control.Applicative
import           Control.Monad
import           Control.Monad.State
import           Control.Lens hiding (pre)
import           Control.Concurrent.STM
import           Data.List
import           Data.Maybe
import           Data.Monoid
import           Data.String
import           Data.Text                   (Text, pack)
import           Happstack.Server            (Method (..), Response, methodM,
                                              ok, seeOther, toResponse)
import           Nomyx.Language
import           Nomyx.Core.Engine
import           Nomyx.Core.Types
import           Nomyx.Core.Mail
import           Nomyx.Core.Session          as S
import           Nomyx.Web.Common            as NWC
import qualified Nomyx.Web.Help              as Help
import           Nomyx.Web.Types
import           Prelude                     hiding (div)
import           Text.Blaze.Html5            (Html, a, br, div, h3, h4,
                                              pre, table, td, toValue, tr, (!))
import           Text.Blaze.Html5.Attributes as A (id, href)
import           Text.Reform                 (eitherForm, viewForm, (<++))
import           Text.Reform.Blaze.String    (inputCheckboxes, label, textarea)
import qualified Text.Reform.Blaze.String    as RB
import           Text.Reform.Happstack       (environment)
import           Web.Routes.RouteT           (liftRouteT)
import           Imprevu.Happstack.Forms     (viewInput, newInput, BackLink)
import           Imprevu.Happstack.Types
import           Imprevu.Evaluation

default (Integer, Double, Data.Text.Text)


viewIOs :: PlayerNumber -> Game -> RoutedNomyxServer Html
viewIOs pn g = do
   vios <- mapM (viewIORule pn g) (sort $ _rules g)
   ok $ do
      titleWithHelpIcon (h3 "Inputs/Ouputs from constitutional rules") Help.inputsOutputs
      a "" ! A.id (toValue inputAnchor)
      mconcat vios

viewIORule :: PlayerNumber -> Game -> RuleInfo -> RoutedNomyxServer Html
viewIORule pn g r = do
   let ruleLink = showRelURLParams (Menu Rules $ _gameName g) [("ruleNumber", Just $ pack $ show $ _rNumber r)]
   vior <- viewIORuleM pn (_rNumber r) g
   ok $ when (isJust vior) $ div ! A.id "IORule" $ do
      div ! A.id "IORuleTitle" $ h4 $ a (fromString $ "Rule " ++ (show $ _rNumber r) ++ " \"" ++ (_rName $ _rRuleTemplate r) ++ "\": ") ! (A.href $ toValue ruleLink)
      fromJust vior

viewIORuleM :: PlayerNumber -> RuleNumber -> Game -> RoutedNomyxServer (Maybe Html)
viewIORuleM pn rn g = do
   vir <- viewInputsRule pn rn (_events g) g
   let vor = viewOutputsRule pn rn g
   return $ if isJust vir || isJust vor then Just $ do
      when (isJust vir) $ fromJust vir
      when (isJust vor) $ fromJust vor
   else Nothing

viewInputsRule :: PlayerNumber -> RuleNumber -> [RuleEventInfo] -> Game -> RoutedNomyxServer (Maybe Html)
viewInputsRule pn rn ehs g = do
   let filtered = filter (\e -> _erRuleNumber e == rn) ehs
   let link en iv = showRelURL (DoInput iv en (_gameName g))
   ws <- use webSession
   mis <- mapM (getViewEvent pn g link) $ (map _erEventInfo $ sort filtered)
   let is = catMaybes mis
   case is of
      [] -> return Nothing
      i -> return $ Just $ table $ mconcat i

getViewEvent :: ClientNumber -> Game -> BackLink -> EventInfo -> RoutedNomyxServer (Maybe Html)
getViewEvent cn g link ei@(EventInfo en _ _ SActive _) = do
   let ss = getRemainingSignals ei (EvalEnv (EvalState g 0) defaultEvalConf)
   liftRouteT $ lift $ viewInput cn link en ss
getViewEvent _ _ _ _ = return Nothing 

viewOutputsRule :: PlayerNumber -> RuleNumber -> Game -> Maybe Html
viewOutputsRule pn rn g = do
   let filtered = filter (\o -> _oRuleNumber o == rn && _oStatus o == SActive) (_outputs g)
   let myos = filter (isPn pn) (sort filtered)
   case myos of
      [] -> Nothing
      os -> Just $ sequence_ $ mapMaybe (viewOutput g) os

isPn pn (Output _ _ (Just mypn) _ SActive) = mypn == pn
isPn _  (Output _ _ Nothing _ SActive) = True
isPn _ _ = False

viewOutput :: Game -> Output -> Maybe Html
viewOutput g o = if (s /= "") then Just (pre $ fromString s >> br) else Nothing where
   s =  (evalOutput g o)

-- | a form result has been sent
newInput' :: Input -> EventNumber -> GameName -> RoutedNomyxServer Response
newInput' is en gn = do
  ws <- use webSession
  let link = showRelURL $ Menu Actions gn
  liftRouteT $ lift $ newInput is en ws (updateSession' gn) link

updateSession' :: GameName -> TVar Session -> Input -> InputData -> EventNumber -> IO ()
updateSession' gn tvs is@(Input _ pn) id en = S.updateSession tvs $ S.inputResult pn en is id gn