summaryrefslogtreecommitdiff
path: root/lib/chessh/schema
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chessh/schema')
-rw-r--r--lib/chessh/schema/bot.ex77
-rw-r--r--lib/chessh/schema/game.ex50
-rw-r--r--lib/chessh/schema/player.ex3
3 files changed, 128 insertions, 2 deletions
diff --git a/lib/chessh/schema/bot.ex b/lib/chessh/schema/bot.ex
new file mode 100644
index 0000000..9a86d69
--- /dev/null
+++ b/lib/chessh/schema/bot.ex
@@ -0,0 +1,77 @@
+defmodule Chessh.Bot do
+ alias Chessh.{Player, Game, Repo}
+ use Ecto.Schema
+ import Ecto.Query
+ import Ecto.Changeset
+
+ require Logger
+
+ @derive {Jason.Encoder, only: [:id, :name, :webhook, :token, :public]}
+ schema "bots" do
+ field(:name, :string)
+ field(:webhook, :string)
+ field(:token, :string)
+ field(:public, :boolean, default: false)
+
+ belongs_to(:player, Player, foreign_key: :player_id)
+
+ timestamps()
+ end
+
+ def changeset(game, attrs) do
+ game
+ |> cast(attrs, [
+ :public,
+ :name,
+ :webhook,
+ :token,
+ :player_id
+ ])
+ |> validate_required([:name, :webhook, :token, :public])
+ |> validate_format(:webhook, ~r/^https:\/\//, message: "must start with https://")
+ |> unique_constraint(:name)
+ end
+
+ def make_game_status_message(%Game{
+ id: game_id,
+ bot: %Chessh.Bot{id: bot_id, name: bot_name},
+ fen: fen,
+ turn: turn,
+ status: status,
+ light_player_id: light_player_id,
+ dark_player_id: dark_player_id
+ }) do
+ %{
+ bot_id: bot_id,
+ bot_name: bot_name,
+ game_id: game_id,
+ fen: fen,
+ turn: Atom.to_string(turn),
+ bot_turn:
+ (is_nil(light_player_id) && turn == :light) || (is_nil(dark_player_id) && turn == :dark),
+ status: Atom.to_string(status)
+ }
+ end
+
+ def redrive_games(%Chessh.Bot{id: bot_id, webhook: webhook}) do
+ messages =
+ Repo.all(from(g in Game, where: g.bot_id == ^bot_id))
+ |> Repo.preload([:bot])
+ |> Enum.map(&make_game_status_message/1)
+
+ send_message(webhook, messages)
+ end
+
+ def send_update(%Game{bot: %Chessh.Bot{webhook: webhook}} = game) do
+ send_message(webhook, make_game_status_message(game))
+ end
+
+ defp send_message(webhook, msg) do
+ :httpc.request(
+ :post,
+ {String.to_charlist(webhook), [], 'application/json', Jason.encode!(msg)},
+ [],
+ []
+ )
+ end
+end
diff --git a/lib/chessh/schema/game.ex b/lib/chessh/schema/game.ex
index 868fec8..8777472 100644
--- a/lib/chessh/schema/game.ex
+++ b/lib/chessh/schema/game.ex
@@ -1,8 +1,10 @@
defmodule Chessh.Game do
- alias Chessh.Player
+ alias Chessh.{Bot, Player, Game}
use Ecto.Schema
import Ecto.Changeset
+ @default_fen "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"
+
schema "games" do
field(:fen, :string)
field(:moves, :integer, default: 0)
@@ -17,6 +19,8 @@ defmodule Chessh.Game do
belongs_to(:light_player, Player, foreign_key: :light_player_id)
belongs_to(:dark_player, Player, foreign_key: :dark_player_id)
+ belongs_to(:bot, Bot, foreign_key: :bot_id)
+
field(:discord_thread_id, :string)
timestamps()
@@ -34,7 +38,51 @@ defmodule Chessh.Game do
:light_player_id,
:dark_player_id,
:discord_thread_id,
+ :bot_id,
:game_moves
])
end
+
+ def new_game(initial_player_color, player_id, fen \\ @default_fen) do
+ Game.changeset(
+ %Game{
+ fen: fen
+ },
+ if(initial_player_color == :light,
+ do: %{light_player_id: player_id},
+ else: %{dark_player_id: player_id}
+ )
+ )
+ end
+
+ def update_with_status(%Game{} = game, move, fen, status) do
+ Game.changeset(
+ game,
+ %{
+ fen: fen,
+ moves: game.moves + 1,
+ turn: if(game.turn == :dark, do: :light, else: :dark),
+ last_move: move,
+ game_moves:
+ if(!is_nil(game) && game.game_moves != "", do: "#{game.game_moves} ", else: "") <> move
+ }
+ |> Map.merge(changeset_from_status(status))
+ )
+ end
+
+ def changeset_from_status(game_status) do
+ case game_status do
+ :continue ->
+ %{}
+
+ {:draw, _} ->
+ %{status: :draw}
+
+ {:checkmate, :white_wins} ->
+ %{status: :winner, winner: :light}
+
+ {:checkmate, :black_wins} ->
+ %{status: :winner, winner: :dark}
+ end
+ end
end
diff --git a/lib/chessh/schema/player.ex b/lib/chessh/schema/player.ex
index dcb3548..d5bcab2 100644
--- a/lib/chessh/schema/player.ex
+++ b/lib/chessh/schema/player.ex
@@ -1,7 +1,7 @@
defmodule Chessh.Player do
use Ecto.Schema
import Ecto.Changeset
- alias Chessh.{Key, Game}
+ alias Chessh.{Key, Game, Bot}
@derive {Inspect, except: [:password]}
schema "players" do
@@ -17,6 +17,7 @@ defmodule Chessh.Player do
has_many(:keys, Key)
has_many(:light_games, Game, foreign_key: :light_player_id, references: :id)
has_many(:dark_games, Game, foreign_key: :dark_player_id, references: :id)
+ has_many(:bots, Bot, foreign_key: :player_id, references: :id)
timestamps()
end