From ccac1fec157092f6519ed4c6bc8c93abe0c14f81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro?= Date: Sun, 16 Jun 2024 12:53:26 +0200 Subject: [PATCH] Filter by patch --- .../champion_played_game_repo.ex | 56 +++++++++++++++++-- .../components/patch_selector.ex | 56 +++++++++++++++++++ .../live/champion_live/index.ex | 54 +++++++++++------- .../live/champion_live/index.html.heex | 2 + .../live/champion_live/show.html.heex | 6 +- 5 files changed, 148 insertions(+), 26 deletions(-) create mode 100644 apps/lol_analytics_web/lib/lol_analytics_web/components/patch_selector.ex diff --git a/apps/lol_analytics/lib/lol_analytics/facts/champion_played_game/champion_played_game_repo.ex b/apps/lol_analytics/lib/lol_analytics/facts/champion_played_game/champion_played_game_repo.ex index a952434..8320360 100644 --- a/apps/lol_analytics/lib/lol_analytics/facts/champion_played_game/champion_played_game_repo.ex +++ b/apps/lol_analytics/lib/lol_analytics/facts/champion_played_game/champion_played_game_repo.ex @@ -32,7 +32,26 @@ defmodule LolAnalytics.Facts.ChampionPlayedGame.Repo do Repo.all(Schema) 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 = from m in Schema, join: c in ChampionSchema, @@ -58,10 +77,9 @@ defmodule LolAnalytics.Facts.ChampionPlayedGame.Repo do Repo.all(query) end - def get_win_rates_by_patch(champion_id, team_position) do + defp get_win_rates_for_patch(patch_number) do query = from m in Schema, - where: m.team_position == ^team_position, join: c in ChampionSchema, on: c.champion_id == m.champion_id, select: %{ @@ -80,12 +98,38 @@ defmodule LolAnalytics.Facts.ChampionPlayedGame.Repo do team_position: m.team_position, 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) 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 diff --git a/apps/lol_analytics_web/lib/lol_analytics_web/components/patch_selector.ex b/apps/lol_analytics_web/lib/lol_analytics_web/components/patch_selector.ex new file mode 100644 index 0000000..52e4ed5 --- /dev/null +++ b/apps/lol_analytics_web/lib/lol_analytics_web/components/patch_selector.ex @@ -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""" +
+ <.form for={@patch_form} phx-change="validate" phx-target={@myself} phx-submit="save"> +
+

Patch

+ +
+ +
+ """ + end +end diff --git a/apps/lol_analytics_web/lib/lol_analytics_web/live/champion_live/index.ex b/apps/lol_analytics_web/lib/lol_analytics_web/live/champion_live/index.ex index 0b7583a..2d6f08d 100644 --- a/apps/lol_analytics_web/lib/lol_analytics_web/live/champion_live/index.ex +++ b/apps/lol_analytics_web/lib/lol_analytics_web/live/champion_live/index.ex @@ -7,22 +7,19 @@ defmodule LoLAnalyticsWeb.ChampionLive.Index do alias LolAnalyticsWeb.ChampionLive.Mapper alias LolAnalyticsWeb.ChampionLive.Components.ChampionFilters + alias LolAnalyticsWeb.PatchSelector @behaviour LolAnalyticsWeb.ChampionFilters.EventHandler @impl true def mount(params, _session, socket) do - role = - case params["role"] do - nil -> "all" - role -> role - end + role = params["role"] || "all" socket = socket |> assign(:selected_role, role) |> assign(:champions, %{status: :loading}) - |> load_champs(role) + |> load_champs(role, "all") {:ok, socket} end @@ -38,19 +35,46 @@ defmodule LoLAnalyticsWeb.ChampionLive.Index do def handle_event("filter", %{"role" => selected_role} = params, socket) do {:reply, %{}, socket - |> push_navigate(to: ~p"/champions?#{params}") + |> push_patch(to: ~p"/champions?#{params}") |> assign(:champions, %{status: :loading}) - |> load_champs(selected_role) + |> load_champs(selected_role, socket.assigns.selected_patch) |> assign(:selected_role, selected_role)} 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 |> start_async( :get_champs, fn -> - LolAnalytics.Facts.ChampionPlayedGame.Repo.get_win_rates() - |> filter_champs(selected_role) + LolAnalytics.Facts.ChampionPlayedGame.Repo.get_win_rates(team_position: 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 @@ -77,14 +101,6 @@ defmodule LoLAnalyticsWeb.ChampionLive.Index do 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 fn champ -> champ.team_position == role || role == "all" diff --git a/apps/lol_analytics_web/lib/lol_analytics_web/live/champion_live/index.html.heex b/apps/lol_analytics_web/lib/lol_analytics_web/live/champion_live/index.html.heex index a33173a..7cd72ae 100644 --- a/apps/lol_analytics_web/lib/lol_analytics_web/live/champion_live/index.html.heex +++ b/apps/lol_analytics_web/lib/lol_analytics_web/live/champion_live/index.html.heex @@ -10,6 +10,8 @@ <.live_component module={ChampionFilters} id="role-filters" selectedrole={@selected_role || "all" } /> + <.live_component module={PatchSelector} id="patch-selector" /> +
<.render_champions champions={@champions} /> diff --git a/apps/lol_analytics_web/lib/lol_analytics_web/live/champion_live/show.html.heex b/apps/lol_analytics_web/lib/lol_analytics_web/live/champion_live/show.html.heex index 80b1469..95b235f 100644 --- a/apps/lol_analytics_web/lib/lol_analytics_web/live/champion_live/show.html.heex +++ b/apps/lol_analytics_web/lib/lol_analytics_web/live/champion_live/show.html.heex @@ -1,7 +1,11 @@ <.header> - <%= @champion.name %> +

+ <%= @champion.name %> +

+
+ <.champion_avatar id={@champion.id} name={@champion.name} image={"https://ddragon.leagueoflegends.com/cdn/14.11.1/img/champion/#{@champion.image}"} />