starts with a dedicated Api module, wip...

This commit is contained in:
2019-11-05 16:03:15 +01:00
parent d56ca38dcb
commit dfd1e99d1c
2 changed files with 243 additions and 215 deletions

173
src/Api.elm Normal file
View File

@@ -0,0 +1,173 @@
module Api exposing (..)
import Http
import Json.Decode as D
import Json.Decode exposing (Decoder, int, string)
import Json.Encode as E
type alias HttpResult a = (Result Http.Error a)
type alias Response =
{ value: Maybe String
, notification: Maybe String
, updates : Maybe (List Update)
, errors : Maybe String
}
type Update
= ItemRemoved Item
| ItemAdded Item
| WealthUpdated Wealth
| ClaimAdded ()
| ClaimRemoved ()
type Msg
= GotPlayer (HttpResult Player)
| GotClaims Int (HttpResult Claims)
| GotLoot ToChest (HttpResult Loot)
| GotActionResult (HttpResult Response)
-- PLAYERS
--
fetchPlayer : Int -> Cmd Msg
fetchPlayer id =
Http.get
{ url = "http://localhost:8088/api/players/" ++ (String.fromInt id) ++ "/"
, expect = Http.expectJson Main.GotPlayer (valueDecoder playerDecoder )
}
playerDecoder : Decoder Player
playerDecoder =
D.map4 Player
(D.field "id" int)
(D.field "name" string)
(D.field "debt" int)
wealthDecoder
wealthDecoder : Decoder Wealth
wealthDecoder =
D.map4 Wealth
(D.field "cp" int)
(D.field "sp" int)
(D.field "gp" int)
(D.field "pp" int)
-- LOOT
-- Location of a loot
type ToChest
= OfPlayer Int
| OfGroup
| OfShop
itemDecoder =
D.map3 Item
(D.field "id" int)
(D.field "name" string)
(D.field "base_price" int)
lootDecoder : Decoder Loot
lootDecoder =
Json.Decode.list itemDecoder
fetchLoot : Main.ToChest -> Cmd Msg
fetchLoot dest =
let
url = case dest of
Main.OfPlayer id -> "http://localhost:8088/api/players/" ++ (String.fromInt id) ++ "/loot"
Main.OfShop -> "http://localhost:8088/api/items"
Main.OfGroup -> "http://localhost:8088/api/players/0/loot"
in
Http.get
{ url = url
, expect = Http.expectJson (GotLoot dest) (valueDecoder lootDecoder)}
-- CLAIMS
claimDecoder =
D.map3 Claim
(D.field "id" int)
(D.field "player_id" int)
(D.field "loot_id" int)
fetchClaims : Int -> Cmd Msg
fetchClaims playerId =
Http.get
{ url = "http://localhost:8088/api/claims"
, expect = valueDecoder (D.list claimDecoder)
|> Http.expectJson (GotClaims playerId)
}
-- API Response
--
valueDecoder : Decoder a -> Decoder a
valueDecoder thenDecoder =
D.field "value" thenDecoder
-- TODO: update server to produce better json
-- like an object with list of updates of the same type
-- { ItemRemoved : [..], Wealth : [ .. ], .. }
updatesDecoder : Decoder DbUpdate
updatesDecoder =
-- We expect one update but do not know it's kind
Json.Decode.oneOf
[ (field "ItemRemoved" (itemDecoder |> Json.Decode.andThen (\i -> succeed <| ItemRemoved i)))
, (field "ItemAdded" (itemDecoder |> Json.Decode.andThen (\i -> succeed <| ItemAdded i)))
, (field "Wealth" (wealthDecoder |> Json.Decode.andThen (\i -> succeed <| WealthUpdated i)))
, (field "ClaimRemoved" (succeed () |> Json.Decode.andThen (\i -> succeed <| ClaimRemoved i)))
, (field "ClaimAdded" (succeed () |> Json.Decode.andThen (\i -> succeed <| ClaimAdded i)))
]
apiResponseDecoder : Decoder ApiResponse
apiResponseDecoder =
Json.Decode.map4 ApiResponse
(D.maybe (field "value" string))
(Json.Decode.maybe (field "notification" string))
(Json.Decode.maybe (field "updates" (Json.Decode.list updatesDecoder)))
(Json.Decode.maybe (field "errors" string))
undoLastAction id = Http.request
{ url = "http://localhost:8088/api/players/" ++ String.fromInt id ++"/events/last"
, method = "DELETE"
, headers = []
, body = Http.emptyBody
, expect = Http.expectJson GotActionResult apiResponseDecoder
, timeout = Nothing
, tracker = Nothing
}
sendRequest : Maybe ViewMode -> Model -> Cmd Msg
sendRequest activeMode model =
case activeMode of
Nothing -> Cmd.none
Just mode ->
let
(endpoint, method) = case mode of
Add ->
( "http://localhost:8088/api/players/" ++ (String.fromInt model.player.id) ++ "/loot"
, "POST"
)
Buy ->
( "http://localhost:8088/api/players/" ++ (String.fromInt model.player.id) ++ "/loot"
, "PUT"
)
Sell ->
( "http://localhost:8088/api/players/" ++ (String.fromInt model.player.id) ++ "/loot"
, "DELETE"
)
Grab ->
( "http://localhost:8088/api/players/" ++ (String.fromInt model.player.id) ++ "/claims"
, "POST")
in
Http.request
{ method = method
, headers = []
, url = endpoint
, body = Http.jsonBody <| buildPayload mode model
, expect = Http.expectJson GotActionResult apiResponseDecoder
, timeout = Nothing
, tracker = Nothing
}