package ru.soune.nocopy.service.statistic; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import ru.soune.nocopy.dto.statistic.TokenStatisticResponse; import ru.soune.nocopy.repository.PaymentRepository; import ru.soune.nocopy.repository.TokenOperationRepository; import ru.soune.nocopy.util.PercentileCalculator; import java.util.List; import java.util.stream.Collectors; @Service @RequiredArgsConstructor @Slf4j public class TokenStatisticService { private final PaymentRepository paymentRepository; private final TokenOperationRepository tokenOperationRepository; private static final int PERCENTILE_5 = 5; private static final int PERCENTILE_50 = 50; private static final int PERCENTILE_95 = 95; public TokenStatisticResponse getTokenStatistics() { Long totalBought = paymentRepository.getTotalTokensBought(); Long totalSpent = tokenOperationRepository.getTotalTokensSpent(); List boughtData = paymentRepository.getTokensBoughtPerUser(); List boughtValues = extractTokenValues(boughtData); List spentData = tokenOperationRepository.getTokensSpentPerUser(); List spentValues = extractTokenValues(spentData); PercentileCalculator.PercentilesResult boughtPercentiles = PercentileCalculator.calculatePercentiles(boughtValues, PERCENTILE_5, PERCENTILE_50, PERCENTILE_95); PercentileCalculator.PercentilesResult spentPercentiles = PercentileCalculator.calculatePercentiles(spentValues, PERCENTILE_5, PERCENTILE_50, PERCENTILE_95); return TokenStatisticResponse.builder() .totalBought(totalBought != null ? totalBought : 0L) .totalSpent(totalSpent != null ? totalSpent : 0L) .boughtPerUser(new TokenStatisticResponse.Percentiles( boughtPercentiles.getP5(), boughtPercentiles.getP50(), boughtPercentiles.getP95() )) .spentPerUser(new TokenStatisticResponse.Percentiles( spentPercentiles.getP5(), spentPercentiles.getP50(), spentPercentiles.getP95() )) .build(); } private List extractTokenValues(List data) { return data.stream() .map(row -> row[1] != null ? ((Number) row[1]).longValue() : 0L) .filter(value -> value > 0) .collect(Collectors.toList()); } }