Files
territory-autobattler/microservices/LocationsApi/Controllers/LocationsController.cs
T
2026-05-19 04:42:57 -05:00

200 lines
6.5 KiB
C#

using LocationsApi.Models;
using LocationsApi.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
namespace LocationsApi.Controllers;
[ApiController]
[Route("api/[controller]")]
public class LocationsController : ControllerBase
{
private readonly LocationService _locations;
private readonly UnitTrainingService _units;
public LocationsController(LocationService locations, UnitTrainingService units)
{
_locations = locations;
_units = units;
}
[Authorize(Roles = "USER,SUPER")]
[HttpGet]
public async Task<ActionResult<List<LocationResponse>>> GetAll(
[FromQuery] int? minQ,
[FromQuery] int? maxQ,
[FromQuery] int? minR,
[FromQuery] int? maxR)
{
if (!User.IsInRole("SUPER"))
{
var username = User.FindFirstValue(ClaimTypes.Name);
if (string.IsNullOrWhiteSpace(username))
{
return Unauthorized();
}
var visible = await _locations.GetVisibleAsync(username);
if (minQ.HasValue && maxQ.HasValue && minR.HasValue && maxR.HasValue)
{
visible = visible
.Where(x => x.Q >= minQ.Value && x.Q <= maxQ.Value && x.R >= minR.Value && x.R <= maxR.Value)
.ToList();
}
return Ok(visible);
}
var locations = minQ.HasValue && maxQ.HasValue && minR.HasValue && maxR.HasValue
? await _locations.GetRangeAsync(minQ.Value, maxQ.Value, minR.Value, maxR.Value)
: await _locations.GetAllAsync();
return Ok(locations.Select(LocationResponse.FromLocation).ToList());
}
[Authorize(Roles = "USER,SUPER")]
[HttpGet("{q:int}/{r:int}")]
public async Task<ActionResult<LocationResponse>> Get(int q, int r)
{
if (!User.IsInRole("SUPER"))
{
var username = User.FindFirstValue(ClaimTypes.Name);
if (string.IsNullOrWhiteSpace(username))
{
return Unauthorized();
}
var visibleLocation = await _locations.GetVisibleLocationAsync(username, q, r);
return visibleLocation is null ? NotFound() : Ok(visibleLocation);
}
var location = await _locations.GetAsync(q, r);
return location is null ? NotFound() : Ok(LocationResponse.FromLocation(location));
}
[Authorize(Roles = "USER,SUPER")]
[HttpPost("claim")]
public async Task<ActionResult<LocationResponse>> Claim([FromBody] ClaimLocationRequest request)
{
var username = User.FindFirstValue(ClaimTypes.Name);
if (string.IsNullOrWhiteSpace(username))
{
return Unauthorized();
}
if (!User.IsInRole("SUPER") && !await _locations.CanSeeAsync(username, request.Q, request.R))
{
return NotFound();
}
if (!User.IsInRole("SUPER") && !await _locations.IsAdjacentToOwnedAsync(username, request.Q, request.R))
{
return BadRequest("Territory claims must be adjacent to controlled territory.");
}
var existingLocation = await _locations.GetAsync(request.Q, request.R);
if (existingLocation is not null && !string.IsNullOrWhiteSpace(existingLocation.OwnerUsername))
{
if (string.Equals(existingLocation.OwnerUsername, username, StringComparison.OrdinalIgnoreCase))
{
return Ok(LocationResponse.FromLocation(existingLocation));
}
return Conflict("Location is already controlled by another player.");
}
if (!User.IsInRole("SUPER") && !await _units.TryConsumeCompletedScoutAsync(username))
{
return BadRequest("A completed scout is required to claim unclaimed territory.");
}
var location = await _locations.ClaimAsync(request.Q, request.R, username);
if (location is null)
{
return Conflict("Location is already controlled by another player.");
}
return Ok(LocationResponse.FromLocation(location));
}
[Authorize(Roles = "USER,SUPER")]
[HttpPost("build")]
public async Task<ActionResult<LocationResponse>> Build([FromBody] BuildLocationRequest request)
{
var username = User.FindFirstValue(ClaimTypes.Name);
if (string.IsNullOrWhiteSpace(username))
{
return Unauthorized();
}
try
{
var location = await _locations.BuildAsync(request, username);
if (location is null)
{
return NotFound("Build target must be controlled by the player.");
}
return Ok(LocationResponse.FromLocation(location));
}
catch (InvalidOperationException ex)
{
return BadRequest(ex.Message);
}
catch (ArgumentException ex)
{
return BadRequest(ex.Message);
}
}
[Authorize(Roles = "USER,SUPER")]
[HttpGet("home")]
public async Task<ActionResult<LocationResponse>> GetHome()
{
var username = User.FindFirstValue(ClaimTypes.Name);
if (string.IsNullOrWhiteSpace(username))
{
return Unauthorized();
}
var home = await _locations.GetHomeAsync(username);
return home is null ? NotFound() : Ok(LocationResponse.FromLocation(home));
}
[Authorize(Roles = "USER,SUPER")]
[HttpPost("home")]
public async Task<ActionResult<LocationResponse>> AssignHome()
{
var username = User.FindFirstValue(ClaimTypes.Name);
if (string.IsNullOrWhiteSpace(username))
{
return Unauthorized();
}
var home = await _locations.AssignHomeAsync(username);
return Ok(LocationResponse.FromLocation(home));
}
[Authorize(Roles = "USER,SUPER")]
[HttpGet("visible")]
public async Task<ActionResult<List<LocationResponse>>> GetVisible([FromQuery] int? depth)
{
var username = User.FindFirstValue(ClaimTypes.Name);
if (string.IsNullOrWhiteSpace(username))
{
return Unauthorized();
}
return Ok(await _locations.GetVisibleAsync(username, depth));
}
[Authorize(Roles = "SUPER")]
[HttpPut]
public async Task<ActionResult<LocationResponse>> Upsert([FromBody] UpsertLocationRequest request)
{
var location = await _locations.UpsertAsync(request);
return Ok(LocationResponse.FromLocation(location));
}
}