diff --git a/apps/lol_analytics/lib/lol_analytics/dimensions/champion/champion_metadata.ex b/apps/lol_analytics/lib/lol_analytics/dimensions/champion/champion_metadata.ex new file mode 100644 index 0000000..d720241 --- /dev/null +++ b/apps/lol_analytics/lib/lol_analytics/dimensions/champion/champion_metadata.ex @@ -0,0 +1,44 @@ +defmodule LolAnalytics.Dimensions.Champion.ChampionMetadata do + alias LolAnalytics.Dimensions.Champion.ChampionRepo + @champions_data_url "https://ddragon.leagueoflegends.com/cdn/14.11.1/data/en_US/champion.json" + + use GenServer + + def update_metadata() do + {:ok, %{"data" => data}} = get_champions() + + data + |> Enum.each(&save_metadata/1) + end + + defp get_champions() do + with {:ok, resp} <- HTTPoison.get(@champions_data_url), + data <- Poison.decode(resp.body) do + data + else + {:error, reason} -> {:error, reason} + end + end + + defp save_metadata({champion, info}) do + %{ + "image" => %{ + "full" => full_image + }, + "name" => name, + "key" => key_string + } = info + + attrs = %{ + image: full_image, + name: name + } + + {champion_id, _} = Integer.parse(key_string) + + ChampionRepo.update(champion_id, attrs) + + info + |> IO.inspect() + end +end diff --git a/apps/lol_analytics/lib/lol_analytics/dimensions/champion/champion_repo.ex b/apps/lol_analytics/lib/lol_analytics/dimensions/champion/champion_repo.ex index 8bc8e44..66da15e 100644 --- a/apps/lol_analytics/lib/lol_analytics/dimensions/champion/champion_repo.ex +++ b/apps/lol_analytics/lib/lol_analytics/dimensions/champion/champion_repo.ex @@ -18,6 +18,13 @@ defmodule LolAnalytics.Dimensions.Champion.ChampionRepo do end end + def update(champion_id, attrs) do + get_or_create(champion_id) + |> ChampionSchema.changeset(attrs) + |> Repo.update() + end + + @spec list_champions() :: any() def list_champions() do Repo.all(ChampionSchema) end diff --git a/apps/lol_analytics/lib/lol_analytics/dimensions/champion/champion_schema.ex b/apps/lol_analytics/lib/lol_analytics/dimensions/champion/champion_schema.ex index 7cc68cb..58cbe24 100644 --- a/apps/lol_analytics/lib/lol_analytics/dimensions/champion/champion_schema.ex +++ b/apps/lol_analytics/lib/lol_analytics/dimensions/champion/champion_schema.ex @@ -4,12 +4,14 @@ defmodule LolAnalytics.Dimensions.Champion.ChampionSchema do schema "dim_champion" do field :champion_id, :integer + field :name, :string + field :image, :string timestamps() end def changeset(champion = %__MODULE__{}, attrs \\ %{}) do champion - |> cast(attrs, [:champion_id]) + |> cast(attrs, [:champion_id, :name, :image]) |> validate_required([:champion_id]) end end 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 6d70cdf..2cde458 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 @@ -1,6 +1,7 @@ defmodule LolAnalytics.Facts.ChampionPlayedGame.ChampionPlayedGameRepo do import Ecto.Query + alias LolAnalytics.Dimensions.Champion.ChampionSchema alias LolAnalytics.Dimensions.Player.PlayerRepo alias LolAnalytics.Dimensions.Champion.ChampionRepo alias LolAnalytics.Dimensions.Match.MatchRepo @@ -9,19 +10,70 @@ defmodule LolAnalytics.Facts.ChampionPlayedGame.ChampionPlayedGameRepo do alias LoLAnalytics.Repo def insert(attrs) do - match = MatchRepo.get_or_create(attrs.match_id) - champion = ChampionRepo.get_or_create(attrs.champion_id) - player = PlayerRepo.get_or_create(attrs.puuid) - IO.puts(">>>>") - IO.inspect(attrs) + _match = MatchRepo.get_or_create(attrs.match_id) + _champion = ChampionRepo.get_or_create(attrs.champion_id) + _player = PlayerRepo.get_or_create(attrs.puuid) changeset = ChampionPlayedGameSchema.changeset(%ChampionPlayedGameSchema{}, attrs) - - IO.inspect(changeset) Repo.insert(changeset) - # Repo.insert(match) end def list_played_matches() do Repo.all(ChampionPlayedGameSchema) end + + def get_win_rates2 do + query2 = + from m in ChampionPlayedGameSchema, + join: c in ChampionSchema, + on: c.champion_id == m.champion_id, + select: %{ + wins: count(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, + name: c.name, + image: c.image + }, + group_by: [m.champion_id, c.image, c.name] + + Repo.all(query2) + end + + def get_win_rates() do + query = """ + SELECT + (cast(count(CASE WHEN is_win THEN 1 END) as float) / cast(count(*) as float)) * 100.0 as win_rate, + count(CASE WHEN is_win THEN 1 END) as games_won, + count(*) as total_games, + champion_id + FROM fact_champion_played_game + + GROUP BY champion_id + ORDER BY win_rate desc; + """ + + case Ecto.Adapters.SQL.query(Repo, query, []) do + {:ok, %Postgrex.Result{rows: rows}} -> + rows + |> Enum.map(fn [win_rate, wins, games, champion_id] -> + %{ + win_rate: win_rate, + wins: wins, + games: games, + champion_id: champion_id + } + end) + + {:error, _exception} -> + :error + end + end + + def get_win_rates_by_roles() do + end end diff --git a/apps/lol_analytics/priv/repo/migrations/20240530194815_champion_dim_name_image.exs b/apps/lol_analytics/priv/repo/migrations/20240530194815_champion_dim_name_image.exs new file mode 100644 index 0000000..ede6005 --- /dev/null +++ b/apps/lol_analytics/priv/repo/migrations/20240530194815_champion_dim_name_image.exs @@ -0,0 +1,10 @@ +defmodule LoLAnalytics.Repo.Migrations.ChampionDimName do + use Ecto.Migration + + def change do + alter table("dim_champion") do + add :name, :string + add :image, :string + end + end +end diff --git a/apps/lol_analytics_web/lib/lol_analytics_web/live/champion_live/form_component.ex b/apps/lol_analytics_web/lib/lol_analytics_web/live/champion_live/form_component.ex new file mode 100644 index 0000000..7932cf1 --- /dev/null +++ b/apps/lol_analytics_web/lib/lol_analytics_web/live/champion_live/form_component.ex @@ -0,0 +1,90 @@ +defmodule LoLAnalyticsWeb.ChampionLive.FormComponent do + use LoLAnalyticsWeb, :live_component + + alias LoLAnalytics.Accounts + + @impl true + def render(assigns) do + ~H""" +
+ <.header> + <%= @title %> + <:subtitle>Use this form to manage champion records in your database. + + + <.simple_form + for={@form} + id="champion-form" + phx-target={@myself} + phx-change="validate" + phx-submit="save" + > + + <:actions> + <.button phx-disable-with="Saving...">Save Champion + + +
+ """ + end + + @impl true + def update(%{champion: champion} = assigns, socket) do + changeset = Accounts.change_champion(champion) + + {:ok, + socket + |> assign(assigns) + |> assign_form(changeset)} + end + + @impl true + def handle_event("validate", %{"champion" => champion_params}, socket) do + changeset = + socket.assigns.champion + |> Accounts.change_champion(champion_params) + |> Map.put(:action, :validate) + + {:noreply, assign_form(socket, changeset)} + end + + def handle_event("save", %{"champion" => champion_params}, socket) do + save_champion(socket, socket.assigns.action, champion_params) + end + + defp save_champion(socket, :edit, champion_params) do + case Accounts.update_champion(socket.assigns.champion, champion_params) do + {:ok, champion} -> + notify_parent({:saved, champion}) + + {:noreply, + socket + |> put_flash(:info, "Champion updated successfully") + |> push_patch(to: socket.assigns.patch)} + + {:error, %Ecto.Changeset{} = changeset} -> + {:noreply, assign_form(socket, changeset)} + end + end + + defp save_champion(socket, :new, champion_params) do + case Accounts.create_champion(champion_params) do + {:ok, champion} -> + notify_parent({:saved, champion}) + + {:noreply, + socket + |> put_flash(:info, "Champion created successfully") + |> push_patch(to: socket.assigns.patch)} + + {:error, %Ecto.Changeset{} = changeset} -> + {:noreply, assign_form(socket, changeset)} + end + end + + defp assign_form(socket, %Ecto.Changeset{} = changeset) do + assign(socket, :form, to_form(changeset)) + end + + defp notify_parent(msg), do: send(self(), {__MODULE__, msg}) +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 new file mode 100644 index 0000000..65270d3 --- /dev/null +++ b/apps/lol_analytics_web/lib/lol_analytics_web/live/champion_live/index.ex @@ -0,0 +1,80 @@ +defmodule LoLAnalyticsWeb.ChampionLive.Index do + alias ElixirLS.LanguageServer.Providers.Completion.Reducers.Struct + use LoLAnalyticsWeb, :live_view + + defstruct id: "", win_rate: 0, wins: 0, image: "", name: "" + + @roles ["all", "TOP", "JUNGLE", "MIDDLE", "BOTTOM", "UTILITY"] + + @impl true + def mount(_params, _session, socket) do + champs = LolAnalytics.Facts.ChampionPlayedGame.ChampionPlayedGameRepo.get_win_rates2() + + mapped = + champs + |> Enum.map(fn champ -> + Kernel.struct!(%__MODULE__{}, champ) + end) + |> Enum.sort(&(&1.win_rate >= &2.win_rate)) + + {:ok, + stream( + socket, + :champions, + mapped + ) + |> assign(:form, to_form(%{"name" => ""}))} + end + + def handle_event("filter", params, socket) do + %{"name" => query_name} = params + + champs = + LolAnalytics.Facts.ChampionPlayedGame.ChampionPlayedGameRepo.get_win_rates2() + |> Enum.filter(fn %{name: name} -> + String.downcase(name) |> String.contains?(query_name) + end) + |> Enum.map(fn champ -> + Kernel.struct!(%__MODULE__{}, champ) + end) + |> Enum.sort(&(&1.win_rate >= &2.win_rate)) + + IO.inspect(champs) + + {:noreply, + stream( + socket, + :champions, + champs + )} + end + + def handle_event("filter_by", %{"name" => name}, socket) do + {:noreply, assign(socket, %{filter_by: name})} + end + + @impl true + def handle_params(params, _url, socket) do + {:noreply, apply_action(socket, socket.assigns.live_action, params)} + end + + defp apply_action(socket, :index, _params) do + socket + |> assign(:page_title, "Listing Champions") + + # |> assign(:champion, nil) + end + + @impl true + def handle_info({LoLAnalyticsWeb.ChampionLive.FormComponent, {:saved, champion}}, socket) do + {:noreply, stream_insert(socket, :champions, champion)} + end + + # @impl true + # def handle_event("delete", %{"id" => id}, socket) do + # champion = Accounts.get_champion!(id) + # {:ok, _} = Accounts.delete_champion(champion) + + # {:noreply, stream_delete(socket, :champions, champion)} + # end +end 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 new file mode 100644 index 0000000..bd689a5 --- /dev/null +++ b/apps/lol_analytics_web/lib/lol_analytics_web/live/champion_live/index.html.heex @@ -0,0 +1,66 @@ +<.header> + Listing Champions + + +

Champions

+<.form for={@form} phx-change="filter" phx-submit="save"> + <.input type="text" field={@form["name"]} /> + <.input type="checkbox" field={@form["all_roles"]} /> +
+
+ <.input type="checkbox" field={@form["top_role"]} /> +

Top

+
+
+ <.input type="checkbox" field={@form["middle_role"]} /> +

Middle

+
+
+ <.input type="checkbox" field={@form["jungle_role"]} /> +

Jungle

+
+
+ <.input type="checkbox" field={@form["bottom_role"]} /> +

Bottom

+
+
+ <.input type="checkbox" field={@form["utility_role"]} /> +

Utility

+
+
+ + + + +
+ <%= for {_, champion} <- @streams.champions do %> +
+ +
+

<%= champion.name %>

+

<%= champion.id %>

+

<%= champion.win_rate %>%

+
+
+ +
+ <.link navigate={~p"/champions/#{champion}"}>Show +
+ <% end %> +
+ +<.modal + :if={@live_action in [:new, :edit]} + id="champion-modal" + show + on_cancel={JS.patch(~p"/champions")} +> + <.live_component + module={LoLAnalyticsWeb.ChampionLive.FormComponent} + id={@champion.champion_id || :new} + title={@page_title} + action={@live_action} + champion={@champion} + patch={~p"/champions"} + /> + diff --git a/apps/lol_analytics_web/lib/lol_analytics_web/live/champion_live/show.ex b/apps/lol_analytics_web/lib/lol_analytics_web/live/champion_live/show.ex new file mode 100644 index 0000000..5d6db86 --- /dev/null +++ b/apps/lol_analytics_web/lib/lol_analytics_web/live/champion_live/show.ex @@ -0,0 +1,21 @@ +defmodule LoLAnalyticsWeb.ChampionLive.Show do + use LoLAnalyticsWeb, :live_view + + alias LoLAnalytics.Accounts + + @impl true + def mount(_params, _session, socket) do + {:ok, socket} + end + + @impl true + def handle_params(%{"id" => id}, _, socket) do + {:noreply, + socket + |> assign(:page_title, page_title(socket.assigns.live_action)) + |> assign(:champion, Accounts.get_champion!(id))} + end + + defp page_title(:show), do: "Show Champion" + defp page_title(:edit), do: "Edit Champion" +end 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 new file mode 100644 index 0000000..c04f3c2 --- /dev/null +++ b/apps/lol_analytics_web/lib/lol_analytics_web/live/champion_live/show.html.heex @@ -0,0 +1,25 @@ +<.header> + Champion <%= @champion.id %> + <:subtitle>This is a champion record from your database. + <:actions> + <.link patch={~p"/champions/#{@champion}/show/edit"} phx-click={JS.push_focus()}> + <.button>Edit champion + + + + +<.list> + + +<.back navigate={~p"/champions"}>Back to champions + +<.modal :if={@live_action == :edit} id="champion-modal" show on_cancel={JS.patch(~p"/champions/#{@champion}")}> + <.live_component + module={LoLAnalyticsWeb.ChampionLive.FormComponent} + id={@champion.id} + title={@page_title} + action={@live_action} + champion={@champion} + patch={~p"/champions/#{@champion}"} + /> + diff --git a/apps/lol_analytics_web/lib/lol_analytics_web/live/role_live/form_component.ex b/apps/lol_analytics_web/lib/lol_analytics_web/live/role_live/form_component.ex new file mode 100644 index 0000000..d2a59b8 --- /dev/null +++ b/apps/lol_analytics_web/lib/lol_analytics_web/live/role_live/form_component.ex @@ -0,0 +1,90 @@ +defmodule LoLAnalyticsWeb.RoleLive.FormComponent do + use LoLAnalyticsWeb, :live_component + + alias LoLAnalytics.Accounts + + @impl true + def render(assigns) do + ~H""" +
+ <.header> + <%= @title %> + <:subtitle>Use this form to manage role records in your database. + + + <.simple_form + for={@form} + id="role-form" + phx-target={@myself} + phx-change="validate" + phx-submit="save" + > + + <:actions> + <.button phx-disable-with="Saving...">Save Role + + +
+ """ + end + + @impl true + def update(%{role: role} = assigns, socket) do + changeset = Accounts.change_role(role) + + {:ok, + socket + |> assign(assigns) + |> assign_form(changeset)} + end + + @impl true + def handle_event("validate", %{"role" => role_params}, socket) do + changeset = + socket.assigns.role + |> Accounts.change_role(role_params) + |> Map.put(:action, :validate) + + {:noreply, assign_form(socket, changeset)} + end + + def handle_event("save", %{"role" => role_params}, socket) do + save_role(socket, socket.assigns.action, role_params) + end + + defp save_role(socket, :edit, role_params) do + case Accounts.update_role(socket.assigns.role, role_params) do + {:ok, role} -> + notify_parent({:saved, role}) + + {:noreply, + socket + |> put_flash(:info, "Role updated successfully") + |> push_patch(to: socket.assigns.patch)} + + {:error, %Ecto.Changeset{} = changeset} -> + {:noreply, assign_form(socket, changeset)} + end + end + + defp save_role(socket, :new, role_params) do + case Accounts.create_role(role_params) do + {:ok, role} -> + notify_parent({:saved, role}) + + {:noreply, + socket + |> put_flash(:info, "Role created successfully") + |> push_patch(to: socket.assigns.patch)} + + {:error, %Ecto.Changeset{} = changeset} -> + {:noreply, assign_form(socket, changeset)} + end + end + + defp assign_form(socket, %Ecto.Changeset{} = changeset) do + assign(socket, :form, to_form(changeset)) + end + + defp notify_parent(msg), do: send(self(), {__MODULE__, msg}) +end diff --git a/apps/lol_analytics_web/lib/lol_analytics_web/live/role_live/index.ex b/apps/lol_analytics_web/lib/lol_analytics_web/live/role_live/index.ex new file mode 100644 index 0000000..2fb8358 --- /dev/null +++ b/apps/lol_analytics_web/lib/lol_analytics_web/live/role_live/index.ex @@ -0,0 +1,37 @@ +defmodule LoLAnalyticsWeb.RoleLive.Index do + use LoLAnalyticsWeb, :live_view + + alias LoLAnalytics.Accounts + alias LoLAnalytics.Accounts.Role + + @roles ["ALL", "TOP", "MIDDLE", "JUNGLE", "UTILITY", "BOTTOM"] + + @impl true + def mount(_params, _session, socket) do + {:ok, stream(socket, :roles, @roles)} + end + + @impl true + def handle_params(params, _url, socket) do + {:noreply, apply_action(socket, socket.assigns.live_action, params)} + end + + defp apply_action(socket, :index, _params) do + socket + |> assign(:page_title, "Listing Roles") + |> assign(:role, nil) + end + + @impl true + def handle_info({LoLAnalyticsWeb.RoleLive.FormComponent, {:saved, role}}, socket) do + {:noreply, stream_insert(socket, :roles, role)} + end + + # @impl true + # def handle_event("delete", %{"id" => id}, socket) do + # role = Accounts.get_role!(id) + # {:ok, _} = Accounts.delete_role(role) + + # {:noreply, stream_delete(socket, :roles, role)} + # end +end diff --git a/apps/lol_analytics_web/lib/lol_analytics_web/live/role_live/index.html.heex b/apps/lol_analytics_web/lib/lol_analytics_web/live/role_live/index.html.heex new file mode 100644 index 0000000..f7a4bdc --- /dev/null +++ b/apps/lol_analytics_web/lib/lol_analytics_web/live/role_live/index.html.heex @@ -0,0 +1,40 @@ +<.header> + Listing Roles + <:actions> + <.link patch={~p"/roles/new"}> + <.button>New Role + + + + +<.table + id="roles" + rows={@streams.roles} + row_click={fn {_id, role} -> JS.navigate(~p"/roles/#{role}") end} +> + <:action :let={{_id, role}}> +
+ <.link navigate={~p"/roles/#{role}"}>Show +
+ <.link patch={~p"/roles/#{role}/edit"}>Edit + + <:action :let={{id, role}}> + <.link + phx-click={JS.push("delete", value: %{id: role.id}) |> hide("##{id}")} + data-confirm="Are you sure?" + > + Delete + + + + +<.modal :if={@live_action in [:new, :edit]} id="role-modal" show on_cancel={JS.patch(~p"/roles")}> + <.live_component + module={LoLAnalyticsWeb.RoleLive.FormComponent} + id={@role.id || :new} + title={@page_title} + action={@live_action} + role={@role} + patch={~p"/roles"} + /> + diff --git a/apps/lol_analytics_web/lib/lol_analytics_web/live/role_live/show.ex b/apps/lol_analytics_web/lib/lol_analytics_web/live/role_live/show.ex new file mode 100644 index 0000000..bf3fbb9 --- /dev/null +++ b/apps/lol_analytics_web/lib/lol_analytics_web/live/role_live/show.ex @@ -0,0 +1,21 @@ +defmodule LoLAnalyticsWeb.RoleLive.Show do + use LoLAnalyticsWeb, :live_view + + alias LoLAnalytics.Accounts + + @impl true + def mount(_params, _session, socket) do + {:ok, socket} + end + + @impl true + def handle_params(%{"id" => id}, _, socket) do + {:noreply, + socket + |> assign(:page_title, page_title(socket.assigns.live_action)) + |> assign(:role, Accounts.get_role!(id))} + end + + defp page_title(:show), do: "Show Role" + defp page_title(:edit), do: "Edit Role" +end diff --git a/apps/lol_analytics_web/lib/lol_analytics_web/live/role_live/show.html.heex b/apps/lol_analytics_web/lib/lol_analytics_web/live/role_live/show.html.heex new file mode 100644 index 0000000..b556238 --- /dev/null +++ b/apps/lol_analytics_web/lib/lol_analytics_web/live/role_live/show.html.heex @@ -0,0 +1,25 @@ +<.header> + Role <%= @role.id %> + <:subtitle>This is a role record from your database. + <:actions> + <.link patch={~p"/roles/#{@role}/show/edit"} phx-click={JS.push_focus()}> + <.button>Edit role + + + + +<.list> + + +<.back navigate={~p"/roles"}>Back to roles + +<.modal :if={@live_action == :edit} id="role-modal" show on_cancel={JS.patch(~p"/roles/#{@role}")}> + <.live_component + module={LoLAnalyticsWeb.RoleLive.FormComponent} + id={@role.id} + title={@page_title} + action={@live_action} + role={@role} + patch={~p"/roles/#{@role}"} + /> + diff --git a/apps/lol_analytics_web/lib/lol_analytics_web/router.ex b/apps/lol_analytics_web/lib/lol_analytics_web/router.ex index 75f3756..2f99a7f 100644 --- a/apps/lol_analytics_web/lib/lol_analytics_web/router.ex +++ b/apps/lol_analytics_web/lib/lol_analytics_web/router.ex @@ -18,6 +18,12 @@ defmodule LoLAnalyticsWeb.Router do pipe_through :browser get "/", PageController, :home + live "/champions", ChampionLive.Index, :index + live "/champions/new", ChampionLive.Index, :new + live "/champions/:id/edit", ChampionLive.Index, :edit + + live "/champions/:id", ChampionLive.Show, :show + live "/champions/:id/show/edit", ChampionLive.Show, :edit end # Other scopes may use custom stacks. diff --git a/apps/lol_analytics_web/test/lol_analytics_web/live/champion_live_test.exs b/apps/lol_analytics_web/test/lol_analytics_web/live/champion_live_test.exs new file mode 100644 index 0000000..85ce5f0 --- /dev/null +++ b/apps/lol_analytics_web/test/lol_analytics_web/live/champion_live_test.exs @@ -0,0 +1,108 @@ +defmodule LoLAnalyticsWeb.ChampionLiveTest do + use LoLAnalyticsWeb.ConnCase + + import Phoenix.LiveViewTest + import LoLAnalytics.AccountsFixtures + + @create_attrs %{} + @update_attrs %{} + @invalid_attrs %{} + + defp create_champion(_) do + champion = champion_fixture() + %{champion: champion} + end + + describe "Index" do + setup [:create_champion] + + test "lists all champions", %{conn: conn} do + {:ok, _index_live, html} = live(conn, ~p"/champions") + + assert html =~ "Listing Champions" + end + + test "saves new champion", %{conn: conn} do + {:ok, index_live, _html} = live(conn, ~p"/champions") + + assert index_live |> element("a", "New Champion") |> render_click() =~ + "New Champion" + + assert_patch(index_live, ~p"/champions/new") + + assert index_live + |> form("#champion-form", champion: @invalid_attrs) + |> render_change() =~ "can't be blank" + + assert index_live + |> form("#champion-form", champion: @create_attrs) + |> render_submit() + + assert_patch(index_live, ~p"/champions") + + html = render(index_live) + assert html =~ "Champion created successfully" + end + + test "updates champion in listing", %{conn: conn, champion: champion} do + {:ok, index_live, _html} = live(conn, ~p"/champions") + + assert index_live |> element("#champions-#{champion.id} a", "Edit") |> render_click() =~ + "Edit Champion" + + assert_patch(index_live, ~p"/champions/#{champion}/edit") + + assert index_live + |> form("#champion-form", champion: @invalid_attrs) + |> render_change() =~ "can't be blank" + + assert index_live + |> form("#champion-form", champion: @update_attrs) + |> render_submit() + + assert_patch(index_live, ~p"/champions") + + html = render(index_live) + assert html =~ "Champion updated successfully" + end + + test "deletes champion in listing", %{conn: conn, champion: champion} do + {:ok, index_live, _html} = live(conn, ~p"/champions") + + assert index_live |> element("#champions-#{champion.id} a", "Delete") |> render_click() + refute has_element?(index_live, "#champions-#{champion.id}") + end + end + + describe "Show" do + setup [:create_champion] + + test "displays champion", %{conn: conn, champion: champion} do + {:ok, _show_live, html} = live(conn, ~p"/champions/#{champion}") + + assert html =~ "Show Champion" + end + + test "updates champion within modal", %{conn: conn, champion: champion} do + {:ok, show_live, _html} = live(conn, ~p"/champions/#{champion}") + + assert show_live |> element("a", "Edit") |> render_click() =~ + "Edit Champion" + + assert_patch(show_live, ~p"/champions/#{champion}/show/edit") + + assert show_live + |> form("#champion-form", champion: @invalid_attrs) + |> render_change() =~ "can't be blank" + + assert show_live + |> form("#champion-form", champion: @update_attrs) + |> render_submit() + + assert_patch(show_live, ~p"/champions/#{champion}") + + html = render(show_live) + assert html =~ "Champion updated successfully" + end + end +end diff --git a/apps/lol_analytics_web/test/lol_analytics_web/live/role_live_test.exs b/apps/lol_analytics_web/test/lol_analytics_web/live/role_live_test.exs new file mode 100644 index 0000000..2070ac7 --- /dev/null +++ b/apps/lol_analytics_web/test/lol_analytics_web/live/role_live_test.exs @@ -0,0 +1,108 @@ +defmodule LoLAnalyticsWeb.RoleLiveTest do + use LoLAnalyticsWeb.ConnCase + + import Phoenix.LiveViewTest + import LoLAnalytics.AccountsFixtures + + @create_attrs %{} + @update_attrs %{} + @invalid_attrs %{} + + defp create_role(_) do + role = role_fixture() + %{role: role} + end + + describe "Index" do + setup [:create_role] + + test "lists all roles", %{conn: conn} do + {:ok, _index_live, html} = live(conn, ~p"/roles") + + assert html =~ "Listing Roles" + end + + test "saves new role", %{conn: conn} do + {:ok, index_live, _html} = live(conn, ~p"/roles") + + assert index_live |> element("a", "New Role") |> render_click() =~ + "New Role" + + assert_patch(index_live, ~p"/roles/new") + + assert index_live + |> form("#role-form", role: @invalid_attrs) + |> render_change() =~ "can't be blank" + + assert index_live + |> form("#role-form", role: @create_attrs) + |> render_submit() + + assert_patch(index_live, ~p"/roles") + + html = render(index_live) + assert html =~ "Role created successfully" + end + + test "updates role in listing", %{conn: conn, role: role} do + {:ok, index_live, _html} = live(conn, ~p"/roles") + + assert index_live |> element("#roles-#{role.id} a", "Edit") |> render_click() =~ + "Edit Role" + + assert_patch(index_live, ~p"/roles/#{role}/edit") + + assert index_live + |> form("#role-form", role: @invalid_attrs) + |> render_change() =~ "can't be blank" + + assert index_live + |> form("#role-form", role: @update_attrs) + |> render_submit() + + assert_patch(index_live, ~p"/roles") + + html = render(index_live) + assert html =~ "Role updated successfully" + end + + test "deletes role in listing", %{conn: conn, role: role} do + {:ok, index_live, _html} = live(conn, ~p"/roles") + + assert index_live |> element("#roles-#{role.id} a", "Delete") |> render_click() + refute has_element?(index_live, "#roles-#{role.id}") + end + end + + describe "Show" do + setup [:create_role] + + test "displays role", %{conn: conn, role: role} do + {:ok, _show_live, html} = live(conn, ~p"/roles/#{role}") + + assert html =~ "Show Role" + end + + test "updates role within modal", %{conn: conn, role: role} do + {:ok, show_live, _html} = live(conn, ~p"/roles/#{role}") + + assert show_live |> element("a", "Edit") |> render_click() =~ + "Edit Role" + + assert_patch(show_live, ~p"/roles/#{role}/show/edit") + + assert show_live + |> form("#role-form", role: @invalid_attrs) + |> render_change() =~ "can't be blank" + + assert show_live + |> form("#role-form", role: @update_attrs) + |> render_submit() + + assert_patch(show_live, ~p"/roles/#{role}") + + html = render(show_live) + assert html =~ "Role updated successfully" + end + end +end diff --git a/queries.md b/queries.md index 4652a32..ebb0775 100644 --- a/queries.md +++ b/queries.md @@ -7,4 +7,16 @@ SELECT FROM fact_champion_played_game GROUP BY champion_id ORDER BY win_rate desc; +``` + +``` +SELECT + (cast(count(CASE WHEN is_win THEN 1 END) as float) / cast(count(*) as float)) * 100.0 as win_rate, + count(CASE WHEN is_win THEN 1 END) as games_won, + count(*) as total_games, + champion_id, + team_position + FROM fact_champion_played_game + GROUP BY champion_id, team_position + ORDER BY win_rate desc; ``` \ No newline at end of file