Skip to content

Instantly share code, notes, and snippets.

@dustinheestand
Last active June 9, 2020 04:34
Show Gist options
  • Save dustinheestand/9c1c97376b845ffb555ad9aec03a1843 to your computer and use it in GitHub Desktop.
Save dustinheestand/9c1c97376b845ffb555ad9aec03a1843 to your computer and use it in GitHub Desktop.
-- Press a button to generate a random number between 1 and 6.
--
-- Read how it works:
-- https://guide.elm-lang.org/effects/random.html
--
import Browser
import Html exposing (..)
import Html.Events exposing (..)
import Process
import Random
import Svg
import Svg.Attributes as A
import Task
-- MAIN
main =
Browser.element
{ init = init
, update = update
, subscriptions = subscriptions
, view = view
}
-- MODEL
type alias Model =
{ dieFaces : (Int, Int)
, numDice : Int
}
init : () -> (Model, Cmd Msg)
init _ =
( Model (1, 1) 1
, Cmd.none
)
-- UPDATE
type Msg
= Roll Int Int
| NewFace Int Int (Int, Int)
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
Roll left num ->
case left of
0 -> ( model
, Cmd.none
)
otherwise -> ( Model (1, 1) num
, Random.generate (NewFace left num) dice
)
NewFace left num (add1, add2) ->
let (face1, face2) = model.dieFaces in
( Model ((modBy 6 (face1 + add1)) + 1, (modBy 6 (face2 + add2)) + 1 ) num
, waitRoll left model.numDice
)
waitRoll : Int -> Int -> Cmd Msg
waitRoll left num =
Process.sleep (toFloat (350 - (25 * left))) |> Task.perform (always <| (Roll (left - 1) num))
dice : Random.Generator (Int, Int)
dice =
Random.pair (Random.int 0 4) (Random.int 0 4)
-- SUBSCRIPTIONS
subscriptions : Model -> Sub Msg
subscriptions model =
Sub.none
-- VIEW
view : Model -> Html Msg
view model =
div []
[ die model.dieFaces model.numDice
, div [] []
, button [ onClick <| Roll 14 1] [ text "Roll 1 die" ]
, button [ onClick <| Roll 14 2] [ text "Roll 2 dice" ]
]
die : (Int, Int) -> Int -> Html Msg
die (roll1, roll2) numDice =
Svg.svg
[ A.width "240"
, A.height "120"
, A.viewBox "0 0 240 120"
]
[Svg.g
[ A.transform "translate (10 10)"
]
(dieBox "#de2424" :: (face roll1)),
Svg.g
[ A.transform "translate (130 10)"
, A.visibility <| display numDice
]
(dieBox "#245ade" :: (face roll2))
]
display num =
case num of
1 -> "hidden"
otherwise -> "visible"
dieBox fill =
Svg.rect
[ A.x "0"
, A.y "0"
, A.width "100"
, A.height "100"
, A.rx "15"
, A.ry "15"
, A.fill fill
, A.stroke "black"
]
[]
dots =
[ { x = "50", y = "50", cond = \x -> modBy 2 x == 1 }
, { x = "25", y = "25", cond = \x -> x /= 1 }
, { x = "75", y = "75", cond = \x -> x /= 1 }
, { x = "25", y = "50", cond = \x -> x == 6 }
, { x = "75", y = "50", cond = \x -> x == 6 }
, { x = "75", y = "25", cond = \x -> x > 3 }
, { x = "25", y = "75", cond = \x -> x > 3 }
]
face : Int -> List (Svg.Svg msg)
face roll =
List.map (dot roll) dots
dot roll d =
Svg.circle
[ A.cx d.x
, A.cy d.y
, A.r (drawR <| d.cond <| roll)
]
[]
drawR b =
case b of
True -> "8"
False -> "0"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment