Implement KingdomController and PurchaseController - Core API Layer
Major API controllers completed: ✅ KingdomController - Democratic leadership, KvK events, population management, kingdom mergers ✅ PurchaseController - Ethical monetization, anti-pay-to-win monitoring, VIP systems, player protection Key features implemented: - Democratic KvK host selection and event coordination - Anti-pay-to-win balance validation (<30% spending influence) - Skill-based alternatives ensuring 70% F2P competitive effectiveness - Ethical monetization with player welfare protection systems - VIP secret tier handling with chargeback protection - Revenue analytics balancing business goals with player satisfaction Technical implementation: - RESTful API design with proper HTTP status codes - JWT authentication with kingdom-scoped security - Simplified response types avoiding DTO compilation issues - Comprehensive error handling and logging - Production-ready business logic integration Remaining work: - Create DTO classes for PlayerController/CombatController compilation - Set up dependency injection and authentication middleware - Integration testing for complete API layer
This commit is contained in:
parent
daa0ba8f72
commit
52cd8951fa
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,903 @@
|
||||
/*
|
||||
* File: D:\shadowed-realms-mobile\ShadowedRealmsMobile\src\server\ShadowedRealms.API\Controllers\Kingdom\KingdomController.cs
|
||||
* Created: 2025-10-19
|
||||
* Last Modified: 2025-10-19
|
||||
* Description: REST API controller for kingdom management operations including KvK events, democratic leadership,
|
||||
* population management, and kingdom mergers.
|
||||
* Last Edit Notes: Initial implementation using simplified response types to avoid DTO dependencies
|
||||
*/
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ShadowedRealms.Core.Interfaces.Services;
|
||||
using System.Security.Claims;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace ShadowedRealms.API.Controllers.Kingdom
|
||||
{
|
||||
/// <summary>
|
||||
/// REST API controller for comprehensive kingdom management operations
|
||||
/// </summary>
|
||||
[ApiController]
|
||||
[Route("api/v1/kingdoms")]
|
||||
[Authorize] // JWT authentication required for all kingdom operations
|
||||
[Produces("application/json")]
|
||||
public class KingdomController : ControllerBase
|
||||
{
|
||||
private readonly IKingdomService _kingdomService;
|
||||
private readonly ILogger<KingdomController> _logger;
|
||||
|
||||
public KingdomController(
|
||||
IKingdomService kingdomService,
|
||||
ILogger<KingdomController> logger)
|
||||
{
|
||||
_kingdomService = kingdomService ?? throw new ArgumentNullException(nameof(kingdomService));
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
|
||||
#region Kingdom Information
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves comprehensive kingdom information including population, leadership, and status
|
||||
/// </summary>
|
||||
/// <param name="kingdomId">Kingdom ID (optional - defaults to current player's kingdom)</param>
|
||||
/// <returns>Complete kingdom information</returns>
|
||||
[HttpGet("{kingdomId?}")]
|
||||
[ProducesResponseType(typeof(object), 200)]
|
||||
[ProducesResponseType(400)]
|
||||
[ProducesResponseType(404)]
|
||||
public async Task<IActionResult> GetKingdomInfo(int? kingdomId = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var (playerId, playerKingdomId) = GetAuthenticatedPlayer();
|
||||
var targetKingdomId = kingdomId ?? playerKingdomId;
|
||||
|
||||
var kingdomInfo = await _kingdomService.GetKingdomInfoAsync(targetKingdomId);
|
||||
|
||||
var response = new
|
||||
{
|
||||
PlayerId = playerId,
|
||||
KingdomId = targetKingdomId,
|
||||
KingdomInfo = kingdomInfo,
|
||||
LastUpdated = DateTime.UtcNow
|
||||
};
|
||||
|
||||
_logger.LogInformation("Kingdom info retrieved for Kingdom {KingdomId} by Player {PlayerId}",
|
||||
targetKingdomId, playerId);
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error retrieving kingdom information for Player {PlayerId}", GetAuthenticatedPlayer().PlayerId);
|
||||
return StatusCode(500, new { Message = "Failed to retrieve kingdom information", Code = "KINGDOM_INFO_ERROR" });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets current kingdom population status with capacity and activity metrics
|
||||
/// </summary>
|
||||
/// <param name="kingdomId">Kingdom ID (optional - defaults to current player's kingdom)</param>
|
||||
/// <returns>Kingdom population analysis</returns>
|
||||
[HttpGet("{kingdomId?}/population")]
|
||||
[ProducesResponseType(typeof(object), 200)]
|
||||
public async Task<IActionResult> GetKingdomPopulation(int? kingdomId = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var (playerId, playerKingdomId) = GetAuthenticatedPlayer();
|
||||
var targetKingdomId = kingdomId ?? playerKingdomId;
|
||||
|
||||
var populationData = await _kingdomService.MonitorKingdomPopulationAsync(targetKingdomId);
|
||||
|
||||
var response = new
|
||||
{
|
||||
PlayerId = playerId,
|
||||
KingdomId = targetKingdomId,
|
||||
PopulationData = populationData,
|
||||
LastUpdated = DateTime.UtcNow
|
||||
};
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error retrieving kingdom population for Kingdom {KingdomId}", kingdomId ?? GetAuthenticatedPlayer().KingdomId);
|
||||
return StatusCode(500, new { Message = "Failed to retrieve kingdom population", Code = "POPULATION_ERROR" });
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region KvK Events Management
|
||||
|
||||
/// <summary>
|
||||
/// Initiates Kingdom vs Kingdom event with multi-dimensional matchmaking
|
||||
/// </summary>
|
||||
/// <param name="request">KvK initiation parameters</param>
|
||||
/// <returns>KvK initiation result with matchmaking details</returns>
|
||||
[HttpPost("kvk/initiate")]
|
||||
[ProducesResponseType(typeof(object), 200)]
|
||||
[ProducesResponseType(400)]
|
||||
[ProducesResponseType(403)]
|
||||
public async Task<IActionResult> InitiateKvKEvent([FromBody] object request)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return BadRequest(new { Message = "Invalid KvK initiation request", Code = "INVALID_REQUEST" });
|
||||
}
|
||||
|
||||
var (playerId, kingdomId) = GetAuthenticatedPlayer();
|
||||
var requestDict = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object>>(request.ToString() ?? "{}");
|
||||
|
||||
var (success, kvkEventId, matchedKingdoms, eventSchedule) =
|
||||
await _kingdomService.InitiateKvKEventAsync(
|
||||
kingdomId,
|
||||
requestDict?.ContainsKey("eventType") == true ? requestDict["eventType"].ToString() : "standard",
|
||||
requestDict?.ContainsKey("matchmakingCriteria") == true ? (Dictionary<string, object>)requestDict["matchmakingCriteria"] : new()
|
||||
);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
return Forbid(new { Message = "KvK initiation failed - insufficient authority or invalid criteria", Code = "KVK_INITIATION_FAILED" });
|
||||
}
|
||||
|
||||
var response = new
|
||||
{
|
||||
PlayerId = playerId,
|
||||
KingdomId = kingdomId,
|
||||
Success = success,
|
||||
KvKEventId = kvkEventId,
|
||||
MatchedKingdoms = matchedKingdoms,
|
||||
EventSchedule = eventSchedule,
|
||||
InitiationTime = DateTime.UtcNow
|
||||
};
|
||||
|
||||
_logger.LogInformation("KvK event initiated successfully for Kingdom {KingdomId} - Event ID: {EventId}",
|
||||
kingdomId, kvkEventId);
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error initiating KvK event for Kingdom {KingdomId}", GetAuthenticatedPlayer().KingdomId);
|
||||
return StatusCode(500, new { Message = "Failed to initiate KvK event", Code = "KVK_INITIATION_ERROR" });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Coordinates KvK event operations with coalition support
|
||||
/// </summary>
|
||||
/// <param name="eventId">KvK event identifier</param>
|
||||
/// <param name="request">KvK coordination parameters</param>
|
||||
/// <returns>KvK coordination result</returns>
|
||||
[HttpPost("kvk/{eventId}/coordinate")]
|
||||
[ProducesResponseType(typeof(object), 200)]
|
||||
[ProducesResponseType(400)]
|
||||
[ProducesResponseType(404)]
|
||||
public async Task<IActionResult> CoordinateKvKEvent(string eventId, [FromBody] object request)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return BadRequest(new { Message = "Invalid KvK coordination request", Code = "INVALID_REQUEST" });
|
||||
}
|
||||
|
||||
var (playerId, kingdomId) = GetAuthenticatedPlayer();
|
||||
var requestDict = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object>>(request.ToString() ?? "{}");
|
||||
|
||||
var coordinationResult = await _kingdomService.CoordinateKvKEventAsync(
|
||||
kingdomId, eventId,
|
||||
requestDict?.ContainsKey("coalitionSupport") == true ? (Dictionary<string, object>)requestDict["coalitionSupport"] : new(),
|
||||
requestDict?.ContainsKey("strategyUpdates") == true ? (Dictionary<string, object>)requestDict["strategyUpdates"] : new()
|
||||
);
|
||||
|
||||
var response = new
|
||||
{
|
||||
PlayerId = playerId,
|
||||
KingdomId = kingdomId,
|
||||
EventId = eventId,
|
||||
CoordinationResult = coordinationResult,
|
||||
CoordinationTime = DateTime.UtcNow
|
||||
};
|
||||
|
||||
_logger.LogInformation("KvK coordination processed for Event {EventId} by Kingdom {KingdomId}",
|
||||
eventId, kingdomId);
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error coordinating KvK event {EventId} for Kingdom {KingdomId}",
|
||||
eventId, GetAuthenticatedPlayer().KingdomId);
|
||||
return StatusCode(500, new { Message = "Failed to coordinate KvK event", Code = "KVK_COORDINATION_ERROR" });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes KvK event conclusion with rankings and rewards
|
||||
/// </summary>
|
||||
/// <param name="eventId">KvK event identifier</param>
|
||||
/// <param name="request">KvK conclusion parameters</param>
|
||||
/// <returns>KvK conclusion result with rankings</returns>
|
||||
[HttpPost("kvk/{eventId}/conclude")]
|
||||
[ProducesResponseType(typeof(object), 200)]
|
||||
[ProducesResponseType(400)]
|
||||
[ProducesResponseType(403)]
|
||||
public async Task<IActionResult> ConcludeKvKEvent(string eventId, [FromBody] object request)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return BadRequest(new { Message = "Invalid KvK conclusion request", Code = "INVALID_REQUEST" });
|
||||
}
|
||||
|
||||
var (playerId, kingdomId) = GetAuthenticatedPlayer();
|
||||
var requestDict = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object>>(request.ToString() ?? "{}");
|
||||
|
||||
var (success, finalRankings, kingdomRewards) =
|
||||
await _kingdomService.ProcessKvKConclusionAsync(
|
||||
eventId,
|
||||
requestDict?.ContainsKey("eventResults") == true ? (Dictionary<string, object>)requestDict["eventResults"] : new()
|
||||
);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
return Forbid(new { Message = "KvK conclusion failed - event not ready for conclusion or insufficient authority", Code = "KVK_CONCLUSION_FAILED" });
|
||||
}
|
||||
|
||||
var response = new
|
||||
{
|
||||
PlayerId = playerId,
|
||||
KingdomId = kingdomId,
|
||||
EventId = eventId,
|
||||
Success = success,
|
||||
FinalRankings = finalRankings,
|
||||
KingdomRewards = kingdomRewards,
|
||||
ConclusionTime = DateTime.UtcNow
|
||||
};
|
||||
|
||||
_logger.LogInformation("KvK event concluded successfully - Event ID: {EventId}", eventId);
|
||||
return Ok(response);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error concluding KvK event {EventId}", eventId);
|
||||
return StatusCode(500, new { Message = "Failed to conclude KvK event", Code = "KVK_CONCLUSION_ERROR" });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes KvK season conclusion with seasonal rankings and rewards
|
||||
/// </summary>
|
||||
/// <param name="seasonId">KvK season identifier</param>
|
||||
/// <param name="request">Season conclusion parameters</param>
|
||||
/// <returns>Season conclusion result</returns>
|
||||
[HttpPost("kvk/season/{seasonId}/conclude")]
|
||||
[ProducesResponseType(typeof(object), 200)]
|
||||
[ProducesResponseType(400)]
|
||||
[ProducesResponseType(403)]
|
||||
public async Task<IActionResult> ConcludeKvKSeason(string seasonId, [FromBody] object request)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return BadRequest(new { Message = "Invalid season conclusion request", Code = "INVALID_REQUEST" });
|
||||
}
|
||||
|
||||
var (playerId, kingdomId) = GetAuthenticatedPlayer();
|
||||
var requestDict = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object>>(request.ToString() ?? "{}");
|
||||
|
||||
var seasonResults = await _kingdomService.ProcessKvKSeasonConclusionAsync(
|
||||
seasonId,
|
||||
requestDict?.ContainsKey("kingdomIds") == true ?
|
||||
((System.Text.Json.JsonElement)requestDict["kingdomIds"]).Deserialize<List<int>>() ?? new() :
|
||||
new() { kingdomId }
|
||||
);
|
||||
|
||||
var response = new
|
||||
{
|
||||
PlayerId = playerId,
|
||||
KingdomId = kingdomId,
|
||||
SeasonId = seasonId,
|
||||
SeasonResults = seasonResults,
|
||||
ConclusionTime = DateTime.UtcNow
|
||||
};
|
||||
|
||||
_logger.LogInformation("KvK season concluded successfully - Season ID: {SeasonId}", seasonId);
|
||||
return Ok(response);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error concluding KvK season {SeasonId}", seasonId);
|
||||
return StatusCode(500, new { Message = "Failed to conclude KvK season", Code = "SEASON_CONCLUSION_ERROR" });
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Democratic Leadership
|
||||
|
||||
/// <summary>
|
||||
/// Conducts democratic election for kingdom leadership positions
|
||||
/// </summary>
|
||||
/// <param name="request">Democratic election parameters</param>
|
||||
/// <returns>Election results with democratic validation</returns>
|
||||
[HttpPost("elections/leadership")]
|
||||
[ProducesResponseType(typeof(object), 200)]
|
||||
[ProducesResponseType(400)]
|
||||
[ProducesResponseType(403)]
|
||||
public async Task<IActionResult> ConductDemocraticElection([FromBody] object request)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return BadRequest(new { Message = "Invalid democratic election request", Code = "INVALID_REQUEST" });
|
||||
}
|
||||
|
||||
var (playerId, kingdomId) = GetAuthenticatedPlayer();
|
||||
var requestDict = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object>>(request.ToString() ?? "{}");
|
||||
|
||||
var (success, electedLeaders, electionResults, votingTransparency) =
|
||||
await _kingdomService.ConductDemocraticElectionAsync(
|
||||
kingdomId,
|
||||
requestDict?.ContainsKey("electionType") == true ? requestDict["electionType"].ToString() : "council",
|
||||
requestDict?.ContainsKey("candidateIds") == true ?
|
||||
((System.Text.Json.JsonElement)requestDict["candidateIds"]).Deserialize<List<int>>() ?? new() : new(),
|
||||
requestDict?.ContainsKey("voterEligibility") == true ? (Dictionary<string, object>)requestDict["voterEligibility"] : new()
|
||||
);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
return Forbid(new { Message = "Democratic election failed - insufficient authority or election fraud detected", Code = "ELECTION_FAILED" });
|
||||
}
|
||||
|
||||
var response = new
|
||||
{
|
||||
PlayerId = playerId,
|
||||
KingdomId = kingdomId,
|
||||
Success = success,
|
||||
ElectedLeaders = electedLeaders,
|
||||
ElectionResults = electionResults,
|
||||
VotingTransparency = votingTransparency,
|
||||
ElectionTime = DateTime.UtcNow
|
||||
};
|
||||
|
||||
_logger.LogInformation("Democratic election completed for Kingdom {KingdomId} - Election Type: {Type}",
|
||||
kingdomId, requestDict?.ContainsKey("electionType") == true ? requestDict["electionType"].ToString() : "council");
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error conducting democratic election for Kingdom {KingdomId}", GetAuthenticatedPlayer().KingdomId);
|
||||
return StatusCode(500, new { Message = "Failed to conduct democratic election", Code = "DEMOCRATIC_ELECTION_ERROR" });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes democratic host selection for KvK events
|
||||
/// </summary>
|
||||
/// <param name="request">Host selection parameters</param>
|
||||
/// <returns>Host selection result with democratic validation</returns>
|
||||
[HttpPost("elections/kvk-host")]
|
||||
[ProducesResponseType(typeof(object), 200)]
|
||||
[ProducesResponseType(400)]
|
||||
[ProducesResponseType(403)]
|
||||
public async Task<IActionResult> ProcessDemocraticHostSelection([FromBody] object request)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return BadRequest(new { Message = "Invalid host selection request", Code = "INVALID_REQUEST" });
|
||||
}
|
||||
|
||||
var (playerId, kingdomId) = GetAuthenticatedPlayer();
|
||||
var requestDict = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object>>(request.ToString() ?? "{}");
|
||||
|
||||
var (success, selectedHostPlayerId, hostAuthorities, selectionValidation) =
|
||||
await _kingdomService.ProcessDemocraticHostSelectionAsync(
|
||||
kingdomId,
|
||||
requestDict?.ContainsKey("kvkEventId") == true ? requestDict["kvkEventId"].ToString() : "",
|
||||
requestDict?.ContainsKey("allianceVotes") == true ? (Dictionary<int, Dictionary<int, int>>)requestDict["allianceVotes"] : new(),
|
||||
requestDict?.ContainsKey("selectionCriteria") == true ? (Dictionary<string, object>)requestDict["selectionCriteria"] : new()
|
||||
);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
return Forbid(new { Message = "Host selection failed - insufficient authority or selection fraud detected", Code = "HOST_SELECTION_FAILED" });
|
||||
}
|
||||
|
||||
var response = new
|
||||
{
|
||||
PlayerId = playerId,
|
||||
KingdomId = kingdomId,
|
||||
Success = success,
|
||||
SelectedHostPlayerId = selectedHostPlayerId,
|
||||
HostAuthorities = hostAuthorities,
|
||||
SelectionValidation = selectionValidation,
|
||||
SelectionTime = DateTime.UtcNow
|
||||
};
|
||||
|
||||
_logger.LogInformation("Host selection completed for Kingdom {KingdomId} - Selected Host: {HostId}",
|
||||
kingdomId, selectedHostPlayerId);
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error processing host selection for Kingdom {KingdomId}", GetAuthenticatedPlayer().KingdomId);
|
||||
return StatusCode(500, new { Message = "Failed to process host selection", Code = "HOST_SELECTION_ERROR" });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes democratic tax distribution with transparent allocation
|
||||
/// </summary>
|
||||
/// <param name="request">Tax distribution parameters</param>
|
||||
/// <returns>Tax distribution result with allocation transparency</returns>
|
||||
[HttpPost("tax-distribution")]
|
||||
[ProducesResponseType(typeof(object), 200)]
|
||||
[ProducesResponseType(400)]
|
||||
[ProducesResponseType(403)]
|
||||
public async Task<IActionResult> ProcessDemocraticTaxDistribution([FromBody] object request)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return BadRequest(new { Message = "Invalid tax distribution request", Code = "INVALID_REQUEST" });
|
||||
}
|
||||
|
||||
var (playerId, kingdomId) = GetAuthenticatedPlayer();
|
||||
var requestDict = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object>>(request.ToString() ?? "{}");
|
||||
|
||||
var (success, distributionPlan, allianceAllocations, distributionAudit) =
|
||||
await _kingdomService.ProcessDemocraticTaxDistributionAsync(
|
||||
kingdomId,
|
||||
requestDict?.ContainsKey("taxCollectionData") == true ? (Dictionary<string, long>)requestDict["taxCollectionData"] : new(),
|
||||
requestDict?.ContainsKey("distributionCriteria") == true ? (Dictionary<string, object>)requestDict["distributionCriteria"] : new(),
|
||||
requestDict?.ContainsKey("councilApproval") == true ? (Dictionary<int, bool>)requestDict["councilApproval"] : new()
|
||||
);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
return Forbid(new { Message = "Tax distribution failed - insufficient council approval or invalid criteria", Code = "TAX_DISTRIBUTION_FAILED" });
|
||||
}
|
||||
|
||||
var response = new
|
||||
{
|
||||
PlayerId = playerId,
|
||||
KingdomId = kingdomId,
|
||||
Success = success,
|
||||
DistributionPlan = distributionPlan,
|
||||
AllianceAllocations = allianceAllocations,
|
||||
DistributionAudit = distributionAudit,
|
||||
DistributionTime = DateTime.UtcNow
|
||||
};
|
||||
|
||||
_logger.LogInformation("Democratic tax distribution processed for Kingdom {KingdomId}", kingdomId);
|
||||
return Ok(response);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error processing tax distribution for Kingdom {KingdomId}", GetAuthenticatedPlayer().KingdomId);
|
||||
return StatusCode(500, new { Message = "Failed to process tax distribution", Code = "TAX_DISTRIBUTION_ERROR" });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manages royal council operations with democratic decision-making
|
||||
/// </summary>
|
||||
/// <param name="request">Royal council parameters</param>
|
||||
/// <returns>Council operation result with voting records</returns>
|
||||
[HttpPost("royal-council/operate")]
|
||||
[ProducesResponseType(typeof(object), 200)]
|
||||
[ProducesResponseType(400)]
|
||||
[ProducesResponseType(403)]
|
||||
public async Task<IActionResult> OperateRoyalCouncil([FromBody] object request)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return BadRequest(new { Message = "Invalid royal council request", Code = "INVALID_REQUEST" });
|
||||
}
|
||||
|
||||
var (playerId, kingdomId) = GetAuthenticatedPlayer();
|
||||
var requestDict = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object>>(request.ToString() ?? "{}");
|
||||
|
||||
var (success, actionResult, councilVotes, governanceTransparency) =
|
||||
await _kingdomService.OperateRoyalCouncilAsync(
|
||||
kingdomId,
|
||||
requestDict?.ContainsKey("councilAction") == true ? requestDict["councilAction"].ToString() : "",
|
||||
requestDict?.ContainsKey("councilMembers") == true ?
|
||||
((System.Text.Json.JsonElement)requestDict["councilMembers"]).Deserialize<List<int>>() ?? new() : new(),
|
||||
requestDict?.ContainsKey("actionDetails") == true ? (Dictionary<string, object>)requestDict["actionDetails"] : new()
|
||||
);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
return Forbid(new { Message = "Royal council operation failed - insufficient authority or council rejection", Code = "COUNCIL_OPERATION_FAILED" });
|
||||
}
|
||||
|
||||
var response = new
|
||||
{
|
||||
PlayerId = playerId,
|
||||
KingdomId = kingdomId,
|
||||
Success = success,
|
||||
ActionResult = actionResult,
|
||||
CouncilVotes = councilVotes,
|
||||
GovernanceTransparency = governanceTransparency,
|
||||
OperationTime = DateTime.UtcNow
|
||||
};
|
||||
|
||||
_logger.LogInformation("Royal council operation processed for Kingdom {KingdomId} - Action: {Action}",
|
||||
kingdomId, requestDict?.ContainsKey("councilAction") == true ? requestDict["councilAction"].ToString() : "unknown");
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error operating royal council for Kingdom {KingdomId}", GetAuthenticatedPlayer().KingdomId);
|
||||
return StatusCode(500, new { Message = "Failed to operate royal council", Code = "ROYAL_COUNCIL_ERROR" });
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Population Management
|
||||
|
||||
/// <summary>
|
||||
/// Monitors kingdom population with scaling recommendations
|
||||
/// </summary>
|
||||
/// <param name="kingdomId">Kingdom ID (optional - defaults to current player's kingdom)</param>
|
||||
/// <returns>Population monitoring analysis</returns>
|
||||
[HttpGet("{kingdomId?}/population/monitor")]
|
||||
[ProducesResponseType(typeof(object), 200)]
|
||||
public async Task<IActionResult> MonitorKingdomPopulation(int? kingdomId = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var (playerId, playerKingdomId) = GetAuthenticatedPlayer();
|
||||
var targetKingdomId = kingdomId ?? playerKingdomId;
|
||||
|
||||
var monitoringResult = await _kingdomService.MonitorKingdomPopulationAsync(targetKingdomId);
|
||||
|
||||
var response = new
|
||||
{
|
||||
PlayerId = playerId,
|
||||
KingdomId = targetKingdomId,
|
||||
MonitoringResult = monitoringResult,
|
||||
MonitoringTime = DateTime.UtcNow
|
||||
};
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error monitoring kingdom population for Kingdom {KingdomId}",
|
||||
kingdomId ?? GetAuthenticatedPlayer().KingdomId);
|
||||
return StatusCode(500, new { Message = "Failed to monitor kingdom population", Code = "POPULATION_MONITORING_ERROR" });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates new kingdom when population capacity is exceeded
|
||||
/// </summary>
|
||||
/// <param name="request">Kingdom creation parameters</param>
|
||||
/// <returns>Kingdom creation result</returns>
|
||||
[HttpPost("create")]
|
||||
[ProducesResponseType(typeof(object), 201)]
|
||||
[ProducesResponseType(400)]
|
||||
[ProducesResponseType(403)]
|
||||
public async Task<IActionResult> CreateKingdom([FromBody] object request)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return BadRequest(new { Message = "Invalid kingdom creation request", Code = "INVALID_REQUEST" });
|
||||
}
|
||||
|
||||
var (playerId, kingdomId) = GetAuthenticatedPlayer();
|
||||
var requestDict = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object>>(request.ToString() ?? "{}");
|
||||
|
||||
var (success, newKingdomId, migrationIncentives) =
|
||||
await _kingdomService.CreateKingdomAsync(
|
||||
requestDict?.ContainsKey("kingdomName") == true ? requestDict["kingdomName"].ToString() : "New Kingdom",
|
||||
requestDict?.ContainsKey("initialSettings") == true ? (Dictionary<string, object>)requestDict["initialSettings"] : new()
|
||||
);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
return Forbid(new { Message = "Kingdom creation failed - insufficient authority or invalid settings", Code = "KINGDOM_CREATION_FAILED" });
|
||||
}
|
||||
|
||||
var response = new
|
||||
{
|
||||
PlayerId = playerId,
|
||||
RequestingKingdomId = kingdomId,
|
||||
Success = success,
|
||||
NewKingdomId = newKingdomId,
|
||||
MigrationIncentives = migrationIncentives,
|
||||
CreationTime = DateTime.UtcNow
|
||||
};
|
||||
|
||||
_logger.LogInformation("Kingdom created successfully - New Kingdom ID: {NewKingdomId}, Created by Player {PlayerId}",
|
||||
newKingdomId, playerId);
|
||||
|
||||
return CreatedAtAction(nameof(GetKingdomInfo), new { kingdomId = newKingdomId }, response);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error creating kingdom for Player {PlayerId}", GetAuthenticatedPlayer().PlayerId);
|
||||
return StatusCode(500, new { Message = "Failed to create kingdom", Code = "KINGDOM_CREATION_ERROR" });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manages kingdom migration with incentive programs
|
||||
/// </summary>
|
||||
/// <param name="request">Migration management parameters</param>
|
||||
/// <returns>Migration management result</returns>
|
||||
[HttpPost("migration/manage")]
|
||||
[ProducesResponseType(typeof(object), 200)]
|
||||
[ProducesResponseType(400)]
|
||||
[ProducesResponseType(403)]
|
||||
public async Task<IActionResult> ManageKingdomMigration([FromBody] object request)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return BadRequest(new { Message = "Invalid migration management request", Code = "INVALID_REQUEST" });
|
||||
}
|
||||
|
||||
var (playerId, kingdomId) = GetAuthenticatedPlayer();
|
||||
var requestDict = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object>>(request.ToString() ?? "{}");
|
||||
|
||||
var migrationResult = await _kingdomService.ManageMigrationIncentivesAsync(
|
||||
kingdomId,
|
||||
requestDict?.ContainsKey("targetKingdomIds") == true ?
|
||||
((System.Text.Json.JsonElement)requestDict["targetKingdomIds"]).Deserialize<List<int>>() ?? new() : new(),
|
||||
requestDict?.ContainsKey("incentivePrograms") == true ? (Dictionary<string, object>)requestDict["incentivePrograms"] : new()
|
||||
);
|
||||
|
||||
var response = new
|
||||
{
|
||||
PlayerId = playerId,
|
||||
KingdomId = kingdomId,
|
||||
MigrationResult = migrationResult,
|
||||
ManagementTime = DateTime.UtcNow
|
||||
};
|
||||
|
||||
_logger.LogInformation("Kingdom migration managed for Kingdom {KingdomId} by Player {PlayerId}",
|
||||
kingdomId, playerId);
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error managing kingdom migration for Kingdom {KingdomId}", GetAuthenticatedPlayer().KingdomId);
|
||||
return StatusCode(500, new { Message = "Failed to manage kingdom migration", Code = "MIGRATION_MANAGEMENT_ERROR" });
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Kingdom Mergers
|
||||
|
||||
/// <summary>
|
||||
/// Initiates voluntary kingdom merger process with democratic approval
|
||||
/// </summary>
|
||||
/// <param name="request">Kingdom merger parameters</param>
|
||||
/// <returns>Kingdom merger initiation result</returns>
|
||||
[HttpPost("merger/initiate")]
|
||||
[ProducesResponseType(typeof(object), 200)]
|
||||
[ProducesResponseType(400)]
|
||||
[ProducesResponseType(403)]
|
||||
public async Task<IActionResult> InitiateKingdomMerger([FromBody] object request)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return BadRequest(new { Message = "Invalid kingdom merger request", Code = "INVALID_REQUEST" });
|
||||
}
|
||||
|
||||
var (playerId, kingdomId) = GetAuthenticatedPlayer();
|
||||
var requestDict = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object>>(request.ToString() ?? "{}");
|
||||
|
||||
var (success, mergerProposalId, compatibilityAnalysis, democraticRequirements) =
|
||||
await _kingdomService.InitiateKingdomMergerAsync(
|
||||
kingdomId,
|
||||
requestDict?.ContainsKey("targetKingdomIds") == true ?
|
||||
((System.Text.Json.JsonElement)requestDict["targetKingdomIds"]).Deserialize<List<int>>() ?? new() : new(),
|
||||
requestDict?.ContainsKey("mergerReasoning") == true ? requestDict["mergerReasoning"].ToString() : "",
|
||||
requestDict?.ContainsKey("proposedTerms") == true ? (Dictionary<string, object>)requestDict["proposedTerms"] : new()
|
||||
);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
return Forbid(new { Message = "Kingdom merger initiation failed - insufficient authority or incompatible kingdoms", Code = "MERGER_INITIATION_FAILED" });
|
||||
}
|
||||
|
||||
var response = new
|
||||
{
|
||||
PlayerId = playerId,
|
||||
KingdomId = kingdomId,
|
||||
Success = success,
|
||||
MergerProposalId = mergerProposalId,
|
||||
CompatibilityAnalysis = compatibilityAnalysis,
|
||||
DemocraticRequirements = democraticRequirements,
|
||||
InitiationTime = DateTime.UtcNow
|
||||
};
|
||||
|
||||
_logger.LogInformation("Kingdom merger initiated for Kingdom {KingdomId} - Proposal ID: {ProposalId}",
|
||||
kingdomId, mergerProposalId);
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error initiating kingdom merger for Kingdom {KingdomId}", GetAuthenticatedPlayer().KingdomId);
|
||||
return StatusCode(500, new { Message = "Failed to initiate kingdom merger", Code = "MERGER_INITIATION_ERROR" });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes democratic approval for kingdom merger
|
||||
/// </summary>
|
||||
/// <param name="mergerProposalId">Merger proposal identifier</param>
|
||||
/// <param name="request">Merger approval parameters</param>
|
||||
/// <returns>Merger approval result with democratic validation</returns>
|
||||
[HttpPost("merger/{mergerProposalId}/approve")]
|
||||
[ProducesResponseType(typeof(object), 200)]
|
||||
[ProducesResponseType(400)]
|
||||
[ProducesResponseType(403)]
|
||||
public async Task<IActionResult> ProcessMergerApproval(string mergerProposalId, [FromBody] object request)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return BadRequest(new { Message = "Invalid merger approval request", Code = "INVALID_REQUEST" });
|
||||
}
|
||||
|
||||
var (playerId, kingdomId) = GetAuthenticatedPlayer();
|
||||
var requestDict = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object>>(request.ToString() ?? "{}");
|
||||
|
||||
var (success, approvalStatus, votingResults, nextSteps) =
|
||||
await _kingdomService.ProcessMergerApprovalAsync(
|
||||
mergerProposalId, kingdomId,
|
||||
requestDict?.ContainsKey("kingdomVotes") == true ? (Dictionary<int, bool>)requestDict["kingdomVotes"] : new(),
|
||||
requestDict?.ContainsKey("voterTurnout") == true ? (Dictionary<int, double>)requestDict["voterTurnout"] : new()
|
||||
);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
return Forbid(new { Message = "Merger approval failed - insufficient votes or approval fraud detected", Code = "MERGER_APPROVAL_FAILED" });
|
||||
}
|
||||
|
||||
var response = new
|
||||
{
|
||||
PlayerId = playerId,
|
||||
KingdomId = kingdomId,
|
||||
MergerProposalId = mergerProposalId,
|
||||
Success = success,
|
||||
ApprovalStatus = approvalStatus,
|
||||
VotingResults = votingResults,
|
||||
NextSteps = nextSteps,
|
||||
ApprovalTime = DateTime.UtcNow
|
||||
};
|
||||
|
||||
_logger.LogInformation("Merger approval processed for Proposal {ProposalId} - Status: {Status}",
|
||||
mergerProposalId, approvalStatus);
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error processing merger approval for Proposal {ProposalId}", mergerProposalId);
|
||||
return StatusCode(500, new { Message = "Failed to process merger approval", Code = "MERGER_APPROVAL_ERROR" });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes approved kingdom merger with integration planning
|
||||
/// </summary>
|
||||
/// <param name="mergerProposalId">Merger proposal identifier</param>
|
||||
/// <param name="request">Merger execution parameters</param>
|
||||
/// <returns>Merger execution result</returns>
|
||||
[HttpPost("merger/{mergerProposalId}/execute")]
|
||||
[ProducesResponseType(typeof(object), 200)]
|
||||
[ProducesResponseType(400)]
|
||||
[ProducesResponseType(403)]
|
||||
public async Task<IActionResult> ExecuteKingdomMerger(string mergerProposalId, [FromBody] object request)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return BadRequest(new { Message = "Invalid merger execution request", Code = "INVALID_REQUEST" });
|
||||
}
|
||||
|
||||
var (playerId, kingdomId) = GetAuthenticatedPlayer();
|
||||
var requestDict = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object>>(request.ToString() ?? "{}");
|
||||
|
||||
var (success, resultingKingdomId, integrationPlan, preservedBenefits) =
|
||||
await _kingdomService.ExecuteKingdomMergerAsync(
|
||||
mergerProposalId,
|
||||
requestDict?.ContainsKey("integrationStrategy") == true ? (Dictionary<string, object>)requestDict["integrationStrategy"] : new(),
|
||||
requestDict?.ContainsKey("leadershipIntegration") == true ? (Dictionary<string, object>)requestDict["leadershipIntegration"] : new()
|
||||
);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
return Forbid(new { Message = "Kingdom merger execution failed - merger not approved or execution error", Code = "MERGER_EXECUTION_FAILED" });
|
||||
}
|
||||
|
||||
var response = new
|
||||
{
|
||||
PlayerId = playerId,
|
||||
OriginKingdomId = kingdomId,
|
||||
MergerProposalId = mergerProposalId,
|
||||
Success = success,
|
||||
ResultingKingdomId = resultingKingdomId,
|
||||
IntegrationPlan = integrationPlan,
|
||||
PreservedBenefits = preservedBenefits,
|
||||
ExecutionTime = DateTime.UtcNow
|
||||
};
|
||||
|
||||
_logger.LogInformation("Kingdom merger executed successfully - Proposal {ProposalId}, Resulting Kingdom: {ResultingKingdomId}",
|
||||
mergerProposalId, resultingKingdomId);
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error executing kingdom merger for Proposal {ProposalId}", mergerProposalId);
|
||||
return StatusCode(500, new { Message = "Failed to execute kingdom merger", Code = "MERGER_EXECUTION_ERROR" });
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helper Methods
|
||||
|
||||
/// <summary>
|
||||
/// Extracts authenticated player information from JWT claims
|
||||
/// </summary>
|
||||
/// <returns>Player ID and Kingdom ID from authentication context</returns>
|
||||
/// <exception cref="UnauthorizedAccessException">Thrown when authentication claims are invalid</exception>
|
||||
private (int PlayerId, int KingdomId) GetAuthenticatedPlayer()
|
||||
{
|
||||
var playerIdClaim = User.FindFirst("player_id")?.Value;
|
||||
var kingdomIdClaim = User.FindFirst("kingdom_id")?.Value;
|
||||
|
||||
if (string.IsNullOrEmpty(playerIdClaim) || string.IsNullOrEmpty(kingdomIdClaim))
|
||||
{
|
||||
throw new UnauthorizedAccessException("Invalid authentication claims - player or kingdom not found");
|
||||
}
|
||||
|
||||
if (!int.TryParse(playerIdClaim, out int playerId) ||
|
||||
!int.TryParse(kingdomIdClaim, out int kingdomId))
|
||||
{
|
||||
throw new UnauthorizedAccessException("Invalid authentication claims - unable to parse player or kingdom ID");
|
||||
}
|
||||
|
||||
return (playerId, kingdomId);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -19,11 +19,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Controllers\Alliance\" />
|
||||
<Folder Include="Controllers\Kingdom\" />
|
||||
<Folder Include="Controllers\Combat\" />
|
||||
<Folder Include="Controllers\Admin\" />
|
||||
<Folder Include="Controllers\Player\" />
|
||||
<Folder Include="Middleware\" />
|
||||
<Folder Include="Filters\" />
|
||||
<Folder Include="DTOs\" />
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user