Compare commits

..

3 Commits

Author SHA1 Message Date
ccac1fec15 Filter by patch
Some checks are pending
ci / docker (push) Waiting to run
2024-06-16 12:53:26 +02:00
bba1913d65 fix 2024-06-15 23:25:38 +02:00
d24dc4726b Log errors on fact processors 2024-06-15 21:24:08 +02:00
8 changed files with 157 additions and 29 deletions

View File

@ -14,7 +14,9 @@ defmodule LolAnalytics.Facts.ChampionPickedItem.FactProcessor do
{:ok, decoded_match} <- Poison.decode(body, as: %LoLAPI.Model.MatchResponse{}) do {:ok, decoded_match} <- Poison.decode(body, as: %LoLAPI.Model.MatchResponse{}) do
process_game_data(decoded_match) process_game_data(decoded_match)
else else
_ -> {:error, "Could not process data from #{url}"} _ ->
Logger.error("Could not process data from #{url} for ChampionPickedItem")
{:error, "Could not process data from #{url}"}
end end
end end

View File

@ -13,7 +13,9 @@ defmodule LolAnalytics.Facts.ChampionPickedSummonerSpell.FactProcessor do
{:ok, decoded_match} <- Poison.decode(body, as: %LoLAPI.Model.MatchResponse{}) do {:ok, decoded_match} <- Poison.decode(body, as: %LoLAPI.Model.MatchResponse{}) do
process_game_data(decoded_match) process_game_data(decoded_match)
else else
_ -> {:error, "Could not process data from #{url}"} _ ->
Logger.error("Could not process data from #{url} for ChampionPickedSummonerSpell")
{:error, "Could not process data from #{url}"}
end end
end end

View File

@ -32,7 +32,26 @@ defmodule LolAnalytics.Facts.ChampionPlayedGame.Repo do
Repo.all(Schema) Repo.all(Schema)
end end
def get_win_rates do def get_win_rates(opts \\ []) do
team_position = Keyword.get(opts, :team_position)
patch = Keyword.get(opts, :patch_number, "14.12")
case {team_position, patch} do
{nil, nil} ->
get_win_rates()
{"all", patch} ->
get_win_rates_for_patch(patch)
{nil, patch} ->
get_win_rates_for_patch(patch)
{team_position, patch} ->
get_win_rates_for_patch_and_team_position(patch, team_position)
end
end
defp get_all_win_rates do
query = query =
from m in Schema, from m in Schema,
join: c in ChampionSchema, join: c in ChampionSchema,
@ -58,10 +77,9 @@ defmodule LolAnalytics.Facts.ChampionPlayedGame.Repo do
Repo.all(query) Repo.all(query)
end end
def get_win_rates_by_patch(champion_id, team_position) do defp get_win_rates_for_patch(patch_number) do
query = query =
from m in Schema, from m in Schema,
where: m.team_position == ^team_position,
join: c in ChampionSchema, join: c in ChampionSchema,
on: c.champion_id == m.champion_id, on: c.champion_id == m.champion_id,
select: %{ select: %{
@ -80,12 +98,38 @@ defmodule LolAnalytics.Facts.ChampionPlayedGame.Repo do
team_position: m.team_position, team_position: m.team_position,
total_games: count("*") total_games: count("*")
}, },
where: c.champion_id == ^champion_id, group_by: [m.champion_id, c.image, c.name, m.team_position, m.patch_number],
group_by: [m.champion_id, c.image, c.name, m.team_position, m.patch_number] having: m.patch_number == ^patch_number and count("*") > 100
Repo.all(query) Repo.all(query)
end end
def get_win_rates_by_roles() do defp get_win_rates_for_patch_and_team_position(patch_number, team_position) do
query =
from m in Schema,
join: c in ChampionSchema,
on: c.champion_id == m.champion_id,
select: %{
wins: fragment("count(CASE WHEN ? THEN 1 END)", m.is_win),
win_rate:
fragment(
"
((cast(count(CASE WHEN ? THEN 1 END) as float) / cast(count(*) as float)) * 100.0
)",
m.is_win
),
id: m.champion_id,
patch_number: m.patch_number,
name: c.name,
image: c.image,
team_position: m.team_position,
total_games: count("*")
},
group_by: [m.champion_id, c.image, c.name, m.team_position, m.patch_number],
having:
m.team_position == ^team_position and m.patch_number == ^patch_number and
count("*") > 100
Repo.all(query)
end end
end end

View File

@ -11,7 +11,9 @@ defmodule LolAnalytics.Facts.ChampionPlayedGame.FactProcessor do
{:ok, decoded_match} <- Poison.decode(body, as: %LoLAPI.Model.MatchResponse{}) do {:ok, decoded_match} <- Poison.decode(body, as: %LoLAPI.Model.MatchResponse{}) do
process_game_data(decoded_match) process_game_data(decoded_match)
else else
_ -> {:error, "Could not process data from #{url}"} _ ->
Logger.error("Could not process data from #{url} for ChampionPlayedGame")
{:error, "Could not process data from #{url}"}
end end
end end

View File

@ -0,0 +1,56 @@
defmodule LolAnalyticsWeb.PatchSelector do
use LoLAnalyticsWeb, :live_component
def mount(socket) do
patches =
LolAnalytics.Dimensions.Patch.PatchRepo.list_patches()
|> Enum.sort(fn %{patch_number: p1}, %{patch_number: p2} ->
[_, minor_1] = String.split(p1, ".") |> Enum.map(&String.to_integer/1)
[_, minor_2] = String.split(p2, ".") |> Enum.map(&String.to_integer/1)
p1 > p2 && minor_1 > minor_2
end)
patch_numbers = Enum.map(patches, & &1.patch_number)
[last_patch | _] = patch_numbers
send(self(), %{patch: last_patch})
socket =
assign(socket, :patch_numbers, patch_numbers)
|> assign(:patch_form, to_form(%{"selected_patch" => last_patch}))
{:ok, socket}
end
@impl true
def handle_event("selected_patch", %{"patch" => patch} = unsigned_params, socket) do
send(self(), %{patch: patch})
{:noreply, assign(socket, :selected_patch, patch)}
end
def render(assigns) do
~H"""
<div phx-feedback-for={@id}>
<.form for={@patch_form} phx-change="validate" phx-target={@myself} phx-submit="save">
<div class="flex gap-4">
<p class="my-auto">Patch</p>
<select
phx-change="selected_patch"
id="patch"
name="patch"
class="block w-full rounded-md border border-gray-300 bg-white shadow-sm focus:border-zinc-400 focus:ring-0 sm:text-sm"
>
<%= for patch <- @patch_numbers do %>
<option key={patch} phx-click="select-patch" name={patch} value={patch}>
<%= patch %>
</option>
<% end %>
</select>
</div>
</.form>
</div>
"""
end
end

View File

@ -7,22 +7,19 @@ defmodule LoLAnalyticsWeb.ChampionLive.Index do
alias LolAnalyticsWeb.ChampionLive.Mapper alias LolAnalyticsWeb.ChampionLive.Mapper
alias LolAnalyticsWeb.ChampionLive.Components.ChampionFilters alias LolAnalyticsWeb.ChampionLive.Components.ChampionFilters
alias LolAnalyticsWeb.PatchSelector
@behaviour LolAnalyticsWeb.ChampionFilters.EventHandler @behaviour LolAnalyticsWeb.ChampionFilters.EventHandler
@impl true @impl true
def mount(params, _session, socket) do def mount(params, _session, socket) do
role = role = params["role"] || "all"
case params["role"] do
nil -> "all"
role -> role
end
socket = socket =
socket socket
|> assign(:selected_role, role) |> assign(:selected_role, role)
|> assign(:champions, %{status: :loading}) |> assign(:champions, %{status: :loading})
|> load_champs(role) |> load_champs(role, "all")
{:ok, socket} {:ok, socket}
end end
@ -38,19 +35,46 @@ defmodule LoLAnalyticsWeb.ChampionLive.Index do
def handle_event("filter", %{"role" => selected_role} = params, socket) do def handle_event("filter", %{"role" => selected_role} = params, socket) do
{:reply, %{}, {:reply, %{},
socket socket
|> push_navigate(to: ~p"/champions?#{params}") |> push_patch(to: ~p"/champions?#{params}")
|> assign(:champions, %{status: :loading}) |> assign(:champions, %{status: :loading})
|> load_champs(selected_role) |> load_champs(selected_role, socket.assigns.selected_patch)
|> assign(:selected_role, selected_role)} |> assign(:selected_role, selected_role)}
end end
defp load_champs(socket, selected_role) do def handle_info(%{patch: patch}, socket) do
selected_role = socket.assigns.selected_role
socket =
assign(socket, :champions, %{status: :loading})
|> assign(:selected_patch, patch)
|> load_champs(selected_role, patch)
{:noreply, socket}
end
defp load_champs(socket, selected_role, "all") do
socket socket
|> start_async( |> start_async(
:get_champs, :get_champs,
fn -> fn ->
LolAnalytics.Facts.ChampionPlayedGame.Repo.get_win_rates() LolAnalytics.Facts.ChampionPlayedGame.Repo.get_win_rates(team_position: selected_role)
|> filter_champs(selected_role) |> Mapper.map_champs()
|> Enum.sort(&(&1.win_rate >= &2.win_rate))
end
)
end
defp load_champs(socket, selected_role, patch) do
socket
|> start_async(
:get_champs,
fn ->
LolAnalytics.Facts.ChampionPlayedGame.Repo.get_win_rates(
team_position: selected_role,
patch_number: patch
)
|> Mapper.map_champs()
|> Enum.sort(&(&1.win_rate >= &2.win_rate))
end end
) )
end end
@ -77,14 +101,6 @@ defmodule LoLAnalyticsWeb.ChampionLive.Index do
end end
end end
defp filter_champs(champs, selected_role) do
champs =
LolAnalytics.Facts.ChampionPlayedGame.Repo.get_win_rates()
|> Enum.filter((&filter_role/1).(selected_role))
|> Mapper.map_champs()
|> Enum.sort(&(&1.win_rate >= &2.win_rate))
end
defp filter_role(role) do defp filter_role(role) do
fn champ -> fn champ ->
champ.team_position == role || role == "all" champ.team_position == role || role == "all"

View File

@ -10,6 +10,8 @@
<.live_component module={ChampionFilters} id="role-filters" selectedrole={@selected_role || "all" } /> <.live_component module={ChampionFilters} id="role-filters" selectedrole={@selected_role || "all" } />
</div> </div>
<.live_component module={PatchSelector} id="patch-selector" />
<div class="h-4"></div> <div class="h-4"></div>
<.render_champions champions={@champions} /> <.render_champions champions={@champions} />

View File

@ -1,7 +1,11 @@
<.header> <.header>
<%= @champion.name %> <h1 class="text-4xl">
<%= @champion.name %>
</h1>
</.header> </.header>
<div class="my-6" />
<.champion_avatar id={@champion.id} name={@champion.name} <.champion_avatar id={@champion.id} name={@champion.name}
image={"https://ddragon.leagueoflegends.com/cdn/14.11.1/img/champion/#{@champion.image}"} /> image={"https://ddragon.leagueoflegends.com/cdn/14.11.1/img/champion/#{@champion.image}"} />