mysnapsession-example 0.1 → 0.2
raw patch · 28 files changed
+487/−347 lines, 28 filesdep +clientsessiondep −MonadCatchIO-transformersdep −hexpatdep −textdep ~mysnapsessiondep ~timenew-component:exe:animalgamenew-component:exe:clientcount
Dependencies added: clientsession
Dependencies removed: MonadCatchIO-transformers, hexpat, text
Dependency ranges changed: mysnapsession, time
Files
- animalgame/resources/static/screen.css +26/−0
- animalgame/resources/templates/conclusion.tpl +15/−0
- animalgame/resources/templates/details.tpl +30/−0
- animalgame/resources/templates/goAgain.tpl +21/−0
- animalgame/resources/templates/guess.tpl +21/−0
- animalgame/resources/templates/index.tpl +22/−0
- animalgame/resources/templates/question.tpl +21/−0
- animalgame/resources/templates/rules.tpl +20/−0
- animalgame/src/Application.hs +52/−0
- animalgame/src/Main.hs +8/−0
- animalgame/src/Site.hs +92/−0
- clientcount/resources/static/screen.css +26/−0
- clientcount/resources/templates/index.tpl +18/−0
- clientcount/src/Application.hs +46/−0
- clientcount/src/Main.hs +8/−0
- clientcount/src/Site.hs +27/−0
- mysnapsession-example.cabal +34/−22
- resources/static/screen.css +0/−26
- resources/templates/conclusion.tpl +0/−15
- resources/templates/details.tpl +0/−30
- resources/templates/goAgain.tpl +0/−21
- resources/templates/guess.tpl +0/−21
- resources/templates/index.tpl +0/−22
- resources/templates/question.tpl +0/−21
- resources/templates/rules.tpl +0/−20
- src/Application.hs +0/−50
- src/Main.hs +0/−8
- src/Site.hs +0/−91
+ animalgame/resources/static/screen.css view
@@ -0,0 +1,26 @@+html {+ padding: 0;+ margin: 0;+ background-color: #ffffff;+ font-family: Verdana, Helvetica, sans-serif;+}+body {+ padding: 0;+ margin: 0;+}+a {+ text-decoration: underline;+}+a :hover {+ cursor: pointer;+ text-decoration: underline;+}+img {+ border: none;+}+#content {+ padding-left: 1em;+}+#info {+ font-size: 60%;+}
+ animalgame/resources/templates/conclusion.tpl view
@@ -0,0 +1,15 @@+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">+<html xmlns="http://www.w3.org/1999/xhtml">+ <head>+ <title>mysnapsessions Sample Application</title>+ <link rel="stylesheet" type="text/css" href="screen.css"/>+ </head>+ <body>+ <div id="content">+ <h1>Conclusion</h1>+ <p>+ Thank you for playing!+ </p>+ </div>+ </body>+</html>
+ animalgame/resources/templates/details.tpl view
@@ -0,0 +1,30 @@+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">+<html xmlns="http://www.w3.org/1999/xhtml">+ <head>+ <title>mysnapsessions Sample Application</title>+ <link rel="stylesheet" type="text/css" href="screen.css"/>+ </head>+ <body>+ <div id="content">+ <h1>Drat!</h1>+ <p>+ Well, perhaps you can help me learn for next time.+ </p>+ <form method="POST" action="/$(dlgid)">+ <p>+ What was the right answer?+ <br/><input type="text" name="newAnimal" value="" />+ </p>+ <p>+ What is a question that distinguishes your animal from a(n) <oldAnimal/>?+ <br/><input type="text" name="question" value="" />+ </p>+ <p>+ Finally, what is the correct answer for your animal?<br/>+ <input type="submit" name="answer" value="yes" />+ <input type="submit" name="answer" value="no" />+ </p>+ </form>+ </div>+ </body>+</html>
+ animalgame/resources/templates/goAgain.tpl view
@@ -0,0 +1,21 @@+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">+<html xmlns="http://www.w3.org/1999/xhtml">+ <head>+ <title>mysnapsessions Sample Application</title>+ <link rel="stylesheet" type="text/css" href="screen.css"/>+ </head>+ <body>+ <div id="content">+ <h1>All done.</h1>+ <p>+ That was fun! Would you like to play again?+ </p>+ <form method="POST" action="/$(dlgid)">+ <p>+ <input type="submit" name="answer" value="yes" />+ <input type="submit" name="answer" value="no" />+ </p>+ </form>+ </div>+ </body>+</html>
+ animalgame/resources/templates/guess.tpl view
@@ -0,0 +1,21 @@+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">+<html xmlns="http://www.w3.org/1999/xhtml">+ <head>+ <title>mysnapsessions Sample Application</title>+ <link rel="stylesheet" type="text/css" href="screen.css"/>+ </head>+ <body>+ <div id="content">+ <h1>I've got it!</h1>+ <p>+ I guess: <b><animal/></b> Am I right?+ </p>+ <form method="POST" action="/$(dlgid)">+ <p>+ <input type="submit" name="answer" value="yes" />+ <input type="submit" name="answer" value="no" />+ </p>+ </form>+ </div>+ </body>+</html>
+ animalgame/resources/templates/index.tpl view
@@ -0,0 +1,22 @@+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">+<html xmlns="http://www.w3.org/1999/xhtml">+ <head>+ <title>mysnapsessions Sample Application</title>+ <link rel="stylesheet" type="text/css" href="screen.css"/>+ </head>+ <body>+ <div id="content">+ <h1>Welcome!</h1>+ <p>+ This simple application demonstrates the continuation-based programming+ model in the <code>mysnapsessions</code> package. You'll be asked to+ think of an animal, and the application will try to guess it. The+ state of the game is stored in your session, so it's not shared between+ users.+ </p>+ <p>+ <a href="/animal">get started!</a>+ </p>+ </div>+ </body>+</html>
+ animalgame/resources/templates/question.tpl view
@@ -0,0 +1,21 @@+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">+<html xmlns="http://www.w3.org/1999/xhtml">+ <head>+ <title>mysnapsessions Sample Application</title>+ <link rel="stylesheet" type="text/css" href="screen.css"/>+ </head>+ <body>+ <div id="content">+ <h1>Hmm...</h1>+ <p>+ Next question: <b><question/></b>+ </p>+ <form method="POST" action="/$(dlgid)">+ <p>+ <input type="submit" name="answer" value="yes" />+ <input type="submit" name="answer" value="no" />+ </p>+ </form>+ </div>+ </body>+</html>
+ animalgame/resources/templates/rules.tpl view
@@ -0,0 +1,20 @@+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">+<html xmlns="http://www.w3.org/1999/xhtml">+ <head>+ <title>mysnapsessions Sample Application</title>+ <link rel="stylesheet" type="text/css" href="screen.css"/>+ </head>+ <body>+ <div id="content">+ <h1>Rules</h1>+ <p>+ Think of an animal, and click OK to get started when you are ready.+ </p>+ <form method="POST" action="/$(dlgid)">+ <p>+ <input type="submit" value="Continue" />+ </p>+ </form>+ </div>+ </body>+</html>
+ animalgame/src/Application.hs view
@@ -0,0 +1,52 @@+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeSynonymInstances #-}++{-++This module defines our application's monad and any application-specific+information it requires.++-}++module Application (+ App,+ appInitializer,+ AppSession(..)+ ) where++import Snap.Extension+import Snap.Extension.Heist.Impl+import Snap.Extension.Session.Memory+import Snap.Dialogues++type App = SnapExtend AppState++data AppState = AppState {+ templateState :: HeistState App,+ sessionMgr :: MemorySessionManager AppSession+ }++instance HasHeistState App AppState where+ getHeistState = templateState+ setHeistState s a = a { templateState = s }++instance HasMemorySessionManager AppState where+ type MemorySessionValue AppState = AppSession+ memorySessionMgr = sessionMgr++data AppSession = AppSession {+ dlgManager :: DlgManager App+ }++instance HasDlgManager App AppSession where+ getDlgManager = dlgManager++appInitializer :: Initializer AppState+appInitializer = do+ heist <- heistInitializer "animalgame/resources/templates"+ sessions <- memorySessionInitializer 1800 newSession+ return $ AppState heist sessions+ where+ newSession = fmap AppSession makeDlgManager+
+ animalgame/src/Main.hs view
@@ -0,0 +1,8 @@+module Main where++import Snap.Extension.Server+import Application+import Site++main :: IO ()+main = quickHttpServe appInitializer site
+ animalgame/src/Site.hs view
@@ -0,0 +1,92 @@+{-# LANGUAGE OverloadedStrings #-}++module Site (site) where++import Data.ByteString.Char8 (ByteString)+import Control.Applicative+import Control.Monad+import Snap.Extension.Heist+import Snap.Dialogues+import Snap.SessionUtil+import Snap.Util.FileServe+import Snap.Types+import Text.Templating.Heist++import Application++data DiKey = Answer ByteString+ | Question ByteString DiKey DiKey++startingKey = Answer "elephant"++animalGame key = do+ rulePage+ key' <- question key+ again <- goAgainPage+ if again then animalGame key' else conclusionPage++question (Answer s) = do+ correct <- guessPage s+ if correct then return (Answer s)+ else do+ (anim, newq, newa) <- detailsPage s+ if newa then return (Question newq (Answer anim) (Answer s))+ else return (Question newq (Answer s) (Answer anim))++question (Question q y n) = do+ ans <- questionPage q+ if ans then do y' <- question y+ return (Question q y' n)+ else do n' <- question n+ return (Question q y n')++rulePage = showPage build parse+ where+ build t = heistLocal (bindStrings [("dlgid", t)]) $ render "rules"+ parse = return ()++conclusionPage = showPage build parse+ where+ build t = heistLocal (bindStrings [("dlgid", t)]) $ render "conclusion"+ parse = return ()++goAgainPage = showPage build parse+ where+ build t = heistLocal (bindStrings [("dlgid", t)]) $ render "goAgain"+ parse = do p <- getParam "answer"+ case p of Just "yes" -> return True+ _ -> return False++guessPage animal = showPage build parse+ where+ build t = heistLocal (bindStrings+ [("dlgid", t), ("animal", animal)]) $ render "guess"+ parse = do p <- getParam "answer"+ case p of Just "yes" -> return True+ _ -> return False++questionPage q = showPage build parse+ where+ build t = heistLocal (bindStrings+ [("dlgid", t), ("question", q)]) $ render "question"+ parse = do p <- getParam "answer"+ case p of Just "yes" -> return True+ _ -> return False++detailsPage oldAnimal = showPage build parse+ where+ build t = heistLocal (bindStrings+ [("dlgid", t), ("oldAnimal", oldAnimal)]) $ render "details"+ parse = do+ newAnimal <- getParam "newAnimal" >>= maybe mzero return+ question <- getParam "question" >>= maybe mzero return+ answerStr <- getParam "answer" >>= maybe mzero return+ let answer = case answerStr of "yes" -> True+ _ -> False+ return (newAnimal, question, answer)++site :: App ()+site = inSession $+ ifTop (render "index")+ <|> dialogue "animal" (animalGame startingKey)+ <|> fileServe "animalgame/resources/static"
+ clientcount/resources/static/screen.css view
@@ -0,0 +1,26 @@+html {+ padding: 0;+ margin: 0;+ background-color: #ffffff;+ font-family: Verdana, Helvetica, sans-serif;+}+body {+ padding: 0;+ margin: 0;+}+a {+ text-decoration: underline;+}+a :hover {+ cursor: pointer;+ text-decoration: underline;+}+img {+ border: none;+}+#content {+ padding-left: 1em;+}+#info {+ font-size: 60%;+}
+ clientcount/resources/templates/index.tpl view
@@ -0,0 +1,18 @@+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">+<html xmlns="http://www.w3.org/1999/xhtml">+ <head>+ <title>mysnapsessions Sample Application</title>+ <link rel="stylesheet" type="text/css" href="screen.css"/>+ </head>+ <body>+ <div id="content">+ <h1>Welcome!</h1>+ <p>+ Your current session count is <num/>.+ </p>+ <p>+ <a href="/">Bump me up one more!</a>+ </p>+ </div>+ </body>+</html>
+ clientcount/src/Application.hs view
@@ -0,0 +1,46 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeSynonymInstances #-}++{-++This module defines our application's monad and any application-specific+information it requires.++-}++module Application (+ App,+ appInitializer+ ) where++import Data.ByteString.Char8 (ByteString)+import Snap.Extension+import Snap.Extension.Heist.Impl+import Snap.Extension.Session.Client+import Web.ClientSession++type App = SnapExtend AppState++data AppState = AppState {+ templateState :: HeistState App,+ sessionMgr :: ClientSessionManager Int+ }++instance HasHeistState App AppState where+ getHeistState = templateState+ setHeistState s a = a { templateState = s }++instance HasClientSessionManager AppState where+ type ClientSessionValue AppState = Int+ clientSessionMgr = sessionMgr++sessionKey :: ByteString+sessionKey = $(embedDefaultKey)++appInitializer :: Initializer AppState+appInitializer = do+ heist <- heistInitializer "clientcount/resources/templates"+ sessions <- clientSessionInitializer sessionKey 0 (Just 10)+ return $ AppState heist sessions
+ clientcount/src/Main.hs view
@@ -0,0 +1,8 @@+module Main where++import Snap.Extension.Server+import Application+import Site++main :: IO ()+main = quickHttpServe appInitializer site
+ clientcount/src/Site.hs view
@@ -0,0 +1,27 @@+{-# LANGUAGE OverloadedStrings #-}++module Site (site) where++import Control.Applicative+import Snap.Extension.Heist+import Snap.Extension.Session+import Snap.SessionUtil+import Snap.Util.FileServe+import Snap.Types+import Text.Templating.Heist++import Data.ByteString.Char8 (ByteString)+import qualified Data.ByteString.Char8 as B++import Application++index :: App ()+index = do+ i <- getSession+ putSession (i+1)+ heistLocal (bindString "num" (B.pack $ show i)) $ render "index"++site :: App ()+site = inSession $+ ifTop index+ <|> fileServe "clientcount/resources/static"
mysnapsession-example.cabal view
@@ -1,9 +1,8 @@ Name: mysnapsession-example-Version: 0.1-Synopsis: Example project using mysnapsession-Description: This is a simple web application that uses the- mysnapsession package's continuation programming model- to build an animal guessing game.+Version: 0.2+Synopsis: Example projects using mysnapsession+Description: This is a collection of simple web applications that use+ the mysnapsession package for stateful HTTP. License: BSD3 License-file: LICENSE Author: Chris Smith <cdsmith@gmail.com>@@ -13,33 +12,46 @@ Build-type: Simple Cabal-version: >=1.6 -Extra-source-files: resources/static/*.css, resources/templates/*.tpl+Extra-source-files: animalgame/resources/static/*.css,+ animalgame/resources/templates/*.tpl -Executable testsnap- Hs-source-dirs: src- Main-is: Main.hs- Other-modules: Main, Application, Site+Extra-source-files: clientcount/resources/static/*.css,+ clientcount/resources/templates/*.tpl +Executable animalgame+ Hs-source-dirs: animalgame/src+ Main-is: Main.hs+ Other-modules: Main, Application, Site+ Build-depends: base >= 4 && < 5, bytestring >= 0.9.1 && < 0.10, heist >= 0.4 && < 0.5,- hexpat >= 0.19 && < 0.20,- MonadCatchIO-transformers >= 0.2.1 && < 0.3, mtl >= 2 && < 3, snap >= 0.3 && < 0.4, snap-core >= 0.3 && < 0.4, snap-server >= 0.3 && <0.4,- text >= 0.11 && < 0.12,- time >= 1.1 && < 1.3,- mysnapsession == 0.1.*+ mysnapsession == 0.2.*,+ clientsession == 0.4.* - extensions: TypeSynonymInstances MultiParamTypeClasses+ Ghc-options: -threaded -Wall -fwarn-tabs -funbox-strict-fields+ -fno-warn-orphans - if impl(ghc >= 6.12.0)- ghc-options: -threaded -Wall -fwarn-tabs -funbox-strict-fields- -fno-warn-orphans -fno-warn-unused-do-bind- else- ghc-options: -threaded -Wall -fwarn-tabs -funbox-strict-fields- -fno-warn-orphans+Executable clientcount+ Hs-source-dirs: clientcount/src+ Main-is: Main.hs+ Other-modules: Main, Application, Site + Build-depends:+ base >= 4 && < 5,+ bytestring >= 0.9.1 && < 0.10,+ heist >= 0.4 && < 0.5,+ mtl >= 2 && < 3,+ snap >= 0.3 && < 0.4,+ snap-core >= 0.3 && < 0.4,+ snap-server >= 0.3 && <0.4,+ time == 1.1.*,+ mysnapsession == 0.2.*++ Ghc-options: -threaded -Wall -fwarn-tabs -funbox-strict-fields+ -fno-warn-orphans
− resources/static/screen.css
@@ -1,26 +0,0 @@-html {- padding: 0;- margin: 0;- background-color: #ffffff;- font-family: Verdana, Helvetica, sans-serif;-}-body {- padding: 0;- margin: 0;-}-a {- text-decoration: underline;-}-a :hover {- cursor: pointer;- text-decoration: underline;-}-img {- border: none;-}-#content {- padding-left: 1em;-}-#info {- font-size: 60%;-}
− resources/templates/conclusion.tpl
@@ -1,15 +0,0 @@-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">-<html xmlns="http://www.w3.org/1999/xhtml">- <head>- <title>mysnapsessions Sample Application</title>- <link rel="stylesheet" type="text/css" href="screen.css"/>- </head>- <body>- <div id="content">- <h1>Conclusion</h1>- <p>- Thank you for playing!- </p>- </div>- </body>-</html>
− resources/templates/details.tpl
@@ -1,30 +0,0 @@-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">-<html xmlns="http://www.w3.org/1999/xhtml">- <head>- <title>mysnapsessions Sample Application</title>- <link rel="stylesheet" type="text/css" href="screen.css"/>- </head>- <body>- <div id="content">- <h1>Drat!</h1>- <p>- Well, perhaps you can help me learn for next time.- </p>- <form method="POST" action="/$(dlgid)">- <p>- What was the right answer?- <br/><input type="text" name="newAnimal" value="" />- </p>- <p>- What is a question that distinguishes your animal from a(n) <oldAnimal/>?- <br/><input type="text" name="question" value="" />- </p>- <p>- Finally, what is the correct answer for your animal?<br/>- <input type="submit" name="answer" value="yes" />- <input type="submit" name="answer" value="no" />- </p>- </form>- </div>- </body>-</html>
− resources/templates/goAgain.tpl
@@ -1,21 +0,0 @@-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">-<html xmlns="http://www.w3.org/1999/xhtml">- <head>- <title>mysnapsessions Sample Application</title>- <link rel="stylesheet" type="text/css" href="screen.css"/>- </head>- <body>- <div id="content">- <h1>All done.</h1>- <p>- That was fun! Would you like to play again?- </p>- <form method="POST" action="/$(dlgid)">- <p>- <input type="submit" name="answer" value="yes" />- <input type="submit" name="answer" value="no" />- </p>- </form>- </div>- </body>-</html>
− resources/templates/guess.tpl
@@ -1,21 +0,0 @@-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">-<html xmlns="http://www.w3.org/1999/xhtml">- <head>- <title>mysnapsessions Sample Application</title>- <link rel="stylesheet" type="text/css" href="screen.css"/>- </head>- <body>- <div id="content">- <h1>I've got it!</h1>- <p>- I guess: <b><animal/></b> Am I right?- </p>- <form method="POST" action="/$(dlgid)">- <p>- <input type="submit" name="answer" value="yes" />- <input type="submit" name="answer" value="no" />- </p>- </form>- </div>- </body>-</html>
− resources/templates/index.tpl
@@ -1,22 +0,0 @@-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">-<html xmlns="http://www.w3.org/1999/xhtml">- <head>- <title>mysnapsessions Sample Application</title>- <link rel="stylesheet" type="text/css" href="screen.css"/>- </head>- <body>- <div id="content">- <h1>Welcome!</h1>- <p>- This simple application demonstrates the continuation-based programming- model in the <code>mysnapsessions</code> package. You'll be asked to- think of an animal, and the application will try to guess it. The- state of the game is stored in your session, so it's not shared between- users.- </p>- <p>- <a href="/animal">get started!</a>- </p>- </div>- </body>-</html>
− resources/templates/question.tpl
@@ -1,21 +0,0 @@-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">-<html xmlns="http://www.w3.org/1999/xhtml">- <head>- <title>mysnapsessions Sample Application</title>- <link rel="stylesheet" type="text/css" href="screen.css"/>- </head>- <body>- <div id="content">- <h1>Hmm...</h1>- <p>- Next question: <b><question/></b>- </p>- <form method="POST" action="/$(dlgid)">- <p>- <input type="submit" name="answer" value="yes" />- <input type="submit" name="answer" value="no" />- </p>- </form>- </div>- </body>-</html>
− resources/templates/rules.tpl
@@ -1,20 +0,0 @@-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">-<html xmlns="http://www.w3.org/1999/xhtml">- <head>- <title>mysnapsessions Sample Application</title>- <link rel="stylesheet" type="text/css" href="screen.css"/>- </head>- <body>- <div id="content">- <h1>Rules</h1>- <p>- Think of an animal, and click OK to get started when you are ready.- </p>- <form method="POST" action="/$(dlgid)">- <p>- <input type="submit" value="Continue" />- </p>- </form>- </div>- </body>-</html>
− src/Application.hs
@@ -1,50 +0,0 @@-{-# LANGUAGE TypeFamilies #-}--{---This module defines our application's monad and any application-specific-information it requires.---}--module Application (- App,- appInitializer,- AppSession(..)- ) where--import Snap.Extension-import Snap.Extension.Heist.Impl-import Snap.Extension.Session.Memory-import Snap.Extension.Dialogues--type App = SnapExtend AppState--data AppState = AppState {- templateState :: HeistState App,- sessionMgr :: MemorySessionManager AppSession- }--instance HasHeistState App AppState where- getHeistState = templateState- setHeistState s a = a { templateState = s }--instance HasMemorySessionManager AppState where- type MemorySessionValue AppState = AppSession- memorySessionMgr = sessionMgr--data AppSession = AppSession {- dlgManager :: DlgManager App- }--instance HasDlgManager App AppSession where- getDlgManager = dlgManager--appInitializer :: Initializer AppState-appInitializer = do- heist <- heistInitializer "resources/templates"- sessions <- memorySessionInitializer 1800 newSession- return $ AppState heist sessions- where- newSession = fmap AppSession makeDlgManager-
− src/Main.hs
@@ -1,8 +0,0 @@-module Main where--import Snap.Extension.Server-import Application-import Site--main :: IO ()-main = quickHttpServe appInitializer site
− src/Site.hs
@@ -1,91 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}--module Site (site) where--import Data.ByteString.Char8 (ByteString)-import Control.Applicative-import Control.Monad-import Snap.Extension.Heist-import Snap.Extension.Dialogues-import Snap.Util.FileServe-import Snap.Types-import Text.Templating.Heist--import Application--data DiKey = Answer ByteString- | Question ByteString DiKey DiKey--startingKey = Answer "elephant"--animalGame key = do- rulePage- key' <- question key- again <- goAgainPage- if again then animalGame key' else conclusionPage--question (Answer s) = do- correct <- guessPage s- if correct then return (Answer s)- else do- (anim, newq, newa) <- detailsPage s- if newa then return (Question newq (Answer anim) (Answer s))- else return (Question newq (Answer s) (Answer anim))--question (Question q y n) = do- ans <- questionPage q- if ans then do y' <- question y- return (Question q y' n)- else do n' <- question n- return (Question q y n')--rulePage = showPage build parse- where- build t = heistLocal (bindStrings [("dlgid", t)]) $ render "rules"- parse = return ()--conclusionPage = showPage build parse- where- build t = heistLocal (bindStrings [("dlgid", t)]) $ render "conclusion"- parse = return ()--goAgainPage = showPage build parse- where- build t = heistLocal (bindStrings [("dlgid", t)]) $ render "goAgain"- parse = do p <- getParam "answer"- case p of Just "yes" -> return True- _ -> return False--guessPage animal = showPage build parse- where- build t = heistLocal (bindStrings- [("dlgid", t), ("animal", animal)]) $ render "guess"- parse = do p <- getParam "answer"- case p of Just "yes" -> return True- _ -> return False--questionPage q = showPage build parse- where- build t = heistLocal (bindStrings- [("dlgid", t), ("question", q)]) $ render "question"- parse = do p <- getParam "answer"- case p of Just "yes" -> return True- _ -> return False--detailsPage oldAnimal = showPage build parse- where- build t = heistLocal (bindStrings- [("dlgid", t), ("oldAnimal", oldAnimal)]) $ render "details"- parse = do- newAnimal <- getParam "newAnimal" >>= maybe mzero return- question <- getParam "question" >>= maybe mzero return- answerStr <- getParam "answer" >>= maybe mzero return- let answer = case answerStr of "yes" -> True- _ -> False- return (newAnimal, question, answer)--site :: App ()-site = ifTop (render "index")- <|> dialogue "animal" (animalGame startingKey)- <|> fileServe "resources/static"-