dev add statistic files protected
Test Workflow / test (push) Successful in 3s

This commit is contained in:
vladp
2026-04-15 18:12:32 +07:00
parent 1b921b525a
commit 2d80b40b27
12 changed files with 467 additions and 1 deletions
@@ -0,0 +1,80 @@
package ru.soune.nocopy.util;
import lombok.experimental.UtilityClass;
import java.util.List;
import java.util.stream.Collectors;
@UtilityClass
public class PercentileCalculator {
/**
* Рассчитать несколько перцентилей за один проход
*
* @param values список значений
* @param percentiles массив перцентилей
* @return PercentilesResult с соответствующими значениями
*/
public PercentilesResult calculatePercentiles(List<Long> values, int... percentiles) {
if (values == null || values.isEmpty()) {
return new PercentilesResult(0L, 0L, 0L);
}
List<Long> sorted = values.stream()
.sorted()
.collect(Collectors.toList());
Long p5 = percentiles.length > 0 ? calculatePercentileFromSorted(sorted, percentiles[0]) : 0L;
Long p50 = percentiles.length > 1 ? calculatePercentileFromSorted(sorted, percentiles[1]) : 0L;
Long p95 = percentiles.length > 2 ? calculatePercentileFromSorted(sorted, percentiles[2]) : 0L;
return new PercentilesResult(p5, p50, p95);
}
public PercentilesResult calculateP5P50P95(List<Long> values) {
return calculatePercentiles(values, 5, 50, 95);
}
private Long calculatePercentileFromSorted(List<Long> sorted, double percentile) {
if (sorted.isEmpty()) {
return 0L;
}
if (percentile <= 0) {
return sorted.get(0);
}
if (percentile >= 100) {
return sorted.get(sorted.size() - 1);
}
double index = (percentile / 100.0) * (sorted.size() - 1);
int lowerIndex = (int) Math.floor(index);
int upperIndex = (int) Math.ceil(index);
if (lowerIndex == upperIndex) {
return sorted.get(lowerIndex);
}
double weight = index - lowerIndex;
long lowerValue = sorted.get(lowerIndex);
long upperValue = sorted.get(upperIndex);
return lowerValue + Math.round(weight * (upperValue - lowerValue));
}
public static class PercentilesResult {
private final Long p5;
private final Long p50;
private final Long p95;
public PercentilesResult(Long p5, Long p50, Long p95) {
this.p5 = p5;
this.p50 = p50;
this.p95 = p95;
}
public Long getP5() { return p5; }
public Long getP50() { return p50; }
public Long getP95() { return p95; }
}
}