2727
2828type alias Model =
2929 { gamesList : List Game
30+ , gameplaysList : List Gameplay
3031 , playersList : List Player
3132 }
3233
@@ -41,8 +42,16 @@ type alias Game =
4142 }
4243
4344
45+ type alias Gameplay =
46+ { gameId : Int
47+ , playerId : Int
48+ , playerScore : Int
49+ }
50+ 51+ 4452type alias Player =
45- { displayName : Maybe String
53+ { displayGameplays : Bool
54+ , displayName : Maybe String
4655 , id : Int
4756 , score : Int
4857 , username : String
@@ -52,6 +61,7 @@ type alias Player =
5261initialModel : Model
5362initialModel =
5463 { gamesList = []
64+ , gameplaysList = []
5565 , playersList = []
5666 }
5767
@@ -60,6 +70,7 @@ initialCommand : Cmd Msg
6070initialCommand =
6171 Cmd . batch
6272 [ fetchGamesList
73+ , fetchGameplaysList
6374 , fetchPlayersList
6475 ]
6576
@@ -81,6 +92,14 @@ fetchGamesList =
8192 }
8293
8394
95+ fetchGameplaysList : Cmd Msg
96+ fetchGameplaysList =
97+ Http . get
98+ { url = " /api/gameplays"
99+ , expect = Http . expectJson FetchGameplaysList decodeGameplaysList
100+ }
101+ 102+ 84103fetchPlayersList : Cmd Msg
85104fetchPlayersList =
86105 Http . get
@@ -107,6 +126,21 @@ decodeGame =
107126 ( Decode . field " title" Decode . string)
108127
109128
129+ decodeGameplaysList : Decode .Decoder (List Gameplay )
130+ decodeGameplaysList =
131+ decodeGameplay
132+ |> Decode . list
133+ |> Decode . at [ " data" ]
134+ 135+ 136+ decodeGameplay : Decode .Decoder Gameplay
137+ decodeGameplay =
138+ Decode . map3 Gameplay
139+ ( Decode . field " game_id" Decode . int)
140+ ( Decode . field " player_id" Decode . int)
141+ ( Decode . field " player_score" Decode . int)
142+ 143+ 110144decodePlayersList : Decode .Decoder (List Player )
111145decodePlayersList =
112146 decodePlayer
@@ -116,7 +150,8 @@ decodePlayersList =
116150
117151decodePlayer : Decode .Decoder Player
118152decodePlayer =
119- Decode . map4 Player
153+ Decode . map5 Player
154+ ( Decode . succeed False )
120155 ( Decode . maybe ( Decode . field " display_name" Decode . string))
121156 ( Decode . field " id" Decode . int)
122157 ( Decode . field " score" Decode . int)
@@ -129,7 +164,9 @@ decodePlayer =
129164
130165type Msg
131166 = FetchGamesList ( Result Http . Error ( List Game ))
167+ | FetchGameplaysList ( Result Http . Error ( List Gameplay ))
132168 | FetchPlayersList ( Result Http . Error ( List Player ))
169+ | TogglePlayerGameplays Player
133170
134171
135172update : Msg -> Model -> ( Model , Cmd Msg )
@@ -144,15 +181,45 @@ update msg model =
144181 Debug . log " Error fetching games from API."
145182 ( model, Cmd . none )
146183
147- FetchPlayersList result ->
184+ FetchGameplaysList result ->
148185 case result of
149- Ok players ->
150- ( { model | playersList = players }, Cmd . none )
186+ Ok gameplays ->
187+ ( { model | gameplaysList = gameplays }, Cmd . none )
151188
152189 Err _ ->
190+ Debug . log " Error fetching gameplays from API."
191+ ( model, Cmd . none )
192+ 193+ FetchPlayersList result ->
194+ case result of
195+ Ok players ->
196+ let
197+ updatedPlayersList =
198+ players
199+ |> List . map
200+ ( \ player -> { player | score = findTotalScoreForPlayer model player } )
201+ in
202+ ( { model | playersList = updatedPlayersList }, Cmd . none )
203+ 204+ Err message ->
153205 Debug . log " Error fetching players from API."
154206 ( model, Cmd . none )
155207
208+ TogglePlayerGameplays player ->
209+ let
210+ updatedPlayersList =
211+ List . map
212+ ( \ p ->
213+ if p. id == player. id then
214+ { player | displayGameplays = not player. displayGameplays }
215+ 216+ else
217+ p
218+ )
219+ model. playersList
220+ in
221+ ( { model | playersList = updatedPlayersList }, Cmd . none )
222+ 156223
157224
158225-- SUBSCRIPTIONS
@@ -252,45 +319,127 @@ gamesListItem game =
252319-- PLAYERS
253320
254321
255- playersIndex : Model -> Html msg
322+ playersIndex : Model -> Html Msg
256323playersIndex model =
257324 if List . isEmpty model. playersList then
258325 div [] []
259326
260327 else
261328 div [ class " players-index container" ]
262- [ h2 [] [ text " Players" ]
263- , model. playersList
264- |> playersSortedByScore
265- |> playersList
329+ [ h2 [] [ text " Player Scores" ]
330+ , playersList model
266331 ]
267332
268333
269- playersSortedByScore : List Player -> List Player
270- playersSortedByScore players =
271- players
272- |> List . sortBy . score
273- |> List . reverse
334+ playersList : Model -> Html Msg
335+ playersList model =
336+ model. playersList
337+ |> sortPlayersByScore
338+ |> List . map ( playersListItem model)
339+ |> ul [ class " players-list" ]
274340
275341
276- playersList : List Player -> Html msg
277- playersList players =
278- ul [ class " players-list" ] ( List . map playersListItem players)
342+ playersListItem : Model -> Player -> Html Msg
343+ playersListItem model player =
344+ li [ class " player-item" ]
345+ [ playersListItemName player
346+ , playersListItemScore model player
347+ , if player. displayGameplays then
348+ gameplaysList model player
349+ 350+ else
351+ div [] []
352+ ]
279353
280354
281- playersListItem : Player -> Html msg
282- playersListItem player =
355+ playersListItemName : Player -> Html Msg
356+ playersListItemName player =
283357 let
284- playerLink name =
285- a [ href ( " players/" ++ String . fromInt player. id) ]
286- [ strong [ class " player-name" ] [ text name ] ]
358+ displayName =
359+ case player. displayName of
360+ Just name ->
361+ name
362+ 363+ Nothing ->
364+ player. username
287365 in
288- li [ class " player-item " ]
289- [ p [ class " player-score " ] [ text ( String . fromInt player. score ) ]
290- , case player . displayName of
291- Just displayName ->
292- playerLink displayName
366+ strong [ ]
367+ [ a [ onClick ( TogglePlayerGameplays player) ]
368+ [ text displayName ]
369+ ]
370+ 293371
294- Nothing ->
295- playerLink player. username
372+ playersListItemScore : Model -> Player -> Html Msg
373+ playersListItemScore model player =
374+ let
375+ playerScore =
376+ findTotalScoreForPlayer model player
377+ in
378+ span [ class " player-score" ]
379+ [ text ( String . fromInt playerScore) ]
380+ 381+ 382+ 383+ -- GAMEPLAYS
384+ 385+ 386+ gameplaysList : Model -> Player -> Html msg
387+ gameplaysList model player =
388+ let
389+ gameplays =
390+ findGameplaysForPlayer model player
391+ in
392+ if List . isEmpty gameplays then
393+ div [ class " gameplays-empty" ]
394+ [ text " No gameplays to display yet!" ]
395+ 396+ else
397+ div [ class " gameplays" ]
398+ ( List . map ( gameplaysListItem model) gameplays)
399+ 400+ 401+ gameplaysListItem : Model -> Gameplay -> Html msg
402+ gameplaysListItem model gameplay =
403+ let
404+ gameTitle =
405+ case findGameForGameplay model gameplay of
406+ Just game ->
407+ game. title
408+ 409+ Nothing ->
410+ String . fromInt gameplay. gameId
411+ in
412+ div []
413+ [ strong [] [ text ( gameTitle ++ " : " ) ]
414+ , span [] [ text ( String . fromInt gameplay. playerScore) ]
296415 ]
416+ 417+ 418+ 419+ -- HELPERS
420+ 421+ 422+ findGameplaysForPlayer : Model -> Player -> List Gameplay
423+ findGameplaysForPlayer model player =
424+ List . filter ( \ gameplay -> gameplay. playerId == player. id) model. gameplaysList
425+ 426+ 427+ findGameForGameplay : Model -> Gameplay -> Maybe Game
428+ findGameForGameplay model gameplay =
429+ model. gamesList
430+ |> List . filter ( \ game -> game. id == gameplay. gameId)
431+ |> List . head
432+ 433+ 434+ findTotalScoreForPlayer : Model -> Player -> Int
435+ findTotalScoreForPlayer model player =
436+ findGameplaysForPlayer model player
437+ |> List . map . playerScore
438+ |> List . sum
439+ 440+ 441+ sortPlayersByScore : List Player -> List Player
442+ sortPlayersByScore players =
443+ players
444+ |> List . sortBy . score
445+ |> List . reverse
0 commit comments