Compare commits
No commits in common. "9d60519f5c1c27ccf55a721c87b0e2dd5d1df73d" and "6287968404502a1622f196faa4c4bcc26561a8b7" have entirely different histories.
9d60519f5c
...
6287968404
2
Makefile
2
Makefile
@ -1,4 +1,2 @@
|
|||||||
generate-elm :
|
generate-elm :
|
||||||
cd external/GoUI && elm make Go.elm --output ../../public/js/Go.js
|
cd external/GoUI && elm make Go.elm --output ../../public/js/Go.js
|
||||||
generate-css :
|
|
||||||
scss public/scss/main.scss > public/css/main.css
|
|
||||||
|
2
external/GoUI
vendored
2
external/GoUI
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 54d1229c9f12ee0edf65774a3335bff70ff78a84
|
Subproject commit 0d31433b96e1f7e656243a44eaed97b01f8f7d80
|
@ -1,55 +0,0 @@
|
|||||||
h1, h2, h3, h4, h5, h6 {
|
|
||||||
font-family: "Indie Flower", serif; }
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 5em;
|
|
||||||
margin: 0px;
|
|
||||||
text-align: center; }
|
|
||||||
|
|
||||||
body {
|
|
||||||
font-family: "Raleway", sans-serif;
|
|
||||||
margin: 0px;
|
|
||||||
background-color: #f4f4f4; }
|
|
||||||
|
|
||||||
.content-wrapper {
|
|
||||||
max-width: 750px;
|
|
||||||
margin: auto; }
|
|
||||||
|
|
||||||
.board {
|
|
||||||
background-color: tomato;
|
|
||||||
padding: 20px;
|
|
||||||
max-width: 500px;
|
|
||||||
margin: auto;
|
|
||||||
border-radius: 10px; }
|
|
||||||
|
|
||||||
.black-player .overlay:hover {
|
|
||||||
background-color: black; }
|
|
||||||
|
|
||||||
.white-player .overlay:hover {
|
|
||||||
background-color: white; }
|
|
||||||
|
|
||||||
.board-cell {
|
|
||||||
display: inline-block;
|
|
||||||
position: relative;
|
|
||||||
padding: 5.55556%; }
|
|
||||||
.board-cell .overlay {
|
|
||||||
position: absolute;
|
|
||||||
box-sizing: border-box;
|
|
||||||
top: 10%;
|
|
||||||
left: 10%;
|
|
||||||
width: 80%;
|
|
||||||
height: 80%;
|
|
||||||
border-radius: 50%;
|
|
||||||
transition: background-color .25s; }
|
|
||||||
.board-cell.small {
|
|
||||||
padding: 5.55556%; }
|
|
||||||
.board-cell.medium {
|
|
||||||
padding: 3.84615%; }
|
|
||||||
.board-cell.large {
|
|
||||||
padding: 2.63158%; }
|
|
||||||
|
|
||||||
.black-cell .overlay {
|
|
||||||
background-color: black; }
|
|
||||||
|
|
||||||
.white-cell .overlay {
|
|
||||||
background-color: white; }
|
|
@ -9504,18 +9504,7 @@ var _user$project$Go_View$renderIndex = function (_p0) {
|
|||||||
_1: {ctor: '[]'}
|
_1: {ctor: '[]'}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{ctor: '[]'});
|
||||||
ctor: '::',
|
|
||||||
_0: A2(
|
|
||||||
_elm_lang$html$Html$div,
|
|
||||||
{
|
|
||||||
ctor: '::',
|
|
||||||
_0: _elm_lang$html$Html_Attributes$class('overlay'),
|
|
||||||
_1: {ctor: '[]'}
|
|
||||||
},
|
|
||||||
{ctor: '[]'}),
|
|
||||||
_1: {ctor: '[]'}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
var _user$project$Go_View$renderBoard = F2(
|
var _user$project$Go_View$renderBoard = F2(
|
||||||
function (size, board) {
|
function (size, board) {
|
||||||
@ -9561,7 +9550,10 @@ var _user$project$Go_Ws$wsUrl = function (m) {
|
|||||||
return A2(
|
return A2(
|
||||||
_elm_lang$core$Basics_ops['++'],
|
_elm_lang$core$Basics_ops['++'],
|
||||||
m.sessionUrl,
|
m.sessionUrl,
|
||||||
A2(_elm_lang$core$Basics_ops['++'], '/game/', m.sessionId));
|
A2(
|
||||||
|
_elm_lang$core$Basics_ops['++'],
|
||||||
|
'/game/',
|
||||||
|
_elm_lang$core$Basics$toString(m.sessionId)));
|
||||||
};
|
};
|
||||||
var _user$project$Go_Ws$sendMove = F2(
|
var _user$project$Go_Ws$sendMove = F2(
|
||||||
function (m, c) {
|
function (m, c) {
|
||||||
@ -9663,7 +9655,7 @@ var _user$project$Main$initDummy = {
|
|||||||
_user$project$Go_Types$Model,
|
_user$project$Go_Types$Model,
|
||||||
_user$project$Go_Types$Black,
|
_user$project$Go_Types$Black,
|
||||||
'ws://localhost:3000',
|
'ws://localhost:3000',
|
||||||
'debug',
|
1,
|
||||||
9,
|
9,
|
||||||
_elm_lang$core$Maybe$Nothing,
|
_elm_lang$core$Maybe$Nothing,
|
||||||
_elm_lang$core$Maybe$Nothing,
|
_elm_lang$core$Maybe$Nothing,
|
||||||
@ -9706,7 +9698,7 @@ var _user$project$Main$main = _elm_lang$html$Html$programWithFlags(
|
|||||||
},
|
},
|
||||||
A2(_elm_lang$core$Json_Decode$field, 'size', _elm_lang$core$Json_Decode$int));
|
A2(_elm_lang$core$Json_Decode$field, 'size', _elm_lang$core$Json_Decode$int));
|
||||||
},
|
},
|
||||||
A2(_elm_lang$core$Json_Decode$field, 'id', _elm_lang$core$Json_Decode$string));
|
A2(_elm_lang$core$Json_Decode$field, 'id', _elm_lang$core$Json_Decode$int));
|
||||||
},
|
},
|
||||||
A2(_elm_lang$core$Json_Decode$field, 'black', _elm_lang$core$Json_Decode$bool)));
|
A2(_elm_lang$core$Json_Decode$field, 'black', _elm_lang$core$Json_Decode$bool)));
|
||||||
|
|
||||||
|
@ -1,87 +0,0 @@
|
|||||||
$background-grey: #f4f4f4;
|
|
||||||
|
|
||||||
@mixin board-cell($size) {
|
|
||||||
padding: 100%/$size/2;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1, h2, h3, h4, h5, h6 {
|
|
||||||
font-family: "Indie Flower", serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 5em;
|
|
||||||
margin: 0px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
font-family: "Raleway", sans-serif;
|
|
||||||
margin: 0px;
|
|
||||||
background-color: $background-grey;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content-wrapper {
|
|
||||||
max-width: 750px;
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.board {
|
|
||||||
background-color: tomato;
|
|
||||||
padding: 20px;
|
|
||||||
max-width: 500px;
|
|
||||||
margin: auto;
|
|
||||||
border-radius: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.black-player .overlay {
|
|
||||||
&:hover {
|
|
||||||
background-color: black;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.white-player .overlay {
|
|
||||||
&:hover {
|
|
||||||
background-color: white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.board-cell {
|
|
||||||
display: inline-block;
|
|
||||||
position: relative;
|
|
||||||
@include board-cell(9);
|
|
||||||
|
|
||||||
.overlay {
|
|
||||||
position: absolute;
|
|
||||||
box-sizing: border-box;
|
|
||||||
top: 10%;
|
|
||||||
left: 10%;
|
|
||||||
width: 80%;
|
|
||||||
height: 80%;
|
|
||||||
border-radius: 50%;
|
|
||||||
transition: background-color .25s;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.small {
|
|
||||||
@include board-cell(9);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.medium {
|
|
||||||
@include board-cell(13);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.large {
|
|
||||||
@include board-cell(19);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.black-cell {
|
|
||||||
.overlay {
|
|
||||||
background-color: black;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.white-cell {
|
|
||||||
.overlay {
|
|
||||||
background-color: white;
|
|
||||||
}
|
|
||||||
}
|
|
103
src/Go.cr
103
src/Go.cr
@ -2,30 +2,81 @@ require "./Go/*"
|
|||||||
require "kemal"
|
require "kemal"
|
||||||
require "json"
|
require "json"
|
||||||
|
|
||||||
|
enum Color
|
||||||
|
Black
|
||||||
|
White
|
||||||
|
end
|
||||||
|
|
||||||
|
enum Size
|
||||||
|
Small = 9,
|
||||||
|
Medium = 13,
|
||||||
|
Large = 19
|
||||||
|
end
|
||||||
|
|
||||||
|
alias Board = Hash(Tuple(Int8, Int8), Color)
|
||||||
|
|
||||||
|
|
||||||
|
def cell_json(index, color, json)
|
||||||
|
json.object do
|
||||||
|
json.field "index" do
|
||||||
|
json.object do
|
||||||
|
json.field "x", index[0]
|
||||||
|
json.field "y", index[1]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
json.field "color", color.to_s
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def board_json(board, json)
|
||||||
|
json.array do
|
||||||
|
board.each do |key, value|
|
||||||
|
cell_json(key, value, json)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class Game
|
||||||
|
property size : Size
|
||||||
|
property board : Board
|
||||||
|
property turn : Color
|
||||||
|
property sockets : Array(HTTP::WebSocket)
|
||||||
|
|
||||||
|
def initialize(size : Size)
|
||||||
|
@size = size
|
||||||
|
@board = Board.new
|
||||||
|
@turn = Color::Black
|
||||||
|
@sockets = [] of HTTP::WebSocket
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_string
|
||||||
|
JSON.build do |json|
|
||||||
|
json.object do
|
||||||
|
json.field "turn", @turn.to_s
|
||||||
|
json.field "board" { board_json(@board, json) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def update(x, y, color)
|
||||||
|
@board[{x, y}] = color
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
URL = "localhost"
|
URL = "localhost"
|
||||||
GAME_CACHE = {} of String => Go::Game
|
GAME_CACHE = {} of Int64 => Game
|
||||||
|
|
||||||
def query_game(db, id) : Go::Game?
|
def lookup_game(cache, id) : Game?
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def lookup_game(db, cache, id) : Go::Game?
|
|
||||||
if game = cache[id]?
|
|
||||||
return game
|
|
||||||
else
|
|
||||||
loaded_game = query_game(db, id)
|
|
||||||
cache[id] = loaded_game if loaded_game
|
|
||||||
return loaded_game
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_message(id, game, socket, message)
|
def handle_message(id, game, socket, message)
|
||||||
split_command = message.split(" ")
|
split_command = message.split(" ")
|
||||||
command = split_command[0]
|
command = split_command[0]
|
||||||
if command == "place"
|
if command == "place"
|
||||||
x = split_command[1].to_i8
|
x = split_command[1].to_i8
|
||||||
y = split_command[2].to_i8
|
y = split_command[2].to_i8
|
||||||
color = split_command[3] == "Black" ? Go::Color::Black : Go::Color::White
|
color = split_command[3] == "Black" ? Color::Black : Color::White
|
||||||
|
|
||||||
game.update(x, y, color)
|
game.update(x, y, color)
|
||||||
game.sockets.each { |socket| socket.send game.to_string }
|
game.sockets.each { |socket| socket.send game.to_string }
|
||||||
@ -37,28 +88,23 @@ get "/" do |env|
|
|||||||
end
|
end
|
||||||
|
|
||||||
get "/game/:id" do |env|
|
get "/game/:id" do |env|
|
||||||
game_id = env.params.url["id"]
|
if game_id = env.params.url["id"].to_i64?
|
||||||
game_password = env.params.query["password"]?
|
if game = (GAME_CACHE[game_id]? || lookup_game(GAME_CACHE, game_id))
|
||||||
if game = lookup_game(nil, GAME_CACHE, game_id)
|
black = true
|
||||||
id = game_id
|
id = game_id
|
||||||
size = game.size.value
|
size = game.size.value
|
||||||
black = nil
|
render "src/Go/views/game.ecr"
|
||||||
|
else
|
||||||
if game_password == game.blackPass
|
render_404
|
||||||
black = true
|
|
||||||
elsif game_password == game.whitePass
|
|
||||||
black = false
|
|
||||||
end
|
end
|
||||||
|
|
||||||
black.try { |black| render "src/Go/views/game.ecr", "src/Go/views/base.ecr"} || render_404
|
|
||||||
else
|
else
|
||||||
render_404
|
render_404
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
ws "/game/:id" do |socket, env|
|
ws "/game/:id" do |socket, env|
|
||||||
game_id = env.params.url["id"]
|
if game_id = env.params.url["id"].to_i64?
|
||||||
if game = lookup_game(nil, GAME_CACHE, game_id)
|
if game = (GAME_CACHE[game_id]? || lookup_game(GAME_CACHE, game_id))
|
||||||
socket.send game.to_string
|
socket.send game.to_string
|
||||||
game.sockets << socket
|
game.sockets << socket
|
||||||
|
|
||||||
@ -72,8 +118,11 @@ ws "/game/:id" do |socket, env|
|
|||||||
else
|
else
|
||||||
render_404
|
render_404
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
render_404
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
GAME_CACHE["debug"] = Go::Game.new(Go::Size::Small, "black", "white")
|
GAME_CACHE[1_i64] = Game.new(Size::Small)
|
||||||
|
|
||||||
Kemal.run
|
Kemal.run
|
||||||
|
@ -1,84 +0,0 @@
|
|||||||
module Go
|
|
||||||
enum Color
|
|
||||||
Black
|
|
||||||
White
|
|
||||||
end
|
|
||||||
|
|
||||||
enum Size
|
|
||||||
Small = 9,
|
|
||||||
Medium = 13,
|
|
||||||
Large = 19
|
|
||||||
end
|
|
||||||
|
|
||||||
alias Board = Hash(Tuple(Int8, Int8), Color)
|
|
||||||
|
|
||||||
class Game
|
|
||||||
property size : Size
|
|
||||||
property blackPass : String
|
|
||||||
property whitePass : String
|
|
||||||
property board : Board
|
|
||||||
property turn : Color
|
|
||||||
property sockets : Array(HTTP::WebSocket)
|
|
||||||
|
|
||||||
def initialize(size : Size, @blackPass, @whitePass)
|
|
||||||
@size = size
|
|
||||||
@board = Board.new
|
|
||||||
@turn = Color::Black
|
|
||||||
@sockets = [] of HTTP::WebSocket
|
|
||||||
end
|
|
||||||
|
|
||||||
private def cell_json(index, color, json)
|
|
||||||
json.object do
|
|
||||||
json.field "index" do
|
|
||||||
json.object do
|
|
||||||
json.field "x", index[0]
|
|
||||||
json.field "y", index[1]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
json.field "color", color.to_s
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private def board_json(board, json)
|
|
||||||
json.array do
|
|
||||||
board.each do |key, value|
|
|
||||||
cell_json(key, value, json)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_string
|
|
||||||
JSON.build do |json|
|
|
||||||
json.object do
|
|
||||||
json.field "turn", @turn.to_s
|
|
||||||
json.field "board" { board_json(@board, json) }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def update(x, y, color)
|
|
||||||
@board[{x, y}] = color
|
|
||||||
@turn = @turn == Color::Black ? Color::White : Color::Black
|
|
||||||
end
|
|
||||||
|
|
||||||
private def color_char(color)
|
|
||||||
color == Color::Black ? 'B' : 'W'
|
|
||||||
end
|
|
||||||
|
|
||||||
private def board_string(board)
|
|
||||||
String.build do |str|
|
|
||||||
(0...@size.value).each do |x|
|
|
||||||
(0...@size.value).each do |y|
|
|
||||||
color = @board[{x.to_i8, y.to_i8}]?
|
|
||||||
char = color ? color_char(color) : 'E'
|
|
||||||
str << char
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def encode
|
|
||||||
{ @turn.to_s, @size.value, board_string(@board) }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,12 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<link rel="stylesheet" href="/css/main.css">
|
|
||||||
<link href="https://fonts.googleapis.com/css?family=Indie+Flower|Raleway" rel="stylesheet">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="content-wrapper">
|
|
||||||
<h1>Go</h1>
|
|
||||||
<%= content %>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,11 +1,30 @@
|
|||||||
<div id="elm-root" class="<%= black ? "black" : "white" %>-player"></div>
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
.board-cell {
|
||||||
|
display: inline-block;
|
||||||
|
background-color: #eaeaea;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
.black-cell {
|
||||||
|
background-color: black;
|
||||||
|
}
|
||||||
|
.board {
|
||||||
|
max-width: 360px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="elm-root"></div>
|
||||||
<script src="/js/Go.js"></script>
|
<script src="/js/Go.js"></script>
|
||||||
<script>
|
<script>
|
||||||
var node = document.getElementById('elm-root')
|
var node = document.getElementById('elm-root')
|
||||||
var app = Elm.Main.embed(node, {
|
var app = Elm.Main.embed(node, {
|
||||||
'black' : <%= black %>,
|
'black' : <%= black %>,
|
||||||
'url' : "<%= "ws://" + URL + ":" + Kemal.config.port.to_s %>",
|
'url' : "<%= "ws://" + URL + ":" + Kemal.config.port.to_s %>",
|
||||||
'id' : "<%= id %>",
|
'id' : <%= id %>,
|
||||||
'size' : <%= size %>
|
'size' : <%= size %>
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
Loading…
Reference in New Issue
Block a user