fix: Repository compilation errors - interface/implementation alignment
- Fixed KingdomRepository return types to match IKingdomRepository exactly - Fixed PlayerRepository base repository method calls and return types - Created IKingdomScoped interface for kingdom security constraints - Player model already implements IKingdomScoped correctly - Resolved 60+ compilation errors from method signature mismatches - All repository interfaces now properly implemented
This commit is contained in:
parent
337a029308
commit
9fd9666d31
@ -6,13 +6,14 @@
|
|||||||
* Last Edit Notes: Initial creation with castle progression, resource management, troop systems, and alliance integration
|
* Last Edit Notes: Initial creation with castle progression, resource management, troop systems, and alliance integration
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using ShadowedRealms.Core.Interfaces;
|
||||||
using ShadowedRealms.Core.Models.Alliance;
|
using ShadowedRealms.Core.Models.Alliance;
|
||||||
using ShadowedRealms.Core.Models.Kingdom;
|
using ShadowedRealms.Core.Models.Kingdom;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace ShadowedRealms.Core.Models.Player
|
namespace ShadowedRealms.Core.Models.Player
|
||||||
{
|
{
|
||||||
public class Player
|
public class Player : IKingdomScoped
|
||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
* File: ShadowedRealms.Data/Repositories/Kingdom/KingdomRepository.cs
|
* File: ShadowedRealms.Data/Repositories/Kingdom/KingdomRepository.cs
|
||||||
* Created: 2025-10-19
|
* Created: 2025-10-19
|
||||||
* Last Modified: 2025-10-19
|
* Last Modified: 2025-10-20
|
||||||
* Description: Kingdom repository implementation providing kingdom-specific operations including population management,
|
* Description: Kingdom repository implementation providing kingdom-specific operations including population management,
|
||||||
* democratic systems, KvK events, merger mechanics, and tax distribution systems.
|
* democratic systems, KvK events, merger mechanics, and tax distribution systems.
|
||||||
* Last Edit Notes: Fixed namespace conflicts and implemented missing interface methods
|
* Last Edit Notes: Fixed method return types to match IKingdomRepository interface signatures exactly
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
@ -178,30 +178,32 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets kingdom population with optional active-only filter
|
/// Gets kingdom population breakdown with active/inactive/total counts
|
||||||
|
/// FIXED: Returns tuple matching interface signature exactly
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public async Task<int> GetKingdomPopulationAsync(int kingdomId, bool activeOnly = true, CancellationToken cancellationToken = default)
|
public async Task<(int ActivePlayers, int InactivePlayers, int TotalPlayers)> GetKingdomPopulationAsync(int kingdomId, bool includeInactive = false, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_logger.LogDebug("Getting population for kingdom {KingdomId}, active only: {ActiveOnly}", kingdomId, activeOnly);
|
_logger.LogDebug("Getting population breakdown for kingdom {KingdomId}", kingdomId);
|
||||||
|
|
||||||
var query = _context.Players.Where(p => p.KingdomId == kingdomId);
|
var activePlayers = await _context.Players
|
||||||
|
.CountAsync(p => p.KingdomId == kingdomId && p.IsActive, cancellationToken);
|
||||||
|
|
||||||
if (activeOnly)
|
var inactivePlayers = await _context.Players
|
||||||
{
|
.CountAsync(p => p.KingdomId == kingdomId && !p.IsActive, cancellationToken);
|
||||||
query = query.Where(p => p.IsActive);
|
|
||||||
}
|
|
||||||
|
|
||||||
var count = await query.CountAsync(cancellationToken);
|
var totalPlayers = activePlayers + inactivePlayers;
|
||||||
|
|
||||||
_logger.LogDebug("Kingdom {KingdomId} has population of {Count}", kingdomId, count);
|
_logger.LogDebug("Kingdom {KingdomId} population: {Active} active, {Inactive} inactive, {Total} total",
|
||||||
return count;
|
kingdomId, activePlayers, inactivePlayers, totalPlayers);
|
||||||
|
|
||||||
|
return (activePlayers, inactivePlayers, totalPlayers);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError(ex, "Error getting population for kingdom {KingdomId}", kingdomId);
|
_logger.LogError(ex, "Error getting population breakdown for kingdom {KingdomId}", kingdomId);
|
||||||
throw new InvalidOperationException($"Failed to get population for kingdom {kingdomId}", ex);
|
throw new InvalidOperationException($"Failed to get population breakdown for kingdom {kingdomId}", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,7 +216,7 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
|
|||||||
{
|
{
|
||||||
_logger.LogDebug("Getting merger eligible kingdoms for {KingdomId}", kingdomId);
|
_logger.LogDebug("Getting merger eligible kingdoms for {KingdomId}", kingdomId);
|
||||||
|
|
||||||
var currentPopulation = await GetKingdomPopulationAsync(kingdomId, true, cancellationToken);
|
var (activePlayers, _, _) = await GetKingdomPopulationAsync(kingdomId, false, cancellationToken);
|
||||||
const int maxMergedPopulation = 1500;
|
const int maxMergedPopulation = 1500;
|
||||||
|
|
||||||
var candidates = new List<KingdomModel>();
|
var candidates = new List<KingdomModel>();
|
||||||
@ -224,8 +226,8 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
|
|||||||
|
|
||||||
foreach (var kingdom in otherKingdoms)
|
foreach (var kingdom in otherKingdoms)
|
||||||
{
|
{
|
||||||
var otherPopulation = await GetKingdomPopulationAsync(kingdom.Id, true, cancellationToken);
|
var (otherActive, _, _) = await GetKingdomPopulationAsync(kingdom.Id, false, cancellationToken);
|
||||||
if (currentPopulation + otherPopulation <= maxMergedPopulation)
|
if (activePlayers + otherActive <= maxMergedPopulation)
|
||||||
{
|
{
|
||||||
candidates.Add(kingdom);
|
candidates.Add(kingdom);
|
||||||
}
|
}
|
||||||
@ -242,9 +244,10 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates kingdom population count
|
/// Updates kingdom population count and returns updated kingdom entity
|
||||||
|
/// FIXED: Returns Kingdom entity matching interface signature exactly
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public async Task<bool> UpdateKingdomPopulationAsync(int kingdomId, int newPopulation, CancellationToken cancellationToken = default)
|
public async Task<KingdomModel> UpdateKingdomPopulationAsync(int kingdomId, int newPopulation, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -255,8 +258,7 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
|
|||||||
|
|
||||||
if (kingdom == null)
|
if (kingdom == null)
|
||||||
{
|
{
|
||||||
_logger.LogWarning("Kingdom {KingdomId} not found for population update", kingdomId);
|
throw new InvalidOperationException($"Kingdom {kingdomId} not found");
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
kingdom.CurrentPopulation = newPopulation;
|
kingdom.CurrentPopulation = newPopulation;
|
||||||
@ -265,7 +267,7 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
|
|||||||
await _context.SaveChangesAsync(cancellationToken);
|
await _context.SaveChangesAsync(cancellationToken);
|
||||||
|
|
||||||
_logger.LogDebug("Successfully updated kingdom {KingdomId} population to {NewPopulation}", kingdomId, newPopulation);
|
_logger.LogDebug("Successfully updated kingdom {KingdomId} population to {NewPopulation}", kingdomId, newPopulation);
|
||||||
return true;
|
return kingdom;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -275,9 +277,10 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets kingdoms eligible for KvK events
|
/// Gets kingdoms eligible for KvK events with compatibility scores
|
||||||
|
/// FIXED: Returns tuple with compatibility scores matching interface signature exactly
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public async Task<IEnumerable<KingdomModel>> GetKvKEligibleKingdomsAsync(int kingdomId, string eventType, CancellationToken cancellationToken = default)
|
public async Task<IEnumerable<(KingdomModel Kingdom, double CompatibilityScore)>> GetKvKEligibleKingdomsAsync(int kingdomId, string eventType, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -286,11 +289,21 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
|
|||||||
var eligibleKingdoms = await _context.Kingdoms
|
var eligibleKingdoms = await _context.Kingdoms
|
||||||
.Where(k => k.Id != kingdomId && k.IsActive && !k.IsInKvK)
|
.Where(k => k.Id != kingdomId && k.IsActive && !k.IsInKvK)
|
||||||
.Where(k => k.CurrentPopulation >= 500) // Minimum population for KvK
|
.Where(k => k.CurrentPopulation >= 500) // Minimum population for KvK
|
||||||
.OrderBy(k => k.CurrentPowerRank)
|
|
||||||
.ToListAsync(cancellationToken);
|
.ToListAsync(cancellationToken);
|
||||||
|
|
||||||
_logger.LogDebug("Found {Count} KvK eligible kingdoms", eligibleKingdoms.Count);
|
var results = new List<(KingdomModel Kingdom, double CompatibilityScore)>();
|
||||||
return eligibleKingdoms;
|
|
||||||
|
foreach (var kingdom in eligibleKingdoms)
|
||||||
|
{
|
||||||
|
var compatibilityScore = await CalculateKvKCompatibilityScore(kingdomId, kingdom.Id, cancellationToken);
|
||||||
|
results.Add((kingdom, compatibilityScore));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Order by compatibility score (highest first)
|
||||||
|
var orderedResults = results.OrderByDescending(r => r.CompatibilityScore);
|
||||||
|
|
||||||
|
_logger.LogDebug("Found {Count} KvK eligible kingdoms with compatibility scores", results.Count);
|
||||||
|
return orderedResults;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -392,9 +405,10 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates KvK performance metrics for a kingdom
|
/// Updates KvK performance metrics for a kingdom and returns updated kingdom
|
||||||
|
/// FIXED: Returns Kingdom entity matching interface signature exactly
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public async Task<bool> UpdateKvKPerformanceAsync(int kingdomId, object battleResults, object performanceMetrics, CancellationToken cancellationToken = default)
|
public async Task<KingdomModel> UpdateKvKPerformanceAsync(int kingdomId, object battleResults, object performanceMetrics, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -405,8 +419,7 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
|
|||||||
|
|
||||||
if (kingdom == null)
|
if (kingdom == null)
|
||||||
{
|
{
|
||||||
_logger.LogWarning("Kingdom {KingdomId} not found for KvK performance update", kingdomId);
|
throw new InvalidOperationException($"Kingdom {kingdomId} not found");
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
kingdom.LastActivity = DateTime.UtcNow;
|
kingdom.LastActivity = DateTime.UtcNow;
|
||||||
@ -415,7 +428,7 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
|
|||||||
await _context.SaveChangesAsync(cancellationToken);
|
await _context.SaveChangesAsync(cancellationToken);
|
||||||
|
|
||||||
_logger.LogInformation("Successfully updated KvK performance for kingdom {KingdomId}", kingdomId);
|
_logger.LogInformation("Successfully updated KvK performance for kingdom {KingdomId}", kingdomId);
|
||||||
return true;
|
return kingdom;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -464,18 +477,59 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets kingdoms compatible for merger with the specified kingdom
|
/// Gets kingdoms compatible for merger with compatibility scores and benefits
|
||||||
|
/// FIXED: Returns tuple with compatibility scores and benefits matching interface signature exactly
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public async Task<IEnumerable<KingdomModel>> GetMergerCompatibleKingdomsAsync(int kingdomId, CancellationToken cancellationToken = default)
|
public async Task<IEnumerable<(KingdomModel Kingdom, double CompatibilityScore, string[] Benefits)>> GetMergerCompatibleKingdomsAsync(int kingdomId, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
// This is the same as GetKingdomsEligibleForMergerAsync
|
try
|
||||||
return await GetKingdomsEligibleForMergerAsync(kingdomId, cancellationToken);
|
{
|
||||||
|
_logger.LogDebug("Getting merger compatible kingdoms for {KingdomId}", kingdomId);
|
||||||
|
|
||||||
|
var (currentActive, _, currentTotal) = await GetKingdomPopulationAsync(kingdomId, false, cancellationToken);
|
||||||
|
const int maxMergedPopulation = 1500;
|
||||||
|
|
||||||
|
var candidates = new List<(KingdomModel Kingdom, double CompatibilityScore, string[] Benefits)>();
|
||||||
|
var otherKingdoms = await _context.Kingdoms
|
||||||
|
.Where(k => k.Id != kingdomId && k.IsActive && !k.IsInKvK)
|
||||||
|
.ToListAsync(cancellationToken);
|
||||||
|
|
||||||
|
var currentKingdom = await _context.Kingdoms.FirstOrDefaultAsync(k => k.Id == kingdomId);
|
||||||
|
if (currentKingdom == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Kingdom {kingdomId} not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var kingdom in otherKingdoms)
|
||||||
|
{
|
||||||
|
var (otherActive, _, otherTotal) = await GetKingdomPopulationAsync(kingdom.Id, false, cancellationToken);
|
||||||
|
|
||||||
|
if (currentActive + otherActive <= maxMergedPopulation)
|
||||||
|
{
|
||||||
|
var compatibilityScore = CalculateMergerCompatibilityScore(currentTotal, otherTotal, currentKingdom, kingdom);
|
||||||
|
var benefits = CalculateMergerBenefits(currentKingdom, currentTotal, otherTotal);
|
||||||
|
|
||||||
|
candidates.Add((kingdom, compatibilityScore, benefits));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var orderedCandidates = candidates.OrderByDescending(c => c.CompatibilityScore);
|
||||||
|
|
||||||
|
_logger.LogDebug("Found {Count} merger compatible kingdoms for kingdom {KingdomId}", candidates.Count, kingdomId);
|
||||||
|
return orderedCandidates;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error getting merger compatible kingdoms for {KingdomId}", kingdomId);
|
||||||
|
throw new InvalidOperationException($"Failed to get merger compatible kingdoms for {kingdomId}", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Executes a kingdom merger
|
/// Executes a kingdom merger and returns the updated target kingdom
|
||||||
|
/// FIXED: Returns Kingdom entity matching interface signature exactly
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public async Task<object> ExecuteMergerAsync(int sourceKingdomId, int targetKingdomId, object mergerConfiguration, CancellationToken cancellationToken = default)
|
public async Task<KingdomModel> ExecuteMergerAsync(int sourceKingdomId, int targetKingdomId, object mergerConfiguration, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -508,27 +562,26 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
|
|||||||
// Archive source kingdom
|
// Archive source kingdom
|
||||||
await ArchiveKingdomAsync(sourceKingdomId, "Merged into another kingdom", cancellationToken);
|
await ArchiveKingdomAsync(sourceKingdomId, "Merged into another kingdom", cancellationToken);
|
||||||
|
|
||||||
// Update target kingdom population
|
// Get updated target kingdom and update population
|
||||||
var newPopulation = await GetKingdomPopulationAsync(targetKingdomId, true, cancellationToken);
|
var targetKingdom = await _context.Kingdoms
|
||||||
await UpdateKingdomPopulationAsync(targetKingdomId, newPopulation, cancellationToken);
|
.FirstOrDefaultAsync(k => k.Id == targetKingdomId, cancellationToken);
|
||||||
|
|
||||||
|
if (targetKingdom == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Target kingdom {targetKingdomId} not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
var (newActive, newInactive, newTotal) = await GetKingdomPopulationAsync(targetKingdomId, false, cancellationToken);
|
||||||
|
targetKingdom.CurrentPopulation = newTotal;
|
||||||
|
targetKingdom.LastActivity = DateTime.UtcNow;
|
||||||
|
|
||||||
await _context.SaveChangesAsync(cancellationToken);
|
await _context.SaveChangesAsync(cancellationToken);
|
||||||
await transaction.CommitAsync(cancellationToken);
|
await transaction.CommitAsync(cancellationToken);
|
||||||
|
|
||||||
var result = new
|
|
||||||
{
|
|
||||||
MergerExecuted = true,
|
|
||||||
SourceKingdomId = sourceKingdomId,
|
|
||||||
TargetKingdomId = targetKingdomId,
|
|
||||||
PlayersMoved = playersToMove.Count,
|
|
||||||
AlliancesMoved = alliancesToMove.Count,
|
|
||||||
ExecutedAt = DateTime.UtcNow
|
|
||||||
};
|
|
||||||
|
|
||||||
_logger.LogInformation("Successfully executed merger: moved {PlayerCount} players and {AllianceCount} alliances",
|
_logger.LogInformation("Successfully executed merger: moved {PlayerCount} players and {AllianceCount} alliances",
|
||||||
playersToMove.Count, alliancesToMove.Count);
|
playersToMove.Count, alliancesToMove.Count);
|
||||||
|
|
||||||
return result;
|
return targetKingdom;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@ -642,9 +695,10 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates tax distribution for a kingdom
|
/// Updates tax distribution for a kingdom and returns updated kingdom
|
||||||
|
/// FIXED: Returns Kingdom entity matching interface signature exactly
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public async Task<bool> UpdateTaxDistributionAsync(int kingdomId, object distributionConfiguration, int distributorPlayerId, CancellationToken cancellationToken = default)
|
public async Task<KingdomModel> UpdateTaxDistributionAsync(int kingdomId, object distributionConfiguration, int distributorPlayerId, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -656,8 +710,7 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
|
|||||||
|
|
||||||
if (kingdom == null)
|
if (kingdom == null)
|
||||||
{
|
{
|
||||||
_logger.LogWarning("Kingdom {KingdomId} not found for tax distribution update", kingdomId);
|
throw new InvalidOperationException($"Kingdom {kingdomId} not found");
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
kingdom.LastActivity = DateTime.UtcNow;
|
kingdom.LastActivity = DateTime.UtcNow;
|
||||||
@ -666,7 +719,7 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
|
|||||||
await _context.SaveChangesAsync(cancellationToken);
|
await _context.SaveChangesAsync(cancellationToken);
|
||||||
|
|
||||||
_logger.LogInformation("Successfully updated tax distribution for kingdom {KingdomId}", kingdomId);
|
_logger.LogInformation("Successfully updated tax distribution for kingdom {KingdomId}", kingdomId);
|
||||||
return true;
|
return kingdom;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -692,7 +745,7 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
|
|||||||
throw new InvalidOperationException($"Kingdom {kingdomId} not found");
|
throw new InvalidOperationException($"Kingdom {kingdomId} not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
var activePlayers = await GetKingdomPopulationAsync(kingdomId, true, cancellationToken);
|
var (activePlayers, _, _) = await GetKingdomPopulationAsync(kingdomId, false, cancellationToken);
|
||||||
|
|
||||||
var taxStatus = new
|
var taxStatus = new
|
||||||
{
|
{
|
||||||
@ -733,7 +786,7 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
|
|||||||
throw new InvalidOperationException($"Kingdom {kingdomId} not found");
|
throw new InvalidOperationException($"Kingdom {kingdomId} not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
var population = await GetKingdomPopulationAsync(kingdomId, true, cancellationToken);
|
var (activePlayers, inactivePlayers, totalPlayers) = await GetKingdomPopulationAsync(kingdomId, false, cancellationToken);
|
||||||
var allianceCount = await _context.Alliances.Where(a => a.KingdomId == kingdomId && a.IsActive).CountAsync(cancellationToken);
|
var allianceCount = await _context.Alliances.Where(a => a.KingdomId == kingdomId && a.IsActive).CountAsync(cancellationToken);
|
||||||
var totalPower = await _context.Players.Where(p => p.KingdomId == kingdomId && p.IsActive).SumAsync(p => p.Power, cancellationToken);
|
var totalPower = await _context.Players.Where(p => p.KingdomId == kingdomId && p.IsActive).SumAsync(p => p.Power, cancellationToken);
|
||||||
|
|
||||||
@ -742,7 +795,9 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
|
|||||||
KingdomId = kingdomId,
|
KingdomId = kingdomId,
|
||||||
KingdomName = kingdom.Name,
|
KingdomName = kingdom.Name,
|
||||||
AnalysisTimeframe = analysisTimeframe.ToString(),
|
AnalysisTimeframe = analysisTimeframe.ToString(),
|
||||||
Population = population,
|
Population = totalPlayers,
|
||||||
|
ActivePlayers = activePlayers,
|
||||||
|
InactivePlayers = inactivePlayers,
|
||||||
AllianceCount = allianceCount,
|
AllianceCount = allianceCount,
|
||||||
TotalPower = totalPower,
|
TotalPower = totalPower,
|
||||||
PowerRank = kingdom.CurrentPowerRank,
|
PowerRank = kingdom.CurrentPowerRank,
|
||||||
@ -750,7 +805,7 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
|
|||||||
TotalTaxCollected = kingdom.TotalTaxCollected,
|
TotalTaxCollected = kingdom.TotalTaxCollected,
|
||||||
CreatedAt = kingdom.CreatedAt,
|
CreatedAt = kingdom.CreatedAt,
|
||||||
LastActivity = kingdom.LastActivity,
|
LastActivity = kingdom.LastActivity,
|
||||||
GrowthRate = population / Math.Max(1, (DateTime.UtcNow - kingdom.CreatedAt).Days),
|
GrowthRate = totalPlayers / Math.Max(1, (DateTime.UtcNow - kingdom.CreatedAt).Days),
|
||||||
Status = kingdom.IsActive ? "Active" : "Archived"
|
Status = kingdom.IsActive ? "Active" : "Archived"
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -785,26 +840,26 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
|
|||||||
.Where(k => k.IsActive)
|
.Where(k => k.IsActive)
|
||||||
.ToListAsync(cancellationToken);
|
.ToListAsync(cancellationToken);
|
||||||
|
|
||||||
var currentPopulation = await GetKingdomPopulationAsync(kingdomId, true, cancellationToken);
|
var (currentActive, _, currentTotal) = await GetKingdomPopulationAsync(kingdomId, false, cancellationToken);
|
||||||
var avgPopulation = 0.0;
|
var avgPopulation = 0.0;
|
||||||
|
|
||||||
if (allKingdoms.Any())
|
if (allKingdoms.Any())
|
||||||
{
|
{
|
||||||
var populationTasks = allKingdoms.Select(async k => await GetKingdomPopulationAsync(k.Id, true, cancellationToken));
|
var populationTasks = allKingdoms.Select(async k => await GetKingdomPopulationAsync(k.Id, false, cancellationToken));
|
||||||
var populations = await Task.WhenAll(populationTasks);
|
var populations = await Task.WhenAll(populationTasks);
|
||||||
avgPopulation = populations.Average();
|
avgPopulation = populations.Select(p => p.TotalPlayers).Average();
|
||||||
}
|
}
|
||||||
|
|
||||||
var benchmark = new
|
var benchmark = new
|
||||||
{
|
{
|
||||||
KingdomId = kingdomId,
|
KingdomId = kingdomId,
|
||||||
BenchmarkType = benchmarkType,
|
BenchmarkType = benchmarkType,
|
||||||
KingdomPopulation = currentPopulation,
|
KingdomPopulation = currentTotal,
|
||||||
AveragePopulation = Math.Round(avgPopulation, 1),
|
AveragePopulation = Math.Round(avgPopulation, 1),
|
||||||
PopulationPercentile = CalculatePercentile(currentPopulation, allKingdoms.Count),
|
PopulationPercentile = CalculatePercentile(currentTotal, allKingdoms.Count),
|
||||||
PowerRank = kingdom.CurrentPowerRank,
|
PowerRank = kingdom.CurrentPowerRank,
|
||||||
TotalKingdoms = allKingdoms.Count,
|
TotalKingdoms = allKingdoms.Count,
|
||||||
Performance = currentPopulation > avgPopulation ? "Above Average" : "Below Average",
|
Performance = currentTotal > avgPopulation ? "Above Average" : "Below Average",
|
||||||
GeneratedAt = DateTime.UtcNow
|
GeneratedAt = DateTime.UtcNow
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -835,19 +890,21 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
|
|||||||
throw new InvalidOperationException($"Kingdom {kingdomId} not found");
|
throw new InvalidOperationException($"Kingdom {kingdomId} not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
var population = await GetKingdomPopulationAsync(kingdomId, true, cancellationToken);
|
var (activePlayers, inactivePlayers, totalPlayers) = await GetKingdomPopulationAsync(kingdomId, false, cancellationToken);
|
||||||
var allianceCount = await _context.Alliances.Where(a => a.KingdomId == kingdomId && a.IsActive).CountAsync(cancellationToken);
|
var allianceCount = await _context.Alliances.Where(a => a.KingdomId == kingdomId && a.IsActive).CountAsync(cancellationToken);
|
||||||
var totalPower = await _context.Players.Where(p => p.KingdomId == kingdomId && p.IsActive).SumAsync(p => p.Power, cancellationToken);
|
var totalPower = await _context.Players.Where(p => p.KingdomId == kingdomId && p.IsActive).SumAsync(p => p.Power, cancellationToken);
|
||||||
|
|
||||||
var healthScore = CalculateHealthScore(population, allianceCount, totalPower, kingdom);
|
var healthScore = CalculateHealthScore(totalPlayers, allianceCount, totalPower, kingdom);
|
||||||
var recommendations = GenerateHealthRecommendations(healthScore, population, allianceCount, kingdom);
|
var recommendations = GenerateHealthRecommendations(healthScore, totalPlayers, allianceCount, kingdom);
|
||||||
|
|
||||||
var healthReport = new
|
var healthReport = new
|
||||||
{
|
{
|
||||||
KingdomId = kingdomId,
|
KingdomId = kingdomId,
|
||||||
KingdomName = kingdom.Name,
|
KingdomName = kingdom.Name,
|
||||||
OverallHealthScore = healthScore,
|
OverallHealthScore = healthScore,
|
||||||
Population = population,
|
Population = totalPlayers,
|
||||||
|
ActivePlayers = activePlayers,
|
||||||
|
InactivePlayers = inactivePlayers,
|
||||||
AllianceCount = allianceCount,
|
AllianceCount = allianceCount,
|
||||||
TotalPower = totalPower,
|
TotalPower = totalPower,
|
||||||
PowerRank = kingdom.CurrentPowerRank,
|
PowerRank = kingdom.CurrentPowerRank,
|
||||||
@ -936,6 +993,58 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
|
|||||||
|
|
||||||
#region Helper Methods
|
#region Helper Methods
|
||||||
|
|
||||||
|
private async Task<double> CalculateKvKCompatibilityScore(int kingdom1Id, int kingdom2Id, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var (kingdom1Active, _, kingdom1Total) = await GetKingdomPopulationAsync(kingdom1Id, false, cancellationToken);
|
||||||
|
var (kingdom2Active, _, kingdom2Total) = await GetKingdomPopulationAsync(kingdom2Id, false, cancellationToken);
|
||||||
|
|
||||||
|
// Simple compatibility calculation based on population similarity
|
||||||
|
var populationDifference = Math.Abs(kingdom1Active - kingdom2Active);
|
||||||
|
var maxPopulation = Math.Max(kingdom1Active, kingdom2Active);
|
||||||
|
|
||||||
|
if (maxPopulation == 0) return 0.5; // Default score for empty kingdoms
|
||||||
|
|
||||||
|
var compatibilityScore = 1.0 - (populationDifference / (double)maxPopulation);
|
||||||
|
return Math.Max(0.0, Math.Min(1.0, compatibilityScore));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(ex, "Error calculating KvK compatibility score, returning default");
|
||||||
|
return 0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private double CalculateMergerCompatibilityScore(int currentPop, int otherPop, KingdomModel currentKingdom, KingdomModel otherKingdom)
|
||||||
|
{
|
||||||
|
// Population size balance (prefer similar sizes)
|
||||||
|
var totalSize = currentPop + otherPop;
|
||||||
|
var sizeBalance = 1.0 - Math.Abs(currentPop - otherPop) / (double)Math.Max(currentPop, otherPop);
|
||||||
|
|
||||||
|
// Optimal total size (prefer mergers that result in viable kingdom size 800-1200)
|
||||||
|
var sizeOptimality = totalSize >= 800 && totalSize <= 1200 ?
|
||||||
|
1.0 : Math.Max(0, (1500 - totalSize) / 300.0);
|
||||||
|
|
||||||
|
return (sizeBalance + sizeOptimality) / 2.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string[] CalculateMergerBenefits(KingdomModel kingdom, int currentPop, int otherPop)
|
||||||
|
{
|
||||||
|
var benefits = new List<string>();
|
||||||
|
|
||||||
|
benefits.Add($"Combined population: {currentPop + otherPop}");
|
||||||
|
benefits.Add("Increased alliance diversity");
|
||||||
|
benefits.Add("Enhanced KvK competitiveness");
|
||||||
|
|
||||||
|
if (kingdom.CurrentPowerRank < 50)
|
||||||
|
{
|
||||||
|
benefits.Add("Access to high-ranking kingdom benefits");
|
||||||
|
}
|
||||||
|
|
||||||
|
return benefits.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
private int CalculatePercentile(int value, int totalCount)
|
private int CalculatePercentile(int value, int totalCount)
|
||||||
{
|
{
|
||||||
if (totalCount == 0) return 50;
|
if (totalCount == 0) return 50;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user