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
|
port module Client exposing (main)
import Browser
import Html exposing (Html)
import Html.Attributes
import Html.Events
import Json.Decode
import Json.Encode
import Messages exposing (GameView)
import Url exposing (Url)
port webSocketIn : (String -> msg) -> Sub msg
port webSocketOut : String -> Cmd msg
type Msg
= Ignore
| Send
| WebSocketIn String
-- Name changes
| ChangeMyName String
| SubmitMyName
type Model
= Error String
| Connecting
{ roomId : String
}
| Game
{ view : GameView
, changeMyName : String
}
parseRoomId : Url -> Result String String
parseRoomId url = case String.split "/" url.path of
_ :: "rooms" :: roomId :: _ -> Ok roomId
_ -> Err <| "Invalid path: " ++ url.path
view : Model -> List (Html Msg)
view model = case model of
Error str ->
[ Html.h1 [] [Html.text "Error"]
, Html.p [] [Html.text str]
]
Connecting state ->
[ Html.h1 []
[Html.text <| "Connecting to room " ++ state.roomId ++ "..."]
]
Game game ->
[ Html.h1 [] [Html.text "Opponents"]
, Html.ul [] <| List.map
(\p -> Html.li [] [Html.text p])
game.view.opponents
, Html.h1 [] [Html.text "You"]
, Html.form
[ Html.Attributes.action ""
, Html.Events.onSubmit SubmitMyName
]
[ Html.input
[ Html.Attributes.value game.changeMyName
, Html.Events.onInput ChangeMyName
]
[]
, Html.button
[ Html.Attributes.type_ "submit"
, Html.Attributes.disabled <|
game.view.myName == game.changeMyName
]
[Html.text "change"]
]
]
subscriptions : Model -> Sub Msg
subscriptions model = webSocketIn WebSocketIn
send : Messages.ClientMessage -> Cmd Msg
send = webSocketOut << Json.Encode.encode 0 << Messages.jsonEncClientMessage
update : Msg -> Model -> (Model, Cmd Msg)
update msg model = case msg of
Ignore -> (model, Cmd.none)
Send -> (model, webSocketOut "Hi")
WebSocketIn json ->
case Json.Decode.decodeString Messages.jsonDecServerMessage json of
Err str -> (Error <| Json.Decode.errorToString str, Cmd.none)
Ok (Messages.Welcome playerId) ->
Debug.log ("Welcome " ++ String.fromInt playerId) (model, Cmd.none)
Ok Messages.Bye -> Debug.log "Bye" (model, Cmd.none)
Ok (Messages.SyncGameView gameView) ->
case model of
Game game -> (Game {game | view = gameView}, Cmd.none)
_ ->
( Game
{ view = gameView
, changeMyName = gameView.myName
}
, Cmd.none
)
ChangeMyName name -> case model of
Game game -> (Game {game | changeMyName = name}, Cmd.none)
_ -> (model, Cmd.none)
SubmitMyName -> case model of
Game game -> (model , send <| Messages.ChangeMyName game.changeMyName)
_ -> (model, Cmd.none)
main : Program () Model Msg
main = Browser.application
{ init = \() url key -> case parseRoomId url of
Err str -> (Error <| "Could not parse room ID: " ++ str, Cmd.none)
Ok roomId -> (Connecting {roomId = roomId}, Cmd.none)
, update = update
, subscriptions = subscriptions
, view = \model -> {title = "Client", body = view model}
, onUrlChange = \url -> Ignore
, onUrlRequest = \urlRequest -> Ignore
}
|