fix: перенёс уровни в бд и пофиксид их отображение на фронте
Backend CI / build-and-test (push) Successful in 52s
Frontend CI / build-and-check (push) Failing after 5m15s
🚀 Create and publish a Docker image / Detect changes in backend and frontend (push) Successful in 16s
🚀 Create and publish a Docker image / Build & publish backend image (push) Successful in 1m0s
🚀 Create and publish a Docker image / Build & publish frontend image (push) Successful in 32s
🚀 Create and publish a Docker image / Update stack on Portainer (push) Successful in 13s
Backend CI / build-and-test (push) Successful in 52s
Frontend CI / build-and-check (push) Failing after 5m15s
🚀 Create and publish a Docker image / Detect changes in backend and frontend (push) Successful in 16s
🚀 Create and publish a Docker image / Build & publish backend image (push) Successful in 1m0s
🚀 Create and publish a Docker image / Build & publish frontend image (push) Successful in 32s
🚀 Create and publish a Docker image / Update stack on Portainer (push) Successful in 13s
This commit is contained in:
@@ -221,7 +221,7 @@ public class AuthService : IAuthService
|
||||
.Include(u => u.Roles)
|
||||
.FirstOrDefaultAsync(u => u.Id == userId)
|
||||
?? throw new NotFoundException("User", userId);
|
||||
return user.ToDto(_gamification.CalculateLevel(user.Xp));
|
||||
return user.ToDto(await _gamification.CalculateLevelAsync(user.Xp));
|
||||
}
|
||||
|
||||
private async Task TrySendLoginNotificationAsync(User user, string? ipAddress)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Globalization;
|
||||
using UniVerse.Application.DTOs.Achievements;
|
||||
@@ -17,17 +16,16 @@ namespace UniVerse.Infrastructure.Services;
|
||||
public class GamificationService : IGamificationService
|
||||
{
|
||||
private readonly AppDbContext _db;
|
||||
private readonly IConfiguration _config;
|
||||
private readonly INotificationService _notifications;
|
||||
private readonly ILogger<GamificationService> _logger;
|
||||
private List<LevelThreshold>? _levelThresholds;
|
||||
|
||||
public GamificationService(
|
||||
AppDbContext db,
|
||||
IConfiguration config,
|
||||
INotificationService notifications,
|
||||
ILogger<GamificationService> logger)
|
||||
{
|
||||
_db = db; _config = config; _notifications = notifications; _logger = logger;
|
||||
_db = db; _notifications = notifications; _logger = logger;
|
||||
}
|
||||
|
||||
public async Task AwardCoinsAsync(int userId, int amount, CoinTransactionType type,
|
||||
@@ -83,7 +81,7 @@ public class GamificationService : IGamificationService
|
||||
"attendance_streak_weeks" => attendanceStreakWeeks >= value,
|
||||
"attended_registered" => attended >= value,
|
||||
"coins_earned" => earnedCoins >= value,
|
||||
"level_reached" => CalculateLevel(user.Xp) >= value,
|
||||
"level_reached" => await CalculateLevelAsync(user.Xp) >= value,
|
||||
"profile_completed" => profileCompleted && value <= 1,
|
||||
"first_activity" => firstActivity && value <= 1,
|
||||
_ => false
|
||||
@@ -184,13 +182,47 @@ public class GamificationService : IGamificationService
|
||||
return DateOnly.FromDateTime(ISOWeek.ToDateTime(isoYear, isoWeek, DayOfWeek.Monday));
|
||||
}
|
||||
|
||||
public int CalculateLevel(int xp)
|
||||
public async Task<int> CalculateLevelAsync(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;
|
||||
var thresholds = await GetLevelThresholdsAsync();
|
||||
return thresholds
|
||||
.Where(t => xp >= t.RequiredXp)
|
||||
.OrderBy(t => t.RequiredXp)
|
||||
.ThenBy(t => t.Level)
|
||||
.LastOrDefault()?.Level ?? thresholds[0].Level;
|
||||
}
|
||||
|
||||
public async Task<LevelProgressDto> GetLevelProgressAsync(int xp)
|
||||
{
|
||||
var thresholds = await GetLevelThresholdsAsync();
|
||||
var current = thresholds
|
||||
.Where(t => xp >= t.RequiredXp)
|
||||
.OrderBy(t => t.RequiredXp)
|
||||
.ThenBy(t => t.Level)
|
||||
.LastOrDefault() ?? thresholds[0];
|
||||
var next = thresholds
|
||||
.Where(t => t.RequiredXp > current.RequiredXp)
|
||||
.OrderBy(t => t.RequiredXp)
|
||||
.ThenBy(t => t.Level)
|
||||
.FirstOrDefault();
|
||||
|
||||
return new LevelProgressDto(current.RequiredXp, next?.RequiredXp);
|
||||
}
|
||||
|
||||
private async Task<List<LevelThreshold>> GetLevelThresholdsAsync()
|
||||
{
|
||||
if (_levelThresholds is { Count: > 0 }) return _levelThresholds;
|
||||
|
||||
_levelThresholds = await _db.LevelThresholds
|
||||
.AsNoTracking()
|
||||
.OrderBy(t => t.RequiredXp)
|
||||
.ThenBy(t => t.Level)
|
||||
.ToListAsync();
|
||||
|
||||
if (_levelThresholds.Count == 0)
|
||||
_levelThresholds.Add(new LevelThreshold { Level = 1, RequiredXp = 0 });
|
||||
|
||||
return _levelThresholds;
|
||||
}
|
||||
|
||||
public async Task<List<UserAchievementDto>> GetUserAchievementsAsync(int userId) =>
|
||||
|
||||
@@ -26,7 +26,7 @@ public class UserService : IUserService
|
||||
.Include(u => u.Roles)
|
||||
.FirstOrDefaultAsync(u => u.Id == id)
|
||||
?? throw new NotFoundException("User", id);
|
||||
return user.ToDto(_gamification.CalculateLevel(user.Xp));
|
||||
return user.ToDto(await _gamification.CalculateLevelAsync(user.Xp));
|
||||
}
|
||||
|
||||
public async Task<UserDto> UpdateProfileAsync(int id, UpdateUserRequest request)
|
||||
@@ -42,7 +42,7 @@ public class UserService : IUserService
|
||||
|
||||
await _db.SaveChangesAsync();
|
||||
await _gamification.CheckAndAwardAchievementsAsync(id);
|
||||
return user.ToDto(_gamification.CalculateLevel(user.Xp));
|
||||
return user.ToDto(await _gamification.CalculateLevelAsync(user.Xp));
|
||||
}
|
||||
|
||||
public async Task<UserStatsDto> GetStatsAsync(int id)
|
||||
@@ -55,9 +55,13 @@ public class UserService : IUserService
|
||||
var reviews = await _db.Reviews.CountAsync(r => r.UserId == id);
|
||||
var achievements = await _db.UserAchievements.CountAsync(ua => ua.UserId == id);
|
||||
|
||||
var level = await _gamification.CalculateLevelAsync(user.Xp);
|
||||
var levelProgress = await _gamification.GetLevelProgressAsync(user.Xp);
|
||||
|
||||
return new UserStatsDto(
|
||||
totalLectures, attended, reviews,
|
||||
user.Xp, user.Coins, _gamification.CalculateLevel(user.Xp), achievements
|
||||
user.Xp, user.Coins, level, achievements,
|
||||
levelProgress.CurrentLevelXp, levelProgress.NextLevelXp
|
||||
);
|
||||
}
|
||||
|
||||
@@ -94,7 +98,10 @@ public class UserService : IUserService
|
||||
.Take(filter.PageSize)
|
||||
.ToListAsync();
|
||||
|
||||
var items = users.Select(u => u.ToDto(_gamification.CalculateLevel(u.Xp))).ToList();
|
||||
var items = new List<UserDto>(users.Count);
|
||||
foreach (var user in users)
|
||||
items.Add(user.ToDto(await _gamification.CalculateLevelAsync(user.Xp)));
|
||||
|
||||
return PagedResult<UserDto>.Create(items, total, filter.Page, filter.PageSize);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user