Files
Shogi/Shogi.Api/Controllers/SessionsController.cs

218 lines
6.1 KiB
C#

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Shogi.Api.Extensions;
using Shogi.Api.Managers;
using Shogi.Api.Repositories;
using Shogi.Contracts.Api;
using Shogi.Contracts.Socket;
using Shogi.Contracts.Types;
using System.Data.SqlClient;
namespace Shogi.Api.Controllers;
[ApiController]
[Route("[controller]")]
[Authorize]
public class SessionsController : ControllerBase
{
private readonly ISocketConnectionManager communicationManager;
private readonly IModelMapper mapper;
private readonly ISessionRepository sessionRepository;
private readonly IQueryRespository queryRespository;
private readonly ILogger<SessionsController> logger;
public SessionsController(
ISocketConnectionManager communicationManager,
IModelMapper mapper,
ISessionRepository sessionRepository,
IQueryRespository queryRespository,
ILogger<SessionsController> logger)
{
this.communicationManager = communicationManager;
this.mapper = mapper;
this.sessionRepository = sessionRepository;
this.queryRespository = queryRespository;
this.logger = logger;
}
[HttpPost]
public async Task<IActionResult> CreateSession([FromBody] CreateSessionCommand request)
{
var userId = User.GetShogiUserId();
var session = new Domain.Aggregates.Session(request.Name, userId);
try
{
await sessionRepository.CreateSession(session);
}
catch (SqlException e)
{
logger.LogError(exception: e, message: "Uh oh");
return this.Conflict();
}
await communicationManager.BroadcastToAll(new SessionCreatedSocketMessage());
return CreatedAtAction(nameof(CreateSession), new { sessionName = request.Name }, null);
}
[HttpDelete("{name}")]
public async Task<IActionResult> DeleteSession(string name)
{
var userId = User.GetShogiUserId();
var session = await sessionRepository.ReadSession(name);
if (session == null) return this.NoContent();
if (session.Player1 == userId)
{
await sessionRepository.DeleteSession(name);
return this.NoContent();
}
return this.Forbid("Cannot delete sessions created by others.");
}
[HttpGet("PlayerCount")]
public async Task<ActionResult<ReadSessionsPlayerCountResponse>> GetSessionsPlayerCount()
{
var sessions = await this.queryRespository.ReadSessionPlayerCount();
return Ok(new ReadSessionsPlayerCountResponse
{
PlayerHasJoinedSessions = Array.Empty<SessionMetadata>(),
AllOtherSessions = sessions.ToList()
});
}
[HttpGet("{name}")]
public async Task<ActionResult<ReadSessionResponse>> GetSession(string name)
{
var session = await sessionRepository.ReadSession(name);
if (session == null) return this.NotFound();
return new ReadSessionResponse
{
Session = new Session
{
BoardState = new BoardState
{
Board = session.Board.BoardState.State.ToContract(),
Player1Hand = session.Board.BoardState.Player1Hand.ToContract(),
Player2Hand = session.Board.BoardState.Player2Hand.ToContract(),
PlayerInCheck = session.Board.BoardState.InCheck?.ToContract(),
WhoseTurn = session.Board.BoardState.WhoseTurn.ToContract()
},
Player1 = session.Player1,
Player2 = session.Player2,
SessionName = session.Name
}
};
}
[HttpPatch("{name}/Move")]
public async Task<IActionResult> Move([FromRoute] string name, [FromBody] MovePieceCommand command)
{
var userId = User.GetShogiUserId();
var session = await sessionRepository.ReadSession(name);
if (session == null) return this.NotFound("Shogi session does not exist.");
if (!session.IsSeated(userId)) return this.Forbid("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);
}
}
catch (InvalidOperationException)
{
return this.Conflict("Move is illegal.");
}
// TODO: sessionRespository.SaveMove();
await communicationManager.BroadcastToPlayers(
new PlayerHasMovedMessage
{
PlayerName = userId,
SessionName = session.Name,
},
session.Player1,
session.Player2);
return this.NoContent();
}
//[HttpPost("{sessionName}/Move")]
//public async Task<IActionResult> MovePiece([FromRoute] string sessionName, [FromBody] MovePieceCommand request)
//{
// var user = await gameboardManager.ReadUser(User);
// var session = await gameboardRepository.ReadSession(sessionName);
// if (session == null)
// {
// return NotFound();
// }
// if (user == null || (session.Player1 != user.Id && session.Player2 != user.Id))
// {
// return Forbid("User is not seated at this game.");
// }
// try
// {
// var move = request.Move;
// if (move.PieceFromCaptured.HasValue)
// session.Move(mapper.Map(move.PieceFromCaptured.Value), move.To);
// else if (!string.IsNullOrWhiteSpace(move.From))
// session.Move(move.From, move.To, move.IsPromotion);
// await gameboardRepository.CreateBoardState(session);
// await communicationManager.BroadcastToPlayers(
// new MoveResponse
// {
// SessionName = session.Name,
// PlayerName = user.Id
// },
// session.Player1,
// session.Player2);
// return Ok();
// }
// catch (InvalidOperationException ex)
// {
// return Conflict(ex.Message);
// }
//}
//[HttpPut("{sessionName}")]
//public async Task<IActionResult> PutJoinSession([FromRoute] string sessionName)
//{
// var user = await ReadUserOrThrow();
// var session = await gameboardRepository.ReadSessionMetaData(sessionName);
// if (session == null)
// {
// return NotFound();
// }
// if (session.Player2 != null)
// {
// return this.Conflict("This session already has two seated players and is full.");
// }
// session.SetPlayer2(user.Id);
// await gameboardRepository.UpdateSession(session);
// var opponentName = user.Id == session.Player1
// ? session.Player2!
// : session.Player1;
// await communicationManager.BroadcastToPlayers(new JoinSessionResponse
// {
// SessionName = session.Name,
// PlayerName = user.Id
// }, opponentName);
// return Ok();
//}
}