refactor: removed unused interfaces

This commit is contained in:
2025-09-30 19:07:00 +03:00
parent 63cee70753
commit dcbdb393cf
5 changed files with 0 additions and 336 deletions

View File

@@ -1,15 +0,0 @@
using LctMonolith.Models.Database;
using LctMonolith.Services.Models;
namespace LctMonolith.Services.Contracts;
/// <summary>Gamification progression logic (progress, rewards, rank evaluation).</summary>
public interface IGamificationService
{
/// <summary>Get current user progression snapshot (xp, mana, next rank requirements).</summary>
Task<ProgressSnapshot> GetProgressAsync(Guid userId, CancellationToken ct = default);
/// <summary>Apply mission completion rewards (xp, mana, skills, artifacts) to user.</summary>
Task ApplyMissionCompletionAsync(Guid userId, Mission mission, CancellationToken ct = default);
/// <summary>Re-evaluate and apply rank upgrade if requirements are met.</summary>
Task EvaluateRankUpgradeAsync(Guid userId, CancellationToken ct = default);
}

View File

@@ -1,11 +0,0 @@
using LctMonolith.Models.Database;
using LctMonolith.Services.Models;
namespace LctMonolith.Services.Contracts;
public interface IMissionService
{
Task<Mission> CreateMissionAsync(CreateMissionModel model, CancellationToken ct = default);
Task<IEnumerable<Mission>> GetAvailableMissionsAsync(Guid userId, CancellationToken ct = default);
Task<UserMission> UpdateStatusAsync(Guid userId, Guid missionId, MissionStatus status, string? submissionData, CancellationToken ct = default);
}

View File

@@ -1,162 +0,0 @@
using System.Linq;
using LctMonolith.Database.UnitOfWork;
using LctMonolith.Models.Database;
using LctMonolith.Services.Contracts;
using LctMonolith.Services.Models;
using Microsoft.EntityFrameworkCore;
using Serilog;
namespace LctMonolith.Services;
/// <summary>
/// Handles progression logic: mission completion rewards and rank advancement evaluation.
/// </summary>
public class GamificationService : IGamificationService
{
private readonly IUnitOfWork _uow;
private readonly INotificationService _notifications;
public GamificationService(IUnitOfWork uow, INotificationService notifications)
{
_uow = uow;
_notifications = notifications;
}
public async Task<ProgressSnapshot> GetProgressAsync(Guid userId, CancellationToken ct = default)
{
var user = await _uow.Users
.Query(u => u.Id == userId, null, u => u.Rank, u => u.Competencies)
.FirstOrDefaultAsync(ct) ?? throw new KeyNotFoundException("User not found");
var ranks = await _uow.Ranks
.Query(null, q => q.OrderBy(r => r.Order), r => r.RequiredMissions, r => r.RequiredCompetencies)
.ToListAsync(ct);
var currentOrder = user.Rank?.Order ?? -1;
var nextRank = ranks.FirstOrDefault(r => r.Order == currentOrder + 1);
var snapshot = new ProgressSnapshot
{
Experience = user.Experience,
Mana = user.Mana,
CurrentRankId = user.RankId,
CurrentRankName = user.Rank?.Name,
NextRankId = nextRank?.Id,
NextRankName = nextRank?.Name,
RequiredExperienceForNextRank = nextRank?.RequiredExperience
};
if (nextRank != null)
{
// Outstanding missions
var userMissionIds = await _uow.UserMissions.Query(um => um.UserId == userId).Select(um => um.MissionId).ToListAsync(ct);
foreach (var rm in nextRank.RequiredMissions)
{
if (!userMissionIds.Contains(rm.MissionId))
snapshot.OutstandingMissionIds.Add(rm.MissionId);
}
// Outstanding competencies
foreach (var rc in nextRank.RequiredCompetencies)
{
var userComp = user.Competencies.FirstOrDefault(c => c.CompetencyId == rc.CompetencyId);
var level = userComp?.Level ?? 0;
if (level < rc.MinLevel)
{
snapshot.OutstandingCompetencies.Add(new OutstandingCompetency
{
CompetencyId = rc.CompetencyId,
CompetencyName = rc.Competency?.Name,
RequiredLevel = rc.MinLevel,
CurrentLevel = level
});
}
}
}
return snapshot;
}
public async Task ApplyMissionCompletionAsync(Guid userId, Mission mission, CancellationToken ct = default)
{
var user = await _uow.Users
.Query(u => u.Id == userId, null, u => u.Competencies, u => u.Rank)
.FirstOrDefaultAsync(ct) ?? throw new KeyNotFoundException("User not found");
user.Experience += mission.ExperienceReward;
user.Mana += mission.ManaReward;
user.UpdatedAt = DateTime.UtcNow;
// Competency rewards
var compRewards = await _uow.MissionCompetencyRewards.Query(m => m.MissionId == mission.Id).ToListAsync(ct);
foreach (var reward in compRewards)
{
var uc = user.Competencies.FirstOrDefault(c => c.CompetencyId == reward.CompetencyId);
if (uc == null)
{
uc = new UserCompetency
{
UserId = userId,
CompetencyId = reward.CompetencyId,
Level = reward.LevelDelta,
ProgressPoints = reward.ProgressPointsDelta
};
await _uow.UserCompetencies.AddAsync(uc, ct);
}
else
{
uc.Level += reward.LevelDelta;
uc.ProgressPoints += reward.ProgressPointsDelta;
}
}
// Artifacts
var artRewards = await _uow.MissionArtifactRewards.Query(m => m.MissionId == mission.Id).ToListAsync(ct);
foreach (var ar in artRewards)
{
var existing = await _uow.UserArtifacts.FindAsync(userId, ar.ArtifactId);
if (existing == null)
{
await _uow.UserArtifacts.AddAsync(new UserArtifact
{
UserId = userId,
ArtifactId = ar.ArtifactId,
ObtainedAt = DateTime.UtcNow
}, ct);
}
}
await _uow.SaveChangesAsync(ct);
await EvaluateRankUpgradeAsync(userId, ct);
}
public async Task EvaluateRankUpgradeAsync(Guid userId, CancellationToken ct = default)
{
var user = await _uow.Users
.Query(u => u.Id == userId, null, u => u.Rank, u => u.Competencies)
.FirstOrDefaultAsync(ct) ?? throw new KeyNotFoundException("User not found");
var ranks = await _uow.Ranks
.Query(null, q => q.OrderBy(r => r.Order), r => r.RequiredMissions, r => r.RequiredCompetencies)
.ToListAsync(ct);
var currentOrder = user.Rank?.Order ?? -1;
var nextRank = ranks.FirstOrDefault(r => r.Order == currentOrder + 1);
if (nextRank == null) return;
if (user.Experience < nextRank.RequiredExperience) return;
var completedMissionIds = await _uow.UserMissions
.Query(um => um.UserId == userId && um.Status == MissionStatus.Completed)
.Select(x => x.MissionId)
.ToListAsync(ct);
if (nextRank.RequiredMissions.Any(rm => !completedMissionIds.Contains(rm.MissionId))) return;
foreach (var rc in nextRank.RequiredCompetencies)
{
var uc = user.Competencies.FirstOrDefault(c => c.CompetencyId == rc.CompetencyId);
if (uc == null || uc.Level < rc.MinLevel)
return;
}
user.RankId = nextRank.Id;
user.Rank = nextRank;
user.UpdatedAt = DateTime.UtcNow;
await _uow.SaveChangesAsync(ct);
Log.Information("User {UserId} promoted to rank {Rank}", userId, nextRank.Name);
await _notifications.CreateAsync(userId, "rank", "Повышение ранга", $"Вы получили ранг '{nextRank.Name}'", ct);
}
}

View File

@@ -1,35 +0,0 @@
using LctMonolith.Database.UnitOfWork;
using LctMonolith.Models.Database;
using LctMonolith.Services.Contracts;
using Microsoft.EntityFrameworkCore;
namespace LctMonolith.Services;
/// <summary>
/// Provides read-only access to user-owned inventory (store items and artifacts).
/// </summary>
public class InventoryService : IInventoryService
{
private readonly IUnitOfWork _uow;
public InventoryService(IUnitOfWork uow)
{
_uow = uow;
}
public async Task<IEnumerable<UserInventoryItem>> GetStoreInventoryAsync(Guid userId, CancellationToken ct = default)
{
return await _uow.UserInventoryItems
.Query(ii => ii.UserId == userId, null, ii => ii.StoreItem)
.OrderByDescending(i => i.AcquiredAt)
.ToListAsync(ct);
}
public async Task<IEnumerable<UserArtifact>> GetArtifactsAsync(Guid userId, CancellationToken ct = default)
{
return await _uow.UserArtifacts
.Query(a => a.UserId == userId, null, a => a.Artifact)
.OrderByDescending(a => a.ObtainedAt)
.ToListAsync(ct);
}
}

View File

@@ -1,113 +0,0 @@
using LctMonolith.Models.Database;
using LctMonolith.Services.Models;
using Microsoft.EntityFrameworkCore;
using Serilog;
using System.Text.Json;
using System.Linq;
using LctMonolith.Database.UnitOfWork;
using LctMonolith.Services.Contracts;
namespace LctMonolith.Services;
/// <summary>
/// Mission management and user mission state transitions.
/// </summary>
public class MissionService : IMissionService
{
private readonly IUnitOfWork _uow;
private readonly IGamificationService _gamification;
public MissionService(IUnitOfWork uow, IGamificationService gamification)
{
_uow = uow;
_gamification = gamification;
}
public async Task<Mission> CreateMissionAsync(CreateMissionModel model, CancellationToken ct = default)
{
var mission = new Mission
{
Title = model.Title,
Description = model.Description,
Branch = model.Branch,
Category = model.Category,
MinRankId = model.MinRankId,
ExperienceReward = model.ExperienceReward,
ManaReward = model.ManaReward,
IsActive = true
};
await _uow.Missions.AddAsync(mission, ct);
foreach (var cr in model.CompetencyRewards)
{
await _uow.MissionCompetencyRewards.AddAsync(new MissionCompetencyReward
{
MissionId = mission.Id,
CompetencyId = cr.CompetencyId,
LevelDelta = cr.LevelDelta,
ProgressPointsDelta = cr.ProgressPointsDelta
}, ct);
}
foreach (var artId in model.ArtifactRewardIds.Distinct())
{
await _uow.MissionArtifactRewards.AddAsync(new MissionArtifactReward
{
MissionId = mission.Id,
ArtifactId = artId
}, ct);
}
await _uow.SaveChangesAsync(ct);
await LogEventAsync(EventType.MissionStatusChanged, null, new { action = "created", missionId = mission.Id }, ct);
return mission;
}
public async Task<IEnumerable<Mission>> GetAvailableMissionsAsync(Guid userId, CancellationToken ct = default)
{
var user = await _uow.Users.Query(u => u.Id == userId, null, u => u.Rank).FirstOrDefaultAsync(ct)
?? throw new KeyNotFoundException("User not found");
var missions = await _uow.Missions.Query(m => m.IsActive, null, m => m.MinRank).ToListAsync(ct);
var userOrder = user.Rank?.Order ?? int.MinValue;
return missions.Where(m => m.MinRank == null || m.MinRank.Order <= userOrder + 1);
}
public async Task<UserMission> UpdateStatusAsync(Guid userId, Guid missionId, MissionStatus status, string? submissionData, CancellationToken ct = default)
{
var mission = await _uow.Missions.Query(m => m.Id == missionId).FirstOrDefaultAsync(ct)
?? throw new KeyNotFoundException("Mission not found");
var userMission = await _uow.UserMissions.FindAsync(userId, missionId);
if (userMission == null)
{
userMission = new UserMission
{
UserId = userId,
MissionId = missionId,
Status = MissionStatus.Available
};
await _uow.UserMissions.AddAsync(userMission, ct);
}
userMission.Status = status;
userMission.SubmissionData = submissionData;
userMission.UpdatedAt = DateTime.UtcNow;
await _uow.SaveChangesAsync(ct);
await LogEventAsync(EventType.MissionStatusChanged, userId, new { missionId, status }, ct);
if (status == MissionStatus.Completed)
{
await _gamification.ApplyMissionCompletionAsync(userId, mission, ct);
await LogEventAsync(EventType.RewardGranted, userId, new { missionId, mission.ExperienceReward, mission.ManaReward }, ct);
}
return userMission;
}
private async Task LogEventAsync(EventType type, Guid? userId, object data, CancellationToken ct)
{
if (userId == null && type != EventType.MissionStatusChanged) return;
var evt = new EventLog
{
Type = type,
UserId = userId ?? Guid.Empty,
Data = JsonSerializer.Serialize(data)
};
await _uow.EventLogs.AddAsync(evt, ct);
await _uow.SaveChangesAsync(ct);
Log.Debug("Event {Type} logged {Data}", type, evt.Data);
}
}