Home Posts Tags Post Search Tag Search

Post 11

Game Site Journal - 02

Published on: 2025-04-08 Tags: elixir, Side Project, stream, LiveView, Game Site, Ecto
Here I will go over some of the things that I needed to do in order to make a new game work on my site.

For every game that is going to be added the socket will take all the needed information about the current state of the game.  In the case of the Guessing Game the socket will have these values to deal with:

%{
      answer: answer,
      score: 0,
      attempt: 1,
      form: to_form(%{"guess" => ""})
}

This is all the info that I needed in order to keep track of the state. I won't go into designing every game but I will go into the functions to set a new score in the Scores table. Assuming that you add an alias 

alias GameSite.Scores

@doc """
  These functions below are used to set the scores for a player. You will have to have unique scores
  for each game and player.
  """
  def handle_event("exit", params, socket) do
    save_score(socket, :new, params)
  end

  defp save_score(socket, :new, score_params) do
    case Scores.create_score(score_params) do
      {:ok, score} ->
        notify_parent({:new, score})

        {:noreply,
         socket
         |> put_flash(:info, "Score created successfully")
         |> push_navigate(to: "/scores")}

      {:error, %Ecto.Changeset{} = changeset} ->
        {:noreply, assign(socket, form: to_form(changeset))}

      {:duplicate, :already_exists} ->
        {:noreply,
         socket
         |> put_flash(:info, "No new High Score")
         |> push_navigate(to: "/scores")}
    end
  end

  defp notify_parent(msg), do: send(self(), {__MODULE__, msg})

These are the functions that I created to deal with a new Score. You will notice that there is 3 cond for the save_score. I wanted to be sure that I wasn't adding in a bunch of scores for each player and game. So I made a new check on the score being entered to see if the combination was unique. 

def create_score(%{"user_id" => user_id, "game_id" => game_id, "score" => score} = attrs) do
    existing_score =
      Repo.get_by(Score,
        user_id: user_id,
        game_id: game_id,
        score: score
      )

    if existing_score do
      {:duplicate, :already_exists}
    else
      %Score{}
      |> Score.changeset(attrs)
      |> Repo.insert()
    end
  end

This is simply to avoid too many entries and it allows me to give better feedback to a player when they exit the game.