Skip to content

Commit

Permalink
markets
Browse files Browse the repository at this point in the history
  • Loading branch information
efcasado committed May 11, 2024
1 parent 14e6794 commit 45e0576
Show file tree
Hide file tree
Showing 7 changed files with 177 additions and 48 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@ erl_crash.dump
hex.config
*.ez
uof_messages-*.tar
*~
*~
\#*
.\#*
10 changes: 0 additions & 10 deletions lib/uof/api/descriptions.ex
Original file line number Diff line number Diff line change
@@ -1,16 +1,6 @@
defmodule UOF.API.Descriptions do
alias UOF.API.Utils.HTTP

@doc """
Describe all currently available markets.
"""
def markets(lang \\ "en") do
# TO-DO: Optional mappings
endpoint = ["descriptions", lang, "markets.xml"]

HTTP.get(%UOF.API.Mappings.MarketDescriptions{}, endpoint)
end

@doc """
Get a list of all variants and which markets they are used for.
"""
Expand Down
149 changes: 149 additions & 0 deletions lib/uof/api/descriptions/market.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
defmodule UOF.API.Descriptions.Market do
@moduledoc """
Markets are the betting proposition with outcomes on which punters place their
bets. Different types of markets are defined for different fixtures.
"""
use Ecto.Schema
import Ecto.Changeset
import UOF.API.EctoHelpers

@doc """
List all supported markets.
"""
@spec all(include_mappings? :: boolean(), lang :: String.t()) :: list(Market.t())
def all(include_mappings? \\ false, lang \\ "en") do
case UOF.API.get("/descriptions/#{lang}/markets.xml",
query: [include_mappings: include_mappings?]
) do
{:ok, %_{status: 200, body: resp}} ->
resp
|> Map.get("market_descriptions")
|> Map.get("market")
|> Enum.map(fn x ->
{:ok, x} = changeset(x)
x
end)

{:error, _} = error ->
error
end
end

defmodule Outcome do
@moduledoc false
use Ecto.Schema
import Ecto.Changeset
import UOF.API.EctoHelpers

@primary_key false

embedded_schema do
field(:id, :integer)
field(:name, :string)
end

def changeset(model \\ %__MODULE__{}, params) do
cast(model, prepare(params), [:id, :name])
end

defp prepare(params) do
params
|> rename_fields
end
end

defmodule Specifier do
@moduledoc false
use Ecto.Schema
import Ecto.Changeset
import UOF.API.EctoHelpers

@primary_key false

embedded_schema do
# ["decimal", "integer", "string", "variable_text"]
field(:type, :string)
field(:name, :string)
end

def changeset(model \\ %__MODULE__{}, params) do
cast(model, prepare(params), [:name, :type])
end

defp prepare(params) do
params
|> rename_fields
end
end

@primary_key false

embedded_schema do
field(:id, :integer)
field(:name, :string)
field(:groups, {:array, :string})
# ["player", "competitor", "free_text"]
field(:outcome_type, :string)
field(:includes_outcomes_of_type, :string)
embeds_many(:outcomes, Outcome)
embeds_many(:specifiers, Specifier)
# TO-DO: embeds_many(:mappings, Mapping)
end

def changeset(model \\ %__MODULE__{}, params) do
model
|> cast(prepare(params), [:id, :name, :groups, :outcome_type, :includes_outcomes_of_type])
|> cast_embed(:outcomes)
|> cast_embed(:specifiers)
|> case do
%Ecto.Changeset{valid?: true} = changeset ->
{:ok, apply_changes(changeset)}

%Ecto.Changeset{} = changeset ->
{:error, {params, traverse_errors(changeset)}}
end
end

defp prepare(params) do
params
|> rename_fields
|> prepare_outcomes
|> prepare_specifiers
|> split_groups
end

defp prepare_outcomes(params) do
outcomes =
params
|> Map.get("outcomes", %{})
|> Map.get("outcome", [])

case outcomes do
outcome when not is_list(outcome) ->
Map.put(params, "outcomes", [outcome])

_ ->
Map.put(params, "outcomes", outcomes)
end
end

defp prepare_specifiers(params) do
specifiers =
params
|> Map.get("specifiers", %{})
|> Map.get("specifier", [])

case specifiers do
specifier when not is_list(specifier) ->
Map.put(params, "specifiers", [specifier])

_ ->
Map.put(params, "specifiers", specifiers)
end
end

defp split_groups(params) do
scope = String.split(params["groups"], "|")
Map.put(params, "groups", scope)
end
end
15 changes: 0 additions & 15 deletions lib/uof/api/mappings/market.ex

This file was deleted.

10 changes: 0 additions & 10 deletions lib/uof/api/mappings/market_descriptions.ex

This file was deleted.

25 changes: 25 additions & 0 deletions test/uof/api/descriptions/market_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
defmodule UOF.API.Descriptions.Market.Test do
use ExUnit.Case

setup do
:ok = Application.put_env(:tesla, UOF.API, adapter: Tesla.Mock)

Tesla.Mock.mock(fn
%{method: :get} ->
resp = File.read!("test/data/markets.xml")
%Tesla.Env{status: 200, headers: [{"content-type", "application/xml"}], body: resp}
end)

:ok
end

test "can parse UOF.API.Descriptions.Market.all/0 response" do
resp = UOF.API.Descriptions.Market.all()

assert Enum.count(resp) == 1172
assert hd(resp).id == 282
assert hd(resp).name == "Innings 1 to 5th top - {$competitor1} total"
assert hd(resp).groups == ["all", "score", "4.5_innings"]
assert Enum.map(hd(resp).outcomes, & &1.id) == [13, 12]
end
end
12 changes: 0 additions & 12 deletions test/uof/api/descriptions_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,6 @@ defmodule UOF.API.Descriptions.Test do
:ok
end

test "can parse UOF.API.Descriptions.markets/{0, 1} response" do
{:ok, desc} = UOF.API.Descriptions.markets()

market = hd(desc.markets)

assert Enum.count(desc.markets) == 1172
assert market.id == 282
assert market.name == "Innings 1 to 5th top - {$competitor1} total"
assert market.groups == "all|score|4.5_innings"
assert Enum.map(market.outcomes, & &1.id) == ["13", "12"]
end

test "can parse UOF.API.Descriptions.variants/{0, 1} response" do
{:ok, desc} = UOF.API.Descriptions.variants()

Expand Down

0 comments on commit 45e0576

Please sign in to comment.