-
Notifications
You must be signed in to change notification settings - Fork 0
/
Dice.elm
160 lines (129 loc) · 3.11 KB
/
Dice.elm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
module Dice exposing (program, DiceSpec)
import Html as H exposing (Html, Attribute)
import Html.Attributes as A
import Html.Events as E
import Html.App as App
import Random exposing (Generator)
import Array exposing (Array)
import Array.Extra
type alias Element msg =
List (Attribute msg) -> Html msg
type alias DiceSpec val =
{ view : val -> Element Msg
, gen : Generator val
, toInt : val -> Int
}
type alias Die =
{ view : Element Msg
, value : Int
}
type alias Model =
Array Die
type alias Id =
Int
type Msg
= Roll Id
| RollAll
| NewRoll Id Die
| NewDice (List Die)
| NewDie Die
| AddDie
| RemoveDie
update :
Generator Die
-> Msg
-> Model
-> ( Model, Cmd Msg )
update gen msg model =
case msg of
Roll id ->
( model
, Random.generate (NewRoll id) gen
)
NewRoll id value ->
( Array.set id value model
, Cmd.none
)
RollAll ->
( model
, model
|> Array.length
|> roll gen
)
AddDie ->
( model
, Random.generate NewDie gen
)
RemoveDie ->
(let
newSize =
(Array.length model) - 1
in
( Array.Extra.removeAt newSize model
, Cmd.none
)
)
NewDice newDice ->
( Array.fromList newDice, Cmd.none )
NewDie value ->
( Array.push value model, Cmd.none )
menu : Model -> Html Msg
menu model =
H.menu []
[ H.button [ E.onClick RemoveDie ] [ H.text "-" ]
, H.button [ E.onClick RollAll ]
[ H.text
(model
|> Array.toList
|> List.map .value
|> List.sum
|> toString
)
]
, H.button [ E.onClick AddDie ] [ H.text "+" ]
]
view : Model -> Html Msg
view model =
let
indexedDie ( id, die ) =
die.view [ E.onClick (Roll id) ]
in
H.div []
[ H.ul
[ A.class "dice" ]
(model
|> Array.toIndexedList
|> List.map indexedDie
|> List.map (\el -> H.li [] [ el ])
)
, menu model
]
roll : Generator Die -> Int -> Cmd Msg
roll gen count =
gen
|> Random.list count
|> Random.generate NewDice
init : Generator Die -> Int -> ( Model, Cmd Msg )
init gen count =
( Array.empty
, roll gen count
)
program : DiceSpec val -> Program Never
program spec =
let
die value =
{ view = spec.view value
, value = spec.toInt value
}
in
spec.gen
|> Random.map die
|> program_
program_ : Generator Die -> Program Never
program_ gen =
App.program
{ init = init gen 4
, update = update gen
, view = view
, subscriptions = (always Sub.none)
}