using Application.Abstractions.Data; using Application.Abstractions.Messaging; using Application.Abstractions.Paper; using Application.Helpers; using Microsoft.EntityFrameworkCore; namespace Application.Features.Api.Paper.GetMyLeaderboardRank; /// /// 내 리더보드 순위·지표 (인증) — 미등재(등재요건 미달·계좌/스냅샷 없음)면 HasRank=false (d4 M3 리더보드 백엔드 구현). /// internal sealed class Handler(IAppDbContext db, IPaperLeaderboardCache cache) : IQueryHandler { public async Task Handle(Query request, CancellationToken ct) { var sort = PaperLeaderboardMetrics.ParseSort(request.Sort); var period = PaperLeaderboardMetrics.ParsePeriod(request.Period); var sortStr = PaperLeaderboardMetrics.SortToString(sort); var periodStr = PaperLeaderboardMetrics.PeriodToString(period); var minFillsForRank = await db.Config.AsNoTracking().OrderByDescending(c => c.ID).Select(c => c.Paper.MinFillsForRank).FirstOrDefaultAsync(ct); if (minFillsForRank <= 0) { minFillsForRank = 3; } var my = await cache.GetMyRankAsync(sort, period, request.MemberID, db, minFillsForRank, ct); if (my is null) { return new Response(sortStr, periodStr, false, 0, 0, 0, 0, 0, 0); } var metrics = await PaperLeaderboardMetrics.ComputeAllAsync(db, period, minFillsForRank, ct); var metric = metrics.FirstOrDefault(c => c.MemberID == request.MemberID); return new Response( sortStr, periodStr, true, my.Rank + 1, my.Total, metric?.ReturnBp ?? 0, metric?.WinRateBp ?? 0, metric?.MddBp ?? 0, metric?.FillCount ?? 0); } }