This commit is contained in:
2022-11-14 20:01:06 -06:00
parent 716470f24d
commit 03c02cceae
2 changed files with 148 additions and 135 deletions

View File

@@ -15,134 +15,146 @@ namespace Shogi.Api.Controllers;
[Authorize] [Authorize]
public class SessionsController : ControllerBase public class SessionsController : ControllerBase
{ {
private readonly ISocketConnectionManager communicationManager; private readonly ISocketConnectionManager communicationManager;
private readonly IModelMapper mapper; private readonly IModelMapper mapper;
private readonly ISessionRepository sessionRepository; private readonly ISessionRepository sessionRepository;
private readonly IQueryRespository queryRespository; private readonly IQueryRespository queryRespository;
private readonly ILogger<SessionsController> logger; private readonly ILogger<SessionsController> logger;
public SessionsController( public SessionsController(
ISocketConnectionManager communicationManager, ISocketConnectionManager communicationManager,
IModelMapper mapper, IModelMapper mapper,
ISessionRepository sessionRepository, ISessionRepository sessionRepository,
IQueryRespository queryRespository, IQueryRespository queryRespository,
ILogger<SessionsController> logger) ILogger<SessionsController> logger)
{ {
this.communicationManager = communicationManager; this.communicationManager = communicationManager;
this.mapper = mapper; this.mapper = mapper;
this.sessionRepository = sessionRepository; this.sessionRepository = sessionRepository;
this.queryRespository = queryRespository; this.queryRespository = queryRespository;
this.logger = logger; this.logger = logger;
} }
[HttpPost] [HttpPost]
public async Task<IActionResult> CreateSession([FromBody] CreateSessionCommand request) public async Task<IActionResult> CreateSession([FromBody] CreateSessionCommand request)
{ {
var userId = User.GetShogiUserId(); var userId = User.GetShogiUserId();
var session = new Domain.Session(request.Name, userId); var session = new Domain.Session(request.Name, userId);
try try
{ {
await sessionRepository.CreateSession(session); await sessionRepository.CreateSession(session);
} }
catch (SqlException e) catch (SqlException e)
{ {
logger.LogError(exception: e, message: "Uh oh"); logger.LogError(exception: e, message: "Uh oh");
return this.Conflict(); return this.Conflict();
} }
await communicationManager.BroadcastToAll(new SessionCreatedSocketMessage()); await communicationManager.BroadcastToAll(new SessionCreatedSocketMessage());
return CreatedAtAction(nameof(CreateSession), new { sessionName = request.Name }, null); return CreatedAtAction(nameof(CreateSession), new { sessionName = request.Name }, null);
} }
[HttpDelete("{name}")] [HttpDelete("{name}")]
public async Task<IActionResult> DeleteSession(string name) public async Task<IActionResult> DeleteSession(string name)
{ {
var userId = User.GetShogiUserId(); var userId = User.GetShogiUserId();
var session = await sessionRepository.ReadSession(name); var session = await sessionRepository.ReadSession(name);
if (session == null) return this.NoContent(); if (session == null) return this.NoContent();
if (session.Player1 == userId) if (session.Player1 == userId)
{ {
await sessionRepository.DeleteSession(name); await sessionRepository.DeleteSession(name);
return this.NoContent(); return this.NoContent();
} }
return this.StatusCode(StatusCodes.Status403Forbidden, "Cannot delete sessions created by others."); return this.StatusCode(StatusCodes.Status403Forbidden, "Cannot delete sessions created by others.");
} }
[HttpGet("PlayerCount")] [HttpGet("PlayerCount")]
public async Task<ActionResult<ReadSessionsPlayerCountResponse>> GetSessionsPlayerCount() public async Task<ActionResult<ReadSessionsPlayerCountResponse>> GetSessionsPlayerCount()
{ {
var sessions = await this.queryRespository.ReadSessionPlayerCount(); var sessions = await this.queryRespository.ReadSessionPlayerCount();
return Ok(new ReadSessionsPlayerCountResponse return Ok(new ReadSessionsPlayerCountResponse
{ {
PlayerHasJoinedSessions = Array.Empty<SessionMetadata>(), PlayerHasJoinedSessions = Array.Empty<SessionMetadata>(),
AllOtherSessions = sessions.ToList() AllOtherSessions = sessions.ToList()
}); });
} }
[HttpGet("{name}")] [HttpGet("{name}")]
public async Task<ActionResult<ReadSessionResponse>> GetSession(string name) public async Task<ActionResult<ReadSessionResponse>> GetSession(string name)
{ {
var session = await sessionRepository.ReadSession(name); var session = await sessionRepository.ReadSession(name);
if (session == null) return this.NotFound(); if (session == null) return this.NotFound();
return new ReadSessionResponse return new ReadSessionResponse
{ {
Session = new Session Session = new Session
{ {
BoardState = new BoardState BoardState = new BoardState
{ {
Board = session.Board.BoardState.State.ToContract(), Board = session.Board.BoardState.State.ToContract(),
Player1Hand = session.Board.BoardState.Player1Hand.ToContract(), Player1Hand = session.Board.BoardState.Player1Hand.ToContract(),
Player2Hand = session.Board.BoardState.Player2Hand.ToContract(), Player2Hand = session.Board.BoardState.Player2Hand.ToContract(),
PlayerInCheck = session.Board.BoardState.InCheck?.ToContract(), PlayerInCheck = session.Board.BoardState.InCheck?.ToContract(),
WhoseTurn = session.Board.BoardState.WhoseTurn.ToContract() WhoseTurn = session.Board.BoardState.WhoseTurn.ToContract()
}, },
Player1 = session.Player1, Player1 = session.Player1,
Player2 = session.Player2, Player2 = session.Player2,
SessionName = session.Name SessionName = session.Name
} }
}; };
} }
[HttpPatch("{sessionName}/Move")] [HttpPut("{name}/Join")]
public async Task<IActionResult> Move([FromRoute] string sessionName, [FromBody] MovePieceCommand command) public async Task<IActionResult> JoinSession(string name)
{ {
var userId = User.GetShogiUserId(); var session = await sessionRepository.ReadSession(name);
var session = await sessionRepository.ReadSession(sessionName); if (session == null) return this.NotFound();
if (session == null) return this.NotFound("Shogi session does not exist."); if (string.IsNullOrEmpty(session.Player2))
{
session.AddPlayer2(User.GetShogiUserId());
}
}
if (!session.IsSeated(userId)) return this.StatusCode(StatusCodes.Status403Forbidden, "Player is not a member of the Shogi session."); [HttpPatch("{sessionName}/Move")]
public async Task<IActionResult> Move([FromRoute] string sessionName, [FromBody] MovePieceCommand command)
{
var userId = User.GetShogiUserId();
var session = await sessionRepository.ReadSession(sessionName);
try if (session == null) return this.NotFound("Shogi session does not exist.");
{
if (command.PieceFromHand.HasValue)
{
session.Board.Move(command.PieceFromHand.Value.ToDomain(), command.To);
}
else
{
session.Board.Move(command.From!, command.To, command.IsPromotion ?? false);
}
}
catch (InvalidOperationException e)
{
return this.Conflict(e.Message);
}
await sessionRepository.CreateMove(sessionName, command);
await communicationManager.BroadcastToPlayers(
new PlayerHasMovedMessage
{
PlayerName = userId,
SessionName = session.Name,
},
session.Player1,
session.Player2);
return this.NoContent(); if (!session.IsSeated(userId)) return this.StatusCode(StatusCodes.Status403Forbidden, "Player is not a member of the Shogi session.");
}
try
{
if (command.PieceFromHand.HasValue)
{
session.Board.Move(command.PieceFromHand.Value.ToDomain(), command.To);
}
else
{
session.Board.Move(command.From!, command.To, command.IsPromotion ?? false);
}
}
catch (InvalidOperationException e)
{
return this.Conflict(e.Message);
}
await sessionRepository.CreateMove(sessionName, command);
await communicationManager.BroadcastToPlayers(
new PlayerHasMovedMessage
{
PlayerName = userId,
SessionName = session.Name,
},
session.Player1,
session.Player2);
return this.NoContent();
}
} }

View File

@@ -4,28 +4,29 @@ namespace Shogi.Domain;
public class Session public class Session
{ {
public Session( public Session(
string name, string name,
string player1Name) string player1Name)
{ {
Name = name; Name = name;
Player1 = player1Name; Player1 = player1Name;
Board = new(BoardState.StandardStarting); Board = new(BoardState.StandardStarting);
} }
public string Name { get; } public string Name { get; }
public ShogiBoard Board { get; } public ShogiBoard Board { get; }
public string Player1 { get; } public string Player1 { get; }
public string? Player2 { get; private set; } public string? Player2 { get; private set; }
public void AddPlayer2(string player2Name) public void AddPlayer2(string player2Name)
{ {
if (Player2 != null) throw new InvalidOperationException("Player 2 already exists while trying to add a second player."); if (Player2 != null) throw new InvalidOperationException("Player 2 already exists while trying to add a second player.");
Player2 = player2Name; if (Player1.Equals(player2Name, StringComparison.OrdinalIgnoreCase)) throw new InvalidOperationException("Player 2 must be different from Player 1");
} Player2 = player2Name;
}
public bool IsSeated(string playerName) public bool IsSeated(string playerName)
{ {
return Player1 == playerName || Player2 == playerName; return Player1 == playerName || Player2 == playerName;
} }
} }