add metadata to summoner spell

This commit is contained in:
Álvaro 2024-06-07 01:42:45 +02:00
parent 6dd8eea3d3
commit 968c2634b7
15 changed files with 143 additions and 19 deletions

View File

@ -0,0 +1,22 @@
defmodule LolAnalytics.Dimensions.SummonerSpell.SummonerSpellMetadata do
alias LolAnalytics.Dimensions.SummonerSpell.SummonerSpellRepo
@spells_url "https://ddragon.leagueoflegends.com/cdn/14.11.1/data/en_US/summoner.json"
def update_metadata() do
get_spells()
|> Enum.each(&save_metadata/1)
end
defp get_spells() do
case HTTPoison.get(@spells_url) do
{:ok, resp} ->
Poison.decode!(resp.body)["data"]
end
end
defp save_metadata({name, metadata}) do
%{"key" => spell_id} = metadata
SummonerSpellRepo.update(spell_id, %{metadata: metadata})
end
end

View File

@ -4,6 +4,7 @@ defmodule LolAnalytics.Dimensions.SummonerSpell.SummonerSpellRepo do
alias LolAnalytics.Dimensions.SummonerSpell.SummonerSpellSchema alias LolAnalytics.Dimensions.SummonerSpell.SummonerSpellSchema
alias LoLAnalytics.Repo alias LoLAnalytics.Repo
@spec get_or_create(String.t()) :: any()
def get_or_create(spell_id) do def get_or_create(spell_id) do
query = from s in SummonerSpellSchema, where: s.spell_id == ^spell_id query = from s in SummonerSpellSchema, where: s.spell_id == ^spell_id
spell = Repo.one(query) spell = Repo.one(query)
@ -23,6 +24,13 @@ defmodule LolAnalytics.Dimensions.SummonerSpell.SummonerSpellRepo do
end end
end end
@spec update(spell_id :: String.t(), attrs :: map()) :: any()
def update(spell_id, attrs) do
get_or_create(spell_id)
|> SummonerSpellSchema.changeset(attrs)
|> Repo.update()
end
def list_spells() do def list_spells() do
Repo.all(SummonerSpellSchema) Repo.all(SummonerSpellSchema)
end end

View File

@ -4,12 +4,13 @@ defmodule LolAnalytics.Dimensions.SummonerSpell.SummonerSpellSchema do
schema "dim_summoner_spell" do schema "dim_summoner_spell" do
field :spell_id, :integer field :spell_id, :integer
field :metadata, :map
timestamps() timestamps()
end end
def changeset(summoner_spell = %__MODULE__{}, attrs) do def changeset(summoner_spell = %__MODULE__{}, attrs) do
summoner_spell summoner_spell
|> cast(attrs, [:spell_id]) |> cast(attrs, [:spell_id, :metadata])
|> validate_required([:spell_id]) |> validate_required([:spell_id])
end end
end end

View File

@ -1,6 +1,7 @@
defmodule LolAnalytics.Facts.ChampionPickedSummonerSpell.Repo do defmodule LolAnalytics.Facts.ChampionPickedSummonerSpell.Repo do
import Ecto.Query import Ecto.Query
alias LolAnalytics.Dimensions.SummonerSpell.SummonerSpellSchema
alias LolAnalytics.Dimensions.SummonerSpell.SummonerSpellRepo alias LolAnalytics.Dimensions.SummonerSpell.SummonerSpellRepo
alias LolAnalytics.Dimensions.Champion.ChampionSchema alias LolAnalytics.Dimensions.Champion.ChampionSchema
@ -13,11 +14,11 @@ defmodule LolAnalytics.Facts.ChampionPickedSummonerSpell.Repo do
alias LoLAnalytics.Repo alias LoLAnalytics.Repo
@type insert_attrs :: %{ @type insert_attrs :: %{
match_id: String.t(), match_id: String.t(),
champion_id: String.t(), champion_id: String.t(),
puuid: String.t(), puuid: String.t(),
summoner_spell_id: :integer summoner_spell_id: :integer
} }
@spec insert(insert_attrs()) :: any() @spec insert(insert_attrs()) :: any()
def insert(attrs) do def insert(attrs) do
@ -33,11 +34,17 @@ defmodule LolAnalytics.Facts.ChampionPickedSummonerSpell.Repo do
|> IO.inspect() |> IO.inspect()
end end
@spec get_champion_spells_by_win_rate(String.t()) :: list()
def get_champion_spells_by_win_rate(championId) do
end
def get_champion_picked_summoners() do def get_champion_picked_summoners() do
query = query =
from f in Schema, from f in Schema,
join: c in ChampionSchema, join: c in ChampionSchema,
on: c.champion_id == f.champion_id, on: c.champion_id == f.champion_id,
join: s in SummonerSpellSchema,
on: s.spell_id == f.summoner_spell_id,
select: %{ select: %{
wins: fragment("count(CASE WHEN ? THEN 1 END)", f.is_win), wins: fragment("count(CASE WHEN ? THEN 1 END)", f.is_win),
win_rate: win_rate:
@ -48,13 +55,23 @@ defmodule LolAnalytics.Facts.ChampionPickedSummonerSpell.Repo do
f.is_win f.is_win
), ),
id: f.champion_id, id: f.champion_id,
spell_id: f.spell_id, spell_id: f.summoner_spell_id,
name: c.name, metadata: s.metadata,
champion_name: c.name,
champion_id: c.champion_id,
image: c.image, image: c.image,
team_position: f.team_position, team_position: f.team_position,
total_games: count("*") total_games: count("*")
}, },
group_by: [f.champion_id, f.spell_id, c.image, c.name, f.team_position] group_by: [
f.champion_id,
f.summoner_spell_id,
s.metadata,
c.image,
c.name,
c.champion_id,
f.team_position
]
Repo.all(query) Repo.all(query)
end end

View File

@ -0,0 +1,9 @@
defmodule LoLAnalytics.Repo.Migrations.SummonerSpellMetadata do
use Ecto.Migration
def change do
alter table("dim_summoner_spell") do
add :metadata, :map
end
end
end

View File

@ -0,0 +1,11 @@
defmodule LoLAnalytics.Repo.Migrations.SummonerSpellMetadataIndex do
use Ecto.Migration
def up do
execute("CREATE INDEX dim_summoner_spell_metadata ON dim_summoner_spell USING GIN(metadata)")
end
def down do
execute("DROP INDEX dim_summoner_spell_metadata")
end
end

View File

@ -0,0 +1,36 @@
defmodule LolAnalyticsWeb.ChampionComponents.SummonerSpells.SummonerSpell do
defstruct [:id, :win_rate, :total_games]
@type t :: %{
id: integer(),
win_rate: float(),
total_games: integer()
}
end
defmodule LolAnalyticsWeb.ChampionComponents.SummonerSpells.Props do
alias LolAnalyticsWeb.ChampionComponents.SummonerSpells.SummonerSpell
defstruct spell1: %SummonerSpell{},
spell2: %SummonerSpell{}
@type t :: %{
spell1: SummonerSpell.t(),
spell2: SummonerSpell.t()
}
end
defmodule LolAnalyticsWeb.ChampionComponents.SummonerSpells do
alias LolAnalyticsWeb.ChampionComponents.SummonerSpells.Props
use Phoenix.Component
attr :spells, Props, default: %Props{}
def summoner_spells(assigns) do
~H"""
<div>
Spells
</div>
"""
end
end

View File

@ -1,3 +1,3 @@
defmodule LolAnalyticsWeb.ChampionLive.Champion do defmodule LolAnalyticsWeb.ChampionLive.ChampionSummary do
defstruct [:id, :win_rate, :image, :name, :team_position, :wins, :total_games] defstruct [:id, :win_rate, :image, :name, :team_position, :wins, :total_games]
end end

View File

@ -1,11 +1,11 @@
defmodule LolAnalyticsWeb.ChampionLive.Mapper do defmodule LolAnalyticsWeb.ChampionLive.Mapper do
alias LolAnalyticsWeb.ChampionLive.Champion alias LolAnalyticsWeb.ChampionLive.ChampionSummary
def map_champs(champs) do def map_champs(champs) do
champs champs
|> Enum.map(fn champ -> |> Enum.map(fn champ ->
%{ %{
Kernel.struct!(%Champion{}, champ) Kernel.struct!(%ChampionSummary{}, champ)
| win_rate: :erlang.float_to_binary(champ.win_rate, decimals: 2) | win_rate: :erlang.float_to_binary(champ.win_rate, decimals: 2)
} }
end) end)

View File

@ -1,6 +1,8 @@
defmodule LoLAnalyticsWeb.ChampionLive.Show do defmodule LoLAnalyticsWeb.ChampionLive.Show do
use LoLAnalyticsWeb, :live_view use LoLAnalyticsWeb, :live_view
import LolAnalyticsWeb.ChampionComponents.SummonerSpells
@impl true @impl true
def mount(_params, _session, socket) do def mount(_params, _session, socket) do
{:ok, socket} {:ok, socket}
@ -11,7 +13,23 @@ defmodule LoLAnalyticsWeb.ChampionLive.Show do
{:noreply, {:noreply,
socket socket
|> assign(:page_title, page_title(socket.assigns.live_action)) |> assign(:page_title, page_title(socket.assigns.live_action))
|> assign(:champion, %{id: id})} |> assign(:champion, %{id: id})
|> assign(:summoner_spells, %{summoner_spells: load_summoner_spells()})}
end
defp load_summoner_spells() do
%LolAnalyticsWeb.ChampionComponents.SummonerSpells.Props{
spell1: %LolAnalyticsWeb.ChampionComponents.SummonerSpells.SummonerSpell{
id: 1,
win_rate: 51.7,
total_games: 400
},
spell2: %LolAnalyticsWeb.ChampionComponents.SummonerSpells.SummonerSpell{
id: 2,
win_rate: 51.7,
total_games: 500
}
}
end end
defp page_title(:show), do: "Show Champion" defp page_title(:show), do: "Show Champion"

View File

@ -4,4 +4,8 @@
<:actions></:actions> <:actions></:actions>
</.header> </.header>
<.back navigate={~p"/champions"}>Back to champions</.back> <.summoner_spells spells={@summoner_spells} />
<.back navigate={~p"/champions"}>
Back to champions
</.back>

View File

@ -3,5 +3,3 @@
<:subtitle>This is a role record from your database.</:subtitle> <:subtitle>This is a role record from your database.</:subtitle>
<:actions></:actions> <:actions></:actions>
</.header> </.header>
<.back navigate={~p"/roles"}>Back to roles</.back>

View File

@ -8,7 +8,7 @@ import Config
config :lol_analytics_web, LoLAnalyticsWeb.Endpoint, config :lol_analytics_web, LoLAnalyticsWeb.Endpoint,
server: true, server: true,
http: [ip: {0, 0, 0, 0}, port: 4000], http: [ip: {0, 0, 0, 0}, port: 4000],
url: [host: "lol-analytics.kaizer.cloud", port: 80], url: [host: "localhost", port: 80],
cache_static_manifest: "priv/static/cache_manifest.json" cache_static_manifest: "priv/static/cache_manifest.json"
# Do not print debug messages in production # Do not print debug messages in production

View File

@ -6,7 +6,7 @@ import Config
# and secrets from environment variables or elsewhere. Do not define # and secrets from environment variables or elsewhere. Do not define
# any compile-time configuration in here, as it won't be applied. # any compile-time configuration in here, as it won't be applied.
# The block below contains prod specific runtime configuration. # The block below contains prod specific runtime configuration.
if config_env() == :prod do if config_env() == :prod || true do
database_url = database_url =
System.get_env("DATABASE_URL") || System.get_env("DATABASE_URL") ||
raise """ raise """

View File

@ -21,7 +21,7 @@
"gen_stage": {:hex, :gen_stage, "1.2.1", "19d8b5e9a5996d813b8245338a28246307fd8b9c99d1237de199d21efc4c76a1", [:mix], [], "hexpm", "83e8be657fa05b992ffa6ac1e3af6d57aa50aace8f691fcf696ff02f8335b001"}, "gen_stage": {:hex, :gen_stage, "1.2.1", "19d8b5e9a5996d813b8245338a28246307fd8b9c99d1237de199d21efc4c76a1", [:mix], [], "hexpm", "83e8be657fa05b992ffa6ac1e3af6d57aa50aace8f691fcf696ff02f8335b001"},
"gettext": {:hex, :gettext, "0.24.0", "6f4d90ac5f3111673cbefc4ebee96fe5f37a114861ab8c7b7d5b30a1108ce6d8", [:mix], [{:expo, "~> 0.5.1", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "bdf75cdfcbe9e4622dd18e034b227d77dd17f0f133853a1c73b97b3d6c770e8b"}, "gettext": {:hex, :gettext, "0.24.0", "6f4d90ac5f3111673cbefc4ebee96fe5f37a114861ab8c7b7d5b30a1108ce6d8", [:mix], [{:expo, "~> 0.5.1", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "bdf75cdfcbe9e4622dd18e034b227d77dd17f0f133853a1c73b97b3d6c770e8b"},
"hackney": {:hex, :hackney, "1.20.1", "8d97aec62ddddd757d128bfd1df6c5861093419f8f7a4223823537bad5d064e2", [:rebar3], [{:certifi, "~> 2.12.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "fe9094e5f1a2a2c0a7d10918fee36bfec0ec2a979994cff8cfe8058cd9af38e3"}, "hackney": {:hex, :hackney, "1.20.1", "8d97aec62ddddd757d128bfd1df6c5861093419f8f7a4223823537bad5d064e2", [:rebar3], [{:certifi, "~> 2.12.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "fe9094e5f1a2a2c0a7d10918fee36bfec0ec2a979994cff8cfe8058cd9af38e3"},
"heroicons": {:git, "https://github.com/tailwindlabs/heroicons.git", "88ab3a0d790e6a47404cba02800a6b25d2afae50", [tag: "v2.1.1", sparse: "optimized"]}, "heroicons": {:git, "https://github.com/tailwindlabs/heroicons.git", "88ab3a0d790e6a47404cba02800a6b25d2afae50", [tag: "v2.1.1", sparse: "optimized", depth: 1]},
"hpax": {:hex, :hpax, "0.1.2", "09a75600d9d8bbd064cdd741f21fc06fc1f4cf3d0fcc335e5aa19be1a7235c84", [:mix], [], "hexpm", "2c87843d5a23f5f16748ebe77969880e29809580efdaccd615cd3bed628a8c13"}, "hpax": {:hex, :hpax, "0.1.2", "09a75600d9d8bbd064cdd741f21fc06fc1f4cf3d0fcc335e5aa19be1a7235c84", [:mix], [], "hexpm", "2c87843d5a23f5f16748ebe77969880e29809580efdaccd615cd3bed628a8c13"},
"httpoison": {:hex, :httpoison, "2.2.1", "87b7ed6d95db0389f7df02779644171d7319d319178f6680438167d7b69b1f3d", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "51364e6d2f429d80e14fe4b5f8e39719cacd03eb3f9a9286e61e216feac2d2df"}, "httpoison": {:hex, :httpoison, "2.2.1", "87b7ed6d95db0389f7df02779644171d7319d319178f6680438167d7b69b1f3d", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "51364e6d2f429d80e14fe4b5f8e39719cacd03eb3f9a9286e61e216feac2d2df"},
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},