-
Notifications
You must be signed in to change notification settings - Fork 72
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #102 from JordanMartinez/development
Make next minor release: PS-0.12.x-v0.9.1
- Loading branch information
Showing
23 changed files
with
547 additions
and
82 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 10 additions & 0 deletions
10
21-Hello-World/09-Games/dist/random-number/free/index.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<!DOCTYPE html> | ||
<html lang="en" dir="ltr"> | ||
<head> | ||
<meta charset="utf-8"> | ||
<title>Game - Guess a Random Number (Free-based)</title> | ||
</head> | ||
<body> | ||
<script src="app.js" charset="utf-8"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<!DOCTYPE html> | ||
<html lang="en" dir="ltr"> | ||
<head> | ||
<meta charset="utf-8"> | ||
<title>Game - Guess a Random Number (Run-Based)</title> | ||
</head> | ||
<body> | ||
<script src="app.js" charset="utf-8"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
78 changes: 78 additions & 0 deletions
78
21-Hello-World/09-Games/src/02-Random-Number/11-Free/05-Halogen/01-User-Input.purs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
-- | This is the same code used in the Run-based version | ||
module Games.RandomNumber.Free.Halogen.UserInput | ||
( Language(..) | ||
, calcLikeInput | ||
) where | ||
|
||
import Prelude | ||
import Data.Maybe (Maybe(..)) | ||
import Effect.Aff (Aff) | ||
import Effect.Aff.Class as AC | ||
import Effect.Aff.AVar (AVar) | ||
import Effect.Aff.AVar as AVar | ||
import Halogen as H | ||
import Halogen.HTML as HH | ||
import Halogen.HTML.Events as HE | ||
|
||
data Language a | ||
= Add String a -- adds a number to the input | ||
| Clear a -- clears out the input | ||
| Submit a -- "submits" the input to the parent | ||
|
||
type CalcState = { input :: String -- the curren tinput | ||
, avar :: AVar String | ||
} | ||
type Msg_UserInput = String | ||
|
||
-- | When rendering, the parent will pass in the avar | ||
-- | that it will block on until this component puts | ||
-- | the user's input into that avar | ||
calcLikeInput :: H.Component HH.HTML Language (AVar String) Msg_UserInput Aff | ||
calcLikeInput = | ||
H.component | ||
{ initialState: (\avar -> {input: "", avar: avar}) | ||
, render | ||
, eval | ||
, receiver: const Nothing | ||
} | ||
where | ||
-- | The interface should look similar to calculator's interface | ||
render :: CalcState -> H.ComponentHTML Language | ||
render state = | ||
HH.div_ | ||
[ HH.div_ [ HH.text $ state.input ] | ||
, HH.table_ | ||
[ HH.tbody_ | ||
[ HH.tr_ [ numberCell "1", numberCell "2", numberCell "3"] | ||
, HH.tr_ [ numberCell "4", numberCell "5", numberCell "6"] | ||
, HH.tr_ [ numberCell "7", numberCell "8", numberCell "9"] | ||
, HH.tr_ | ||
[ numberCell "0" | ||
, HH.td_ [ HH.button [HE.onClick $ HE.input_ $ Clear] [ HH.text "Clear" ] ] | ||
, HH.td_ [ HH.button [HE.onClick $ HE.input_ $ Submit] [ HH.text "Submit" ] ] | ||
] | ||
] | ||
] | ||
] | ||
|
||
numberCell numText = | ||
HH.td_ | ||
[ HH.button | ||
[HE.onClick $ HE.input_ $ Add numText] | ||
[ HH.text numText ] | ||
] | ||
|
||
-- | Change the input based on the user's button clicks | ||
-- | and submit the final input back to parent once done | ||
eval :: Language ~> H.ComponentDSL CalcState Language Msg_UserInput Aff | ||
eval = case _ of | ||
Add n next -> do | ||
H.modify_ (\state -> state { input = state.input <> n }) | ||
pure next | ||
Clear next -> do | ||
H.modify_ (\s -> s { input = "" }) | ||
pure next | ||
Submit next -> do | ||
state <- H.get | ||
_ <- AC.liftAff $ AVar.put state.input state.avar | ||
pure next |
94 changes: 94 additions & 0 deletions
94
21-Hello-World/09-Games/src/02-Random-Number/11-Free/05-Halogen/02-Terminal.purs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
module Games.RandomNumber.Free.Halogen.Terminal (terminal) where | ||
|
||
import Prelude | ||
import Data.Array (snoc) | ||
import Data.Maybe (Maybe(..)) | ||
import Effect.Aff (Aff) | ||
import Effect.Aff.Class as AffClass | ||
import Effect.Aff.AVar (AVar) | ||
import Effect.Aff.AVar as AVar | ||
import Effect.Random (randomInt) | ||
import Games.RandomNumber.Free.Halogen.UserInput (Language, calcLikeInput) | ||
import Games.RandomNumber.Core (unBounds) | ||
import Games.RandomNumber.Free.API (API_F(..)) | ||
import Halogen as H | ||
import Halogen.HTML as HH | ||
import Halogen.HTML.Events as HE | ||
import Halogen (liftEffect) | ||
|
||
-- Rather than defining our query language | ||
-- for this component, we'll just re-use the API language | ||
|
||
-- | Store the messages that should appear in the terminal (history). | ||
-- | When `getInput == Nothing`, just display the terminal. | ||
-- | When `getInput == Just avar`, display the calculator-like interface | ||
-- | to get the user's input. | ||
type State = { history :: Array String | ||
, getInput :: Maybe (AVar String) | ||
} | ||
|
||
-- | Rather than defining a new query language here, | ||
-- | we'll just reuse the API_F one. | ||
type Query = API_F | ||
|
||
-- | No need to raise any messages to listeners outside of this | ||
-- | root component as we'll be emitting messages via AVars. | ||
type Message = Void | ||
|
||
-- | There's only one child, so this slot type is overkill. Oh well... | ||
newtype Slot = Slot Int | ||
derive newtype instance e :: Eq Slot | ||
derive newtype instance s :: Ord Slot | ||
|
||
-- | | ||
terminal :: H.Component HH.HTML Query Unit Message Aff | ||
terminal = | ||
H.parentComponent | ||
{ initialState: const { history: [], getInput: Nothing } | ||
, render | ||
, eval | ||
, receiver: const Nothing | ||
} | ||
where | ||
render :: State -> H.ParentHTML Query Language Slot Aff | ||
render state = case state.getInput of | ||
Just avar -> | ||
HH.div_ | ||
[ HH.div_ $ state.history <#> \msg -> HH.div_ [HH.text msg] | ||
, HH.slot (Slot 1) calcLikeInput avar (HE.input Log) | ||
] | ||
Nothing -> | ||
HH.div_ | ||
[ HH.div_ $ state.history <#> \msg -> HH.div_ [HH.text msg] | ||
] | ||
|
||
-- | Log: Our game's business logic outside this | ||
-- | component will send a query into this root component | ||
-- | to add the message to the terminal | ||
-- | GetUserInput: Our game's business logic outside this | ||
-- | component will send a query into this root component | ||
-- | to get the user's input. This component will re-render | ||
-- | itself with the calculator-like interface, | ||
-- | so that user can submit their input. Evaluation will block | ||
-- | until user submits their input. Once received, this component | ||
-- | will re-render so that the interface disappears. | ||
-- | and then return the user's input to the game logic code outside. | ||
-- | GenRandomInt: We don't need to use the UI to generate a random int. | ||
-- | However, because this instance is part of the `API_F` type, | ||
-- | we need to account for it, so that we have a total function. | ||
eval :: Query ~> H.ParentDSL State Query Language Slot Message Aff | ||
eval = case _ of | ||
Log msg next -> do | ||
H.modify_ (\state -> state { history = state.history `snoc` msg}) | ||
pure next | ||
GetUserInput msg reply -> do | ||
avar <- AffClass.liftAff AVar.empty | ||
H.modify_ (\state -> state { history = state.history `snoc` msg | ||
, getInput = Just avar }) | ||
value <- AffClass.liftAff $ AVar.take avar | ||
H.modify_ (\state -> state { getInput = Nothing }) | ||
pure $ reply value | ||
GenRandomInt bounds reply -> do | ||
random <- unBounds bounds (\l u -> liftEffect $ randomInt l u) | ||
|
||
pure (reply random) |
28 changes: 28 additions & 0 deletions
28
...llo-World/09-Games/src/02-Random-Number/11-Free/05-Halogen/03-Halogen-Infrastructure.purs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
module Games.RandomNumber.Free.Halogen.Infrastructure where | ||
|
||
import Prelude | ||
|
||
import Control.Monad.Free (foldFree) | ||
import Effect (Effect) | ||
import Effect.Aff (Aff) | ||
import Games.RandomNumber.Free.Core (game) | ||
import Games.RandomNumber.Free.Domain (runCore) | ||
import Games.RandomNumber.Free.API (API_F(..), API, runDomain) | ||
import Games.RandomNumber.Free.Halogen.Terminal (terminal) | ||
import Halogen as H | ||
import Halogen.Aff as HA | ||
import Halogen.VDom.Driver (runUI) | ||
|
||
main :: Effect Unit | ||
main = do | ||
HA.runHalogenAff do | ||
body <- HA.awaitBody | ||
io <- runUI terminal unit body | ||
|
||
runAPI io.query (runDomain (runCore game)) | ||
|
||
-- | (io :: HalogenIO).query | ||
type QueryRoot = API_F ~> Aff | ||
|
||
runAPI :: QueryRoot -> API ~> Aff | ||
runAPI query = foldFree query |
18 changes: 18 additions & 0 deletions
18
21-Hello-World/09-Games/src/02-Random-Number/11-Free/05-Halogen/ReadMe.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Halogen | ||
|
||
As the SVG files in this folder showed, we can easily implement our game using a web browser user interface rather than a console based one. | ||
|
||
Since I'm already somewhat familiar with it, I decided to implement this next part using Halogen. Halogen has a lot of generic/polymorphic types. So, read through my "bottom up" approach first, which introduces these types one at a time. Then, read through the "top-down" approach alongside of the flowchart: | ||
- [My "bottom-up" explanation](https://github.com/slamdata/purescript-halogen/tree/1e13c931f242f0ea72a92ed1b560110833ab2f1c/docs/v2). I stopped at a certain point because of the currently not-well-documented API changes they are making in the upcoming `5.0.0` release. | ||
- [Their "top-down" approach](https://github.com/slamdata/purescript-halogen/tree/v4.0.0/docs). | ||
- [The flowchart I made](https://github.com/slamdata/purescript-halogen/issues/528#issuecomment-400071113) that helps one see how the code actually works. While this flowchart is highly accurate, the issue in which it is contained explains more context on the parts where I misunderstood something. | ||
|
||
## Halogen Warning | ||
|
||
**WARNING!** As of this writing, Halogen's `master` branch is currently in development and their `examples` directory within that branch has not yet been updated. If you try to compile the examples with the `master` branch checked out, it will fail to compile. Instead, check out their `v4.0.0` tag and try the examples there. | ||
|
||
## Code Warning | ||
|
||
The browser-based UI you will see in both the Free- and Run-based code will look utterly horrible! This is intentional for two reasons: | ||
1. The pattern to follow is easier to see without CSS and additional events cluttering up the code base | ||
2. While I know some HTML/CSS, my learning focus has been on Purescript. I currently don't know best practices when it comes to HTML and CSS, but I will learn those things after I get more familiar with Purescript. |
Oops, something went wrong.