mirror of
https://github.com/danbee/chess
synced 2025-03-04 08:39:06 +00:00
Compare commits
12 Commits
205d5a5a24
...
080574070b
| Author | SHA1 | Date | |
|---|---|---|---|
| 080574070b | |||
| 13cc64dd56 | |||
| a905c75174 | |||
| d0ece1434d | |||
| f7756a971a | |||
| 5363271b95 | |||
| dfc3fd669e | |||
| ba6909e90d | |||
| 3351d75cc1 | |||
| 7af5f8ce33 | |||
| e36b561412 | |||
| 805efc4795 |
@ -8,13 +8,16 @@
|
||||
width: 1.5%;
|
||||
}
|
||||
|
||||
.board__container {
|
||||
grid-area: board;
|
||||
}
|
||||
|
||||
.board {
|
||||
background: $background-color;
|
||||
border-collapse: unset;
|
||||
border-radius: 2.8%;
|
||||
border-spacing: 1px;
|
||||
color: $foreground-color;
|
||||
grid-area: board;
|
||||
height: var(--board-size);
|
||||
padding: calc(var(--board-size) / 20);
|
||||
position: relative;
|
||||
@ -58,6 +61,14 @@
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.board__body {
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
|
||||
.board__row {
|
||||
flex-direction: row;
|
||||
}
|
||||
}
|
||||
|
||||
.board--player-is-black {
|
||||
@ -70,20 +81,45 @@
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
.board__body {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.board__row {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
}
|
||||
|
||||
.board__body {
|
||||
background: $background-color;
|
||||
border: 0.25rem solid $foreground-color;
|
||||
border-radius: calc(var(--board-size) / 100);
|
||||
display: grid;
|
||||
grid-template-columns: repeat(8, 1fr);
|
||||
grid-template-rows: repeat(8, 1fr);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
padding: 1%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.board__row {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
|
||||
@include odd-between(1, 8) {
|
||||
.square {
|
||||
@include odd-between(1, 8) { @extend %square--black; }
|
||||
@include even-between(1, 8) { @extend %square--white; }
|
||||
}
|
||||
}
|
||||
@include even-between(1, 8) {
|
||||
.square {
|
||||
@include odd-between(1, 8) { @extend %square--white; }
|
||||
@include even-between(1, 8) { @extend %square--black; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.board__rank-labels {
|
||||
display: none;
|
||||
height: 90%;
|
||||
|
||||
@ -57,36 +57,13 @@
|
||||
border-radius: 4%;
|
||||
margin: 0.5px;
|
||||
position: relative;
|
||||
flex-grow: 1;
|
||||
|
||||
// This is to ensure the squares can be clicked on in PhantomJS
|
||||
// TODO: Figure out why we need this
|
||||
min-height: 20px;
|
||||
min-width: 20px;
|
||||
|
||||
@include odd-between(1, 8) { @extend %square--white; }
|
||||
@include even-between(1, 8) { @extend %square--black; }
|
||||
|
||||
@include odd-between(9, 16) { @extend %square--black; }
|
||||
@include even-between(9, 16) { @extend %square--white; }
|
||||
|
||||
@include odd-between(17, 24) { @extend %square--white; }
|
||||
@include even-between(17, 24) { @extend %square--black; }
|
||||
|
||||
@include odd-between(25, 32) { @extend %square--black; }
|
||||
@include even-between(25, 32) { @extend %square--white; }
|
||||
|
||||
@include odd-between(33, 40) { @extend %square--white; }
|
||||
@include even-between(33, 40) { @extend %square--black; }
|
||||
|
||||
@include odd-between(41, 48) { @extend %square--black; }
|
||||
@include even-between(41, 48) { @extend %square--white; }
|
||||
|
||||
@include odd-between(49, 56) { @extend %square--white; }
|
||||
@include even-between(49, 56) { @extend %square--black; }
|
||||
|
||||
@include odd-between(57, 64) { @extend %square--black; }
|
||||
@include even-between(57, 64) { @extend %square--white; }
|
||||
|
||||
&::before {
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
|
||||
@ -1,5 +1,20 @@
|
||||
"use strict";
|
||||
|
||||
import {Socket} from "phoenix";
|
||||
import LiveSocket from "phoenix_live_view";
|
||||
|
||||
let csrfToken = document
|
||||
.querySelector("meta[name='csrf-token']").getAttribute("content");
|
||||
let liveSocket = new LiveSocket(
|
||||
"/live",
|
||||
Socket,
|
||||
{params: {_csrf_token: csrfToken}}
|
||||
);
|
||||
|
||||
liveSocket.connect()
|
||||
|
||||
window.liveSocket = liveSocket
|
||||
|
||||
import "@babel/polyfill";
|
||||
import "phoenix_html";
|
||||
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
"lodash": "^4.17.21",
|
||||
"phoenix": "file:../deps/phoenix",
|
||||
"phoenix_html": "file:../deps/phoenix_html",
|
||||
"phoenix_live_view": "file:../deps/phoenix_live_view",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-redux": "^7.2.4",
|
||||
|
||||
@ -3130,6 +3130,8 @@ picomatch@^2.2.1, picomatch@^2.2.3:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
|
||||
integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==
|
||||
"phoenix_live_view@file:../deps/phoenix_live_view":
|
||||
version "0.15.3"
|
||||
|
||||
pify@^2.0.0:
|
||||
version "2.3.0"
|
||||
|
||||
@ -16,7 +16,8 @@ config :chess, ChessWeb.Endpoint,
|
||||
url: [host: "localhost"],
|
||||
secret_key_base: "iiTDTKorCWTFoeBgAkr35XZp22cNIM2RsmnHiHdzKAuSHXUGXx42z7lawAwiu1B1",
|
||||
render_errors: [view: ChessWeb.ErrorView, accepts: ~w(html json)],
|
||||
pubsub_server: Chess.PubSub
|
||||
pubsub_server: Chess.PubSub,
|
||||
live_view: [signing_salt: "R3JjvjiRi64kjFCHqCJCfk7EY8hohfadgLqO/VUFRO8="]
|
||||
|
||||
# Configures Elixir's Logger
|
||||
config :logger, :console,
|
||||
|
||||
@ -2,17 +2,19 @@ defmodule Chess.Board do
|
||||
@moduledoc false
|
||||
|
||||
def transform(board) do
|
||||
Enum.map(0..7, fn (rank) ->
|
||||
Enum.map(0..7, fn (file) ->
|
||||
Enum.map(0..7, fn rank ->
|
||||
{rank,
|
||||
Enum.map(0..7, fn file ->
|
||||
{file,
|
||||
board
|
||||
|> piece({file, rank})
|
||||
end)
|
||||
|> piece({file, rank})}
|
||||
end)}
|
||||
end)
|
||||
end
|
||||
|
||||
def search(board, %{"type" => type, "colour" => colour}) do
|
||||
board
|
||||
|> Enum.filter(fn({_index, piece}) ->
|
||||
|> Enum.filter(fn {_index, piece} ->
|
||||
match?(%{"type" => ^type, "colour" => ^colour}, piece)
|
||||
end)
|
||||
|> indexes_to_tuples
|
||||
@ -20,7 +22,7 @@ defmodule Chess.Board do
|
||||
|
||||
def search(board, %{"colour" => colour}) do
|
||||
board
|
||||
|> Enum.filter(fn({_index, piece}) ->
|
||||
|> Enum.filter(fn {_index, piece} ->
|
||||
match?(%{"colour" => ^colour}, piece)
|
||||
end)
|
||||
|> indexes_to_tuples
|
||||
@ -31,8 +33,8 @@ defmodule Chess.Board do
|
||||
end
|
||||
|
||||
def move_piece(board, %{
|
||||
"from" => [from_file, from_rank],
|
||||
"to" => [to_file, to_rank]
|
||||
from: {from_file, from_rank},
|
||||
to: {to_file, to_rank}
|
||||
}) do
|
||||
{piece, board} = Map.pop(board, to_index({from_file, from_rank}))
|
||||
{piece_captured, board} = Map.pop(board, to_index({to_file, to_rank}))
|
||||
@ -42,8 +44,8 @@ defmodule Chess.Board do
|
||||
if castling_move?(piece, from_file, to_file) do
|
||||
board
|
||||
|> castling_move(%{
|
||||
"from" => [from_file, from_rank],
|
||||
"to" => [to_file, to_rank]
|
||||
from: {from_file, from_rank},
|
||||
to: {to_file, to_rank}
|
||||
})
|
||||
|> Map.get(:board)
|
||||
else
|
||||
@ -55,25 +57,27 @@ defmodule Chess.Board do
|
||||
to: %{"file" => to_file, "rank" => to_rank},
|
||||
board: board,
|
||||
piece: piece,
|
||||
piece_captured: piece_captured,
|
||||
piece_captured: piece_captured
|
||||
}
|
||||
end
|
||||
|
||||
def castling_move?(%{"type" => "king"}, 4, to_file) do
|
||||
to_file == 2 || to_file == 6
|
||||
end
|
||||
|
||||
def castling_move?(_, _, _), do: false
|
||||
|
||||
def castling_move(board, %{"from" => [4, rank], "to" => [2, _rank]}) do
|
||||
def castling_move(board, %{from: {4, rank}, to: {2, _rank}}) do
|
||||
move_piece(board, %{
|
||||
"from" => [0, rank],
|
||||
"to" => [3, rank],
|
||||
from: {0, rank},
|
||||
to: {3, rank}
|
||||
})
|
||||
end
|
||||
def castling_move(board, %{"from" => [4, rank], "to" => [6, _rank]}) do
|
||||
|
||||
def castling_move(board, %{from: {4, rank}, to: {6, _rank}}) do
|
||||
move_piece(board, %{
|
||||
"from" => [7, rank],
|
||||
"to" => [5, rank],
|
||||
from: {7, rank},
|
||||
to: {5, rank}
|
||||
})
|
||||
end
|
||||
|
||||
@ -87,7 +91,6 @@ defmodule Chess.Board do
|
||||
"5,7" => %{"type" => "bishop", "colour" => "black"},
|
||||
"6,7" => %{"type" => "knight", "colour" => "black"},
|
||||
"7,7" => %{"type" => "rook", "colour" => "black"},
|
||||
|
||||
"0,6" => %{"type" => "pawn", "colour" => "black"},
|
||||
"1,6" => %{"type" => "pawn", "colour" => "black"},
|
||||
"2,6" => %{"type" => "pawn", "colour" => "black"},
|
||||
@ -96,7 +99,6 @@ defmodule Chess.Board do
|
||||
"5,6" => %{"type" => "pawn", "colour" => "black"},
|
||||
"6,6" => %{"type" => "pawn", "colour" => "black"},
|
||||
"7,6" => %{"type" => "pawn", "colour" => "black"},
|
||||
|
||||
"0,1" => %{"type" => "pawn", "colour" => "white"},
|
||||
"1,1" => %{"type" => "pawn", "colour" => "white"},
|
||||
"2,1" => %{"type" => "pawn", "colour" => "white"},
|
||||
@ -105,7 +107,6 @@ defmodule Chess.Board do
|
||||
"5,1" => %{"type" => "pawn", "colour" => "white"},
|
||||
"6,1" => %{"type" => "pawn", "colour" => "white"},
|
||||
"7,1" => %{"type" => "pawn", "colour" => "white"},
|
||||
|
||||
"0,0" => %{"type" => "rook", "colour" => "white"},
|
||||
"1,0" => %{"type" => "knight", "colour" => "white"},
|
||||
"2,0" => %{"type" => "bishop", "colour" => "white"},
|
||||
@ -123,13 +124,13 @@ defmodule Chess.Board do
|
||||
|
||||
defp indexes_to_tuples(list) do
|
||||
list
|
||||
|> Enum.map(fn({index, _piece}) -> index_to_tuple(index) end)
|
||||
|> Enum.map(fn {index, _piece} -> index_to_tuple(index) end)
|
||||
end
|
||||
|
||||
defp index_to_tuple(index) do
|
||||
index
|
||||
|> String.split(",")
|
||||
|> Enum.map(&(String.to_integer(&1)))
|
||||
|> List.to_tuple
|
||||
|> Enum.map(&String.to_integer(&1))
|
||||
|> List.to_tuple()
|
||||
end
|
||||
end
|
||||
|
||||
@ -14,11 +14,15 @@ defmodule Chess.GameState do
|
||||
cond do
|
||||
player_checkmated?(board, colour) ->
|
||||
"checkmate"
|
||||
|
||||
player_stalemated?(board, colour) ->
|
||||
"stalemate"
|
||||
|
||||
king_in_check?(board, colour) ->
|
||||
"check"
|
||||
true -> nil
|
||||
|
||||
true ->
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
@ -36,7 +40,7 @@ defmodule Chess.GameState do
|
||||
king =
|
||||
board
|
||||
|> Board.search(%{"type" => "king", "colour" => colour})
|
||||
|> List.first
|
||||
|> List.first()
|
||||
|
||||
if is_nil(king) do
|
||||
raise "There is no #{colour} king!"
|
||||
@ -49,7 +53,7 @@ defmodule Chess.GameState do
|
||||
def player_cannot_move?(board, colour) do
|
||||
board
|
||||
|> Board.search(%{"colour" => colour})
|
||||
|> Enum.all?(fn({file, rank}) ->
|
||||
|> Enum.all?(fn {file, rank} ->
|
||||
board
|
||||
|> piece_cannot_move?({file, rank})
|
||||
end)
|
||||
@ -62,9 +66,9 @@ defmodule Chess.GameState do
|
||||
|
||||
board
|
||||
|> Moves.available({file, rank})
|
||||
|> Enum.all?(fn({to_file, to_rank}) ->
|
||||
|> Enum.all?(fn {to_file, to_rank} ->
|
||||
board
|
||||
|> Board.move_piece(%{"from" => [file, rank], "to" => [to_file, to_rank]})
|
||||
|> Board.move_piece(%{from: {file, rank}, to: {to_file, to_rank}})
|
||||
|> Map.get(:board)
|
||||
|> king_in_check?(piece["colour"])
|
||||
end)
|
||||
|
||||
@ -19,10 +19,10 @@ defmodule Chess.Moves do
|
||||
game.board
|
||||
|> Board.move_piece(move_params)
|
||||
|
||||
Multi.new
|
||||
Multi.new()
|
||||
|> Multi.update(:game, Game.move_changeset(game, params))
|
||||
|> Multi.insert(:move, Ecto.build_assoc(game, :moves, params))
|
||||
|> Repo.transaction
|
||||
|> Repo.transaction()
|
||||
end
|
||||
|
||||
def available(board, {file, rank}, move_list \\ []) do
|
||||
@ -33,14 +33,19 @@ defmodule Chess.Moves do
|
||||
case piece do
|
||||
%{"type" => "pawn"} ->
|
||||
Pawn.moves(board, {file, rank})
|
||||
|
||||
%{"type" => "rook"} ->
|
||||
Rook.moves(board, {file, rank})
|
||||
|
||||
%{"type" => "bishop"} ->
|
||||
Bishop.moves(board, {file, rank})
|
||||
|
||||
%{"type" => "knight"} ->
|
||||
Knight.moves(board, {file, rank})
|
||||
|
||||
%{"type" => "king"} ->
|
||||
King.moves(board, {file, rank}, move_list)
|
||||
|
||||
%{"type" => "queen"} ->
|
||||
Queen.moves(board, {file, rank})
|
||||
end
|
||||
|
||||
@ -18,12 +18,13 @@ defmodule Chess.Moves.Pieces.King.Castling do
|
||||
[]
|
||||
end
|
||||
end
|
||||
|
||||
def moves(_board, _piece, _move_list), do: []
|
||||
|
||||
def _moves(board, _rank, colour, move_list) do
|
||||
board
|
||||
|> Board.search(%{"type" => "rook", "colour" => colour})
|
||||
|> Enum.map(fn ({file, rank}) ->
|
||||
|> Enum.map(fn {file, rank} ->
|
||||
case file do
|
||||
0 -> queen_side_move(board, rank, colour, move_list)
|
||||
7 -> king_side_move(board, rank, colour, move_list)
|
||||
@ -35,10 +36,13 @@ defmodule Chess.Moves.Pieces.King.Castling do
|
||||
|
||||
defp king_has_moved?(move_list, colour) do
|
||||
move_list
|
||||
|> Enum.any?(fn (move) ->
|
||||
match?(%Move{
|
||||
|> Enum.any?(fn move ->
|
||||
match?(
|
||||
%Move{
|
||||
piece: %{"type" => "king", "colour" => ^colour}
|
||||
}, move)
|
||||
},
|
||||
move
|
||||
)
|
||||
end)
|
||||
end
|
||||
|
||||
@ -60,19 +64,22 @@ defmodule Chess.Moves.Pieces.King.Castling do
|
||||
|
||||
defp rook_has_moved?(file, move_list, colour) do
|
||||
move_list
|
||||
|> Enum.any?(fn (move) ->
|
||||
match?(%Move{
|
||||
|> Enum.any?(fn move ->
|
||||
match?(
|
||||
%Move{
|
||||
piece: %{"type" => "rook", "colour" => ^colour},
|
||||
from: %{"file" => ^file},
|
||||
}, move)
|
||||
from: %{"file" => ^file}
|
||||
},
|
||||
move
|
||||
)
|
||||
end)
|
||||
end
|
||||
|
||||
defp queen_side_in_check?(board, rank, colour) do
|
||||
[{2, rank}, {3, rank}]
|
||||
|> Enum.any?(fn ({to_file, to_rank}) ->
|
||||
|> Enum.any?(fn {to_file, to_rank} ->
|
||||
board
|
||||
|> Board.move_piece(%{"from" => [4, rank], "to" => [to_file, to_rank]})
|
||||
|> Board.move_piece(%{from: {4, rank}, to: {to_file, to_rank}})
|
||||
|> Map.get(:board)
|
||||
|> GameState.king_in_check?(colour)
|
||||
end)
|
||||
@ -80,9 +87,9 @@ defmodule Chess.Moves.Pieces.King.Castling do
|
||||
|
||||
defp king_side_in_check?(board, rank, colour) do
|
||||
[{5, rank}, {6, rank}]
|
||||
|> Enum.any?(fn ({to_file, to_rank}) ->
|
||||
|> Enum.any?(fn {to_file, to_rank} ->
|
||||
board
|
||||
|> Board.move_piece(%{"from" => [4, rank], "to" => [to_file, to_rank]})
|
||||
|> Board.move_piece(%{from: {4, rank}, to: {to_file, to_rank}})
|
||||
|> Map.get(:board)
|
||||
|> GameState.king_in_check?(colour)
|
||||
end)
|
||||
|
||||
@ -14,14 +14,14 @@ defmodule Chess.Store.Game do
|
||||
alias Chess.Store.User
|
||||
|
||||
schema "games" do
|
||||
field :board, :map, default: Board.default()
|
||||
field :turn, :string, default: "white"
|
||||
field :state, :string
|
||||
field(:board, :map, default: Board.default())
|
||||
field(:turn, :string, default: "white")
|
||||
field(:state, :string)
|
||||
|
||||
belongs_to :user, User
|
||||
belongs_to :opponent, User, references: :id
|
||||
belongs_to(:user, User)
|
||||
belongs_to(:opponent, User, references: :id)
|
||||
|
||||
has_many :moves, Move
|
||||
has_many(:moves, Move)
|
||||
|
||||
timestamps()
|
||||
end
|
||||
@ -55,15 +55,17 @@ defmodule Chess.Store.Game do
|
||||
end
|
||||
|
||||
def for_user_id(user_id) do
|
||||
from game in Game,
|
||||
from(game in Game,
|
||||
where: game.user_id == ^user_id,
|
||||
or_where: game.opponent_id == ^user_id
|
||||
)
|
||||
end
|
||||
|
||||
def check_game_state(changeset) do
|
||||
changeset
|
||||
|> put_change(
|
||||
:state, GameState.state(changeset.changes.board, changeset.changes.turn)
|
||||
:state,
|
||||
GameState.state(changeset.changes.board, changeset.changes.turn)
|
||||
)
|
||||
end
|
||||
|
||||
@ -78,6 +80,7 @@ defmodule Chess.Store.Game do
|
||||
changeset
|
||||
end
|
||||
end
|
||||
|
||||
def validate_king_in_check(changeset, _, _), do: changeset
|
||||
|
||||
def ordered(query) do
|
||||
|
||||
@ -19,6 +19,7 @@ defmodule ChessWeb do
|
||||
def controller do
|
||||
quote do
|
||||
use Phoenix.Controller, namespace: ChessWeb
|
||||
import Phoenix.LiveView.Controller
|
||||
|
||||
alias Chess.Repo
|
||||
import Ecto
|
||||
@ -37,6 +38,7 @@ defmodule ChessWeb do
|
||||
# Import convenience functions from controllers
|
||||
import Phoenix.Controller,
|
||||
only: [get_csrf_token: 0, get_flash: 2, view_module: 1]
|
||||
import Phoenix.LiveView.Helpers
|
||||
|
||||
# Use all HTML functionality (forms, tags, etc)
|
||||
use Phoenix.HTML
|
||||
@ -49,9 +51,45 @@ defmodule ChessWeb do
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def live_view do
|
||||
quote do
|
||||
use Phoenix.LiveView,
|
||||
layout: {ChessWeb.LayoutView, "live.html"}
|
||||
|
||||
unquote(view_helpers())
|
||||
end
|
||||
end
|
||||
|
||||
def live_component do
|
||||
quote do
|
||||
use Phoenix.LiveComponent
|
||||
|
||||
unquote(view_helpers())
|
||||
end
|
||||
end
|
||||
|
||||
defp view_helpers do
|
||||
quote do
|
||||
# Use all HTML functionality (forms, tags, etc)
|
||||
use Phoenix.HTML
|
||||
|
||||
# Import LiveView helpers (live_render, live_component, live_patch, etc)
|
||||
import Phoenix.LiveView.Helpers
|
||||
|
||||
# Import basic rendering functionality (render, render_layout, etc)
|
||||
import Phoenix.View
|
||||
|
||||
import ChessWeb.ErrorHelpers
|
||||
import ChessWeb.Gettext
|
||||
alias ChessWeb.Router.Helpers, as: Routes
|
||||
end
|
||||
end
|
||||
|
||||
def router do
|
||||
quote do
|
||||
use Phoenix.Router
|
||||
import Phoenix.LiveView.Router
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -32,7 +32,7 @@ defmodule ChessWeb.GameChannel do
|
||||
board: Board.transform(game.board),
|
||||
turn: game.turn,
|
||||
state: game.state,
|
||||
moves: MoveList.transform(game.moves),
|
||||
moves: MoveList.transform(game.moves)
|
||||
}
|
||||
|
||||
socket
|
||||
@ -57,6 +57,7 @@ defmodule ChessWeb.GameChannel do
|
||||
update_opponent(socket, game)
|
||||
|
||||
{:noreply, socket}
|
||||
|
||||
{:error, :game, changeset, _} ->
|
||||
{message, _} = changeset.errors[:board]
|
||||
|
||||
@ -73,13 +74,18 @@ defmodule ChessWeb.GameChannel do
|
||||
socket.assigns.user_id
|
||||
|> Queries.game_with_moves(socket.assigns.game_id)
|
||||
|
||||
moves = Moves.available(game.board, {
|
||||
moves =
|
||||
Moves.available(
|
||||
game.board,
|
||||
{
|
||||
String.to_integer(file),
|
||||
String.to_integer(rank)
|
||||
}, game.moves)
|
||||
},
|
||||
game.moves
|
||||
)
|
||||
|
||||
reply = %{
|
||||
moves: Enum.map(moves, &(Tuple.to_list(&1)))
|
||||
moves: Enum.map(moves, &Tuple.to_list(&1))
|
||||
}
|
||||
|
||||
{:reply, {:ok, reply}, socket}
|
||||
@ -88,24 +94,26 @@ defmodule ChessWeb.GameChannel do
|
||||
def update_opponent(socket, game) do
|
||||
opponent_id =
|
||||
opponent(game, socket.assigns.user_id).id
|
||||
|> Integer.to_string
|
||||
|> Integer.to_string()
|
||||
|
||||
send_update(socket)
|
||||
|
||||
"game:#{game.id}"
|
||||
|> Presence.list
|
||||
|> Presence.list()
|
||||
|> case do
|
||||
%{^opponent_id => _} ->
|
||||
nil
|
||||
|
||||
_ ->
|
||||
socket
|
||||
|> Emails.opponent_moved_email(game)
|
||||
|> Mailer.deliver_later
|
||||
|> Mailer.deliver_later()
|
||||
end
|
||||
end
|
||||
|
||||
def track_presence(socket) do
|
||||
{:ok, _} = Presence.track(socket, socket.assigns.user_id, %{
|
||||
{:ok, _} =
|
||||
Presence.track(socket, socket.assigns.user_id, %{
|
||||
user_id: socket.assigns.user_id,
|
||||
online_at: inspect(System.system_time(:second))
|
||||
})
|
||||
@ -116,8 +124,8 @@ defmodule ChessWeb.GameChannel do
|
||||
|
||||
def convert_params(%{"from" => from, "to" => to}) do
|
||||
%{
|
||||
"from" => Enum.map(from, &(String.to_integer(&1))),
|
||||
"to" => Enum.map(to, &(String.to_integer(&1))),
|
||||
"from" => Enum.map(from, &String.to_integer(&1)),
|
||||
"to" => Enum.map(to, &String.to_integer(&1))
|
||||
}
|
||||
end
|
||||
|
||||
@ -130,7 +138,7 @@ defmodule ChessWeb.GameChannel do
|
||||
board: Board.transform(game.board),
|
||||
turn: game.turn,
|
||||
state: game.state,
|
||||
moves: MoveList.transform(game.moves),
|
||||
moves: MoveList.transform(game.moves)
|
||||
}
|
||||
|
||||
ChessWeb.Endpoint.broadcast("game:#{game.id}", "game:update", payload)
|
||||
|
||||
@ -15,9 +15,9 @@ defmodule ChessWeb.GameController do
|
||||
conn
|
||||
|> current_user()
|
||||
|> Game.for_user()
|
||||
|> Game.ordered
|
||||
|> Game.ordered()
|
||||
|> preload([:user, :opponent])
|
||||
|> Repo.all
|
||||
|> Repo.all()
|
||||
|
||||
conn
|
||||
|> render("index.html", games: games, changeset: changeset)
|
||||
@ -42,7 +42,7 @@ defmodule ChessWeb.GameController do
|
||||
|> Repo.preload(:user)
|
||||
|> Repo.preload(:opponent)
|
||||
)
|
||||
|> Mailer.deliver_later
|
||||
|> Mailer.deliver_later()
|
||||
|
||||
conn
|
||||
|> put_flash(:info, "Game created successfully.")
|
||||
@ -53,7 +53,7 @@ defmodule ChessWeb.GameController do
|
||||
conn
|
||||
|> current_user()
|
||||
|> User.opponents()
|
||||
|> Repo.all
|
||||
|> Repo.all()
|
||||
|
||||
conn
|
||||
|> render("new.html", changeset: changeset, opponents: opponents)
|
||||
|
||||
@ -1,12 +1,20 @@
|
||||
defmodule ChessWeb.Endpoint do
|
||||
use Phoenix.Endpoint, otp_app: :chess
|
||||
|
||||
if sandbox = Application.get_env(:chess, :sandbox) do
|
||||
plug(Phoenix.Ecto.SQL.Sandbox, sandbox: sandbox)
|
||||
@session_options [
|
||||
store: :cookie,
|
||||
key: "_chess_key",
|
||||
signing_salt: "9LqUhZTU"
|
||||
]
|
||||
|
||||
if Application.get_env(:chess, :sql_sandbox) do
|
||||
plug(Phoenix.Ecto.SQL.Sandbox)
|
||||
end
|
||||
|
||||
socket("/socket", ChessWeb.UserSocket)
|
||||
|
||||
socket("/live", Phoenix.LiveView.Socket, websocket: [connect_info: [session: @session_options]])
|
||||
|
||||
# Serve at "/" the static files from "priv/static" directory.
|
||||
#
|
||||
# You should set gzip to true if you are running phoenix.digest
|
||||
@ -45,11 +53,7 @@ defmodule ChessWeb.Endpoint do
|
||||
# The session will be stored in the cookie and signed,
|
||||
# this means its contents can be read but not tampered with.
|
||||
# Set :encryption_salt if you would also like to encrypt it.
|
||||
plug(Plug.Session,
|
||||
store: :cookie,
|
||||
key: "_chess_key",
|
||||
signing_salt: "9LqUhZTU"
|
||||
)
|
||||
plug(Plug.Session, @session_options)
|
||||
|
||||
plug(ChessWeb.Router)
|
||||
end
|
||||
|
||||
@ -6,7 +6,7 @@ defmodule ChessWeb.Router do
|
||||
pipeline :browser do
|
||||
plug :accepts, ["html"]
|
||||
plug :fetch_session
|
||||
plug :fetch_flash
|
||||
plug :fetch_live_flash
|
||||
plug :protect_from_forgery
|
||||
plug :put_secure_browser_headers
|
||||
end
|
||||
|
||||
43
lib/chess_web/templates/game/board.html.leex
Normal file
43
lib/chess_web/templates/game/board.html.leex
Normal file
@ -0,0 +1,43 @@
|
||||
<div class="board board--<%= @game.turn %>-to-move board--player-is-<%= player_colour(@user, @game) %>">
|
||||
<div class="board__rank-labels">
|
||||
<div class="board__label">1</div>
|
||||
<div class="board__label">2</div>
|
||||
<div class="board__label">3</div>
|
||||
<div class="board__label">4</div>
|
||||
<div class="board__label">5</div>
|
||||
<div class="board__label">6</div>
|
||||
<div class="board__label">7</div>
|
||||
<div class="board__label">8</div>
|
||||
</div>
|
||||
|
||||
<div class="board__file-labels">
|
||||
<div class="board__label">a</div>
|
||||
<div class="board__label">b</div>
|
||||
<div class="board__label">c</div>
|
||||
<div class="board__label">d</div>
|
||||
<div class="board__label">e</div>
|
||||
<div class="board__label">f</div>
|
||||
<div class="board__label">g</div>
|
||||
<div class="board__label">h</div>
|
||||
</div>
|
||||
|
||||
<div class="board__body">
|
||||
<%= for {rank, row} <- @board do %>
|
||||
<div class="board__row">
|
||||
<%= for {file, piece} <- row do %>
|
||||
<%= render ChessWeb.SquareView,
|
||||
"square.html",
|
||||
rank: rank,
|
||||
file: file,
|
||||
piece: piece,
|
||||
selected: {file, rank} == @selected,
|
||||
available: {file, rank} in @available %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="game-state game-state--<%= @game.state %>">
|
||||
<%= states[@game.state] %>
|
||||
</div>
|
||||
</div>
|
||||
6
lib/chess_web/templates/game/game_info.html.leex
Normal file
6
lib/chess_web/templates/game/game_info.html.leex
Normal file
@ -0,0 +1,6 @@
|
||||
<div class="game-info">
|
||||
<p>
|
||||
Playing <%= opponent(@game, @user.id).name %>
|
||||
<img class="game-info__opponent-status" src="/images/eye-closed.svg" alt="offline">
|
||||
</p>
|
||||
</div>
|
||||
@ -6,7 +6,7 @@
|
||||
<tr class="<%= turn_class(@conn, game) %>">
|
||||
<td>
|
||||
<span class="games-list__player-indicator">
|
||||
<img src="images/pawn_<%= player_colour(@conn, game) %>.svg">
|
||||
<img src="images/pawn_<%= player_colour(current_user(@conn), game) %>.svg">
|
||||
</span>
|
||||
<%= link gettext(
|
||||
"Game with %{name}",
|
||||
|
||||
@ -1,2 +1,33 @@
|
||||
<div id="game" data-game-id="<%= @game.id %>">
|
||||
<div data-game-id="<%= @game.id %>">
|
||||
<div class="game-grid">
|
||||
<%= live_render(
|
||||
@conn,
|
||||
ChessWeb.BoardLive,
|
||||
session: %{"user_id" => current_user(@conn).id, "game_id" => @game.id}
|
||||
) %>
|
||||
|
||||
<%= live_render(
|
||||
@conn,
|
||||
ChessWeb.GameInfoLive,
|
||||
session: %{"user_id" => current_user(@conn).id, "game_id" => @game.id}
|
||||
) %>
|
||||
|
||||
<div class="move-list">
|
||||
<table class="table table--condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="move-list__line-number"><span class="visually-hidden">Move no.</span></th>
|
||||
<th class="move-list__header--white">White</th>
|
||||
<th class="move-list__header--black">Black</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row" class="move-list__line-number">1.</th>
|
||||
<td class="move-list__move move-list__move--white">e4</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
<%= csrf_meta_tag() %>
|
||||
|
||||
<title><%= gettext "64squares" %></title>
|
||||
<link href="https://fonts.googleapis.com/css?family=Enriqueta:400,700" rel="stylesheet">
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<div class="form">
|
||||
<h2><%= gettext "Password" %></h2>
|
||||
|
||||
<%= form_for @changeset, password_path(@conn, :update), [class: "update-password"], fn f -> %>
|
||||
<%= form_for @changeset, password_path(@conn, :update), [class: "update-password", novalidate: true], fn f -> %>
|
||||
<%= if @changeset.action do %>
|
||||
<div class="alert alert-danger">
|
||||
<p>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<div class="form">
|
||||
<h2><%= gettext "Profile" %></h2>
|
||||
|
||||
<%= form_for @changeset, profile_path(@conn, :update), [class: "update-profile"], fn f -> %>
|
||||
<%= form_for @changeset, profile_path(@conn, :update), [class: "update-profile", novalidate: true], fn f -> %>
|
||||
<%= if @changeset.action do %>
|
||||
<div class="alert alert-danger">
|
||||
<p>
|
||||
|
||||
7
lib/chess_web/templates/square/square.html.leex
Normal file
7
lib/chess_web/templates/square/square.html.leex
Normal file
@ -0,0 +1,7 @@
|
||||
<div
|
||||
id="f<%= @file %>-r<%= @rank %>"
|
||||
phx-click="click"
|
||||
phx-value-rank="<%= @rank %>"
|
||||
phx-value-file="<%= @file %>"
|
||||
class="<%= classes(@file, @rank, @piece, @selected, @available) %>"
|
||||
></div>
|
||||
@ -7,8 +7,8 @@ defmodule ChessWeb.GameView do
|
||||
|
||||
def won_lost(conn, game) do
|
||||
if game_over?(game) && game.state == "checkmate" do
|
||||
your_turn?(conn, game) &&
|
||||
gettext("You lost") ||
|
||||
(your_turn?(conn, game) &&
|
||||
gettext("You lost")) ||
|
||||
gettext("You won")
|
||||
end
|
||||
end
|
||||
@ -21,9 +21,12 @@ defmodule ChessWeb.GameView do
|
||||
cond do
|
||||
GameState.game_over?(game) ->
|
||||
states()[game.state]
|
||||
|
||||
your_turn?(conn, game) ->
|
||||
gettext("Your turn")
|
||||
true -> nil
|
||||
|
||||
true ->
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
@ -34,11 +37,26 @@ defmodule ChessWeb.GameView do
|
||||
end
|
||||
|
||||
def your_turn?(conn, game) do
|
||||
player_colour(conn, game) == game.turn
|
||||
conn
|
||||
|> current_user()
|
||||
|> player_colour(game) == game.turn
|
||||
end
|
||||
|
||||
def player_colour(conn, game) do
|
||||
current_user(conn).id == game.user_id && "white" || "black"
|
||||
def player_colour(user, game) do
|
||||
(user.id == game.user_id && "white") || "black"
|
||||
end
|
||||
|
||||
def files(conn, game) do
|
||||
ranks(conn, game)
|
||||
|> Enum.reverse()
|
||||
end
|
||||
|
||||
def ranks(conn, game) do
|
||||
if game.user_id == current_user(conn).id do
|
||||
7..0
|
||||
else
|
||||
0..7
|
||||
end
|
||||
end
|
||||
|
||||
def player(game, user_id) do
|
||||
@ -61,7 +79,7 @@ defmodule ChessWeb.GameView do
|
||||
%{
|
||||
"checkmate" => gettext("Checkmate!"),
|
||||
"stalemate" => gettext("Stalemate"),
|
||||
"check" => gettext("Check"),
|
||||
"check" => gettext("Check")
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
118
lib/chess_web/views/live/board_live.ex
Normal file
118
lib/chess_web/views/live/board_live.ex
Normal file
@ -0,0 +1,118 @@
|
||||
defmodule ChessWeb.BoardLive do
|
||||
use Phoenix.LiveView, container: {:div, class: "board__container"}
|
||||
|
||||
alias Chess.Store.User
|
||||
alias Chess.Store.Game
|
||||
alias Chess.Repo
|
||||
alias Chess.Board
|
||||
alias Chess.Moves
|
||||
|
||||
import Chess.Auth, only: [get_user!: 1]
|
||||
|
||||
def render(assigns) do
|
||||
Phoenix.View.render(ChessWeb.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: Board.transform(game.board),
|
||||
game: game,
|
||||
user: user,
|
||||
selected: nil,
|
||||
available: []
|
||||
}
|
||||
end
|
||||
|
||||
def handle_info(%{event: "move", payload: state}, socket) do
|
||||
{:noreply, assign(socket, state)}
|
||||
end
|
||||
|
||||
defp handle_click(socket, file, rank) do
|
||||
game = socket.assigns[:game]
|
||||
board = game.board
|
||||
user = socket.assigns[:user]
|
||||
|
||||
colour = ChessWeb.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 Board.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
|
||||
new_game =
|
||||
game
|
||||
|> Moves.make_move(%{from: selected, to: {file, rank}})
|
||||
|> case do
|
||||
{:ok, %{game: game}} ->
|
||||
board = Board.transform(game.board)
|
||||
|
||||
broadcast_move(game, board)
|
||||
|
||||
[
|
||||
{:selected, nil},
|
||||
{:available, []},
|
||||
{:board, 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
|
||||
21
lib/chess_web/views/live/game_info_live.ex
Normal file
21
lib/chess_web/views/live/game_info_live.ex
Normal file
@ -0,0 +1,21 @@
|
||||
defmodule ChessWeb.GameInfoLive do
|
||||
use Phoenix.LiveView
|
||||
|
||||
alias Chess.Store.User
|
||||
alias Chess.Store.Game
|
||||
alias Chess.Repo
|
||||
|
||||
def render(assigns) do
|
||||
Phoenix.View.render(ChessWeb.GameView, "game_info.html", assigns)
|
||||
end
|
||||
|
||||
def mount(_params, %{"game_id" => game_id, "user_id" => user_id}, socket) do
|
||||
user = Repo.get!(User, user_id)
|
||||
|
||||
game =
|
||||
Game.for_user(user)
|
||||
|> Repo.get!(game_id)
|
||||
|
||||
{:ok, assign(socket, game: game, user: user)}
|
||||
end
|
||||
end
|
||||
39
lib/chess_web/views/square_view.ex
Normal file
39
lib/chess_web/views/square_view.ex
Normal file
@ -0,0 +1,39 @@
|
||||
defmodule ChessWeb.SquareView do
|
||||
use ChessWeb, :view
|
||||
|
||||
def classes(_file, _rank, piece, selected, available) do
|
||||
square_class()
|
||||
|> add_piece_classes(piece)
|
||||
|> add_selected_class(selected)
|
||||
|> add_available_class(available)
|
||||
|> Enum.join(" ")
|
||||
end
|
||||
|
||||
defp square_class do
|
||||
["square"]
|
||||
end
|
||||
|
||||
defp add_piece_classes(classes, piece) do
|
||||
if piece != nil do
|
||||
classes ++ ["square--#{piece["type"]}", "square--#{piece["colour"]}"]
|
||||
else
|
||||
classes
|
||||
end
|
||||
end
|
||||
|
||||
defp add_selected_class(classes, selected) do
|
||||
if selected do
|
||||
classes ++ ["square--selected"]
|
||||
else
|
||||
classes
|
||||
end
|
||||
end
|
||||
|
||||
defp add_available_class(classes, available) do
|
||||
if available do
|
||||
classes ++ ["square--available"]
|
||||
else
|
||||
classes
|
||||
end
|
||||
end
|
||||
end
|
||||
2
mix.exs
2
mix.exs
@ -41,6 +41,7 @@ defmodule Chess.Mixfile do
|
||||
{:plug_cowboy, "~> 2.1"},
|
||||
{:credo, "~> 1.0", only: [:dev, :test]},
|
||||
{:ecto_sql, "~> 3.0"},
|
||||
{:floki, ">= 0.27.0", only: :test},
|
||||
{:formulator, "~> 0.1.6"},
|
||||
{:gettext, "~> 0.16.0"},
|
||||
{:guardian, "~> 1.0"},
|
||||
@ -49,6 +50,7 @@ defmodule Chess.Mixfile do
|
||||
{:phoenix_ecto, "~> 4.0"},
|
||||
{:phoenix_html, "~> 2.0"},
|
||||
{:phoenix_live_reload, "~> 1.0", only: :dev},
|
||||
{:phoenix_live_view, "~> 0.15.3"},
|
||||
{:phoenix_pubsub, "~> 2.0"},
|
||||
{:postgrex, ">= 0.15.0"},
|
||||
{:secure_random, "~> 0.5"},
|
||||
|
||||
373
mix.lock
373
mix.lock
@ -1,53 +1,324 @@
|
||||
%{
|
||||
"argon2_elixir": {:hex, :argon2_elixir, "1.3.3", "487ffa071ef78c51d9b16e50ff3cf30cf8204e0aa4bdc8afd3765fdd8195e213", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "0ca19822ba4b85fe6dab75d1ed36bd9257a88cc4385bc32be177d861a1f3ec31"},
|
||||
"bamboo": {:hex, :bamboo, "1.6.0", "adfb583bef028923aae6f22deaea6667290561da1246058556ecaeb0fec5a175", [:mix], [{:hackney, ">= 1.13.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "454e67feacbc9b6e00553ce1d2fba003c861e0035600d59b09d6159985b17f9b"},
|
||||
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"},
|
||||
"certifi": {:hex, :certifi, "2.6.1", "dbab8e5e155a0763eea978c913ca280a6b544bfa115633fa20249c3d396d9493", [:rebar3], [], "hexpm", "524c97b4991b3849dd5c17a631223896272c6b0af446778ba4675a1dff53bb7e"},
|
||||
"combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"},
|
||||
"comeonin": {:hex, :comeonin, "4.1.2", "3eb5620fd8e35508991664b4c2b04dd41e52f1620b36957be837c1d7784b7592", [:mix], [{:argon2_elixir, "~> 1.2", [hex: :argon2_elixir, repo: "hexpm", optional: true]}, {:bcrypt_elixir, "~> 0.12.1 or ~> 1.0", [hex: :bcrypt_elixir, repo: "hexpm", optional: true]}, {:pbkdf2_elixir, "~> 0.12", [hex: :pbkdf2_elixir, repo: "hexpm", optional: true]}], "hexpm", "d8700a0ca4dbb616c22c9b3f6dd539d88deaafec3efe66869d6370c9a559b3e9"},
|
||||
"connection": {:hex, :connection, "1.1.0", "ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm", "722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"},
|
||||
"cowboy": {:hex, :cowboy, "2.8.0", "f3dc62e35797ecd9ac1b50db74611193c29815401e53bac9a5c0577bd7bc667d", [:rebar3], [{:cowlib, "~> 2.9.1", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "4643e4fba74ac96d4d152c75803de6fad0b3fa5df354c71afdd6cbeeb15fac8a"},
|
||||
"cowboy_telemetry": {:hex, :cowboy_telemetry, "0.3.1", "ebd1a1d7aff97f27c66654e78ece187abdc646992714164380d8a041eda16754", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3a6efd3366130eab84ca372cbd4a7d3c3a97bdfcfb4911233b035d117063f0af"},
|
||||
"cowlib": {:hex, :cowlib, "2.9.1", "61a6c7c50cf07fdd24b2f45b89500bb93b6686579b069a89f88cb211e1125c78", [:rebar3], [], "hexpm", "e4175dc240a70d996156160891e1c62238ede1729e45740bdd38064dad476170"},
|
||||
"credo": {:hex, :credo, "1.5.4", "9914180105b438e378e94a844ec3a5088ae5875626fc945b7c1462b41afc3198", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "cf51af45eadc0a3f39ba13b56fdac415c91b34f7b7533a13dc13550277141bc4"},
|
||||
"db_connection": {:hex, :db_connection, "2.3.1", "4c9f3ed1ef37471cbdd2762d6655be11e38193904d9c5c1c9389f1b891a3088e", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm", "abaab61780dde30301d840417890bd9f74131041afd02174cf4e10635b3a63f5"},
|
||||
"decimal": {:hex, :decimal, "2.0.0", "a78296e617b0f5dd4c6caf57c714431347912ffb1d0842e998e9792b5642d697", [:mix], [], "hexpm", "34666e9c55dea81013e77d9d87370fe6cb6291d1ef32f46a1600230b1d44f577"},
|
||||
"ecto": {:hex, :ecto, "3.5.5", "48219a991bb86daba6e38a1e64f8cea540cded58950ff38fbc8163e062281a07", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "98dd0e5e1de7f45beca6130d13116eae675db59adfa055fb79612406acf6f6f1"},
|
||||
"ecto_sql": {:hex, :ecto_sql, "3.5.3", "1964df0305538364b97cc4661a2bd2b6c89d803e66e5655e4e55ff1571943efd", [:mix], [{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.5.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.3.0 or ~> 0.4.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d2f53592432ce17d3978feb8f43e8dc0705e288b0890caf06d449785f018061c"},
|
||||
"elixir_make": {:hex, :elixir_make, "0.6.2", "7dffacd77dec4c37b39af867cedaabb0b59f6a871f89722c25b28fcd4bd70530", [:mix], [], "hexpm", "03e49eadda22526a7e5279d53321d1cced6552f344ba4e03e619063de75348d9"},
|
||||
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
|
||||
"formulator": {:hex, :formulator, "0.1.8", "eb43e1646828edb6614c2cf9c269d55b3d970414684f1e0290734d22c4936af4", [:mix], [{:gettext, ">= 0.11.0", [hex: :gettext, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.4", [hex: :phoenix_html, repo: "hexpm", optional: false]}], "hexpm", "dae3ff05743db0e31ef722e6e6ef7ed32836a65c422979e4c09b7c2f0494cf2c"},
|
||||
"gettext": {:hex, :gettext, "0.16.1", "e2130b25eebcbe02bb343b119a07ae2c7e28bd4b146c4a154da2ffb2b3507af2", [:mix], [], "hexpm", "dd3a7ea5e3e87ee9df29452dd9560709b4c7cc8141537d0b070155038d92bdf1"},
|
||||
"guardian": {:hex, :guardian, "1.2.1", "bdc8dd3dbf0fb7216cb6f91c11831faa1a64d39cdaed9a611e37f2413e584983", [:mix], [{:jose, "~> 1.8", [hex: :jose, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.3", [hex: :phoenix, repo: "hexpm", optional: true]}, {:plug, "~> 1.3.3 or ~> 1.4", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "723fc404edfb7bd5cba4cd83329b352037f102aa97468f44e58ac7f47c136a98"},
|
||||
"hackney": {:hex, :hackney, "1.17.4", "99da4674592504d3fb0cfef0db84c3ba02b4508bae2dff8c0108baa0d6e0977c", [:rebar3], [{:certifi, "~>2.6.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "de16ff4996556c8548d512f4dbe22dd58a587bf3332e7fd362430a7ef3986b16"},
|
||||
"httpoison": {:hex, :httpoison, "1.8.0", "6b85dea15820b7804ef607ff78406ab449dd78bed923a49c7160e1886e987a3d", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "28089eaa98cf90c66265b6b5ad87c59a3729bea2e74e9d08f9b51eb9729b3c3a"},
|
||||
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
|
||||
"jason": {:hex, :jason, "1.2.2", "ba43e3f2709fd1aa1dce90aaabfd039d000469c05c56f0b8e31978e03fa39052", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "18a228f5f0058ee183f29f9eae0805c6e59d61c3b006760668d8d18ff0d12179"},
|
||||
"jose": {:hex, :jose, "1.11.1", "59da64010c69aad6cde2f5b9248b896b84472e99bd18f246085b7b9fe435dcdb", [:mix, :rebar3], [], "hexpm", "078f6c9fb3cd2f4cfafc972c814261a7d1e8d2b3685c0a76eb87e158efff1ac5"},
|
||||
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
|
||||
"mime": {:hex, :mime, "1.5.0", "203ef35ef3389aae6d361918bf3f952fa17a09e8e43b5aa592b93eba05d0fb8d", [:mix], [], "hexpm", "55a94c0f552249fc1a3dd9cd2d3ab9de9d3c89b559c2bd01121f824834f24746"},
|
||||
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"},
|
||||
"parse_trans": {:hex, :parse_trans, "3.3.1", "16328ab840cc09919bd10dab29e431da3af9e9e7e7e6f0089dd5a2d2820011d8", [:rebar3], [], "hexpm", "07cd9577885f56362d414e8c4c4e6bdf10d43a8767abb92d24cbe8b24c54888b"},
|
||||
"phoenix": {:hex, :phoenix, "1.5.7", "2923bb3af924f184459fe4fa4b100bd25fa6468e69b2803dfae82698269aa5e0", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 2.13", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.1.2 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "774cd64417c5a3788414fdbb2be2eb9bcd0c048d9e6ad11a0c1fd67b7c0d0978"},
|
||||
"phoenix_ecto": {:hex, :phoenix_ecto, "4.2.1", "13f124cf0a3ce0f1948cf24654c7b9f2347169ff75c1123f44674afee6af3b03", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 2.15", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "478a1bae899cac0a6e02be1deec7e2944b7754c04e7d4107fc5a517f877743c0"},
|
||||
"phoenix_html": {:hex, :phoenix_html, "2.14.3", "51f720d0d543e4e157ff06b65de38e13303d5778a7919bcc696599e5934271b8", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "efd697a7fff35a13eeeb6b43db884705cba353a1a41d127d118fda5f90c8e80f"},
|
||||
"phoenix_live_reload": {:hex, :phoenix_live_reload, "1.3.0", "f35f61c3f959c9a01b36defaa1f0624edd55b87e236b606664a556d6f72fd2e7", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "02c1007ae393f2b76ec61c1a869b1e617179877984678babde131d716f95b582"},
|
||||
"phoenix_pubsub": {:hex, :phoenix_pubsub, "2.0.0", "a1ae76717bb168cdeb10ec9d92d1480fec99e3080f011402c0a2d68d47395ffb", [:mix], [], "hexpm", "c52d948c4f261577b9c6fa804be91884b381a7f8f18450c5045975435350f771"},
|
||||
"plug": {:hex, :plug, "1.11.0", "f17217525597628298998bc3baed9f8ea1fa3f1160aa9871aee6df47a6e4d38e", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2d9c633f0499f9dc5c2fd069161af4e2e7756890b81adcbb2ceaa074e8308876"},
|
||||
"plug_cowboy": {:hex, :plug_cowboy, "2.4.1", "779ba386c0915027f22e14a48919a9545714f849505fa15af2631a0d298abf0f", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d72113b6dff7b37a7d9b2a5b68892808e3a9a752f2bf7e503240945385b70507"},
|
||||
"plug_crypto": {:hex, :plug_crypto, "1.2.0", "1cb20793aa63a6c619dd18bb33d7a3aa94818e5fd39ad357051a67f26dfa2df6", [:mix], [], "hexpm", "a48b538ae8bf381ffac344520755f3007cc10bd8e90b240af98ea29b69683fc2"},
|
||||
"poison": {:hex, :poison, "4.0.1", "bcb755a16fac91cad79bfe9fc3585bb07b9331e50cfe3420a24bcc2d735709ae", [:mix], [], "hexpm", "ba8836feea4b394bb718a161fc59a288fe0109b5006d6bdf97b6badfcf6f0f25"},
|
||||
"poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm", "dad79704ce5440f3d5a3681c8590b9dc25d1a561e8f5a9c995281012860901e3"},
|
||||
"postgrex": {:hex, :postgrex, "0.15.7", "724410acd48abac529d0faa6c2a379fb8ae2088e31247687b16cacc0e0883372", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "88310c010ff047cecd73d5ceca1d99205e4b1ab1b9abfdab7e00f5c9d20ef8f9"},
|
||||
"ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm", "451d8527787df716d99dc36162fca05934915db0b6141bbdac2ea8d3c7afc7d7"},
|
||||
"secure_random": {:hex, :secure_random, "0.5.1", "c5532b37c89d175c328f5196a0c2a5680b15ebce3e654da37129a9fe40ebf51b", [:mix], [], "hexpm", "1b9754f15e3940a143baafd19da12293f100044df69ea12db5d72878312ae6ab"},
|
||||
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"},
|
||||
"telemetry": {:hex, :telemetry, "0.4.2", "2808c992455e08d6177322f14d3bdb6b625fbcfd233a73505870d8738a2f4599", [:rebar3], [], "hexpm", "2d1419bd9dda6a206d7b5852179511722e2b18812310d304620c7bd92a13fcef"},
|
||||
"tesla": {:hex, :tesla, "1.3.3", "26ae98627af5c406584aa6755ab5fc96315d70d69a24dd7f8369cfcb75094a45", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, "~> 1.3", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "~> 4.4.0", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "2648f1c276102f9250299e0b7b57f3071c67827349d9173f34c281756a1b124c"},
|
||||
"timex": {:hex, :timex, "3.6.3", "58ce6c9eda8ed47fc80c24dde09d481465838d3bcfc230949287fc1b0b0041c1", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 0.1.8 or ~> 0.5 or ~> 1.0.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "6d69f4f95fcf5684102a9cb3cf92c5ba6545bd60ed8d8a6a93cd2a4a4fb0d9ec"},
|
||||
"timex_ecto": {:hex, :timex_ecto, "3.4.0", "7871043345626a591bfa3e313aa271df4a4eda79f51eb69e83f326f0b8f3181c", [:mix], [{:ecto, "~> 2.2", [hex: :ecto, repo: "hexpm", optional: false]}, {:timex, "~> 3.6", [hex: :timex, repo: "hexpm", optional: false]}], "hexpm", "4237fa971c8fb9baeeb901b3ae4efee663e0da335e291228f215d99cf8a64799"},
|
||||
"tzdata": {:hex, :tzdata, "1.0.5", "69f1ee029a49afa04ad77801febaf69385f3d3e3d1e4b56b9469025677b89a28", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "55519aa2a99e5d2095c1e61cc74c9be69688f8ab75c27da724eb8279ff402a5a"},
|
||||
"unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"},
|
||||
"wallaby": {:hex, :wallaby, "0.28.0", "2ff217c0f245cadb3e5d91748ebcf0102873ceb9ef8a3507717c8bdd73915668", [:mix], [{:ecto_sql, ">= 3.0.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}, {:httpoison, "~> 0.12 or ~> 1.0", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:phoenix_ecto, ">= 3.0.0", [hex: :phoenix_ecto, repo: "hexpm", optional: true]}, {:web_driver_client, "~> 0.1.0", [hex: :web_driver_client, repo: "hexpm", optional: false]}], "hexpm", "e58112650d0b51e81714a626eab7d486d7a77342c9bbc2ba262b6653f9b22558"},
|
||||
"web_driver_client": {:hex, :web_driver_client, "0.1.0", "19466a989c76b7ec803c796cec0fec4611a64f445fd5120ce50c9e3817e09c2c", [:mix], [{:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:tesla, "~> 1.3.0", [hex: :tesla, repo: "hexpm", optional: false]}], "hexpm", "c9c031ca915e8fc75b5e24ac93503244f3cc406dd7f53047087a45aa62d60e9e"},
|
||||
argon2_elixir:
|
||||
{:hex, :argon2_elixir, "1.3.3",
|
||||
"487ffa071ef78c51d9b16e50ff3cf30cf8204e0aa4bdc8afd3765fdd8195e213", [:make, :mix],
|
||||
[{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm",
|
||||
"0ca19822ba4b85fe6dab75d1ed36bd9257a88cc4385bc32be177d861a1f3ec31"},
|
||||
bamboo:
|
||||
{:hex, :bamboo, "1.6.0", "adfb583bef028923aae6f22deaea6667290561da1246058556ecaeb0fec5a175",
|
||||
[:mix],
|
||||
[
|
||||
{:hackney, ">= 1.13.0", [hex: :hackney, repo: "hexpm", optional: false]},
|
||||
{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]},
|
||||
{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}
|
||||
], "hexpm", "454e67feacbc9b6e00553ce1d2fba003c861e0035600d59b09d6159985b17f9b"},
|
||||
bunt:
|
||||
{:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38",
|
||||
[:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"},
|
||||
certifi:
|
||||
{:hex, :certifi, "2.6.1", "dbab8e5e155a0763eea978c913ca280a6b544bfa115633fa20249c3d396d9493",
|
||||
[:rebar3], [], "hexpm", "524c97b4991b3849dd5c17a631223896272c6b0af446778ba4675a1dff53bb7e"},
|
||||
combine:
|
||||
{:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f",
|
||||
[:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"},
|
||||
comeonin:
|
||||
{:hex, :comeonin, "4.1.2", "3eb5620fd8e35508991664b4c2b04dd41e52f1620b36957be837c1d7784b7592",
|
||||
[:mix],
|
||||
[
|
||||
{:argon2_elixir, "~> 1.2", [hex: :argon2_elixir, repo: "hexpm", optional: true]},
|
||||
{:bcrypt_elixir, "~> 0.12.1 or ~> 1.0",
|
||||
[hex: :bcrypt_elixir, repo: "hexpm", optional: true]},
|
||||
{:pbkdf2_elixir, "~> 0.12", [hex: :pbkdf2_elixir, repo: "hexpm", optional: true]}
|
||||
], "hexpm", "d8700a0ca4dbb616c22c9b3f6dd539d88deaafec3efe66869d6370c9a559b3e9"},
|
||||
connection:
|
||||
{:hex, :connection, "1.1.0",
|
||||
"ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm",
|
||||
"722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"},
|
||||
cowboy:
|
||||
{:hex, :cowboy, "2.8.0", "f3dc62e35797ecd9ac1b50db74611193c29815401e53bac9a5c0577bd7bc667d",
|
||||
[:rebar3],
|
||||
[
|
||||
{:cowlib, "~> 2.9.1", [hex: :cowlib, repo: "hexpm", optional: false]},
|
||||
{:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}
|
||||
], "hexpm", "4643e4fba74ac96d4d152c75803de6fad0b3fa5df354c71afdd6cbeeb15fac8a"},
|
||||
cowboy_telemetry:
|
||||
{:hex, :cowboy_telemetry, "0.3.1",
|
||||
"ebd1a1d7aff97f27c66654e78ece187abdc646992714164380d8a041eda16754", [:rebar3],
|
||||
[
|
||||
{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]},
|
||||
{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}
|
||||
], "hexpm", "3a6efd3366130eab84ca372cbd4a7d3c3a97bdfcfb4911233b035d117063f0af"},
|
||||
cowlib:
|
||||
{:hex, :cowlib, "2.9.1", "61a6c7c50cf07fdd24b2f45b89500bb93b6686579b069a89f88cb211e1125c78",
|
||||
[:rebar3], [], "hexpm", "e4175dc240a70d996156160891e1c62238ede1729e45740bdd38064dad476170"},
|
||||
credo:
|
||||
{:hex, :credo, "1.5.4", "9914180105b438e378e94a844ec3a5088ae5875626fc945b7c1462b41afc3198",
|
||||
[:mix],
|
||||
[
|
||||
{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]},
|
||||
{:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]},
|
||||
{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}
|
||||
], "hexpm", "cf51af45eadc0a3f39ba13b56fdac415c91b34f7b7533a13dc13550277141bc4"},
|
||||
db_connection:
|
||||
{:hex, :db_connection, "2.3.1",
|
||||
"4c9f3ed1ef37471cbdd2762d6655be11e38193904d9c5c1c9389f1b891a3088e", [:mix],
|
||||
[{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm",
|
||||
"abaab61780dde30301d840417890bd9f74131041afd02174cf4e10635b3a63f5"},
|
||||
decimal:
|
||||
{:hex, :decimal, "2.0.0", "a78296e617b0f5dd4c6caf57c714431347912ffb1d0842e998e9792b5642d697",
|
||||
[:mix], [], "hexpm", "34666e9c55dea81013e77d9d87370fe6cb6291d1ef32f46a1600230b1d44f577"},
|
||||
ecto:
|
||||
{:hex, :ecto, "3.5.5", "48219a991bb86daba6e38a1e64f8cea540cded58950ff38fbc8163e062281a07",
|
||||
[:mix],
|
||||
[
|
||||
{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]},
|
||||
{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]},
|
||||
{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}
|
||||
], "hexpm", "98dd0e5e1de7f45beca6130d13116eae675db59adfa055fb79612406acf6f6f1"},
|
||||
ecto_sql:
|
||||
{:hex, :ecto_sql, "3.5.3", "1964df0305538364b97cc4661a2bd2b6c89d803e66e5655e4e55ff1571943efd",
|
||||
[:mix],
|
||||
[
|
||||
{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]},
|
||||
{:ecto, "~> 3.5.0", [hex: :ecto, repo: "hexpm", optional: false]},
|
||||
{:myxql, "~> 0.3.0 or ~> 0.4.0", [hex: :myxql, repo: "hexpm", optional: true]},
|
||||
{:postgrex, "~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]},
|
||||
{:tds, "~> 2.1.1", [hex: :tds, repo: "hexpm", optional: true]},
|
||||
{:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}
|
||||
], "hexpm", "d2f53592432ce17d3978feb8f43e8dc0705e288b0890caf06d449785f018061c"},
|
||||
elixir_make:
|
||||
{:hex, :elixir_make, "0.6.2",
|
||||
"7dffacd77dec4c37b39af867cedaabb0b59f6a871f89722c25b28fcd4bd70530", [:mix], [], "hexpm",
|
||||
"03e49eadda22526a7e5279d53321d1cced6552f344ba4e03e619063de75348d9"},
|
||||
file_system:
|
||||
{:hex, :file_system, "0.2.10",
|
||||
"fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm",
|
||||
"41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
|
||||
floki:
|
||||
{:hex, :floki, "0.29.0", "b1710d8c93a2f860dc2d7adc390dd808dc2fb8f78ee562304457b75f4c640881",
|
||||
[:mix],
|
||||
[{:html_entities, "~> 0.5.0", [hex: :html_entities, repo: "hexpm", optional: false]}],
|
||||
"hexpm", "008585ce64b9f74c07d32958ec9866f4b8a124bf4da1e2941b28e41384edaaad"},
|
||||
formulator:
|
||||
{:hex, :formulator, "0.1.8",
|
||||
"eb43e1646828edb6614c2cf9c269d55b3d970414684f1e0290734d22c4936af4", [:mix],
|
||||
[
|
||||
{:gettext, ">= 0.11.0", [hex: :gettext, repo: "hexpm", optional: false]},
|
||||
{:phoenix_html, "~> 2.4", [hex: :phoenix_html, repo: "hexpm", optional: false]}
|
||||
], "hexpm", "dae3ff05743db0e31ef722e6e6ef7ed32836a65c422979e4c09b7c2f0494cf2c"},
|
||||
gettext:
|
||||
{:hex, :gettext, "0.16.1", "e2130b25eebcbe02bb343b119a07ae2c7e28bd4b146c4a154da2ffb2b3507af2",
|
||||
[:mix], [], "hexpm", "dd3a7ea5e3e87ee9df29452dd9560709b4c7cc8141537d0b070155038d92bdf1"},
|
||||
guardian:
|
||||
{:hex, :guardian, "1.2.1", "bdc8dd3dbf0fb7216cb6f91c11831faa1a64d39cdaed9a611e37f2413e584983",
|
||||
[:mix],
|
||||
[
|
||||
{:jose, "~> 1.8", [hex: :jose, repo: "hexpm", optional: false]},
|
||||
{:phoenix, "~> 1.3", [hex: :phoenix, repo: "hexpm", optional: true]},
|
||||
{:plug, "~> 1.3.3 or ~> 1.4", [hex: :plug, repo: "hexpm", optional: true]}
|
||||
], "hexpm", "723fc404edfb7bd5cba4cd83329b352037f102aa97468f44e58ac7f47c136a98"},
|
||||
hackney:
|
||||
{:hex, :hackney, "1.17.4", "99da4674592504d3fb0cfef0db84c3ba02b4508bae2dff8c0108baa0d6e0977c",
|
||||
[:rebar3],
|
||||
[
|
||||
{:certifi, "~>2.6.1", [hex: :certifi, repo: "hexpm", optional: false]},
|
||||
{:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]},
|
||||
{:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]},
|
||||
{:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]},
|
||||
{:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]},
|
||||
{:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]},
|
||||
{:unicode_util_compat, "~>0.7.0",
|
||||
[hex: :unicode_util_compat, repo: "hexpm", optional: false]}
|
||||
], "hexpm", "de16ff4996556c8548d512f4dbe22dd58a587bf3332e7fd362430a7ef3986b16"},
|
||||
html_entities:
|
||||
{:hex, :html_entities, "0.5.1",
|
||||
"1c9715058b42c35a2ab65edc5b36d0ea66dd083767bef6e3edb57870ef556549", [:mix], [], "hexpm",
|
||||
"30efab070904eb897ff05cd52fa61c1025d7f8ef3a9ca250bc4e6513d16c32de"},
|
||||
httpoison:
|
||||
{:hex, :httpoison, "1.8.0",
|
||||
"6b85dea15820b7804ef607ff78406ab449dd78bed923a49c7160e1886e987a3d", [:mix],
|
||||
[{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm",
|
||||
"28089eaa98cf90c66265b6b5ad87c59a3729bea2e74e9d08f9b51eb9729b3c3a"},
|
||||
idna:
|
||||
{:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d",
|
||||
[:rebar3],
|
||||
[
|
||||
{:unicode_util_compat, "~>0.7.0",
|
||||
[hex: :unicode_util_compat, repo: "hexpm", optional: false]}
|
||||
], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
|
||||
jason:
|
||||
{:hex, :jason, "1.2.2", "ba43e3f2709fd1aa1dce90aaabfd039d000469c05c56f0b8e31978e03fa39052",
|
||||
[:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}],
|
||||
"hexpm", "18a228f5f0058ee183f29f9eae0805c6e59d61c3b006760668d8d18ff0d12179"},
|
||||
jose:
|
||||
{:hex, :jose, "1.11.1", "59da64010c69aad6cde2f5b9248b896b84472e99bd18f246085b7b9fe435dcdb",
|
||||
[:mix, :rebar3], [], "hexpm",
|
||||
"078f6c9fb3cd2f4cfafc972c814261a7d1e8d2b3685c0a76eb87e158efff1ac5"},
|
||||
metrics:
|
||||
{:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486",
|
||||
[:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
|
||||
mime:
|
||||
{:hex, :mime, "1.5.0", "203ef35ef3389aae6d361918bf3f952fa17a09e8e43b5aa592b93eba05d0fb8d",
|
||||
[:mix], [], "hexpm", "55a94c0f552249fc1a3dd9cd2d3ab9de9d3c89b559c2bd01121f824834f24746"},
|
||||
mimerl:
|
||||
{:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3",
|
||||
[:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"},
|
||||
parse_trans:
|
||||
{:hex, :parse_trans, "3.3.1",
|
||||
"16328ab840cc09919bd10dab29e431da3af9e9e7e7e6f0089dd5a2d2820011d8", [:rebar3], [], "hexpm",
|
||||
"07cd9577885f56362d414e8c4c4e6bdf10d43a8767abb92d24cbe8b24c54888b"},
|
||||
phoenix:
|
||||
{:hex, :phoenix, "1.5.7", "2923bb3af924f184459fe4fa4b100bd25fa6468e69b2803dfae82698269aa5e0",
|
||||
[:mix],
|
||||
[
|
||||
{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]},
|
||||
{:phoenix_html, "~> 2.13", [hex: :phoenix_html, repo: "hexpm", optional: true]},
|
||||
{:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]},
|
||||
{:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]},
|
||||
{:plug_cowboy, "~> 1.0 or ~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]},
|
||||
{:plug_crypto, "~> 1.1.2 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]},
|
||||
{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}
|
||||
], "hexpm", "774cd64417c5a3788414fdbb2be2eb9bcd0c048d9e6ad11a0c1fd67b7c0d0978"},
|
||||
phoenix_ecto:
|
||||
{:hex, :phoenix_ecto, "4.2.1",
|
||||
"13f124cf0a3ce0f1948cf24654c7b9f2347169ff75c1123f44674afee6af3b03", [:mix],
|
||||
[
|
||||
{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]},
|
||||
{:phoenix_html, "~> 2.14.2 or ~> 2.15",
|
||||
[hex: :phoenix_html, repo: "hexpm", optional: true]},
|
||||
{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}
|
||||
], "hexpm", "478a1bae899cac0a6e02be1deec7e2944b7754c04e7d4107fc5a517f877743c0"},
|
||||
phoenix_html:
|
||||
{:hex, :phoenix_html, "2.14.3",
|
||||
"51f720d0d543e4e157ff06b65de38e13303d5778a7919bcc696599e5934271b8", [:mix],
|
||||
[{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm",
|
||||
"efd697a7fff35a13eeeb6b43db884705cba353a1a41d127d118fda5f90c8e80f"},
|
||||
phoenix_live_reload:
|
||||
{:hex, :phoenix_live_reload, "1.3.0",
|
||||
"f35f61c3f959c9a01b36defaa1f0624edd55b87e236b606664a556d6f72fd2e7", [:mix],
|
||||
[
|
||||
{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]},
|
||||
{:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}
|
||||
], "hexpm", "02c1007ae393f2b76ec61c1a869b1e617179877984678babde131d716f95b582"},
|
||||
phoenix_live_view:
|
||||
{:hex, :phoenix_live_view, "0.15.3",
|
||||
"70c7917e5c421e32d1a1c8ddf8123378bb741748cd8091eb9d557fb4be92a94f", [:mix],
|
||||
[
|
||||
{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]},
|
||||
{:phoenix, "~> 1.5.7", [hex: :phoenix, repo: "hexpm", optional: false]},
|
||||
{:phoenix_html, "~> 2.14", [hex: :phoenix_html, repo: "hexpm", optional: false]},
|
||||
{:telemetry, "~> 0.4.2 or ~> 0.5", [hex: :telemetry, repo: "hexpm", optional: false]}
|
||||
], "hexpm", "cabcfb6738419a08600009219a5f0d861de97507fc1232121e1d5221aba849bd"},
|
||||
phoenix_pubsub:
|
||||
{:hex, :phoenix_pubsub, "2.0.0",
|
||||
"a1ae76717bb168cdeb10ec9d92d1480fec99e3080f011402c0a2d68d47395ffb", [:mix], [], "hexpm",
|
||||
"c52d948c4f261577b9c6fa804be91884b381a7f8f18450c5045975435350f771"},
|
||||
plug:
|
||||
{:hex, :plug, "1.11.0", "f17217525597628298998bc3baed9f8ea1fa3f1160aa9871aee6df47a6e4d38e",
|
||||
[:mix],
|
||||
[
|
||||
{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]},
|
||||
{:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]},
|
||||
{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}
|
||||
], "hexpm", "2d9c633f0499f9dc5c2fd069161af4e2e7756890b81adcbb2ceaa074e8308876"},
|
||||
plug_cowboy:
|
||||
{:hex, :plug_cowboy, "2.4.1",
|
||||
"779ba386c0915027f22e14a48919a9545714f849505fa15af2631a0d298abf0f", [:mix],
|
||||
[
|
||||
{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]},
|
||||
{:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]},
|
||||
{:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]},
|
||||
{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}
|
||||
], "hexpm", "d72113b6dff7b37a7d9b2a5b68892808e3a9a752f2bf7e503240945385b70507"},
|
||||
plug_crypto:
|
||||
{:hex, :plug_crypto, "1.2.0",
|
||||
"1cb20793aa63a6c619dd18bb33d7a3aa94818e5fd39ad357051a67f26dfa2df6", [:mix], [], "hexpm",
|
||||
"a48b538ae8bf381ffac344520755f3007cc10bd8e90b240af98ea29b69683fc2"},
|
||||
poison:
|
||||
{:hex, :poison, "4.0.1", "bcb755a16fac91cad79bfe9fc3585bb07b9331e50cfe3420a24bcc2d735709ae",
|
||||
[:mix], [], "hexpm", "ba8836feea4b394bb718a161fc59a288fe0109b5006d6bdf97b6badfcf6f0f25"},
|
||||
poolboy:
|
||||
{:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b",
|
||||
[:rebar3], [], "hexpm", "dad79704ce5440f3d5a3681c8590b9dc25d1a561e8f5a9c995281012860901e3"},
|
||||
postgrex:
|
||||
{:hex, :postgrex, "0.15.7",
|
||||
"724410acd48abac529d0faa6c2a379fb8ae2088e31247687b16cacc0e0883372", [:mix],
|
||||
[
|
||||
{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]},
|
||||
{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]},
|
||||
{:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]},
|
||||
{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}
|
||||
], "hexpm", "88310c010ff047cecd73d5ceca1d99205e4b1ab1b9abfdab7e00f5c9d20ef8f9"},
|
||||
ranch:
|
||||
{:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881",
|
||||
[:rebar3], [], "hexpm", "451d8527787df716d99dc36162fca05934915db0b6141bbdac2ea8d3c7afc7d7"},
|
||||
secure_random:
|
||||
{:hex, :secure_random, "0.5.1",
|
||||
"c5532b37c89d175c328f5196a0c2a5680b15ebce3e654da37129a9fe40ebf51b", [:mix], [], "hexpm",
|
||||
"1b9754f15e3940a143baafd19da12293f100044df69ea12db5d72878312ae6ab"},
|
||||
ssl_verify_fun:
|
||||
{:hex, :ssl_verify_fun, "1.1.6",
|
||||
"cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3],
|
||||
[], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"},
|
||||
telemetry:
|
||||
{:hex, :telemetry, "0.4.2",
|
||||
"2808c992455e08d6177322f14d3bdb6b625fbcfd233a73505870d8738a2f4599", [:rebar3], [], "hexpm",
|
||||
"2d1419bd9dda6a206d7b5852179511722e2b18812310d304620c7bd92a13fcef"},
|
||||
tesla:
|
||||
{:hex, :tesla, "1.3.3", "26ae98627af5c406584aa6755ab5fc96315d70d69a24dd7f8369cfcb75094a45",
|
||||
[:mix],
|
||||
[
|
||||
{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: true]},
|
||||
{:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]},
|
||||
{:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]},
|
||||
{:gun, "~> 1.3", [hex: :gun, repo: "hexpm", optional: true]},
|
||||
{:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]},
|
||||
{:ibrowse, "~> 4.4.0", [hex: :ibrowse, repo: "hexpm", optional: true]},
|
||||
{:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]},
|
||||
{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]},
|
||||
{:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]},
|
||||
{:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]},
|
||||
{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: true]}
|
||||
], "hexpm", "2648f1c276102f9250299e0b7b57f3071c67827349d9173f34c281756a1b124c"},
|
||||
timex:
|
||||
{:hex, :timex, "3.6.3", "58ce6c9eda8ed47fc80c24dde09d481465838d3bcfc230949287fc1b0b0041c1",
|
||||
[:mix],
|
||||
[
|
||||
{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]},
|
||||
{:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]},
|
||||
{:tzdata, "~> 0.1.8 or ~> 0.5 or ~> 1.0.0", [hex: :tzdata, repo: "hexpm", optional: false]}
|
||||
], "hexpm", "6d69f4f95fcf5684102a9cb3cf92c5ba6545bd60ed8d8a6a93cd2a4a4fb0d9ec"},
|
||||
timex_ecto:
|
||||
{:hex, :timex_ecto, "3.4.0",
|
||||
"7871043345626a591bfa3e313aa271df4a4eda79f51eb69e83f326f0b8f3181c", [:mix],
|
||||
[
|
||||
{:ecto, "~> 2.2", [hex: :ecto, repo: "hexpm", optional: false]},
|
||||
{:timex, "~> 3.6", [hex: :timex, repo: "hexpm", optional: false]}
|
||||
], "hexpm", "4237fa971c8fb9baeeb901b3ae4efee663e0da335e291228f215d99cf8a64799"},
|
||||
tzdata:
|
||||
{:hex, :tzdata, "1.0.5", "69f1ee029a49afa04ad77801febaf69385f3d3e3d1e4b56b9469025677b89a28",
|
||||
[:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm",
|
||||
"55519aa2a99e5d2095c1e61cc74c9be69688f8ab75c27da724eb8279ff402a5a"},
|
||||
unicode_util_compat:
|
||||
{:hex, :unicode_util_compat, "0.7.0",
|
||||
"bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm",
|
||||
"25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"},
|
||||
wallaby:
|
||||
{:hex, :wallaby, "0.28.0", "2ff217c0f245cadb3e5d91748ebcf0102873ceb9ef8a3507717c8bdd73915668",
|
||||
[:mix],
|
||||
[
|
||||
{:ecto_sql, ">= 3.0.0", [hex: :ecto_sql, repo: "hexpm", optional: true]},
|
||||
{:httpoison, "~> 0.12 or ~> 1.0", [hex: :httpoison, repo: "hexpm", optional: false]},
|
||||
{:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]},
|
||||
{:phoenix_ecto, ">= 3.0.0", [hex: :phoenix_ecto, repo: "hexpm", optional: true]},
|
||||
{:web_driver_client, "~> 0.1.0", [hex: :web_driver_client, repo: "hexpm", optional: false]}
|
||||
], "hexpm", "e58112650d0b51e81714a626eab7d486d7a77342c9bbc2ba262b6653f9b22558"},
|
||||
web_driver_client:
|
||||
{:hex, :web_driver_client, "0.1.0",
|
||||
"19466a989c76b7ec803c796cec0fec4611a64f445fd5120ce50c9e3817e09c2c", [:mix],
|
||||
[
|
||||
{:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: false]},
|
||||
{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]},
|
||||
{:tesla, "~> 1.3.0", [hex: :tesla, repo: "hexpm", optional: false]}
|
||||
], "hexpm", "c9c031ca915e8fc75b5e24ac93503244f3cc406dd7f53047087a45aa62d60e9e"}
|
||||
}
|
||||
|
||||
@ -6,35 +6,62 @@ defmodule Chess.BoardTest do
|
||||
alias Chess.Board
|
||||
|
||||
test "returns a piece from the board" do
|
||||
board = Board.default
|
||||
board = Board.default()
|
||||
|
||||
expected_piece = %{"type" => "pawn", "colour" => "white"}
|
||||
assert Board.piece(board, {4, 1}) == expected_piece
|
||||
end
|
||||
|
||||
test "finds pieces on the board" do
|
||||
board = Board.default
|
||||
board = Board.default()
|
||||
|
||||
piece = %{"type" => "pawn", "colour" => "white"}
|
||||
|
||||
expected_result = [
|
||||
{0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}, {6, 1}, {7, 1},
|
||||
{0, 1},
|
||||
{1, 1},
|
||||
{2, 1},
|
||||
{3, 1},
|
||||
{4, 1},
|
||||
{5, 1},
|
||||
{6, 1},
|
||||
{7, 1}
|
||||
]
|
||||
|
||||
assert Board.search(board, piece) == expected_result
|
||||
end
|
||||
|
||||
test "finds pieces on the board with a partial search" do
|
||||
board = Board.default
|
||||
board = Board.default()
|
||||
|
||||
piece = %{"colour" => "white"}
|
||||
expected_result = [
|
||||
{0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}, {6, 1}, {7, 1},
|
||||
{0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0}, {6, 0}, {7, 0},
|
||||
] |> Enum.sort
|
||||
|
||||
expected_result =
|
||||
[
|
||||
{0, 1},
|
||||
{1, 1},
|
||||
{2, 1},
|
||||
{3, 1},
|
||||
{4, 1},
|
||||
{5, 1},
|
||||
{6, 1},
|
||||
{7, 1},
|
||||
{0, 0},
|
||||
{1, 0},
|
||||
{2, 0},
|
||||
{3, 0},
|
||||
{4, 0},
|
||||
{5, 0},
|
||||
{6, 0},
|
||||
{7, 0}
|
||||
]
|
||||
|> Enum.sort()
|
||||
|
||||
assert Board.search(board, piece) == expected_result
|
||||
end
|
||||
|
||||
test "finds a single piece on the board" do
|
||||
board = Board.default
|
||||
board = Board.default()
|
||||
|
||||
piece = %{"type" => "king", "colour" => "black"}
|
||||
assert Board.search(board, piece) == [{4, 7}]
|
||||
@ -42,44 +69,41 @@ defmodule Chess.BoardTest do
|
||||
|
||||
test "moves a piece" do
|
||||
board = %{
|
||||
"3,0" => %{"type" => "queen", "colour" => "white"},
|
||||
"3,0" => %{"type" => "queen", "colour" => "white"}
|
||||
}
|
||||
|
||||
%{board: new_board} =
|
||||
Board.move_piece(board, %{"from" => [3, 0], "to" => [5, 2]})
|
||||
%{board: new_board} = Board.move_piece(board, %{from: {3, 0}, to: {5, 2}})
|
||||
|
||||
assert new_board == %{
|
||||
"5,2" => %{"type" => "queen", "colour" => "white"},
|
||||
"5,2" => %{"type" => "queen", "colour" => "white"}
|
||||
}
|
||||
end
|
||||
|
||||
test "can perform a castling move on the kings side" do
|
||||
board = %{
|
||||
"4,0" => %{"type" => "king", "colour" => "white"},
|
||||
"7,0" => %{"type" => "rook", "colour" => "white"},
|
||||
"7,0" => %{"type" => "rook", "colour" => "white"}
|
||||
}
|
||||
|
||||
%{board: new_board} =
|
||||
Board.move_piece(board, %{"from" => [4, 0], "to" => [6, 0]})
|
||||
%{board: new_board} = Board.move_piece(board, %{from: {4, 0}, to: {6, 0}})
|
||||
|
||||
assert new_board == %{
|
||||
"6,0" => %{"type" => "king", "colour" => "white"},
|
||||
"5,0" => %{"type" => "rook", "colour" => "white"},
|
||||
"5,0" => %{"type" => "rook", "colour" => "white"}
|
||||
}
|
||||
end
|
||||
|
||||
test "can perform a castling move on the queens side" do
|
||||
board = %{
|
||||
"4,0" => %{"type" => "king", "colour" => "white"},
|
||||
"0,0" => %{"type" => "rook", "colour" => "white"},
|
||||
"0,0" => %{"type" => "rook", "colour" => "white"}
|
||||
}
|
||||
|
||||
%{board: new_board} =
|
||||
Board.move_piece(board, %{"from" => [4, 0], "to" => [2, 0]})
|
||||
%{board: new_board} = Board.move_piece(board, %{from: {4, 0}, to: {2, 0}})
|
||||
|
||||
assert new_board == %{
|
||||
"2,0" => %{"type" => "king", "colour" => "white"},
|
||||
"3,0" => %{"type" => "rook", "colour" => "white"},
|
||||
"3,0" => %{"type" => "rook", "colour" => "white"}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
@ -20,6 +20,7 @@ defmodule Chess.Store.GameTest do
|
||||
opponent_id: opponent.id,
|
||||
turn: "white"
|
||||
}
|
||||
|
||||
changeset = Game.changeset(%Game{}, attrs)
|
||||
|
||||
assert changeset.valid?
|
||||
@ -33,6 +34,7 @@ defmodule Chess.Store.GameTest do
|
||||
opponent_id: 2,
|
||||
turn: "white"
|
||||
}
|
||||
|
||||
changeset = Game.changeset(%Game{}, attrs)
|
||||
|
||||
assert changeset.valid?
|
||||
@ -81,15 +83,17 @@ defmodule Chess.Store.GameTest do
|
||||
user = insert(:user)
|
||||
opponent = insert(:opponent)
|
||||
|
||||
game = insert(:game, %{
|
||||
board: Board.default,
|
||||
game =
|
||||
insert(:game, %{
|
||||
board: Board.default(),
|
||||
user_id: user.id,
|
||||
opponent_id: opponent.id,
|
||||
opponent_id: opponent.id
|
||||
})
|
||||
|
||||
move_params = %{"from" => [4, 1], "to" => [4, 3]}
|
||||
move_params = %{from: {4, 1}, to: {4, 3}}
|
||||
|
||||
changeset = Game.move_changeset(
|
||||
changeset =
|
||||
Game.move_changeset(
|
||||
game,
|
||||
Board.move_piece(game.board, move_params)
|
||||
)
|
||||
|
||||
@ -60,7 +60,7 @@ defmodule ChessWeb.GameControllerTest do
|
||||
|> login(user)
|
||||
|> get(game_path(conn, :show, game))
|
||||
|
||||
assert html_response(conn, 200) =~ "<div id=\"game\" data-game-id=\"#{game.id}\">"
|
||||
assert html_response(conn, 200) =~ "<div data-game-id=\"#{game.id}\">"
|
||||
end
|
||||
|
||||
test "does not show a game if the user is not a player", %{conn: conn} do
|
||||
@ -74,25 +74,25 @@ defmodule ChessWeb.GameControllerTest do
|
||||
conn
|
||||
|> login(other_user)
|
||||
|
||||
assert_error_sent 404, fn ->
|
||||
get conn, game_path(conn, :show, game.id)
|
||||
end
|
||||
assert_error_sent(404, fn ->
|
||||
get(conn, game_path(conn, :show, game.id))
|
||||
end)
|
||||
end
|
||||
|
||||
test "renders page not found when id is nonexistent", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
conn = login(conn, user)
|
||||
|
||||
assert_error_sent 404, fn ->
|
||||
get conn, game_path(conn, :show, -1)
|
||||
end
|
||||
assert_error_sent(404, fn ->
|
||||
get(conn, game_path(conn, :show, -1))
|
||||
end)
|
||||
end
|
||||
|
||||
test "deletes game", %{conn: conn} do
|
||||
game = Repo.insert! %Game{}
|
||||
game = Repo.insert!(%Game{})
|
||||
user = insert(:user)
|
||||
conn = login(conn, user)
|
||||
conn = delete conn, game_path(conn, :delete, game)
|
||||
conn = delete(conn, game_path(conn, :delete, game))
|
||||
assert redirected_to(conn) == game_path(conn, :index)
|
||||
refute Repo.get(Game, game.id)
|
||||
end
|
||||
|
||||
@ -7,7 +7,8 @@ defmodule Chess.Features.ProfileTest do
|
||||
import Chess.AuthenticationHelpers
|
||||
|
||||
test "user can update their details", %{session: session} do
|
||||
user = insert(:user, %{
|
||||
user =
|
||||
insert(:user, %{
|
||||
name: "Link",
|
||||
email: "link@hyrule.com",
|
||||
password: "ilovezelda"
|
||||
@ -25,7 +26,8 @@ defmodule Chess.Features.ProfileTest do
|
||||
end
|
||||
|
||||
test "name cannot be blank", %{session: session} do
|
||||
user = insert(:user, %{
|
||||
user =
|
||||
insert(:user, %{
|
||||
name: "Link",
|
||||
email: "link@hyrule.com",
|
||||
password: "ilovezelda"
|
||||
@ -40,13 +42,12 @@ defmodule Chess.Features.ProfileTest do
|
||||
|> click(button("Update Profile"))
|
||||
|
||||
session
|
||||
|> assert_has(
|
||||
css("[data-role='name-error']", text: "can't be blank")
|
||||
)
|
||||
|> assert_has(css("[data-role='name-error']", text: "can't be blank"))
|
||||
end
|
||||
|
||||
test "email cannot be blank", %{session: session} do
|
||||
user = insert(:user, %{
|
||||
user =
|
||||
insert(:user, %{
|
||||
name: "Link",
|
||||
email: "link@hyrule.com",
|
||||
password: "ilovezelda"
|
||||
@ -61,8 +62,6 @@ defmodule Chess.Features.ProfileTest do
|
||||
|> click(button("Update Profile"))
|
||||
|
||||
session
|
||||
|> assert_has(
|
||||
css("[data-role='email-error']", text: "can't be blank")
|
||||
)
|
||||
|> assert_has(css("[data-role='email-error']", text: "can't be blank"))
|
||||
end
|
||||
end
|
||||
|
||||
Loading…
Reference in New Issue
Block a user