Добавил слой Infrastructure
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using UniVerse.Application.DTOs.Achievements;
|
||||
using UniVerse.Application.DTOs.Common;
|
||||
using UniVerse.Application.DTOs.Gamification;
|
||||
using UniVerse.Application.Interfaces;
|
||||
using UniVerse.Application.Mappings;
|
||||
using UniVerse.Domain.Entities;
|
||||
using UniVerse.Domain.Enums;
|
||||
using UniVerse.Infrastructure.Data;
|
||||
|
||||
namespace UniVerse.Infrastructure.Services;
|
||||
|
||||
public class GamificationService : IGamificationService
|
||||
{
|
||||
private readonly AppDbContext _db;
|
||||
private readonly IConfiguration _config;
|
||||
private readonly ILogger<GamificationService> _logger;
|
||||
|
||||
public GamificationService(AppDbContext db, IConfiguration config, ILogger<GamificationService> logger)
|
||||
{
|
||||
_db = db; _config = config; _logger = logger;
|
||||
}
|
||||
|
||||
public async Task AwardCoinsAsync(int userId, int amount, CoinTransactionType type,
|
||||
int? reviewId = null, int? achievementId = null, string? description = null)
|
||||
{
|
||||
var user = await _db.Users.FindAsync(userId);
|
||||
if (user == null) return;
|
||||
user.Coins += amount;
|
||||
user.Xp += amount;
|
||||
_db.CoinTransactions.Add(new CoinTransaction
|
||||
{
|
||||
UserId = userId, Amount = amount, Type = type,
|
||||
ReviewId = reviewId, AchievementId = achievementId, Description = description
|
||||
});
|
||||
await _db.SaveChangesAsync();
|
||||
_logger.LogInformation("Awarded {Amount} coins to user {UserId} ({Type})", amount, userId, type);
|
||||
}
|
||||
|
||||
public async Task CheckAndAwardAchievementsAsync(int userId)
|
||||
{
|
||||
var achievements = await _db.Achievements.ToListAsync();
|
||||
var existing = await _db.UserAchievements.Where(ua => ua.UserId == userId)
|
||||
.Select(ua => ua.AchievementId).ToListAsync();
|
||||
var reviews = await _db.Reviews.CountAsync(r => r.UserId == userId);
|
||||
var attended = await _db.LectureEnrollments.CountAsync(e => e.UserId == userId && e.Attended);
|
||||
|
||||
foreach (var achievement in achievements.Where(a => !existing.Contains(a.Id)))
|
||||
{
|
||||
var earned = achievement.Condition switch
|
||||
{
|
||||
"reviews_1" => reviews >= 1,
|
||||
"reviews_5" => reviews >= 5,
|
||||
"reviews_10" => reviews >= 10,
|
||||
"attended_5" => attended >= 5,
|
||||
"attended_10" => attended >= 10,
|
||||
_ => false
|
||||
};
|
||||
if (!earned) continue;
|
||||
_db.UserAchievements.Add(new UserAchievement { UserId = userId, AchievementId = achievement.Id });
|
||||
if (achievement.CoinReward > 0)
|
||||
await AwardCoinsAsync(userId, achievement.CoinReward, CoinTransactionType.AchievementReward,
|
||||
achievementId: achievement.Id, description: $"Achievement: {achievement.Name}");
|
||||
}
|
||||
await _db.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public int CalculateLevel(int xp)
|
||||
{
|
||||
var thresholds = _config.GetSection("Gamification:XpThresholds").Get<int[]>()
|
||||
?? [0, 100, 300, 600, 1000, 1500, 2500, 4000];
|
||||
for (int i = thresholds.Length - 1; i >= 0; i--)
|
||||
if (xp >= thresholds[i]) return i + 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
public async Task<List<UserAchievementDto>> GetUserAchievementsAsync(int userId) =>
|
||||
await _db.UserAchievements.Include(ua => ua.Achievement)
|
||||
.Where(ua => ua.UserId == userId).OrderByDescending(ua => ua.AwardedAt)
|
||||
.Select(ua => ua.ToDto()).ToListAsync();
|
||||
|
||||
public async Task<PagedResult<CoinTransactionDto>> GetTransactionsAsync(int userId, PaginationRequest pagination)
|
||||
{
|
||||
var query = _db.CoinTransactions.Where(ct => ct.UserId == userId);
|
||||
var total = await query.CountAsync();
|
||||
var items = await query.OrderByDescending(ct => ct.CreatedAt)
|
||||
.Skip((pagination.Page - 1) * pagination.PageSize).Take(pagination.PageSize)
|
||||
.Select(ct => ct.ToDto()).ToListAsync();
|
||||
return PagedResult<CoinTransactionDto>.Create(items, total, pagination.Page, pagination.PageSize);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user