checkpoint

This commit is contained in:
2024-11-16 12:37:56 -06:00
parent 13e79eb490
commit 460dfd608e
10 changed files with 139 additions and 49 deletions

View File

@@ -129,4 +129,38 @@ public class ShogiApplication(
return userManager.Users.FirstOrDefault(u => u.Id == userId)?.UserName!;
}
public async Task<IActionResult> ReadSessionSnapshots(string sessionId)
{
var session = this.ReadSession(sessionId);
if (session == null)
{
return new NotFoundResult();
}
var snapshots = await queryRepository.ReadSessionSnapshots(sessionId);
var boardStates = snapshots.Select(snap => new Contracts.Types.BoardState
{
Board = snap.Board.ToDictionary(
kvp => kvp.Key,
kvp => kvp.Value == null
? null
: new Contracts.Types.Piece
{
IsPromoted = kvp.Value.IsPromoted,
Owner = (Contracts.Types.WhichPlayer)kvp.Value.Owner,
WhichPiece = (Contracts.Types.WhichPiece)kvp.Value.WhichPiece,
}),
Player1Hand = snap.Player1Hand.Cast<Contracts.Types.WhichPiece>().ToArray(),
Player2Hand = snap.Player2Hand.Cast<Contracts.Types.WhichPiece>().ToArray(),
PlayerInCheck = snap.PlayerInCheck == null ? null : (Contracts.Types.WhichPlayer)snap.PlayerInCheck,
Victor = snap.IsGameOver
? snap.PlayerInCheck == Repositories.Dto.SessionState.WhichPlayer.Player1 ? Contracts.Types.WhichPlayer.Player2 : Contracts.Types.WhichPlayer.Player1
: null,
WhoseTurn = (Contracts.Types.WhichPlayer)snap.WhoseTurn,
});
return new OkObjectResult(boardStates.ToArray());
}
}

View File

@@ -65,8 +65,8 @@ public class SessionsController(
BoardState = new BoardState
{
Board = session.Board.BoardState.State.ToContract(),
Player1Hand = session.Board.BoardState.Player1Hand.ToContract(),
Player2Hand = session.Board.BoardState.Player2Hand.ToContract(),
Player1Hand = session.Board.BoardState.Player1Hand.Select(p => p.WhichPiece.ToContract()).ToArray(),
Player2Hand = session.Board.BoardState.Player2Hand.Select(p => p.WhichPiece.ToContract()).ToArray(),
PlayerInCheck = session.Board.BoardState.InCheck?.ToContract(),
WhoseTurn = session.Board.BoardState.WhoseTurn.ToContract(),
Victor = session.Board.BoardState.IsCheckmate
@@ -118,4 +118,14 @@ public class SessionsController(
return await application.MovePiece(id, sessionId, command);
}
/// <summary>
/// Returns an array of board states, one per player move of the given session, in the same order that player moves occurred.
/// </summary>
[HttpGet("{sessionId}/History")]
[AllowAnonymous]
public async Task<IActionResult> GetHistory([FromRoute] string sessionId)
{
return await application.ReadSessionSnapshots(sessionId);
}
}

View File

@@ -38,14 +38,6 @@ public static class ContractsExtensions
WhichPiece = piece.WhichPiece.ToContract()
};
public static IReadOnlyList<Piece> ToContract(this List<Domain.ValueObjects.Piece> pieces)
{
return pieces
.Select(ToContract)
.ToList()
.AsReadOnly();
}
public static Dictionary<string, Piece?> ToContract(this ReadOnlyDictionary<string, Domain.ValueObjects.Piece?> boardState) =>
boardState.ToDictionary(kvp => kvp.Key, kvp => kvp.Value?.ToContract());

View File

@@ -1,7 +1,9 @@
using Dapper;
using Shogi.Api.Repositories.Dto;
using Shogi.Api.Repositories.Dto.SessionState;
using System.Data;
using System.Data.SqlClient;
using System.Text.Json;
namespace Shogi.Api.Repositories;
@@ -21,4 +23,27 @@ public class QueryRepository(IConfiguration configuration)
return await results.ReadAsync<SessionDto>();
}
public async Task<List<SessionStateDocument>> ReadSessionSnapshots(string sessionId)
{
using var connection = new SqlConnection(this.connectionString);
var command = connection.CreateCommand();
command.CommandText = "session.ReadStatesBySession";
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue("SessionId", sessionId);
await using var reader = await command.ExecuteReaderAsync();
var documents = new List<SessionStateDocument>(20);
while (await reader.ReadAsync())
{
var json = reader.GetString("Document");
var document = JsonSerializer.Deserialize<SessionStateDocument>(json);
if (document != null)
{
documents.Add(document);
}
}
return documents;
}
}