-
Notifications
You must be signed in to change notification settings - Fork 2
/
View.elm
260 lines (200 loc) · 7.09 KB
/
View.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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
module View exposing (view)
import Array exposing (Array)
import Browser exposing (Document)
import Domain exposing (..)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onClick)
import Style exposing (stylesheet)
import Time exposing (Posix)
import UI as PlayerAction exposing (Msg, PlayerAction)
import Util exposing (mapMaybeToList, otherElements)
onClickDo : PlayerAction -> Attribute Msg
onClickDo action =
onClick (PlayerAction.PlayerAction action)
cardContent : Card -> List (Html Msg) -> List (Html Msg)
cardContent card buttons =
List.append buttons [ text card.name, priceMeterView card.cardType ]
viewCard : Card -> Html Msg
viewCard card =
div [ class "card" ]
(cardContent card [])
fieldView : Player -> Index -> Field -> Html Msg
fieldView player index field =
let
{ amount, card } =
field
cardText =
text (card.name ++ " (" ++ String.fromInt amount ++ ")")
sellAmount =
Domain.sellPrice amount card.cardType
sellButton =
button [ onClickDo (PlayerAction.SellField player index) ] [ text ("Sell $" ++ String.fromInt sellAmount) ]
in
div [ class "card" ] [ cardText, sellButton, priceMeterView card.cardType ]
tradeButtonsView players player cardIndex =
let
tradeForPlayer toPlayer =
button
[ class "tradeButton"
, onClickDo (PlayerAction.Trade player cardIndex toPlayer)
]
[ text ("to " ++ toPlayer.nick) ]
in
List.map tradeForPlayer players
tradeFromHandButtonsView players player cardIndex =
let
tradeForPlayer toPlayer =
button
[ class "tradeButton"
, onClickDo (PlayerAction.TradeFromHand player cardIndex toPlayer)
]
[ text ("to " ++ toPlayer.nick) ]
in
List.map tradeForPlayer players
plantButton player =
button
[ class "plantButton"
, onClickDo (PlayerAction.PlantFromHand player)
]
[ text "Plant" ]
plantSideButton player index =
button
[ class "plantButton"
, onClickDo (PlayerAction.PlantFromSide player index)
]
[ text "Plant" ]
keepButton player index =
button [ onClickDo (PlayerAction.KeepFromTrade player index) ]
[ text "Keep" ]
viewTopMostHandCard players player card =
let
cardIndex =
0
tradeButtons =
tradeFromHandButtonsView players player cardIndex
buttons =
plantButton player :: tradeButtons
in
div [ class "card" ] (cardContent card buttons)
amountToPriceView { amount, money } =
div [ class "priceMapping" ]
[ div [ class "coins" ]
[ text (String.fromInt money) ]
, div [ class "meterLimit" ]
[ text (String.fromInt amount) ]
]
priceMeterView : CardType -> Html Msg
priceMeterView cardType =
let
meterList =
Domain.priceMeterList cardType
priceColumns =
Array.map amountToPriceView meterList |> Array.toList
in
div [ class "priceMeter" ] priceColumns
viewHand : List Player -> Player -> List Card -> List (Html Msg)
viewHand players player hand =
let
topmost =
List.head hand
topmostView =
mapMaybeToList (viewTopMostHandCard players player) topmost
cardWithTrades cardIndex card =
div [ class "card" ]
(cardContent card (tradeFromHandButtonsView players player cardIndex))
-- note: indexing contains the first hand so that the rest get correct hand index
cardsUnderTopView =
List.drop 1 (List.indexedMap cardWithTrades hand)
in
List.append topmostView cardsUnderTopView
sideView : List Player -> Player -> List Card -> List (Html Msg)
sideView players player side =
let
sideCardView index card =
div [ class "card" ] (cardContent card [ plantSideButton player index ])
in
List.indexedMap sideCardView side
fieldsView : Player -> Array Field -> List (Html Msg)
fieldsView player fields =
let
fv index field =
div [ class "field" ] [ fieldView player index field ]
in
Array.indexedMap fv fields |> Array.toList
tradeView : List Player -> Player -> List Card -> List (Html Msg)
tradeView players player trade =
let
tradeCardView index card =
let
tradeButtons =
tradeButtonsView players player index
keepBtn =
keepButton player index
tradeViewContent =
cardContent card (keepBtn :: tradeButtons)
iv =
div [] [ text (String.fromInt index) ]
in
div [ class "card" ] (iv :: tradeViewContent)
in
List.indexedMap tradeCardView trade
playerView : List Player -> Player -> List (Html Msg)
playerView players player =
let
( o1, o2 ) =
otherElements players (\( i, p ) -> p.nick == player.nick)
otherPlayers =
List.append o1 o2
in
[ div [ class "player-info" ]
[ text ("Player: " ++ player.nick)
, span [ class "money" ] [ text ("Money: " ++ String.fromInt player.money) ]
]
, button [ onClickDo (PlayerAction.DrawCardsToTrade player) ] [ text "Draw cards for trade" ]
, button [ onClickDo (PlayerAction.DrawCardsToHand player) ] [ text "Draw cards to hand" ]
, div [ class "fields-and-hand" ]
[ div [ class "fields" ] (fieldsView player player.fields)
, div [ class "hand" ] (viewHand otherPlayers player (Array.toList player.hand))
]
, div [ class "trading" ]
[ div [ class "trade" ] (tradeView otherPlayers player (Array.toList player.trade))
, div [ class "side" ] (sideView otherPlayers player (Array.toList player.side))
]
]
timeView : Maybe Posix -> Posix -> Html Msg
timeView startTime currentTime =
let
currentM =
Time.posixToMillis currentTime
startM =
Maybe.map Time.posixToMillis startTime
playTime =
Maybe.withDefault 0 (Maybe.map (\start -> currentM - start) startM)
timeInSeconds =
playTime // 1000 |> String.fromInt
in
div [ class "time" ]
[ text "Play time: "
, span [ class "seconds" ] [ text <| timeInSeconds ]
, text " seconds."
]
view : Model -> Document Msg
view model =
let
playerList =
Array.toList model.players
deckView =
div [ class "deck" ] (List.map viewCard (Array.toList model.deck))
discardView =
div [ class "discard" ] (List.map viewCard (Array.toList model.discard))
playersView =
List.concatMap (playerView playerList) playerList
playTimeView =
timeView model.startTime model.currentTime
gameView =
stylesheet :: playTimeView :: deckView :: discardView :: playersView
in
{ title = "Elmonkorjuu"
, body = [ div [ class "game-view" ] gameView ]
}