< Summary

Information
Class: Chronicis.Api.Services.CharacterClaimService
Assembly: Chronicis.Api
File(s): /home/runner/work/chronicis/chronicis/src/Chronicis.Api/Services/CharacterClaimService.cs
Line coverage
100%
Covered lines: 2
Uncovered lines: 0
Coverable lines: 2
Total lines: 98
Line coverage: 100%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%

File(s)

/home/runner/work/chronicis/chronicis/src/Chronicis.Api/Services/CharacterClaimService.cs

#LineLine coverage
 1using Chronicis.Api.Data;
 2using Chronicis.Api.Models;
 3using Chronicis.Shared.DTOs;
 4using Chronicis.Shared.Enums;
 5using Microsoft.EntityFrameworkCore;
 6
 7namespace Chronicis.Api.Services;
 8
 9public sealed class CharacterClaimService : ICharacterClaimService
 10{
 11    private readonly ChronicisDbContext _context;
 12
 13    public CharacterClaimService(ChronicisDbContext context)
 14    {
 615        _context = context;
 616    }
 17
 18    public async Task<List<ClaimedCharacterDto>> GetClaimedCharactersAsync(Guid userId)
 19    {
 20        return await _context.Articles
 21            .Where(a => a.PlayerId == userId && a.Type == ArticleType.Character)
 22            .Where(a => a.WorldId.HasValue)
 23            .Select(a => new ClaimedCharacterDto
 24            {
 25                Id = a.Id,
 26                Title = a.Title ?? "Unnamed Character",
 27                IconEmoji = a.IconEmoji,
 28                WorldId = a.WorldId!.Value,
 29                WorldName = a.World != null ? a.World.Name : "Unknown World",
 30                ModifiedAt = a.ModifiedAt,
 31                CreatedAt = a.CreatedAt
 32            })
 33            .ToListAsync();
 34    }
 35
 36    public async Task<(bool Found, Guid? PlayerId, string? PlayerName)> GetClaimStatusAsync(Guid characterId)
 37    {
 38        var article = await _context.Articles
 39            .Where(a => a.Id == characterId && a.Type == ArticleType.Character)
 40            .Select(a => new
 41            {
 42                a.PlayerId,
 43                PlayerName = a.Player != null ? a.Player.DisplayName : null
 44            })
 45            .FirstOrDefaultAsync();
 46
 47        if (article == null)
 48        {
 49            return (false, null, null);
 50        }
 51
 52        return (true, article.PlayerId, article.PlayerName);
 53    }
 54
 55    public async Task<ServiceResult<bool>> ClaimCharacterAsync(Guid characterId, Guid userId)
 56    {
 57        var article = await _context.Articles
 58            .Where(a => a.Id == characterId && a.Type == ArticleType.Character)
 59            .Where(a => a.WorldId.HasValue && a.World!.Members.Any(m => m.UserId == userId))
 60            .FirstOrDefaultAsync();
 61
 62        if (article == null)
 63        {
 64            return ServiceResult<bool>.NotFound("Character not found or access denied");
 65        }
 66
 67        if (article.PlayerId.HasValue && article.PlayerId != userId)
 68        {
 69            return ServiceResult<bool>.Conflict("Character is already claimed by another player");
 70        }
 71
 72        article.PlayerId = userId;
 73        article.ModifiedAt = DateTime.UtcNow;
 74        await _context.SaveChangesAsync();
 75
 76        return ServiceResult<bool>.Success(true);
 77    }
 78
 79    public async Task<ServiceResult<bool>> UnclaimCharacterAsync(Guid characterId, Guid userId)
 80    {
 81        var article = await _context.Articles
 82            .Where(a => a.Id == characterId && a.Type == ArticleType.Character)
 83            .Where(a => a.PlayerId == userId)
 84            .FirstOrDefaultAsync();
 85
 86        if (article == null)
 87        {
 88            return ServiceResult<bool>.NotFound("Character not found or not claimed by you");
 89        }
 90
 91        article.PlayerId = null;
 92        article.ModifiedAt = DateTime.UtcNow;
 93        await _context.SaveChangesAsync();
 94
 95        return ServiceResult<bool>.Success(true);
 96    }
 97}
 98