Skip to content

Commit

Permalink
WIP Refactoring
Browse files Browse the repository at this point in the history
- Simplify dependencies
- Remove structs (use maps)
- Make use of helper functions more
  • Loading branch information
hkyplyr committed Feb 27, 2024
1 parent 6a6da51 commit ab76438
Show file tree
Hide file tree
Showing 55 changed files with 1,317 additions and 1,535 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ jobs:
if: ${{ matrix.lint }}

- name: Run tests
run: mix test --cover --include ci_only
run: mix test --cover

- name: Run dialyzer
run: mix dialyzer
3 changes: 2 additions & 1 deletion config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Config
config :yahoo_fantasy_ex,
base_url: "https://fantasysports.yahooapis.com/fantasy/v2",
authorize_url: "https://api.login.yahoo.com/oauth2/request_auth",
token_url: "https://api.login.yahoo.com/oauth2/get_token"
token_url: "https://api.login.yahoo.com/oauth2/get_token",
token_file: ".tokens.json"

import_config "#{Mix.env()}.exs"
4 changes: 0 additions & 4 deletions config/test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,3 @@ config :yahoo_fantasy_ex,
base_url: "http://localhost:7997",
authorize_url: "http://localhost:7998",
token_url: "http://localhost:7999"

config :bypass, enable_debug_log: true

config :logger, level: :debug
3 changes: 0 additions & 3 deletions lib/yahoo_fantasy_ex.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ defmodule YahooFantasyEx do

def model do
quote do
use ExConstructor

import YahooFantasyEx.Models.Helpers
import YahooFantasyEx.Models.Types.Positions
import YahooFantasyEx.Models.Types.PositionTypes
Expand All @@ -15,7 +13,6 @@ defmodule YahooFantasyEx do
alias YahooFantasyEx.Models.League.DraftResult
alias YahooFantasyEx.Models.League.Settings
alias YahooFantasyEx.Models.League.Settings.RosterPosition
alias YahooFantasyEx.Models.League.Settings.StatCategory
alias YahooFantasyEx.Models.League.Settings.StatModifier
alias YahooFantasyEx.Models.Manager
alias YahooFantasyEx.Models.Matchup
Expand Down
5 changes: 3 additions & 2 deletions lib/yahoo_fantasy_ex/api/client.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ defmodule YahooFantasyEx.Api.Client do

url = "#{base_url()}#{path}"

%Req.Response{body: body} = Req.get!(url: url, headers: headers, params: @params)
%Req.Response{body: body} =
Req.get!(url: url, headers: headers, params: @params, http_errors: :raise)

Jason.decode!(body)
Jason.decode!(body, keys: :atoms)
end

defp base_url, do: Application.get_env(:yahoo_fantasy_ex, :base_url)
Expand Down
55 changes: 2 additions & 53 deletions lib/yahoo_fantasy_ex/api/parser.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,62 +2,11 @@ defmodule YahooFantasyEx.Api.Parser do
@moduledoc false

alias YahooFantasyEx.Models.League
alias YahooFantasyEx.Models.League.DraftResult
alias YahooFantasyEx.Models.League.Settings
alias YahooFantasyEx.Models.Matchup
alias YahooFantasyEx.Models.Player
alias YahooFantasyEx.Models.Team
alias YahooFantasyEx.Models.Transaction

@spec parse(map()) :: League.t()
def parse(%{"fantasy_content" => fantasy_content}), do: do_parse(fantasy_content)
def parse(%{fantasy_content: fantasy_content}), do: do_parse(fantasy_content)

defp do_parse(%{"league" => league}) do
defp do_parse(%{league: league}) do
League.new(league)
end

@type subresource ::
Settings.t()
| [DraftResult.t()]
| [Matchup.t()]
| [Player.t()]
| [Team.t()]
| [Transaction.t()]

@spec parse_subresource(%{String.t() => map()}, any()) :: {atom(), subresource()}
def parse_subresource(subresource, parent \\ nil)

def parse_subresource(%{"teams" => teams}, _parent) do
{:teams, parse_valid_entities(teams, &Team.new/1)}
end

def parse_subresource(%{"settings" => settings}, parent) do
{:settings, Settings.new(settings, parent)}
end

def parse_subresource(%{"draft_results" => draft_results}, _parent) do
{:draft_results, parse_valid_entities(draft_results, &DraftResult.new/1)}
end

def parse_subresource(%{"players" => players}, _parent) do
{:players, parse_valid_entities(players, &Player.new/1)}
end

def parse_subresource(%{"transactions" => transactions}, _parent) do
{:transactions, parse_valid_entities(transactions, &Transaction.new/1)}
end

def parse_subresource(%{"scoreboard" => %{"0" => %{"matchups" => matchups}}}, _parent) do
{:scoreboard, parse_valid_entities(matchups, &Matchup.new/1)}
end

def parse_subresource(%{"standings" => [%{"teams" => teams}]}, _parent) do
{:standings, parse_valid_entities(teams, &Team.new/1)}
end

defp parse_valid_entities(entities, constructor) do
entities
|> Enum.reject(&(elem(&1, 0) == "count"))
|> Enum.map(&constructor.(&1))
end
end
20 changes: 6 additions & 14 deletions lib/yahoo_fantasy_ex/auth.ex
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
defmodule YahooFantasyEx.Auth do
@moduledoc false

defp client_id, do: System.get_env("CLIENT_ID")
defp client_secret, do: System.get_env("CLIENT_SECRET")
alias YahooFantasyEx.Tokens

@doc """
Retrieves the access token to include in the request.
## Examples
iex> YahooFantasyEx.Auth.get_access_token()
"access_token"
"""
@spec get_access_token :: String.t()
def get_access_token do
case token_manager().read() do
case Tokens.read() do
{:ok, binary} ->
%{
"access_token" => access_token,
Expand Down Expand Up @@ -46,7 +40,7 @@ defmodule YahooFantasyEx.Auth do
|> Jason.decode!()
|> put_expires_by()

token_manager().write(updated)
Tokens.write(updated)

Map.get(updated, "access_token")
end
Expand All @@ -68,7 +62,7 @@ defmodule YahooFantasyEx.Auth do
|> Jason.decode!()
|> put_expires_by()

token_manager().write(updated)
Tokens.write(updated)

Map.get(updated, "access_token")
end
Expand Down Expand Up @@ -111,10 +105,8 @@ defmodule YahooFantasyEx.Auth do
Application.get_env(:yahoo_fantasy_ex, :io, IO)
end

defp token_manager do
Application.get_env(:yahoo_fantasy_ex, :token_manager, YahooFantasyEx.Tokens.File)
end

defp client_id, do: System.get_env("CLIENT_ID")
defp client_secret, do: System.get_env("CLIENT_SECRET")
defp authorize_url, do: Application.get_env(:yahoo_fantasy_ex, :authorize_url)
defp token_url, do: Application.get_env(:yahoo_fantasy_ex, :token_url)
end
21 changes: 21 additions & 0 deletions lib/yahoo_fantasy_ex/model.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
defmodule YahooFantasyEx.Model do
@moduledoc false
@spec __using__(Keyword.t()) :: Macro.t()
defmacro __using__(opts) do
quote do
import YahooFantasyEx.Models.Helpers
alias __MODULE__
alias YahooFantasyEx.Models.Decoder

@fields unquote(opts[:fields])

@type t :: %{}

@spec new(any()) :: t()
def new(json), do: Decoder.decode(json, @fields)

@spec new(any(), map()) :: t()
def new(decoded, parent), do: Decoder.decode_subresources(decoded, parent, @fields)
end
end
end
85 changes: 85 additions & 0 deletions lib/yahoo_fantasy_ex/models/decoder.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
defmodule YahooFantasyEx.Models.Decoder do
@moduledoc false

alias YahooFantasyEx.Models.Decoder.Function
alias YahooFantasyEx.Models.Decoder.Primitive
alias YahooFantasyEx.Models.Decoder.Subresource

@spec decode(any(), any()) :: {:error, Jason.DecodeError.t()} | map()
def decode(decoded, fields) do
flattened = flatten_attributes(decoded)
Map.new(fields, &parse(&1, flattened))
end

def decode_subresources(decoded, parent, fields) do
flattened = flatten_attributes(decoded)
Map.new(fields, &parse(&1, flattened, parent))
end

defp parse({field, type_or_func}, entity, parent \\ nil) do
value = Map.get(entity, field)
{field, do_parse(type_or_func, value, entity, parent)}
end

defp do_parse(function, value, decoded, parent) when is_function(function),
do: Function.apply(function, value, decoded, parent)

defp do_parse({:array, function}, value, decoded, parent) when is_function(function),
do: Function.apply_many(function, value, decoded, parent)

defp do_parse({:many, module}, value, decoded, _parent),
do: Subresource.build(value, module, decoded)

defp do_parse({:array, type}, value, _decoded, _parent), do: Primitive.cast_many(type, value)
defp do_parse(type, value, _decoded, _parent), do: Primitive.cast(type, value)

defp flatten_attributes(attributes) do
attributes
|> List.flatten()
|> Enum.reduce(&Map.merge(&1, &2, fn _k, v1, v2 -> v2 ++ v1 end))
end

defmodule Primitive do
@moduledoc false
alias YahooFantasyEx.Models.Helpers

def cast(:atom, value), do: Helpers.cast_atom!(value)
def cast(:boolean, value), do: Helpers.cast_boolean(value)
def cast(:date, value), do: Helpers.cast_date(value)
def cast(:float, value), do: Helpers.cast_float(value)
def cast(:integer, value), do: Helpers.cast_integer(value)
def cast(:string, value), do: value

def cast_many(type, values), do: Enum.map(values, &cast(type, &1))
end

defmodule Function do
@moduledoc false
def apply(function, value, _decoded, _parent) when is_function(function, 1),
do: function.(value)

def apply(function, value, decoded, _parent) when is_function(function, 2),
do: function.(value, decoded)

def apply(function, value, decoded, parent) when is_function(function, 3),
do: function.(value, decoded, parent)

def apply_many(function, values, decoded, parent),
do: Enum.map(values, &apply(function, &1, decoded, parent))
end

defmodule Subresource do
@moduledoc false
def build(value, module, decoded) do
value
|> Enum.map(&flatten/1)
|> Enum.map(&module.new(&1, decoded))
end

defp flatten({_, data}) do
data
|> Map.values()
|> List.flatten()
end
end
end
13 changes: 2 additions & 11 deletions lib/yahoo_fantasy_ex/models/helpers.ex
Original file line number Diff line number Diff line change
@@ -1,15 +1,6 @@
defmodule YahooFantasyEx.Models.Helpers do
@moduledoc false

@spec flatten_attributes(list()) :: map()
def flatten_attributes(attributes) do
attributes
|> List.flatten()
|> Enum.reduce(fn x, y ->
Map.merge(x, y, fn _k, v1, v2 -> v2 ++ v1 end)
end)
end

@spec cast_boolean(term()) :: boolean()
def cast_boolean(value) when is_binary(value), do: String.to_integer(value) == 1
def cast_boolean(value) when is_integer(value), do: value == 1
Expand Down Expand Up @@ -60,10 +51,10 @@ defmodule YahooFantasyEx.Models.Helpers do
def translate_status("IR-NR"), do: :non_roster_injured_reserve
def translate_status(_), do: nil

@spec transform(struct(), Keyword.t()) :: struct()
@spec transform(map(), Keyword.t()) :: struct()
def transform(struct, transform_functions) do
transform_functions
|> Enum.reduce(struct, fn {field, transform_function}, acc ->
|> Enum.reduce(%{}, fn {field, transform_function}, acc ->
transformed_value =
struct
|> Map.get(field)
Expand Down
Loading

0 comments on commit ab76438

Please sign in to comment.