diff options
Diffstat (limited to 'lib/chessh/schema')
-rw-r--r-- | lib/chessh/schema/bot.ex | 77 | ||||
-rw-r--r-- | lib/chessh/schema/game.ex | 50 | ||||
-rw-r--r-- | lib/chessh/schema/player.ex | 3 |
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 |