diff --git a/assets/css/app.css b/assets/css/app.css index dce23b9..f880f41 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -49,7 +49,32 @@ h1 { color: var(--text-color); } -.game { +a { + position: relative; + text-decoration: none; +} + +/* Animate a solid underline sliding in and out on hover. */ +a::after { + content: ''; + position: absolute; + width: 100%; + height: 0.075em; + bottom: 0.1em; + left: 0; + z-index: -1; + background-color: var(--text-color); + transform: scaleX(0); + transform-origin: bottom right; + transition: transform 0.25s ease-out; +} + +a:hover::after { + transform: scaleX(1); + transform-origin: bottom left; +} + +.cozy { padding: 8px; background-color: #fbcfe8; border-radius: 8px; diff --git a/lib/twenty_fourty_eight/application.ex b/lib/twenty_fourty_eight/application.ex index ff904d7..c9d7041 100644 --- a/lib/twenty_fourty_eight/application.ex +++ b/lib/twenty_fourty_eight/application.ex @@ -10,7 +10,8 @@ defmodule TwentyFourtyEight.Application do children = [ TwentyFourtyEightWeb.Telemetry, TwentyFourtyEight.Repo, - {DNSCluster, query: Application.get_env(:twenty_fourty_eight, :dns_cluster_query) || :ignore}, + {DNSCluster, + query: Application.get_env(:twenty_fourty_eight, :dns_cluster_query) || :ignore}, {Phoenix.PubSub, name: TwentyFourtyEight.PubSub}, # Start the Finch HTTP client for sending emails {Finch, name: TwentyFourtyEight.Finch}, diff --git a/lib/twenty_fourty_eight/game/game.ex b/lib/twenty_fourty_eight/game/game.ex new file mode 100644 index 0000000..05d68f7 --- /dev/null +++ b/lib/twenty_fourty_eight/game/game.ex @@ -0,0 +1,47 @@ +defmodule TwentyFourtyEight.Game.Game do + use Ecto.Schema + import Ecto.Changeset + + alias TwentyFourtyEight.Repo + + @slug_length 8 + @slug_alphabet String.graphemes( + "_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + ) + + schema "game" do + field :num_rows, :integer, default: 6 + field :num_cols, :integer, default: 6 + field :starting_number, :integer, default: 2 + field :turn_start_number, :integer, default: 1 + field :winning_number, :integer, default: 2048 + field :slug, :string + timestamps() + end + + def changeset(attrs) do + %__MODULE__{} + |> cast(attrs, [:num_rows, :num_cols, :starting_number, :turn_start_number, :winning_number]) + |> validate_inclusion(:num_rows, 1..6) + |> validate_inclusion(:num_cols, 1..6) + |> validate_inclusion(:starting_number, [1, 2, 4]) + |> validate_inclusion(:turn_start_number, [1, 2, 4]) + |> validate_inclusion(:winning_number, [1024, 2048]) + end + + def insert(changeset) do + changeset + |> cast(%{slug: generate_slug()}, [:slug]) + |> unique_constraint(:slug) + |> Repo.insert() + end + + def get_by_slug(slug) do + Repo.get_by(__MODULE__, slug: slug) + end + + defp generate_slug() do + 1..@slug_length + |> Enum.map_join("", fn _ -> Enum.random(@slug_alphabet) end) + end +end diff --git a/lib/twenty_fourty_eight/game/manager.ex b/lib/twenty_fourty_eight/game/manager.ex index cf3a354..3c9e780 100644 --- a/lib/twenty_fourty_eight/game/manager.ex +++ b/lib/twenty_fourty_eight/game/manager.ex @@ -6,7 +6,7 @@ defmodule TwentyFourtyEight.Game.Manager do @registry TwentyFourtyEight.Game.Registry @supervisor TwentyFourtyEight.Game.Supervisor - def get_game(name) when is_binary(name) do + def get_game(name, _state) when is_binary(name) do case Registry.lookup(@registry, name) do [{pid, _value}] -> {:ok, pid} [] -> DynamicSupervisor.start_child(@supervisor, {__MODULE__, name}) @@ -52,4 +52,4 @@ defmodule TwentyFourtyEight.Game.Manager do defp via_tuple(name) do {:via, Registry, {@registry, name}} end -end \ No newline at end of file +end diff --git a/lib/twenty_fourty_eight_web/components/core_components.ex b/lib/twenty_fourty_eight_web/components/core_components.ex index 12e3649..7d9954c 100644 --- a/lib/twenty_fourty_eight_web/components/core_components.ex +++ b/lib/twenty_fourty_eight_web/components/core_components.ex @@ -201,7 +201,7 @@ defmodule TwentyFourtyEightWeb.CoreComponents do def simple_form(assigns) do ~H""" <.form :let={f} for={@for} as={@as} {@rest}> -
<%= @name %>