1
0
mirror of https://github.com/danbee/chess synced 2025-03-04 08:39:06 +00:00
chess/lib/chess_web/views/live/board_live.ex

130 lines
2.8 KiB
Elixir

defmodule ChessWeb.BoardLive do
use Phoenix.LiveView, container: {:div, class: "board__container"}
alias Chess.Store.User
alias Chess.Store.Game
alias Chess.Store.Move
alias Chess.Repo
alias Chess.Moves
alias ChessWeb.GameView
import Ecto.Query
require Logger
def render(assigns) do
Phoenix.View.render(GameView, "board.html", assigns)
end
def mount(_params, %{"user_id" => user_id, "game_id" => game_id}, socket) do
ChessWeb.Endpoint.subscribe("game:#{game_id}")
user = Repo.get!(User, user_id)
game =
Game.for_user(user)
|> Repo.get!(game_id)
{:ok, assign(socket, default_assigns(game, user))}
end
def handle_event("click", %{"rank" => rank, "file" => file}, socket) do
{
:noreply,
socket |> handle_click(String.to_integer(file), String.to_integer(rank))
}
end
defp default_assigns(game, user) do
%{
board: game.board,
game: game,
user: user,
selected: nil,
available: []
}
end
def handle_info(%{event: "move", payload: state}, socket) do
Logger.info("Handling move from board")
{:noreply, assign(socket, state)}
end
defp handle_click(socket, file, rank) do
game = socket.assigns[:game]
board = game.board
user = socket.assigns[:user]
colour = GameView.player_colour(user, game)
assigns =
if colour == game.turn do
case socket.assigns do
%{selected: nil} ->
handle_selection(board, colour, file, rank)
_ ->
handle_move(socket.assigns, file, rank)
end
end
assign(socket, assigns)
end
defp handle_selection(board, colour, file, rank) do
case GameView.piece(board, {file, rank}) do
%{"colour" => ^colour} ->
[
{:selected, {file, rank}},
{:available, Moves.available(board, {file, rank})}
]
_ ->
[]
end
end
defp handle_move(
%{game: game, available: available, selected: selected},
file,
rank
) do
if {file, rank} in available do
game
|> Moves.make_move(%{from: selected, to: {file, rank}})
|> case do
{:ok, %{game: game}} ->
game
|> Repo.preload([:user, :opponent])
|> Repo.preload(
moves:
from(
move in Move,
order_by: [asc: move.inserted_at]
)
)
|> broadcast_move(game.board)
[
{:selected, nil},
{:available, []},
{:board, game.board},
{:game, game}
]
end
else
[{:selected, nil}, {:available, []}]
end
end
defp broadcast_move(game, board) do
ChessWeb.Endpoint.broadcast_from(
self(),
"game:#{game.id}",
"move",
%{game: game, board: board}
)
end
end