From f11e5e274b2beb0c90249e98c9cfd1df373e07a3 Mon Sep 17 00:00:00 2001 From: sanchezvem Date: Thu, 14 May 2026 18:16:19 +0100 Subject: [PATCH] Added AchievementService.cs for gestion of achievements --- .../GetAllAchievementsEndpoint.cs | 18 --- .../GetLockedAchievementsEndpoint.cs | 27 ---- .../Achievements/UnlockAchievementEndpoint.cs | 50 ------ .../Friends/GetAllFriendRequestsEndpoint.cs | 3 +- .../Friends/GetAllFriendsEndpoint.cs | 4 +- .../Endpoints/Users/GetUserDetailsEndpoint.cs | 4 +- BeReadyBackend/Services/AchievementService.cs | 144 ++++++++++++++++++ .../GetAchievementUnlockedSpec.cs | 13 ++ .../Achievements/GetLockedAchievementsSpec.cs | 13 -- .../Posts/GetPostsLikedByUserSpec.cs | 13 ++ 10 files changed, 175 insertions(+), 114 deletions(-) delete mode 100644 BeReadyBackend/Endpoints/Achievements/GetAllAchievementsEndpoint.cs delete mode 100644 BeReadyBackend/Endpoints/Achievements/GetLockedAchievementsEndpoint.cs delete mode 100644 BeReadyBackend/Endpoints/Achievements/UnlockAchievementEndpoint.cs create mode 100644 BeReadyBackend/Services/AchievementService.cs create mode 100644 BeReadyBackend/Specifications/Achievements/GetAchievementUnlockedSpec.cs delete mode 100644 BeReadyBackend/Specifications/Achievements/GetLockedAchievementsSpec.cs create mode 100644 BeReadyBackend/Specifications/Posts/GetPostsLikedByUserSpec.cs diff --git a/BeReadyBackend/Endpoints/Achievements/GetAllAchievementsEndpoint.cs b/BeReadyBackend/Endpoints/Achievements/GetAllAchievementsEndpoint.cs deleted file mode 100644 index c536de4..0000000 --- a/BeReadyBackend/Endpoints/Achievements/GetAllAchievementsEndpoint.cs +++ /dev/null @@ -1,18 +0,0 @@ -using BeReadyBackend.DTO.Achievements; -using BeReadyBackend.Repositories; -using FastEndpoints; - -namespace BeReadyBackend.Endpoints.Achievements; - -public class GetAllAchievementsEndpoint(AchievementsRepository achievementsRepository) : EndpointWithoutRequest> -{ - public override void Configure() - { - Get("/Achievements/"); - } - - public override async Task HandleAsync(CancellationToken ct) - { - await Send.OkAsync(await achievementsRepository.ProjectToListAsync(ct), ct); - } -} \ No newline at end of file diff --git a/BeReadyBackend/Endpoints/Achievements/GetLockedAchievementsEndpoint.cs b/BeReadyBackend/Endpoints/Achievements/GetLockedAchievementsEndpoint.cs deleted file mode 100644 index 09f59bf..0000000 --- a/BeReadyBackend/Endpoints/Achievements/GetLockedAchievementsEndpoint.cs +++ /dev/null @@ -1,27 +0,0 @@ -using BeReadyBackend.DTO.Achievements; -using BeReadyBackend.Repositories; -using BeReadyBackend.Services; -using BeReadyBackend.Specifications.Achievements; -using FastEndpoints; - -namespace BeReadyBackend.Endpoints.Achievements; - -public class GetLockedAchievementsEndpoint( - AchievementsRepository achievementsRepository, - UserService userService) - : EndpointWithoutRequest> -{ - public override void Configure() - { - Get("/Achievements/Locked/Users/"); - } - - public override async Task HandleAsync(CancellationToken ct) - { - int userId = userService.GetUserIdFromToken(); - - List achievementsLocked = await achievementsRepository.ProjectToListAsync(new GetLockedAchievementsSpec(userId), ct); - - await Send.OkAsync(achievementsLocked, ct); - } -} \ No newline at end of file diff --git a/BeReadyBackend/Endpoints/Achievements/UnlockAchievementEndpoint.cs b/BeReadyBackend/Endpoints/Achievements/UnlockAchievementEndpoint.cs deleted file mode 100644 index e386ca2..0000000 --- a/BeReadyBackend/Endpoints/Achievements/UnlockAchievementEndpoint.cs +++ /dev/null @@ -1,50 +0,0 @@ -using BeReadyBackend.DTO.Achievements; -using BeReadyBackend.Models; -using BeReadyBackend.Repositories; -using BeReadyBackend.Services; -using BeReadyBackend.Specifications.Achievements; -using BeReadyBackend.Specifications.UserAchievements; -using FastEndpoints; - -namespace BeReadyBackend.Endpoints.Achievements; - -public class UnlockAchievementEndpoint( - UserAchievementsRepository userAchievementsRepository, - AchievementsRepository achievementsRepository, - UserService userService) : Endpoint -{ - public override void Configure() - { - Post("/Achievements/{@AchievementId}/Users/", x => new { x.AchievementId }); - Description(x => x.Accepts()); - } - - public override async Task HandleAsync(UnlockAchievementDto req, CancellationToken ct) - { - int userId = userService.GetUserIdFromToken(); - - Achievement? achievement = await achievementsRepository.SingleOrDefaultAsync(new GetAchievementByIdSpec(req.AchievementId), ct); - - if (achievement is null) - { - await Send.NotFoundAsync(ct); - return; - } - - UserAchievement? userAchievement = await userAchievementsRepository.SingleOrDefaultAsync(new GetUserAchievementByIdSpec(userId, req.AchievementId), ct); - if (userAchievement is not null) - { - await Send.StringAsync("Le succès est déjà attribué à cet utilisateur", 500, cancellation: ct); - return; - } - - userAchievement = new UserAchievement - { - UserId = userId, - AchievementId = req.AchievementId - }; - - await userAchievementsRepository.AddAsync(userAchievement, ct); - await Send.NoContentAsync(ct); - } -} \ No newline at end of file diff --git a/BeReadyBackend/Endpoints/Friends/GetAllFriendRequestsEndpoint.cs b/BeReadyBackend/Endpoints/Friends/GetAllFriendRequestsEndpoint.cs index cb02124..63944dd 100644 --- a/BeReadyBackend/Endpoints/Friends/GetAllFriendRequestsEndpoint.cs +++ b/BeReadyBackend/Endpoints/Friends/GetAllFriendRequestsEndpoint.cs @@ -6,8 +6,7 @@ using FastEndpoints; namespace BeReadyBackend.Endpoints.Friends; -public class GetAllFriendRequestsEndpoint(UserFriendsRepository userFriendsRepository, UserService userService, AutoMapper.IMapper mapper) - : EndpointWithoutRequest> +public class GetAllFriendRequestsEndpoint(UserFriendsRepository userFriendsRepository, UserService userService): EndpointWithoutRequest> { public override void Configure() { diff --git a/BeReadyBackend/Endpoints/Friends/GetAllFriendsEndpoint.cs b/BeReadyBackend/Endpoints/Friends/GetAllFriendsEndpoint.cs index 997e6c2..bc315bc 100644 --- a/BeReadyBackend/Endpoints/Friends/GetAllFriendsEndpoint.cs +++ b/BeReadyBackend/Endpoints/Friends/GetAllFriendsEndpoint.cs @@ -6,8 +6,7 @@ using FastEndpoints; namespace BeReadyBackend.Endpoints.Friends; -public class GetAllFriendsEndpoint(UserFriendsRepository userFriendsRepository, UsersRepository usersRepository, UserService userService, AutoMapper.IMapper mapper) - : EndpointWithoutRequest> +public class GetAllFriendsEndpoint(UserFriendsRepository userFriendsRepository, UserService userService) : EndpointWithoutRequest> { public override void Configure() { @@ -17,7 +16,6 @@ public class GetAllFriendsEndpoint(UserFriendsRepository userFriendsRepository, public override async Task HandleAsync(CancellationToken ct) { int userId = userService.GetUserIdFromToken(); - await Send.OkAsync(await userFriendsRepository.ProjectToListAsync(new GetFriendsByUserIdSpec(userId), ct), ct); } } \ No newline at end of file diff --git a/BeReadyBackend/Endpoints/Users/GetUserDetailsEndpoint.cs b/BeReadyBackend/Endpoints/Users/GetUserDetailsEndpoint.cs index ccdf323..a0c4370 100644 --- a/BeReadyBackend/Endpoints/Users/GetUserDetailsEndpoint.cs +++ b/BeReadyBackend/Endpoints/Users/GetUserDetailsEndpoint.cs @@ -7,7 +7,8 @@ using FastEndpoints; namespace BeReadyBackend.Endpoints.Users; -public class GetUserDetailsEndpoint(UsersRepository usersRepository, UserService userService, AutoMapper.IMapper mapper) : EndpointWithoutRequest +public class GetUserDetailsEndpoint(UsersRepository usersRepository, UserService userService, AutoMapper.IMapper mapper, AchievementService achievementService) + : EndpointWithoutRequest { public override void Configure() { @@ -18,6 +19,7 @@ public class GetUserDetailsEndpoint(UsersRepository usersRepository, UserService { int userId = userService.GetUserIdFromToken(); User? user = await usersRepository.SingleOrDefaultAsync(new GetUserByIdSpec(userId), ct); + await achievementService.CheckAchievement(userId); await Send.OkAsync(mapper.Map(user), ct); } diff --git a/BeReadyBackend/Services/AchievementService.cs b/BeReadyBackend/Services/AchievementService.cs new file mode 100644 index 0000000..20305f4 --- /dev/null +++ b/BeReadyBackend/Services/AchievementService.cs @@ -0,0 +1,144 @@ +using BeReadyBackend.Models; +using BeReadyBackend.Repositories; +using BeReadyBackend.Specifications.Achievements; +using BeReadyBackend.Specifications.Friends; +using BeReadyBackend.Specifications.Posts; +using BeReadyBackend.Specifications.UserAchievements; +using BeReadyBackend.Specifications.Users; + +namespace BeReadyBackend.Services; + +public class AchievementService( + UsersRepository usersRepository, + AchievementsRepository achievementsRepository, + UserAchievementsRepository userAchievementsRepository, + UserPostsRepository userPostsRepository, + UserFriendsRepository userFriendsRepository) +{ + public async Task Unlock(int userId, int achievementId) + { + Achievement? achievement = await achievementsRepository.SingleOrDefaultAsync(new GetAchievementByIdSpec(achievementId)); + + if (achievement is null) return; + + bool alreadyUnlocked = await userAchievementsRepository.CountAsync(new GetUserAchievementByIdSpec(userId, achievement.Id)) > 0; + + if (alreadyUnlocked) return; + + UserAchievement userAchievement = new() + { + UserId = userId, + AchievementId = achievement.Id + }; + + await userAchievementsRepository.AddAsync(userAchievement); + } + + public async Task CheckAchievement(int userId) + { + User? user = await usersRepository.SingleOrDefaultAsync(new GetUserByIdSpec(userId)); + if (user is null) return; + + int challengesCounter = await usersRepository.CountAsync(new GetProofOrChallengeByUserIdSpec(userId)); + int likedCounter = await userPostsRepository.CountAsync(new GetPostsLikedByUserSpec(userId)); + int friendsCounter = await userFriendsRepository.CountAsync(new GetFriendsByUserIdSpec(userId)); + int friendsRequestsCounter = await userFriendsRepository.CountAsync(new GetFriendRequestSpec(userId)); + int achievementsCounter = await userAchievementsRepository.CountAsync(new GetAchievementUnlockedSpec(userId)); + + switch (challengesCounter) + { + case 1: + await Unlock(userId, 1); + break; + case 10: + await Unlock(userId, 12); + break; + case 20: + await Unlock(userId, 3); + break; + case 50: + await Unlock(userId, 29); + break; + case 100: + await Unlock(userId, 32); + break; + } + + switch (user.Series) + { + case 5: + await Unlock(userId, 2); + break; + case 7: + await Unlock(userId, 39); + break; + case 10: + await Unlock(userId, 4); + break; + case 30: + await Unlock(userId, 40); + break; + } + + switch (likedCounter) + { + case 50: + await Unlock(userId, 37); + break; + case 100: + await Unlock(userId, 9); + break; + case 200: + await Unlock(userId, 38); + break; + } + + switch (user.TotalLikes) + { + case 50: + await Unlock(userId, 13); + break; + case 500: + await Unlock(userId, 44); + break; + case 1000: + await Unlock(userId, 33); + break; + } + + switch (friendsCounter) + { + case 5: + await Unlock(userId, 18); + break; + case 10: + await Unlock(userId, 19); + break; + case 20: + await Unlock(userId, 36); + break; + } + + switch (friendsRequestsCounter) + { + case 10: + await Unlock(userId, 21); + break; + } + + switch (achievementsCounter) + { + case 5: + await Unlock(userId,22); + break; + case 20: + await Unlock(userId, 23); + break; + case 23: + await Unlock(userId, 46); + break; + } + + if (DateTime.Now >= DateTime.Today.AddHours(20)) await Unlock(userId, 25); + } +} \ No newline at end of file diff --git a/BeReadyBackend/Specifications/Achievements/GetAchievementUnlockedSpec.cs b/BeReadyBackend/Specifications/Achievements/GetAchievementUnlockedSpec.cs new file mode 100644 index 0000000..34b56f3 --- /dev/null +++ b/BeReadyBackend/Specifications/Achievements/GetAchievementUnlockedSpec.cs @@ -0,0 +1,13 @@ +using Ardalis.Specification; +using BeReadyBackend.Models; + +namespace BeReadyBackend.Specifications.Achievements; + +public class GetAchievementUnlockedSpec : Specification +{ + public GetAchievementUnlockedSpec(int userId) + { + Query + .Where(x => x.UserId == userId); + } +} \ No newline at end of file diff --git a/BeReadyBackend/Specifications/Achievements/GetLockedAchievementsSpec.cs b/BeReadyBackend/Specifications/Achievements/GetLockedAchievementsSpec.cs deleted file mode 100644 index 54fa353..0000000 --- a/BeReadyBackend/Specifications/Achievements/GetLockedAchievementsSpec.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Ardalis.Specification; -using BeReadyBackend.Models; - -namespace BeReadyBackend.Specifications.Achievements; - -public class GetLockedAchievementsSpec : Specification -{ - public GetLockedAchievementsSpec(int userId) - { - Query - .Where(x => x.UserAchievements != null && x.UserAchievements.All(y => y.UserId != userId)); - } -} \ No newline at end of file diff --git a/BeReadyBackend/Specifications/Posts/GetPostsLikedByUserSpec.cs b/BeReadyBackend/Specifications/Posts/GetPostsLikedByUserSpec.cs new file mode 100644 index 0000000..0f3de9d --- /dev/null +++ b/BeReadyBackend/Specifications/Posts/GetPostsLikedByUserSpec.cs @@ -0,0 +1,13 @@ +using Ardalis.Specification; +using BeReadyBackend.Models; + +namespace BeReadyBackend.Specifications.Posts; + +public class GetPostsLikedByUserSpec : Specification +{ + public GetPostsLikedByUserSpec(int userId) + { + Query + .Where(x => x.UserId == userId); + } +} \ No newline at end of file