206 lines
5.2 KiB
Elm
206 lines
5.2 KiB
Elm
module EloTracker exposing (main)
|
|
|
|
import Api.Elo as Elo
|
|
import Element exposing (Element)
|
|
import Element.Background
|
|
import Element.Font
|
|
import Http
|
|
import Json.Decode as D
|
|
import Layout
|
|
import Pixels
|
|
import Program
|
|
import Screen.Leaderboard
|
|
import Theme
|
|
import Time
|
|
import Widget.Icon
|
|
|
|
|
|
main =
|
|
Program.document
|
|
{ flagsDecoder = D.field "baseUrl" D.string
|
|
, headers = headers
|
|
, init = init
|
|
, subscriptions = subscriptions
|
|
, title = title
|
|
, update = update
|
|
, view = view
|
|
}
|
|
|
|
|
|
|
|
-- MODEL
|
|
|
|
|
|
type alias Model =
|
|
{ baseUrl : String
|
|
, leaderboard : Result Int Elo.Leaderboard
|
|
, matches : Result Int (List Elo.Match)
|
|
, selectedName : String
|
|
}
|
|
|
|
|
|
type Msg
|
|
= OnLeaderboard (Result Http.Error Elo.Leaderboard)
|
|
| OnMatches (Result Http.Error (List Elo.Match))
|
|
| OnSelectLeaderboardName String
|
|
| RefreshLeaderboard
|
|
| RefreshMatches
|
|
|
|
|
|
init : Result D.Error String -> ( Model, Cmd Msg )
|
|
init flag =
|
|
let
|
|
baseUrl =
|
|
case flag of
|
|
Err _ ->
|
|
"http://localhost:5000"
|
|
|
|
Ok v ->
|
|
v
|
|
|
|
model =
|
|
{ baseUrl = baseUrl
|
|
, leaderboard = Err 0
|
|
, matches = Err 0
|
|
, selectedName = "tic-tac-toe"
|
|
}
|
|
in
|
|
( model
|
|
, Cmd.batch
|
|
[ getLeaderboard model
|
|
, getMatches model
|
|
]
|
|
)
|
|
|
|
|
|
|
|
-- UPDATE
|
|
|
|
|
|
update : Msg -> Model -> ( Model, Cmd Msg )
|
|
update msg model =
|
|
case msg of
|
|
OnLeaderboard (Err _) ->
|
|
case model.leaderboard of
|
|
Err n ->
|
|
( { model | leaderboard = Err (n + 1) }, Cmd.none )
|
|
|
|
Ok _ ->
|
|
( model, Cmd.none )
|
|
|
|
OnLeaderboard (Ok v) ->
|
|
( { model | leaderboard = Ok v }, Cmd.none )
|
|
|
|
OnMatches (Err _) ->
|
|
case model.matches of
|
|
Err n ->
|
|
( { model | matches = Err (n + 1) }, Cmd.none )
|
|
|
|
Ok _ ->
|
|
( model, Cmd.none )
|
|
|
|
OnMatches (Ok v) ->
|
|
( { model | matches = Ok v }, Cmd.none )
|
|
|
|
OnSelectLeaderboardName name ->
|
|
( { model | selectedName = name }, Cmd.none )
|
|
|
|
RefreshLeaderboard ->
|
|
( model, getLeaderboard model )
|
|
|
|
RefreshMatches ->
|
|
( model, getMatches model )
|
|
|
|
|
|
getLeaderboard : Model -> Cmd Msg
|
|
getLeaderboard model =
|
|
Elo.getLeaderboard { baseUrl = model.baseUrl, toMsg = OnLeaderboard }
|
|
|
|
|
|
getMatches : Model -> Cmd Msg
|
|
getMatches model =
|
|
Elo.getMatches { baseUrl = model.baseUrl, toMsg = OnMatches }
|
|
|
|
|
|
|
|
-- SUBSCRIPTIONS
|
|
|
|
|
|
subscriptions : Model -> Sub Msg
|
|
subscriptions _ =
|
|
Sub.batch
|
|
[ Time.every (5 * 1000) (always RefreshLeaderboard)
|
|
, Time.every (1 * 60 * 1000) (always RefreshMatches)
|
|
]
|
|
|
|
|
|
|
|
-- VIEW
|
|
|
|
|
|
headers : Model -> List { icon : Widget.Icon.Icon msg, onPress : msg }
|
|
headers _ =
|
|
[]
|
|
|
|
|
|
title : Model -> String
|
|
title model =
|
|
case model.leaderboard of
|
|
Err _ ->
|
|
"EloTracker | Loading..."
|
|
|
|
Ok _ ->
|
|
"EloTracker | Leaderboard"
|
|
|
|
|
|
view : Program.ViewBox Model -> Element Msg
|
|
view data =
|
|
case data.model.leaderboard of
|
|
Err 0 ->
|
|
Element.column
|
|
[ Element.width <| Element.px <| Pixels.inPixels data.size.width
|
|
, Element.height <| Element.px <| Pixels.inPixels data.size.height
|
|
]
|
|
[ Element.column
|
|
[ Element.centerX
|
|
, Element.centerY
|
|
, Element.Background.color (Theme.mantleUI data.flavor)
|
|
, Element.padding 15
|
|
, Element.spacing 10
|
|
]
|
|
[ Element.text "Loading leaderboard..."
|
|
, Layout.loadingIndicator { color = Theme.lavender data.flavor }
|
|
|> Element.el [ Element.centerX ]
|
|
]
|
|
]
|
|
|
|
Err n ->
|
|
Element.column
|
|
[ Element.width <| Element.px <| Pixels.inPixels data.size.width
|
|
, Element.height <| Element.px <| Pixels.inPixels data.size.height
|
|
]
|
|
[ Element.column
|
|
[ Element.centerX
|
|
, Element.centerY
|
|
, Element.Background.color (Theme.mantleUI data.flavor)
|
|
, Element.padding 15
|
|
, Element.spacing 10
|
|
]
|
|
[ Element.text "Loading leaderboard..."
|
|
, Element.el [ Element.centerX, Element.Font.color (Theme.redUI data.flavor) ] (Element.text ("Failed " ++ String.fromInt n ++ " times"))
|
|
, Layout.loadingIndicator { color = Theme.lavender data.flavor }
|
|
|> Element.el [ Element.centerX ]
|
|
]
|
|
]
|
|
|
|
Ok leaderboard ->
|
|
Screen.Leaderboard.view
|
|
{ flavor = data.flavor
|
|
, model =
|
|
{ board = leaderboard
|
|
, onSelect = OnSelectLeaderboardName
|
|
, selectedName = data.model.selectedName
|
|
}
|
|
, size = data.size
|
|
}
|