mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2024-12-15 05:41:51 +08:00
Changed gathered ping average to be median instead #691
(For each datapoint a median is calculated, which is then used in calculation for mean values, averages)
This commit is contained in:
parent
268474d5ca
commit
3afaad9731
@ -9,10 +9,12 @@ import com.djrapitops.plan.data.store.objects.DateObj;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plan.system.processing.CriticalRunnable;
|
||||
import com.djrapitops.plan.utilities.analysis.Median;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.OptionalInt;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Processes 60s values of a Ping list.
|
||||
@ -44,23 +46,28 @@ public class PingInsertProcessor implements CriticalRunnable {
|
||||
return;
|
||||
}
|
||||
|
||||
int minValue = history.stream()
|
||||
.mapToInt(DateObj::getValue)
|
||||
.filter(i -> i > 0 && i < 4000)
|
||||
.min().orElse(-1);
|
||||
int minValue = getMinValue(history);
|
||||
|
||||
double avgValue = history.stream()
|
||||
.mapToInt(DateObj::getValue)
|
||||
.filter(i -> i > 0 && i < 4000)
|
||||
.average().orElse(-1);
|
||||
int meanValue = getMeanValue(history);
|
||||
|
||||
int maxValue = max.getAsInt();
|
||||
|
||||
Ping ping = new Ping(lastDate, ServerInfo.getServerUUID(),
|
||||
minValue,
|
||||
maxValue,
|
||||
avgValue);
|
||||
meanValue);
|
||||
|
||||
Database.getActive().save().ping(uuid, ping);
|
||||
}
|
||||
|
||||
int getMinValue(List<DateObj<Integer>> history) {
|
||||
return history.stream()
|
||||
.mapToInt(DateObj::getValue)
|
||||
.filter(i -> i > 0 && i < 4000)
|
||||
.min().orElse(-1);
|
||||
}
|
||||
|
||||
int getMeanValue(List<DateObj<Integer>> history) {
|
||||
return (int) Median.forInt(history.stream().map(DateObj::getValue).collect(Collectors.toList())).calculate();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,58 @@
|
||||
package com.djrapitops.plan.utilities.analysis;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Math utility for calculating the median from Integer values.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class Median {
|
||||
|
||||
private final List<Long> values;
|
||||
private int size;
|
||||
|
||||
private Median(Collection<Integer> values, int b) {
|
||||
this(values.stream().map(i -> (long) i).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
private Median(List<Long> values) {
|
||||
this.values = values;
|
||||
Collections.sort(values);
|
||||
size = values.size();
|
||||
}
|
||||
|
||||
public static Median forInt(Collection<Integer> integers) {
|
||||
return new Median(integers, 0);
|
||||
}
|
||||
|
||||
public static Median forLong(List<Long> longs) {
|
||||
return new Median(longs);
|
||||
}
|
||||
|
||||
public double calculate() {
|
||||
if (values.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
if (size % 2 == 0) {
|
||||
return calculateEven();
|
||||
} else {
|
||||
return calculateOdd();
|
||||
}
|
||||
}
|
||||
|
||||
private double calculateEven() {
|
||||
int half = size / 2;
|
||||
double x1 = values.get(half);
|
||||
double x2 = values.get(half - 1);
|
||||
return (x1 + x2) / 2;
|
||||
}
|
||||
|
||||
private double calculateOdd() {
|
||||
int half = size / 2;
|
||||
return (double) values.get(half);
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
package com.djrapitops.plan.system.processing.processors.player;
|
||||
|
||||
import com.djrapitops.plan.data.store.objects.DateObj;
|
||||
import com.djrapitops.plan.utilities.analysis.Median;
|
||||
import com.djrapitops.plugin.api.TimeAmount;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import utilities.RandomData;
|
||||
import utilities.TestConstants;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Test for {@link PingInsertProcessor}.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class PingInsertProcessorTest {
|
||||
|
||||
private List<DateObj<Integer>> testPing;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
testPing = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < TimeAmount.MINUTE.ms(); i += TimeAmount.SECOND.ms() * 2L) {
|
||||
testPing.add(new DateObj<>(i, RandomData.randomInt(1, 4000)));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMedian() {
|
||||
List<Integer> collect = testPing.stream().map(DateObj::getValue).sorted().collect(Collectors.toList());
|
||||
System.out.println(collect);
|
||||
int expected = (int) Median.forInt(collect).calculate();
|
||||
int result = new PingInsertProcessor(TestConstants.PLAYER_ONE_UUID, new ArrayList<>()).getMeanValue(testPing);
|
||||
System.out.println(result);
|
||||
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMedianSingleEntry() {
|
||||
int expected = 50;
|
||||
int result = new PingInsertProcessor(TestConstants.PLAYER_ONE_UUID, new ArrayList<>()).getMeanValue(
|
||||
Collections.singletonList(new DateObj<>(0, expected))
|
||||
);
|
||||
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMedianEmpty() {
|
||||
int expected = -1;
|
||||
int result = new PingInsertProcessor(TestConstants.PLAYER_ONE_UUID, new ArrayList<>()).getMeanValue(
|
||||
Collections.emptyList()
|
||||
);
|
||||
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
package com.djrapitops.plan.utilities.analysis;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Tests for {@link Median}.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class MedianTest {
|
||||
|
||||
@Test
|
||||
public void simpleOdd() {
|
||||
List<Integer> testValues = Arrays.asList(1, 3, 3, 6, 7, 8, 9);
|
||||
Collections.shuffle(testValues);
|
||||
double expected = 6;
|
||||
double result = Median.forInt(testValues).calculate();
|
||||
|
||||
assertEquals(expected, result, 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleEven() {
|
||||
List<Integer> testValues = Arrays.asList(1, 2, 3, 4, 5, 6, 8, 9);
|
||||
Collections.shuffle(testValues);
|
||||
double expected = 4.5;
|
||||
double result = Median.forInt(testValues).calculate();
|
||||
|
||||
assertEquals(expected, result, 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void empty() {
|
||||
double expected = -1;
|
||||
double result = Median.forInt(Collections.emptyList()).calculate();
|
||||
|
||||
assertEquals(expected, result, 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singleValue() {
|
||||
double expected = 50;
|
||||
double result = Median.forInt(Collections.singletonList((int) expected)).calculate();
|
||||
|
||||
assertEquals(expected, result, 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void twoValues() {
|
||||
List<Integer> testValues = Arrays.asList(1, 2);
|
||||
double expected = 1.5;
|
||||
double result = Median.forInt(testValues).calculate();
|
||||
|
||||
assertEquals(expected, result, 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void overflowOdd() {
|
||||
List<Integer> testValues = Arrays.asList(Integer.MIN_VALUE, 2, Integer.MAX_VALUE);
|
||||
double expected = 2;
|
||||
double result = Median.forInt(testValues).calculate();
|
||||
|
||||
assertEquals(expected, result, 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void overflowEven() {
|
||||
List<Integer> testValues = Arrays.asList(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
|
||||
double expected = -0.5;
|
||||
double result = Median.forInt(testValues).calculate();
|
||||
|
||||
assertEquals(expected, result, 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void overflowEven2() {
|
||||
List<Integer> testValues = Arrays.asList(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
|
||||
double expected = Integer.MAX_VALUE;
|
||||
double result = Median.forInt(testValues).calculate();
|
||||
|
||||
assertEquals(expected, result, 0.01);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user