summaryrefslogtreecommitdiff
path: root/lib/chessh/ssh/client/menus
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chessh/ssh/client/menus')
-rw-r--r--lib/chessh/ssh/client/menus/create_game.ex42
-rw-r--r--lib/chessh/ssh/client/menus/main_menu.ex16
-rw-r--r--lib/chessh/ssh/client/menus/select_bot.ex119
-rw-r--r--lib/chessh/ssh/client/menus/select_current_game.ex9
-rw-r--r--lib/chessh/ssh/client/menus/select_joinable_game.ex13
-rw-r--r--lib/chessh/ssh/client/menus/select_paginate_poller.ex83
-rw-r--r--lib/chessh/ssh/client/menus/select_previous_game.ex9
-rw-r--r--lib/chessh/ssh/client/menus/selector.ex (renamed from lib/chessh/ssh/client/menus/game_selector.ex)3
8 files changed, 231 insertions, 63 deletions
diff --git a/lib/chessh/ssh/client/menus/create_game.ex b/lib/chessh/ssh/client/menus/create_game.ex
new file mode 100644
index 0000000..99d2c0e
--- /dev/null
+++ b/lib/chessh/ssh/client/menus/create_game.ex
@@ -0,0 +1,42 @@
+defmodule Chessh.SSH.Client.CreateGameMenu do
+ alias IO.ANSI
+
+ alias Chessh.PlayerSession
+ alias Chessh.SSH.Client.Game
+
+ require Logger
+
+ use Chessh.SSH.Client.SelectPaginatePoller
+
+ def dynamic_options(), do: false
+ def tick_delay_ms(), do: 1000
+ def max_displayed_options(), do: 4
+ def title(), do: ["-- Create A New Game --"]
+
+ def initial_options(%State{player_session: %PlayerSession{} = player_session}) do
+ [
+ {"😀 vs 😀 | ⬜ White", {Game, %Game.State{player_session: player_session, color: :light}}},
+ {"😀 vs 😀 | ⬛ Black", {Game, %Game.State{player_session: player_session, color: :dark}}},
+ {"😀 vs 🤖 | ⬜ White",
+ {Chessh.SSH.Client.SelectBot,
+ %Chessh.SSH.Client.SelectPaginatePoller.State{
+ player_session: player_session,
+ extra_info: %{
+ color: :light
+ }
+ }}},
+ {"🤖 vs 😀 | ⬛ Black",
+ {Chessh.SSH.Client.SelectBot,
+ %Chessh.SSH.Client.SelectPaginatePoller.State{
+ player_session: player_session,
+ extra_info: %{
+ color: :dark
+ }
+ }}}
+ ]
+ end
+
+ def make_process_tuple(selected, _state) do
+ selected
+ end
+end
diff --git a/lib/chessh/ssh/client/menus/main_menu.ex b/lib/chessh/ssh/client/menus/main_menu.ex
index ee4b976..7b83b76 100644
--- a/lib/chessh/ssh/client/menus/main_menu.ex
+++ b/lib/chessh/ssh/client/menus/main_menu.ex
@@ -1,6 +1,5 @@
defmodule Chessh.SSH.Client.MainMenu do
alias IO.ANSI
- alias Chessh.PlayerSession
require Logger
@@ -22,9 +21,12 @@ defmodule Chessh.SSH.Client.MainMenu do
def max_box_cols(), do: @logo_cols
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: player_session}) do
[
- {"My Current Games",
+ {"Create Game",
+ {Chessh.SSH.Client.CreateGameMenu,
+ %Chessh.SSH.Client.SelectPaginatePoller.State{player_session: player_session}}},
+ {"Current Games",
{Chessh.SSH.Client.SelectCurrentGame,
%Chessh.SSH.Client.SelectPaginatePoller.State{player_session: player_session}}},
{"Joinable Games (lobby)",
@@ -32,13 +34,7 @@ defmodule Chessh.SSH.Client.MainMenu do
%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)",
- {Chessh.SSH.Client.Game,
- %Chessh.SSH.Client.Game.State{player_session: player_session, color: :light}}},
- {"Start A Game (Dark)",
- {Chessh.SSH.Client.Game,
- %Chessh.SSH.Client.Game.State{player_session: player_session, color: :dark}}}
+ %Chessh.SSH.Client.SelectPaginatePoller.State{player_session: player_session}}}
]
end
diff --git a/lib/chessh/ssh/client/menus/select_bot.ex b/lib/chessh/ssh/client/menus/select_bot.ex
new file mode 100644
index 0000000..86fc7cd
--- /dev/null
+++ b/lib/chessh/ssh/client/menus/select_bot.ex
@@ -0,0 +1,119 @@
+defmodule Chessh.SSH.Client.SelectBot do
+ alias Chessh.{Utils, Bot, Repo, Game}
+ alias Chessh.SSH.Client.Selector
+ import Ecto.Query
+ require Logger
+
+ use Chessh.SSH.Client.SelectPaginatePoller
+
+ def refresh_options_ms(), do: 4000
+ def max_displayed_options(), do: 5
+ def title(), do: ["-- Select Bot To Play Against --"]
+ def dynamic_options(), do: true
+
+ def get_bots(player_id, current_id \\ nil, direction \\ :desc) do
+ Selector.paginate_ish_query(
+ Bot
+ |> where([b], b.player_id == ^player_id or b.public == true)
+ |> limit(^max_displayed_options()),
+ current_id,
+ direction
+ )
+ end
+
+ def format_bot_tuple(%Bot{id: id, name: name}), do: {name, id}
+
+ def next_page_options(%State{
+ options: options,
+ player_session: %PlayerSession{
+ player_id: player_id
+ }
+ }) do
+ {_label, previous_last_bot_id} = List.last(options)
+ next_bots = get_bots(player_id, previous_last_bot_id, :desc)
+
+ if length(next_bots) > 0,
+ do:
+ next_bots
+ |> Enum.map(&format_bot_tuple/1),
+ else: options
+ end
+
+ def previous_page_options(%State{
+ options: options,
+ player_session: %PlayerSession{player_id: player_id}
+ }) do
+ {_label, previous_first_bot_id} = List.first(options)
+
+ previous_bots = get_bots(player_id, previous_first_bot_id, :asc)
+
+ if length(previous_bots) > 0,
+ do:
+ previous_bots
+ |> Enum.map(&format_bot_tuple/1),
+ else: options
+ end
+
+ def initial_options(%State{
+ player_session: %PlayerSession{player_id: player_id}
+ }) do
+ get_bots(player_id)
+ |> Enum.map(&format_bot_tuple/1)
+ end
+
+ def refresh_options(%State{
+ options: options,
+ player_session: %PlayerSession{player_id: player_id}
+ }) do
+ previous_last_bot_id =
+ case List.last(options) do
+ {_name, id} -> id
+ _ -> 1
+ end
+
+ current_screen_games = get_bots(player_id, previous_last_bot_id - 1, :asc)
+
+ if !is_nil(current_screen_games) && length(current_screen_games),
+ do:
+ current_screen_games
+ |> Enum.map(&format_bot_tuple/1),
+ else: options
+ end
+
+ def make_process_tuple(selected_id, %State{
+ player_session: player_session,
+ extra_info: %{color: color}
+ }) do
+ [create_game_ms, create_game_rate] =
+ Application.get_env(:chessh, RateLimits)
+ |> Keyword.take([:create_game_ms, :create_game_rate])
+ |> Keyword.values()
+
+ case Hammer.check_rate_inc(
+ :redis,
+ "player-#{player_session.player_id}-create-game-rate",
+ create_game_ms,
+ create_game_rate,
+ 1
+ ) do
+ {:allow, _count} ->
+ {:ok, game} =
+ Game.changeset(
+ Game.new_game(color, player_session.player_id),
+ %{
+ bot_id: selected_id
+ }
+ )
+ |> Repo.insert()
+
+ spawn(fn -> Bot.send_update(game |> Repo.preload([:bot])) end)
+
+ {Chessh.SSH.Client.Game,
+ %Chessh.SSH.Client.Game.State{player_session: player_session, color: color, game: game}}
+
+ {:deny, _limit} ->
+ {Chessh.SSH.Client.MainMenu,
+ %Chessh.SSH.Client.SelectPaginatePoller.State{player_session: player_session}}
+ end
+ end
+end
diff --git a/lib/chessh/ssh/client/menus/select_current_game.ex b/lib/chessh/ssh/client/menus/select_current_game.ex
index 3c47b15..7c49a30 100644
--- a/lib/chessh/ssh/client/menus/select_current_game.ex
+++ b/lib/chessh/ssh/client/menus/select_current_game.ex
@@ -1,6 +1,6 @@
defmodule Chessh.SSH.Client.SelectCurrentGame do
alias Chessh.{Utils, Repo, Game, PlayerSession}
- alias Chessh.SSH.Client.GameSelector
+ alias Chessh.SSH.Client.Selector
import Ecto.Query
require Logger
@@ -12,7 +12,7 @@ defmodule Chessh.SSH.Client.SelectCurrentGame do
def dynamic_options(), do: true
def get_player_sorted_current_games_with_id(player_id, current_id \\ nil, direction \\ :desc) do
- GameSelector.paginate_ish_query(
+ Selector.paginate_ish_query(
Game
|> where([g], g.status == :continue)
|> where([g], g.light_player_id == ^player_id or g.dark_player_id == ^player_id)
@@ -20,6 +20,7 @@ defmodule Chessh.SSH.Client.SelectCurrentGame do
current_id,
direction
)
+ |> Repo.preload([:light_player, :dark_player, :bot])
end
def format_game_selection_tuple(%Game{id: game_id} = game) do
@@ -67,7 +68,7 @@ defmodule Chessh.SSH.Client.SelectCurrentGame do
order_by: [desc: g.id]
)
|> Repo.all()
- |> Repo.preload([:light_player, :dark_player])
+ |> Repo.preload([:light_player, :dark_player, :bot])
|> Enum.map(&format_game_selection_tuple/1)
end
@@ -78,7 +79,7 @@ defmodule Chessh.SSH.Client.SelectCurrentGame do
previous_last_game_id =
case List.last(options) do
{_label, id} -> id
- _ -> 0
+ _ -> 1
end
current_screen_games =
diff --git a/lib/chessh/ssh/client/menus/select_joinable_game.ex b/lib/chessh/ssh/client/menus/select_joinable_game.ex
index f2b7b1f..b0d0cbe 100644
--- a/lib/chessh/ssh/client/menus/select_joinable_game.ex
+++ b/lib/chessh/ssh/client/menus/select_joinable_game.ex
@@ -1,7 +1,8 @@
defmodule Chessh.SSH.Client.SelectJoinableGame do
alias Chessh.{Utils, Repo, Game, PlayerSession}
- alias Chessh.SSH.Client.GameSelector
+ alias Chessh.SSH.Client.Selector
import Ecto.Query
+ require Logger
use Chessh.SSH.Client.SelectPaginatePoller
@@ -12,18 +13,20 @@ defmodule Chessh.SSH.Client.SelectJoinableGame do
def dynamic_options(), do: true
def get_player_joinable_games_with_id(player_id, current_id \\ nil, direction \\ :desc) do
- GameSelector.paginate_ish_query(
+ Selector.paginate_ish_query(
Game
|> where([g], g.status == :continue)
|> where(
[g],
(is_nil(g.dark_player_id) or is_nil(g.light_player_id)) and
- (g.dark_player_id != ^player_id or g.light_player_id != ^player_id)
+ (g.dark_player_id != ^player_id or g.light_player_id != ^player_id) and
+ is_nil(g.bot_id)
)
|> limit(^max_displayed_options()),
current_id,
direction
)
+ |> Repo.preload([:light_player, :dark_player, :bot])
end
def format_game_selection_tuple(%Game{id: game_id} = game) do
@@ -60,6 +63,8 @@ defmodule Chessh.SSH.Client.SelectJoinableGame do
end
def initial_options(%State{player_session: %PlayerSession{player_id: player_id}}) do
+ Logger.info(player_id)
+
get_player_joinable_games_with_id(player_id)
|> Enum.map(&format_game_selection_tuple/1)
end
@@ -71,7 +76,7 @@ defmodule Chessh.SSH.Client.SelectJoinableGame do
previous_last_game_id =
case List.last(options) do
{_label, id} -> id
- _ -> 0
+ _ -> 1
end
current_screen_games =
diff --git a/lib/chessh/ssh/client/menus/select_paginate_poller.ex b/lib/chessh/ssh/client/menus/select_paginate_poller.ex
index adca697..23808b5 100644
--- a/lib/chessh/ssh/client/menus/select_paginate_poller.ex
+++ b/lib/chessh/ssh/client/menus/select_paginate_poller.ex
@@ -26,7 +26,8 @@ defmodule Chessh.SSH.Client.SelectPaginatePoller do
player_session: nil,
options: [],
tick: 0,
- cursor: nil
+ cursor: nil,
+ extra_info: %{}
end
defmacro __using__(_) do
@@ -127,51 +128,55 @@ defmodule Chessh.SSH.Client.SelectPaginatePoller do
max_item = min(length(options), max_displayed_options())
new_state =
- if(max_item > 0,
- do:
- case action do
- :up ->
- %State{
- state
- | selected_option_idx: Utils.wrap_around(selected_option_idx, -1, max_item),
- tick: 0
- }
-
- :down ->
- %State{
- state
- | selected_option_idx: Utils.wrap_around(selected_option_idx, 1, max_item),
- tick: 0
- }
-
- :left ->
- if dynamic_options(),
- do: %State{
+ if max_item > 0 do
+ if action == :return do
+ {_, selected} = Enum.at(options, selected_option_idx)
+ {module, state} = make_process_tuple(selected, state)
+ send(client_pid, {:set_screen_process, module, state})
+ state
+ else
+ if(max_item > 1) do
+ case action do
+ :up ->
+ %State{
state
- | options: previous_page_options(state),
- selected_option_idx: 0,
+ | selected_option_idx: Utils.wrap_around(selected_option_idx, -1, max_item),
tick: 0
}
- :right ->
- if dynamic_options(),
- do: %State{
+ :down ->
+ %State{
state
- | options: next_page_options(state),
- selected_option_idx: 0,
+ | selected_option_idx: Utils.wrap_around(selected_option_idx, 1, max_item),
tick: 0
}
- :return ->
- {_, selected} = Enum.at(options, selected_option_idx)
- {module, state} = make_process_tuple(selected, state)
- send(client_pid, {:set_screen_process, module, state})
- state
-
- _ ->
- nil
+ :left ->
+ if dynamic_options(),
+ do: %State{
+ state
+ | options: previous_page_options(state),
+ selected_option_idx: 0,
+ tick: 0
+ }
+
+ :right ->
+ if dynamic_options(),
+ do: %State{
+ state
+ | options: next_page_options(state),
+ selected_option_idx: 0,
+ tick: 0
+ }
+
+ _ ->
+ state
+ end
+ else
+ state
end
- ) || state
+ end
+ end
if !(action == :return) do
render(width, height, new_state)
@@ -229,7 +234,7 @@ defmodule Chessh.SSH.Client.SelectPaginatePoller do
if i == selected_option_idx do
ANSI.format_fragment(
- [:light_cyan, :bright, "> #{line} <", :reset],
+ [:light_cyan, :bright, "♜ #{line} ♜", :reset],
true
)
else
@@ -238,7 +243,7 @@ defmodule Chessh.SSH.Client.SelectPaginatePoller do
end
)
else
- ["Looks like there's nothing here.", "Use Ctrl+b to go back."]
+ ["Looks like there's nothing here.", "Use Ctrl+b return to the menu."]
end
end
diff --git a/lib/chessh/ssh/client/menus/select_previous_game.ex b/lib/chessh/ssh/client/menus/select_previous_game.ex
index 5f55c3d..c348268 100644
--- a/lib/chessh/ssh/client/menus/select_previous_game.ex
+++ b/lib/chessh/ssh/client/menus/select_previous_game.ex
@@ -1,6 +1,6 @@
defmodule Chessh.SSH.Client.SelectPreviousGame do
alias Chessh.{Utils, Repo, Game, PlayerSession}
- alias Chessh.SSH.Client.GameSelector
+ alias Chessh.SSH.Client.Selector
import Ecto.Query
require Logger
@@ -12,7 +12,7 @@ defmodule Chessh.SSH.Client.SelectPreviousGame do
def dynamic_options(), do: true
def get_player_sorted_current_games_with_id(player_id, current_id \\ nil, direction \\ :desc) do
- GameSelector.paginate_ish_query(
+ Selector.paginate_ish_query(
Game
|> where([g], g.status != :continue)
|> where([g], g.light_player_id == ^player_id or g.dark_player_id == ^player_id)
@@ -20,6 +20,7 @@ defmodule Chessh.SSH.Client.SelectPreviousGame do
current_id,
direction
)
+ |> Repo.preload([:light_player, :dark_player, :bot])
end
def format_game_selection_tuple(%Game{id: game_id} = game) do
@@ -67,7 +68,7 @@ defmodule Chessh.SSH.Client.SelectPreviousGame do
order_by: [desc: g.id]
)
|> Repo.all()
- |> Repo.preload([:light_player, :dark_player])
+ |> Repo.preload([:light_player, :dark_player, :bot])
|> Enum.map(&format_game_selection_tuple/1)
end
@@ -78,7 +79,7 @@ defmodule Chessh.SSH.Client.SelectPreviousGame do
previous_last_game_id =
case List.last(options) do
{_label, id} -> id
- _ -> 0
+ _ -> 1
end
current_screen_games =
diff --git a/lib/chessh/ssh/client/menus/game_selector.ex b/lib/chessh/ssh/client/menus/selector.ex
index 7792082..225c41f 100644
--- a/lib/chessh/ssh/client/menus/game_selector.ex
+++ b/lib/chessh/ssh/client/menus/selector.ex
@@ -1,4 +1,4 @@
-defmodule Chessh.SSH.Client.GameSelector do
+defmodule Chessh.SSH.Client.Selector do
import Ecto.Query
alias Chessh.Repo
@@ -17,7 +17,6 @@ defmodule Chessh.SSH.Client.GameSelector do
sorted_query
end
|> Repo.all()
- |> Repo.preload([:light_player, :dark_player])
if direction == :desc, do: results, else: Enum.reverse(results)
end