Add previous game viewer

This commit is contained in:
Elizabeth Hunt 2023-03-13 14:09:52 -06:00
parent aa5aad7715
commit 19bab0bbe3
Signed by: simponic
GPG Key ID: 52B3774857EB24B1
6 changed files with 161 additions and 45 deletions

View File

@ -12,8 +12,6 @@ defmodule Chessh.SSH.Client.Game do
game: nil, game: nil,
client_pid: nil, client_pid: nil,
binbo_pid: nil, binbo_pid: nil,
width: 0,
height: 0,
flipped: false, flipped: false,
color: nil, color: nil,
player_session: nil player_session: nil
@ -25,7 +23,6 @@ defmodule Chessh.SSH.Client.Game do
:syn.add_node_to_scopes([:games]) :syn.add_node_to_scopes([:games])
:ok = :syn.join(:games, {:game, game_id}, self()) :ok = :syn.join(:games, {:game, game_id}, self())
:binbo.start()
{:ok, binbo_pid} = :binbo.new_server() {:ok, binbo_pid} = :binbo.new_server()
:binbo.new_game(binbo_pid, fen) :binbo.new_game(binbo_pid, fen)
@ -177,11 +174,9 @@ defmodule Chessh.SSH.Client.Game do
flipped: player_color == :dark flipped: player_color == :dark
}) })
send( # Clear screen and do initial render
client_pid, send(client_pid, {:send_to_ssh, Utils.clear_codes()})
{:send_to_ssh, [Utils.clear_codes() | Renderer.render_board_state(new_state)]} render(new_state)
)
{:ok, new_state} {:ok, new_state}
end end
@ -227,8 +222,8 @@ defmodule Chessh.SSH.Client.Game do
end end
def input( def input(
width, _width,
height, _height,
action, action,
%State{ %State{
move_from: move_from, move_from: move_from,
@ -300,8 +295,6 @@ defmodule Chessh.SSH.Client.Game do
state state
| cursor: new_cursor, | cursor: new_cursor,
move_from: new_move_from, move_from: new_move_from,
width: width,
height: height,
flipped: if(action == "f", do: !flipped, else: flipped) flipped: if(action == "f", do: !flipped, else: flipped)
}) })
@ -349,13 +342,7 @@ defmodule Chessh.SSH.Client.Game do
end end
end end
send(client_pid, {:send_to_ssh, Renderer.render_board_state(new_state)}) render(new_state)
new_state
end
def render(width, height, %State{client_pid: client_pid} = state) do
new_state = %State{state | width: width, height: height}
send(client_pid, {:send_to_ssh, Renderer.render_board_state(new_state)})
new_state new_state
end end
@ -499,4 +486,11 @@ defmodule Chessh.SSH.Client.Game do
end end
|> Map.merge(extra_highlights) |> Map.merge(extra_highlights)
end end
def render(_width, _height, %State{} = state), do: render(state)
def render(%State{client_pid: client_pid} = state) do
send(client_pid, {:send_to_ssh, Renderer.render_board_state(state)})
state
end
end end

View File

@ -0,0 +1,121 @@
defmodule Chessh.SSH.Client.PreviousGame do
@start_fen "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"
alias Chessh.{Game, Utils}
alias Chessh.SSH.Client.Game.Renderer
alias IO.ANSI
require Logger
defmodule State do
defstruct move_fens: %{},
move_idx: 0,
binbo_pid: nil,
game: %Game{},
client_pid: nil,
flipped: false
end
use Chessh.SSH.Client.Screen
def init([
%State{
client_pid: client_pid,
game: %Game{
game_moves: game_moves
}
} = state
]) do
{:ok, binbo_pid} = :binbo.new_server()
:binbo.new_game(binbo_pid, @start_fen)
{move_fens, _moves} =
game_moves
|> String.trim()
|> String.split(" ")
|> Enum.reduce({%{"0" => @start_fen}, 1}, fn move, {move_idx_fen_map, curr_turn} ->
{:ok, _status} = :binbo.move(binbo_pid, move)
{:ok, fen} = :binbo.get_fen(binbo_pid)
{Map.put(move_idx_fen_map, "#{curr_turn}", fen), curr_turn + 1}
end)
new_state = %State{
state
| binbo_pid: binbo_pid,
move_fens: move_fens
}
send(client_pid, {:send_to_ssh, Utils.clear_codes()})
render(new_state)
{:ok, new_state}
end
def input(
_width,
_height,
action,
%State{
move_idx: move_idx,
flipped: flipped,
game: %Game{
moves: num_moves
}
} = state
) do
new_move_idx =
case action do
:left ->
Utils.wrap_around(move_idx, -1, num_moves)
:right ->
Utils.wrap_around(move_idx, 1, num_moves)
_ ->
move_idx
end
new_state = %State{
state
| move_idx: new_move_idx,
flipped: if(action == "f", do: !flipped, else: flipped)
}
render(new_state)
new_state
end
def render(
%State{
flipped: flipped,
client_pid: client_pid,
move_fens: move_fens,
move_idx: move_idx,
game: %Game{id: game_id, moves: total_moves}
} = state
) do
{:ok, fen} = Map.fetch(move_fens, "#{move_idx}")
lines =
["Game #{game_id} | Move #{move_idx} / #{total_moves}"] ++
Renderer.draw_board(fen, flipped) ++
["<- previous | next ->"]
send(
client_pid,
{:send_to_ssh,
[ANSI.home()] ++
Enum.map(
Enum.zip(1..length(lines), lines),
fn {i, line} ->
[ANSI.cursor(i, 0), ANSI.clear_line(), line]
end
)}
)
state
end
def render(_width, _height, %State{} = state), do: render(state)
end

View File

@ -69,8 +69,6 @@ defmodule Chessh.SSH.Client.Game.Renderer do
end end
def render_board_state(%Game.State{ def render_board_state(%Game.State{
width: _width,
height: _height,
highlighted: highlighted, highlighted: highlighted,
flipped: flipped, flipped: flipped,
game: game:
@ -169,7 +167,13 @@ defmodule Chessh.SSH.Client.Game.Renderer do
) )
end end
defp draw_board( def draw_board(
fen,
flipped
),
do: draw_board(fen, {@tile_width, @tile_height}, %{}, flipped)
def draw_board(
fen, fen,
{tile_width, tile_height} = tile_dims, {tile_width, tile_height} = tile_dims,
highlights, highlights,

View File

@ -18,27 +18,27 @@ defmodule Chessh.SSH.Client.MainMenu do
def dynamic_options(), do: false def dynamic_options(), do: false
def tick_delay_ms(), do: 1000 def tick_delay_ms(), do: 1000
def max_displayed_options(), do: 4 def max_displayed_options(), do: 5
def max_box_cols(), do: @logo_cols def max_box_cols(), do: @logo_cols
def title(), do: @logo ++ ["- Connected on: #{System.get_env("NODE_ID")}"] def title(), do: @logo ++ ["- Connected on: #{System.get_env("NODE_ID")}"]
def initial_options(%State{player_session: %PlayerSession{} = player_session}) do def initial_options(%State{player_session: %PlayerSession{} = player_session}) do
[ [
{"My Current Games",
{Chessh.SSH.Client.SelectCurrentGame,
%Chessh.SSH.Client.SelectPaginatePoller.State{player_session: player_session}}},
{"Joinable Games (lobby)",
{Chessh.SSH.Client.SelectJoinableGame,
%Chessh.SSH.Client.SelectPaginatePoller.State{player_session: player_session}}},
{"Previous Games",
{Chessh.SSH.Client.SelectPreviousGame,
%Chessh.SSH.Client.SelectPaginatePoller.State{player_session: player_session}}},
{"Start A Game (Light)", {"Start A Game (Light)",
{Chessh.SSH.Client.Game, {Chessh.SSH.Client.Game,
%Chessh.SSH.Client.Game.State{player_session: player_session, color: :light}}}, %Chessh.SSH.Client.Game.State{player_session: player_session, color: :light}}},
{"Start A Game (Dark)", {"Start A Game (Dark)",
{Chessh.SSH.Client.Game, {Chessh.SSH.Client.Game,
%Chessh.SSH.Client.Game.State{player_session: player_session, color: :dark}}}, %Chessh.SSH.Client.Game.State{player_session: player_session, color: :dark}}}
{"Current Games",
{Chessh.SSH.Client.SelectCurrentGame,
%Chessh.SSH.Client.SelectPaginatePoller.State{player_session: player_session}}},
{"Previous Games",
{Chessh.SSH.Client.SelectPreviousGame,
%Chessh.SSH.Client.SelectPaginatePoller.State{player_session: player_session}}},
{"Joinable Games (lobby)",
{Chessh.SSH.Client.SelectJoinableGame,
%Chessh.SSH.Client.SelectPaginatePoller.State{player_session: player_session}}}
] ]
end end

View File

@ -91,14 +91,11 @@ defmodule Chessh.SSH.Client.SelectPreviousGame do
else: options else: options
end end
def make_process_tuple(selected_id, %State{ def make_process_tuple(selected_id, _state) do
player_session: player_session
}) do
game = Repo.get(Game, selected_id) game = Repo.get(Game, selected_id)
{Chessh.SSH.Client.Game, {Chessh.SSH.Client.PreviousGame,
%Chessh.SSH.Client.Game.State{ %Chessh.SSH.Client.PreviousGame.State{
player_session: player_session,
game: game game: game
}} }}
end end

View File

@ -17,7 +17,7 @@ defmodule Chessh.MixProject do
def application do def application do
[ [
mod: {Chessh.Application, []}, mod: {Chessh.Application, []},
extra_applications: [:logger, :crypto, :syn, :ssh, :plug_cowboy, :inets, :ssl] extra_applications: [:logger, :crypto, :syn, :ssh, :plug_cowboy, :inets, :ssl, :binbo]
] ]
end end