From cc3d13f15d8f1182f6ec730d3da308cebf13796d Mon Sep 17 00:00:00 2001 From: xuef Date: Sat, 25 Nov 2023 08:49:02 +0000 Subject: [PATCH] Allow viewing all games --- .../Aiursoft.ChessServer.csproj | 17 ++++ .../Aiursoft.ChessServer.sln | 25 ++++++ .../Controllers/GamesController.cs | 85 +++++++++++++++++++ .../Controllers/HomeController.cs | 11 +++ .../Data/InMemoryDatabase.cs | 34 ++++++++ src/Aiursoft.ChessServer/Program.cs | 32 +++++++ src/Aiursoft.ChessServer/appsettings.json | 9 ++ 7 files changed, 213 insertions(+) create mode 100644 src/Aiursoft.ChessServer/Aiursoft.ChessServer.csproj create mode 100644 src/Aiursoft.ChessServer/Aiursoft.ChessServer.sln create mode 100644 src/Aiursoft.ChessServer/Controllers/GamesController.cs create mode 100644 src/Aiursoft.ChessServer/Controllers/HomeController.cs create mode 100644 src/Aiursoft.ChessServer/Data/InMemoryDatabase.cs create mode 100644 src/Aiursoft.ChessServer/Program.cs create mode 100644 src/Aiursoft.ChessServer/appsettings.json diff --git a/src/Aiursoft.ChessServer/Aiursoft.ChessServer.csproj b/src/Aiursoft.ChessServer/Aiursoft.ChessServer.csproj new file mode 100644 index 0000000..9902a79 --- /dev/null +++ b/src/Aiursoft.ChessServer/Aiursoft.ChessServer.csproj @@ -0,0 +1,17 @@ + + + Exe + net8.0 + Aiursoft.ChessServer + Aiursoft.ChessServer + false + false + enable + enable + + + + + + + \ No newline at end of file diff --git a/src/Aiursoft.ChessServer/Aiursoft.ChessServer.sln b/src/Aiursoft.ChessServer/Aiursoft.ChessServer.sln new file mode 100644 index 0000000..ddd1537 --- /dev/null +++ b/src/Aiursoft.ChessServer/Aiursoft.ChessServer.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.002.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aiursoft.ChessServer", "Aiursoft.ChessServer.csproj", "{D98D0049-4854-441F-80EB-CE5CB6A6F82E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D98D0049-4854-441F-80EB-CE5CB6A6F82E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D98D0049-4854-441F-80EB-CE5CB6A6F82E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D98D0049-4854-441F-80EB-CE5CB6A6F82E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D98D0049-4854-441F-80EB-CE5CB6A6F82E}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {69CD7AC4-0BEF-4640-A27A-3F0B15E89D04} + EndGlobalSection +EndGlobal diff --git a/src/Aiursoft.ChessServer/Controllers/GamesController.cs b/src/Aiursoft.ChessServer/Controllers/GamesController.cs new file mode 100644 index 0000000..319acfe --- /dev/null +++ b/src/Aiursoft.ChessServer/Controllers/GamesController.cs @@ -0,0 +1,85 @@ +using Aiursoft.ChessServer.Data; +using Microsoft.AspNetCore.Mvc; + +namespace Aiursoft.ChessServer.Controllers; + +public class GamesController : ControllerBase +{ + private readonly InMemoryDatabase _database; + + public GamesController(InMemoryDatabase database) + { + _database = database; + } + + [Route("games")] + public IActionResult GetAll() + { + var games = _database.GetActiveGames(); + return Ok(games); + } + + [Route("games/{id}")] + public IActionResult GetInfo([FromRoute] int id) + { + var game = _database.GetOrAdd(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 + { + { "ascii", $"game/{id}/ascii"}, + { "fen", $"game/{id}/fen"}, + { "pgn", $"game/{id}/pgn"}, + { "move", $"game/{id}/move"} + } + }); + } + + [Route("games/{id}/ascii")] + public IActionResult GetAscii([FromRoute] int id) + { + var game = _database.GetOrAdd(id); + return Ok(game.ToAscii()); + } + + [Route("games/{id}/fen")] + public IActionResult GetFen([FromRoute] int id) + { + var game = _database.GetOrAdd(id); + return Ok(game.ToFen()); + } + + [Route("games/{id}/pgn")] + public IActionResult GetPgn([FromRoute]int id) + { + var game = _database.GetOrAdd(id); + return Ok(game.ToPgn()); + } + + [HttpPost] + [Route("games/{id}/move")] + public IActionResult Move([FromRoute]int id, [FromQuery]string move) + { + var game = _database.GetOrAdd(id); + try + { + if (game.IsValidMove(move) && !game.IsEndGame) + { + game.Move(move); + return Ok(); + } + return BadRequest(); + } + catch + { + return BadRequest(); + } + } +} diff --git a/src/Aiursoft.ChessServer/Controllers/HomeController.cs b/src/Aiursoft.ChessServer/Controllers/HomeController.cs new file mode 100644 index 0000000..3cfc726 --- /dev/null +++ b/src/Aiursoft.ChessServer/Controllers/HomeController.cs @@ -0,0 +1,11 @@ +using Microsoft.AspNetCore.Mvc; + +namespace Aiursoft.ChessServer.Controllers; + +public class HomeController : ControllerBase +{ + public IActionResult Index() + { + return this.Ok("Welcome to chess server! Please go to '/games/12345' to view more."); + } +} diff --git a/src/Aiursoft.ChessServer/Data/InMemoryDatabase.cs b/src/Aiursoft.ChessServer/Data/InMemoryDatabase.cs new file mode 100644 index 0000000..f127f22 --- /dev/null +++ b/src/Aiursoft.ChessServer/Data/InMemoryDatabase.cs @@ -0,0 +1,34 @@ +using Aiursoft.Scanner.Abstractions; +using Chess; +using System.Collections.Concurrent; + +namespace Aiursoft.ChessServer.Data; + +public class Game +{ + public bool Ended { get; set; } + public int Key { get; set; } +} + +public class InMemoryDatabase : ISingletonDependency +{ + public ConcurrentDictionary Boards { get; private set; } = new ConcurrentDictionary(); + + public Game[] GetActiveGames() + { + return Boards.Select(t => new Game + { + Ended = t.Value.IsEndGame, + Key = t.Key + }).ToArray(); + } + + public ChessBoard GetOrAdd(int id) + { + if (!Boards.ContainsKey(id)) + { + Boards.TryAdd(id, new ChessBoard()); + } + return Boards[id]; + } +} diff --git a/src/Aiursoft.ChessServer/Program.cs b/src/Aiursoft.ChessServer/Program.cs new file mode 100644 index 0000000..02477b4 --- /dev/null +++ b/src/Aiursoft.ChessServer/Program.cs @@ -0,0 +1,32 @@ +using System.Reflection; +using Aiursoft.Scanner; +using Aiursoft.WebTools; +using Aiursoft.WebTools.Models; + +namespace Aiursoft.ChessServer; + +public class Program +{ + public static async Task Main(string[] args) + { + var app = Aiursoft.WebTools.Extends.App(args); + await app.RunAsync(); + } +} + +public class Startup : IWebStartup +{ + public void ConfigureServices(IConfiguration configuration, IWebHostEnvironment environment, IServiceCollection services) + { + services.AddLibraryDependencies(); + services + .AddControllers() + .AddApplicationPart(Assembly.GetExecutingAssembly()); + } + + public void Configure(WebApplication app) + { + app.UseRouting(); + app.MapDefaultControllerRoute(); + } +} diff --git a/src/Aiursoft.ChessServer/appsettings.json b/src/Aiursoft.ChessServer/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/src/Aiursoft.ChessServer/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +}