add rudimentary web interface

This commit is contained in:
Stefan Steininger
2024-01-28 00:42:48 +01:00
parent 5527c4e4c3
commit a3fdb0c361
16 changed files with 125 additions and 1 deletions

View File

@@ -9,5 +9,6 @@ dependencies = [
"chess==1.10.0",
"numpy==1.26.3",
"stockfish==3.28.0",
"aiohttp==3.9.1",
]
requires-python = ">= 3.10"

View File

@@ -1,3 +1,4 @@
chess==1.10.0
numpy==1.26.3
stockfish==3.28.0
stockfish==3.28.0
aiohttp

BIN
src/chesspp/res/bB.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
src/chesspp/res/bK.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
src/chesspp/res/bN.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
src/chesspp/res/bP.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 777 B

BIN
src/chesspp/res/bQ.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
src/chesspp/res/bR.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 748 B

View File

@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>
<head>
<title>ChessPP</title>
<link rel="stylesheet"
href="https://unpkg.com/@chrisoakman/chessboardjs@1.0.0/dist/chessboard-1.0.0.min.css"
integrity="sha384-q94+BZtLrkL1/ohfjR8c6L+A6qzNH9R2hBLwyoAfu3i/WCvQjzL2RQJ3uNHDISdU"
crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://unpkg.com/@chrisoakman/chessboardjs@1.0.0/dist/chessboard-1.0.0.min.js"
integrity="sha384-8Vi8VHwn3vjQ9eUHUxex3JSN/NFqUg3QbPyX8kWyb93+8AC/pPWTzj+nHtbC5bxD"
crossorigin="anonymous"></script>
</head>
<body>
<div id="board1" style="width: 400px"></div>
<script>
var board1 = Chessboard('board1', 'start')
const socket = new WebSocket("ws://localhost:8080/ws");
socket.addEventListener("open", (event) => {
socket.send("Hello Server!");
});
socket.addEventListener("message", (event) => {
move = event.data;
from = move.substr(0, 2);
to = move.substr(2, 2);
board1.move(from + '-' + to);
console.log("Message from server ", event.data);
});
</script>
</body>
</html>

BIN
src/chesspp/res/wB.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
src/chesspp/res/wK.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
src/chesspp/res/wN.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
src/chesspp/res/wP.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
src/chesspp/res/wQ.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
src/chesspp/res/wR.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

79
src/chesspp/web.py Normal file
View File

@@ -0,0 +1,79 @@
import os
import asyncio
import aiohttp
from aiohttp import web
import chess
from chesspp import engine
_DIR = os.path.abspath(os.path.dirname(__file__))
_INDEX = os.path.join(_DIR, "res/index.html")
def load_index():
with open(_INDEX, 'r') as fp:
return fp.read()
index_data = load_index()
async def handle_index(request):
#raise web.HTTPFound('/index.html')
return web.Response(text=load_index(), content_type='text/html')
class Simulate:
def __init__(self):
self.white = engine.ClassicMctsEngine(chess.WHITE)
self.black = engine.ClassicMctsEngine(chess.BLACK)
def run(self):
board = chess.Board()
is_white_playing = True
while not board.is_game_over():
play_result = self.white.play(board) if is_white_playing else self.black.play(board)
yield play_result.move
board.push(play_result.move)
is_white_playing = not is_white_playing
async def websocket_handler(request):
ws = web.WebSocketResponse()
await ws.prepare(request)
async def wait_msg():
async for msg in ws:
if msg.type == aiohttp.WSMsgType.TEXT:
if msg.data == 'close':
await ws.close()
elif msg.type == aiohttp.WSMsgType.ERROR:
print(f'ws connection closed with exception {ws.exception()}')
async def turns():
runner = Simulate().run()
def sim():
return next(runner, None)
turn = await asyncio.to_thread(sim)
while turn is not None:
await ws.send_str(turn.uci())
turn = await asyncio.to_thread(sim)
async with asyncio.TaskGroup() as tg:
tg.create_task(wait_msg())
tg.create_task(turns())
print('websocket connection closed')
return ws
app = web.Application()
app.add_routes([
web.get('/', handle_index),
#web.static('/', os.path.join(_DIR, 'res')),
web.static('/img/chesspieces/wikipedia/', os.path.join(_DIR, 'res')),
web.get('/ws', websocket_handler),
])
if __name__ == '__main__':
web.run_app(app)