Files
ChessServer/src/Aiursoft.ChessServer/Controllers/GamesController.cs
T
2023-11-28 09:27:48 +00:00

136 lines
3.7 KiB
C#

using AiurObserver;
using Aiursoft.ChessServer.Data;
using Aiursoft.ChessServer.Models;
using Aiursoft.ChessServer.Services;
using Microsoft.AspNetCore.Mvc;
namespace Aiursoft.ChessServer.Controllers;
[Route("games")]
public class GamesController : Controller
{
private readonly WebSocketPusher _pusher;
private readonly InMemoryDatabase _database;
public GamesController(
WebSocketPusher pusher,
InMemoryDatabase database)
{
_pusher = pusher;
_database = database;
}
[Route("")]
public IActionResult GetAll()
{
var games = _database.GetActiveGames();
return Ok(games);
}
[Route("{id:int}")]
public IActionResult GetInfo([FromRoute] int id)
{
var game = _database.GetOrAddBoard(id);
return Ok(new
{
Turn = game.Turn.AsChar,
Ended = game.IsEndGame,
End = game.EndGame?.EndgameType,
Won = game.EndGame?.WonSide,
game.MoveIndex,
game.WhiteKingChecked,
game.BlackKingChecked,
links = new Dictionary<string, string>
{
{ "ascii", $"games/{id}/ascii" },
{ "fen", $"games/{id}/fen" },
{ "pgn", $"games/{id}/pgn" },
{ "html", $"games/{id}/html" },
{ "websocket", $"games/{id}/websocket" },
{ "move-post", $"games/{id}/move/{{player}}/{{move_algebraic_notation}}" }
},
Listeners = _database.GetOrAddChannel(id).GetListenerCount()
});
}
[Route("{id:int}/ws")]
public async Task GetWebSocket([FromRoute] int id)
{
var channel = _database.GetOrAddChannel(id);
IDisposable? subscription = null;
await _pusher.Accept(HttpContext);
try
{
await Task.Factory.StartNew(_pusher.PendingClose);
subscription = channel.Subscribe(async t => { await _pusher.SendMessage(t.Content); });
while (_pusher.Connected)
{
try
{
await Task.Delay(int.MaxValue, HttpContext.RequestAborted);
}
catch (TaskCanceledException)
{
break;
}
}
}
finally
{
await _pusher.Close();
subscription?.Dispose();
}
}
[Route("{id:int}/ascii")]
public IActionResult GetAscii([FromRoute] int id)
{
var game = _database.GetOrAddBoard(id);
return Ok(game.ToAscii());
}
[Route("{id:int}/html")]
public IActionResult GetHtml([FromRoute] int id)
{
return View(id);
}
[Route("{id:int}/fen")]
public IActionResult GetFen([FromRoute] int id)
{
var game = _database.GetOrAddBoard(id);
return Ok(game.ToFen());
}
[Route("{id:int}/pgn")]
public IActionResult GetPgn([FromRoute] int id)
{
var game = _database.GetOrAddBoard(id);
return Ok(game.ToPgn());
}
[HttpPost]
[Route("{id:int}/move/{player}/{move}")]
public async Task<IActionResult> Move([FromRoute] int id, [FromRoute] string player, [FromRoute] string move)
{
var game = _database.GetOrAddBoard(id);
try
{
if (!game.IsValidMove(move) || game.IsEndGame || game.Turn.AsChar.ToString() != player)
{
return BadRequest();
}
game.Move(move);
var fen = game.ToFen();
var channel = _database.GetOrAddChannel(id);
await channel.Push(new Message(fen));
return Ok(fen);
}
catch
{
return BadRequest();
}
}
}