Files
pos-system/services/mining-service-net/src/MiningService.API/Application/Queries/MiningQueries.cs

151 lines
4.8 KiB
C#

using MediatR;
using MiningService.Domain.AggregatesModel.MinerAggregate;
namespace MiningService.API.Application.Queries;
/// <summary>
/// EN: Query to get mining history for a user.
/// VI: Query để lấy lịch sử đào của người dùng.
/// </summary>
public record GetMiningHistoryQuery(Guid UserId, int Page = 1, int PageSize = 20) : IRequest<MiningHistoryDto>;
public record MiningHistoryDto(
List<MiningHistoryItemDto> Items,
int TotalCount,
int Page,
int PageSize);
public record MiningHistoryItemDto(
Guid Id,
decimal Amount,
string Source,
decimal RateSnapshot,
DateTime CreatedAt);
public class GetMiningHistoryQueryHandler : IRequestHandler<GetMiningHistoryQuery, MiningHistoryDto>
{
private readonly IMinerRepository _minerRepository;
public GetMiningHistoryQueryHandler(IMinerRepository minerRepository)
{
_minerRepository = minerRepository;
}
public async Task<MiningHistoryDto> Handle(GetMiningHistoryQuery request, CancellationToken cancellationToken)
{
var miner = await _minerRepository.GetByUserIdAsync(request.UserId, cancellationToken);
if (miner == null)
return new MiningHistoryDto(new List<MiningHistoryItemDto>(), 0, request.Page, request.PageSize);
var history = miner.MiningHistories
.OrderByDescending(h => h.EarnedAt)
.Skip((request.Page - 1) * request.PageSize)
.Take(request.PageSize)
.Select(h => new MiningHistoryItemDto(h.Id, h.PointsEarned, h.Source, h.HourlyRateSnapshot, h.EarnedAt))
.ToList();
return new MiningHistoryDto(history, miner.MiningHistories.Count, request.Page, request.PageSize);
}
}
/// <summary>
/// EN: Query to get current mining rate breakdown.
/// VI: Query để lấy chi tiết tỷ lệ đào hiện tại.
/// </summary>
public record GetMiningRateQuery(Guid UserId) : IRequest<MiningRateDto?>;
public record MiningRateDto(
decimal BaseRate,
decimal RoleMultiplier,
decimal CircleBonus,
decimal ReferralBonus,
decimal StreakBonus,
decimal TotalRate,
decimal HourlyPoints,
decimal DailyPoints);
public class GetMiningRateQueryHandler : IRequestHandler<GetMiningRateQuery, MiningRateDto?>
{
private readonly IMinerRepository _minerRepository;
public GetMiningRateQueryHandler(IMinerRepository minerRepository)
{
_minerRepository = minerRepository;
}
public async Task<MiningRateDto?> Handle(GetMiningRateQuery request, CancellationToken cancellationToken)
{
var miner = await _minerRepository.GetByUserIdAsync(request.UserId, cancellationToken);
if (miner == null) return null;
var rate = miner.CurrentRate;
var baseRate = 0.25m;
var roleMultiplier = GetRoleMultiplier(miner.Role);
var circleBonus = miner.CircleId.HasValue ? 0.25m : 0m;
var referralBonus = 0m; // Would need to query repository for actual count
var streakBonus = miner.Streak.BonusMultiplier;
var totalRate = baseRate * (1 + roleMultiplier) * (1 + circleBonus) * (1 + referralBonus) * (1 + streakBonus);
return new MiningRateDto(
baseRate,
roleMultiplier,
circleBonus,
referralBonus,
streakBonus,
totalRate,
totalRate,
totalRate * 24);
}
private static decimal GetRoleMultiplier(MinerRole role) => role switch
{
MinerRole.Pioneer => 0m,
MinerRole.Contributor => 0.10m,
MinerRole.Ambassador => 0.25m,
MinerRole.NodeOperator => 0.50m,
_ => 0m
};
}
/// <summary>
/// EN: Query to get top miners leaderboard.
/// VI: Query để lấy bảng xếp hạng thợ đào.
/// </summary>
public record GetLeaderboardQuery(int Limit = 100) : IRequest<LeaderboardDto>;
public record LeaderboardDto(List<LeaderboardEntryDto> Entries);
public record LeaderboardEntryDto(
int Rank,
Guid MinerId,
Guid UserId,
decimal TotalPoints,
int StreakDays,
MinerRole Role);
public class GetLeaderboardQueryHandler : IRequestHandler<GetLeaderboardQuery, LeaderboardDto>
{
private readonly IMinerRepository _minerRepository;
public GetLeaderboardQueryHandler(IMinerRepository minerRepository)
{
_minerRepository = minerRepository;
}
public async Task<LeaderboardDto> Handle(GetLeaderboardQuery request, CancellationToken cancellationToken)
{
var topMiners = await _minerRepository.GetTopMinersAsync(request.Limit, cancellationToken);
var entries = topMiners.Select((m, i) => new LeaderboardEntryDto(
i + 1,
m.Id,
m.UserId,
m.TotalMinedPoints,
m.Streak.CurrentStreak,
m.Role)).ToList();
return new LeaderboardDto(entries);
}
}