diff --git a/ShadowedRealmsMobile/src/server/ShadowedRealms.Core/Models/Player/Player.cs b/ShadowedRealmsMobile/src/server/ShadowedRealms.Core/Models/Player/Player.cs
index 08f43b4..dda2302 100644
--- a/ShadowedRealmsMobile/src/server/ShadowedRealms.Core/Models/Player/Player.cs
+++ b/ShadowedRealmsMobile/src/server/ShadowedRealms.Core/Models/Player/Player.cs
@@ -6,13 +6,14 @@
* 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.Kingdom;
using System.ComponentModel.DataAnnotations;
namespace ShadowedRealms.Core.Models.Player
{
- public class Player
+ public class Player : IKingdomScoped
{
public int Id { get; set; }
diff --git a/ShadowedRealmsMobile/src/server/ShadowedRealms.Data/Repositories/Kingdom/KingdomRepository.cs b/ShadowedRealmsMobile/src/server/ShadowedRealms.Data/Repositories/Kingdom/KingdomRepository.cs
index 7d80e2b..860a3d2 100644
--- a/ShadowedRealmsMobile/src/server/ShadowedRealms.Data/Repositories/Kingdom/KingdomRepository.cs
+++ b/ShadowedRealmsMobile/src/server/ShadowedRealms.Data/Repositories/Kingdom/KingdomRepository.cs
@@ -1,10 +1,10 @@
/*
* File: ShadowedRealms.Data/Repositories/Kingdom/KingdomRepository.cs
* 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,
* 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;
@@ -178,30 +178,32 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
}
///
- /// Gets kingdom population with optional active-only filter
+ /// Gets kingdom population breakdown with active/inactive/total counts
+ /// FIXED: Returns tuple matching interface signature exactly
///
- public async Task 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
{
- _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)
- {
- query = query.Where(p => p.IsActive);
- }
+ var inactivePlayers = await _context.Players
+ .CountAsync(p => p.KingdomId == kingdomId && !p.IsActive, cancellationToken);
- var count = await query.CountAsync(cancellationToken);
+ var totalPlayers = activePlayers + inactivePlayers;
- _logger.LogDebug("Kingdom {KingdomId} has population of {Count}", kingdomId, count);
- return count;
+ _logger.LogDebug("Kingdom {KingdomId} population: {Active} active, {Inactive} inactive, {Total} total",
+ kingdomId, activePlayers, inactivePlayers, totalPlayers);
+
+ return (activePlayers, inactivePlayers, totalPlayers);
}
catch (Exception ex)
{
- _logger.LogError(ex, "Error getting population for kingdom {KingdomId}", kingdomId);
- throw new InvalidOperationException($"Failed to get population for kingdom {kingdomId}", ex);
+ _logger.LogError(ex, "Error getting population breakdown for kingdom {KingdomId}", kingdomId);
+ 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);
- var currentPopulation = await GetKingdomPopulationAsync(kingdomId, true, cancellationToken);
+ var (activePlayers, _, _) = await GetKingdomPopulationAsync(kingdomId, false, cancellationToken);
const int maxMergedPopulation = 1500;
var candidates = new List();
@@ -224,8 +226,8 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
foreach (var kingdom in otherKingdoms)
{
- var otherPopulation = await GetKingdomPopulationAsync(kingdom.Id, true, cancellationToken);
- if (currentPopulation + otherPopulation <= maxMergedPopulation)
+ var (otherActive, _, _) = await GetKingdomPopulationAsync(kingdom.Id, false, cancellationToken);
+ if (activePlayers + otherActive <= maxMergedPopulation)
{
candidates.Add(kingdom);
}
@@ -242,9 +244,10 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
}
///
- /// Updates kingdom population count
+ /// Updates kingdom population count and returns updated kingdom entity
+ /// FIXED: Returns Kingdom entity matching interface signature exactly
///
- public async Task UpdateKingdomPopulationAsync(int kingdomId, int newPopulation, CancellationToken cancellationToken = default)
+ public async Task UpdateKingdomPopulationAsync(int kingdomId, int newPopulation, CancellationToken cancellationToken = default)
{
try
{
@@ -255,8 +258,7 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
if (kingdom == null)
{
- _logger.LogWarning("Kingdom {KingdomId} not found for population update", kingdomId);
- return false;
+ throw new InvalidOperationException($"Kingdom {kingdomId} not found");
}
kingdom.CurrentPopulation = newPopulation;
@@ -265,7 +267,7 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
await _context.SaveChangesAsync(cancellationToken);
_logger.LogDebug("Successfully updated kingdom {KingdomId} population to {NewPopulation}", kingdomId, newPopulation);
- return true;
+ return kingdom;
}
catch (Exception ex)
{
@@ -275,9 +277,10 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
}
///
- /// 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
///
- public async Task> GetKvKEligibleKingdomsAsync(int kingdomId, string eventType, CancellationToken cancellationToken = default)
+ public async Task> GetKvKEligibleKingdomsAsync(int kingdomId, string eventType, CancellationToken cancellationToken = default)
{
try
{
@@ -286,11 +289,21 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
var eligibleKingdoms = await _context.Kingdoms
.Where(k => k.Id != kingdomId && k.IsActive && !k.IsInKvK)
.Where(k => k.CurrentPopulation >= 500) // Minimum population for KvK
- .OrderBy(k => k.CurrentPowerRank)
.ToListAsync(cancellationToken);
- _logger.LogDebug("Found {Count} KvK eligible kingdoms", eligibleKingdoms.Count);
- return eligibleKingdoms;
+ var results = new List<(KingdomModel Kingdom, double CompatibilityScore)>();
+
+ 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)
{
@@ -392,9 +405,10 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
}
///
- /// 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
///
- public async Task UpdateKvKPerformanceAsync(int kingdomId, object battleResults, object performanceMetrics, CancellationToken cancellationToken = default)
+ public async Task UpdateKvKPerformanceAsync(int kingdomId, object battleResults, object performanceMetrics, CancellationToken cancellationToken = default)
{
try
{
@@ -405,8 +419,7 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
if (kingdom == null)
{
- _logger.LogWarning("Kingdom {KingdomId} not found for KvK performance update", kingdomId);
- return false;
+ throw new InvalidOperationException($"Kingdom {kingdomId} not found");
}
kingdom.LastActivity = DateTime.UtcNow;
@@ -415,7 +428,7 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
await _context.SaveChangesAsync(cancellationToken);
_logger.LogInformation("Successfully updated KvK performance for kingdom {KingdomId}", kingdomId);
- return true;
+ return kingdom;
}
catch (Exception ex)
{
@@ -464,18 +477,59 @@ namespace ShadowedRealms.Data.Repositories.Kingdom
}
///
- /// 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
///
- public async Task> GetMergerCompatibleKingdomsAsync(int kingdomId, CancellationToken cancellationToken = default)
+ public async Task> GetMergerCompatibleKingdomsAsync(int kingdomId, CancellationToken cancellationToken = default)
{
- // This is the same as GetKingdomsEligibleForMergerAsync
- return await GetKingdomsEligibleForMergerAsync(kingdomId, cancellationToken);
+ try
+ {
+ _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);
+ }
}
///
- /// Executes a kingdom merger
+ /// Executes a kingdom merger and returns the updated target kingdom
+ /// FIXED: Returns Kingdom entity matching interface signature exactly
///
- public async Task