Rewrote Unique player and new player counters for #560

This commit is contained in:
Rsl1122 2018-07-13 15:27:06 +03:00
parent 9369a863b2
commit 0549ce32f5
7 changed files with 123 additions and 58 deletions

View File

@ -168,13 +168,13 @@ public class AnalysisContainer extends DataContainer {
.filterRegisteredBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_MONTH_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
);
putSupplier(uniqueDay, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
.filterRegisteredBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_DAY_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
.filterPlayedBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_DAY_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
);
putSupplier(uniqueWeek, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
.filterRegisteredBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_WEEK_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
.filterPlayedBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_WEEK_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
);
putSupplier(uniqueMonth, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
.filterRegisteredBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_MONTH_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
.filterPlayedBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_MONTH_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
);
putSupplier(AnalysisKeys.PLAYERS_NEW_DAY, () -> getUnsafe(newDay).count());
@ -183,10 +183,10 @@ public class AnalysisContainer extends DataContainer {
putSupplier(AnalysisKeys.PLAYERS_DAY, () -> getUnsafe(uniqueDay).count());
putSupplier(AnalysisKeys.PLAYERS_WEEK, () -> getUnsafe(uniqueWeek).count());
putSupplier(AnalysisKeys.PLAYERS_MONTH, () -> getUnsafe(uniqueMonth).count());
putSupplier(AnalysisKeys.AVG_PLAYERS_NEW, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR).newPerDay());
putSupplier(AnalysisKeys.AVG_PLAYERS_NEW_DAY, () -> getUnsafe(uniqueDay).newPerDay());
putSupplier(AnalysisKeys.AVG_PLAYERS_NEW_WEEK, () -> getUnsafe(uniqueWeek).newPerDay());
putSupplier(AnalysisKeys.AVG_PLAYERS_NEW_MONTH, () -> getUnsafe(uniqueMonth).newPerDay());
putSupplier(AnalysisKeys.AVG_PLAYERS_NEW, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR).averageNewPerDay());
putSupplier(AnalysisKeys.AVG_PLAYERS_NEW_DAY, () -> getUnsafe(newDay).averageNewPerDay());
putSupplier(AnalysisKeys.AVG_PLAYERS_NEW_WEEK, () -> getUnsafe(newWeek).averageNewPerDay());
putSupplier(AnalysisKeys.AVG_PLAYERS_NEW_MONTH, () -> getUnsafe(newMonth).averageNewPerDay());
Key<Integer> retentionDay = new Key<>(Integer.class, "RETENTION_DAY");
// compareAndFindThoseLikelyToBeRetained can throw exception.
@ -290,10 +290,10 @@ public class AnalysisContainer extends DataContainer {
);
putSupplier(AnalysisKeys.PUNCHCARD_SERIES, () -> new PunchCardGraph(getUnsafe(sessionsMonth).all()).toHighChartsSeries());
putSupplier(AnalysisKeys.AVG_PLAYERS, () -> getUnsafe(AnalysisKeys.SESSIONS_MUTATOR).toUniqueJoinsPerDay());
putSupplier(AnalysisKeys.AVG_PLAYERS_DAY, () -> getUnsafe(sessionsDay).toUniqueJoinsPerDay());
putSupplier(AnalysisKeys.AVG_PLAYERS_WEEK, () -> getUnsafe(sessionsWeek).toUniqueJoinsPerDay());
putSupplier(AnalysisKeys.AVG_PLAYERS_MONTH, () -> getUnsafe(sessionsMonth).toUniqueJoinsPerDay());
putSupplier(AnalysisKeys.AVG_PLAYERS, () -> getUnsafe(AnalysisKeys.SESSIONS_MUTATOR).toAverageUniqueJoinsPerDay());
putSupplier(AnalysisKeys.AVG_PLAYERS_DAY, () -> getUnsafe(sessionsDay).toAverageUniqueJoinsPerDay());
putSupplier(AnalysisKeys.AVG_PLAYERS_WEEK, () -> getUnsafe(sessionsWeek).toAverageUniqueJoinsPerDay());
putSupplier(AnalysisKeys.AVG_PLAYERS_MONTH, () -> getUnsafe(sessionsMonth).toAverageUniqueJoinsPerDay());
}
private void addGraphSuppliers() {

View File

@ -0,0 +1,39 @@
package com.djrapitops.plan.data.store.mutators;
import com.djrapitops.plan.data.store.objects.DateHolder;
import com.djrapitops.plugin.api.TimeAmount;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;
public class DateHoldersMutator<T extends DateHolder> {
private final List<T> dateHolders;
public DateHoldersMutator(List<T> dateHolders) {
this.dateHolders = dateHolders;
}
public TreeMap<Long, List<T>> groupByStartOfDay() {
TreeMap<Long, List<T>> map = new TreeMap<>();
long twentyFourHours = 24L * TimeAmount.HOUR.ms();
for (T holder : dateHolders) {
long date = holder.getDate();
long startOfDate = date - (date % twentyFourHours);
List<T> list = map.getOrDefault(startOfDate, new ArrayList<>());
list.add(holder);
map.put(startOfDate, list);
}
// Add missing in-between dates
for (long date = map.firstKey(); date < map.lastKey(); date += twentyFourHours) {
map.putIfAbsent(date, new ArrayList<>());
}
return map;
}
}

View File

@ -0,0 +1,24 @@
package com.djrapitops.plan.data.store.mutators;
import com.djrapitops.plan.utilities.html.graphs.line.Point;
import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
import java.util.stream.Collectors;
public class MutatorFunctions {
public static List<Point> toPoints(NavigableMap<Long, Integer> map) {
return map.entrySet().stream()
.map(entry -> new Point(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
}
public static int average(Map<Long, Integer> map) {
return (int) map.values().stream()
.mapToInt(i -> i)
.average().orElse(0);
}
}

View File

@ -7,13 +7,12 @@ import com.djrapitops.plan.data.store.containers.PlayerContainer;
import com.djrapitops.plan.data.store.keys.PlayerKeys;
import com.djrapitops.plan.data.store.keys.ServerKeys;
import com.djrapitops.plan.data.store.keys.SessionKeys;
import com.djrapitops.plan.data.store.mutators.formatting.Formatters;
import com.djrapitops.plan.data.store.objects.DateObj;
import com.djrapitops.plan.utilities.analysis.AnalysisUtils;
import com.djrapitops.plugin.api.TimeAmount;
import com.djrapitops.plugin.api.utility.log.Log;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@ -128,22 +127,22 @@ public class PlayersMutator {
return players.size();
}
public int newPerDay() {
List<Long> registerDates = registerDates();
int total = 0;
Function<Long, Integer> formatter = Formatters.dayOfYear();
Set<Integer> days = new HashSet<>();
for (Long date : registerDates) {
int day = formatter.apply(date);
days.add(day);
total++;
}
int numberOfDays = days.size();
public int averageNewPerDay() {
return MutatorFunctions.average(newPerDay());
}
if (numberOfDays == 0) {
return 0;
public TreeMap<Long, Integer> newPerDay() {
List<DateObj> registerDates = registerDates().stream()
.map(value -> new DateObj<>(value, value))
.collect(Collectors.toList());
TreeMap<Long, List<DateObj>> byDay = new DateHoldersMutator<>(registerDates).groupByStartOfDay();
TreeMap<Long, Integer> byDayCounts = new TreeMap<>();
for (Map.Entry<Long, List<DateObj>> entry : byDay.entrySet()) {
byDayCounts.put(entry.getKey(), entry.getValue().size());
}
return total / numberOfDays;
return byDayCounts;
}
/**

View File

@ -2,7 +2,10 @@ package com.djrapitops.plan.data.store.mutators;
import com.djrapitops.plan.utilities.html.graphs.line.Point;
import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.TreeMap;
/**
* Resolves dates into players online numbers with a help of a NavigableMap.
@ -11,22 +14,19 @@ import java.util.*;
*
* @author Rsl1122
*/
public class PlayersOnlineResolver {
private final NavigableMap<Long, Integer> onlineNumberMap;
public class PlayersOnlineResolver extends TreeMap<Long, Integer> {
public PlayersOnlineResolver(TPSMutator mutator) {
List<Point> points = mutator.playersOnlinePoints();
onlineNumberMap = new TreeMap<>();
for (Point point : points) {
double date = point.getX();
double value = point.getY();
onlineNumberMap.put((long) date, (int) value);
put((long) date, (int) value);
}
}
public Optional<Integer> getOnlineOn(long date) {
Map.Entry<Long, Integer> entry = onlineNumberMap.floorEntry(date);
Map.Entry<Long, Integer> entry = floorEntry(date);
if (entry == null) {
return Optional.empty();
}
@ -34,7 +34,7 @@ public class PlayersOnlineResolver {
}
public boolean isServerOnline(long date, long timeLimit) {
Long lastEntry = onlineNumberMap.floorKey(date);
Long lastEntry = floorKey(date);
return date - lastEntry < timeLimit;
}
}

View File

@ -6,12 +6,10 @@ import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.data.store.containers.DataContainer;
import com.djrapitops.plan.data.store.keys.CommonKeys;
import com.djrapitops.plan.data.store.keys.SessionKeys;
import com.djrapitops.plan.data.store.mutators.formatting.Formatters;
import com.djrapitops.plan.data.time.WorldTimes;
import com.djrapitops.plugin.api.utility.log.Log;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@ -51,6 +49,10 @@ public class SessionsMutator {
.collect(Collectors.toList()));
}
public DateHoldersMutator<Session> toDateHoldersMutator() {
return new DateHoldersMutator<>(sessions);
}
public WorldTimes toTotalWorldTimes() {
WorldTimes total = new WorldTimes(new HashMap<>());
@ -141,30 +143,29 @@ public class SessionsMutator {
return sessionLengths.get(sessionLengths.size() / 2);
}
public int toUniqueJoinsPerDay() {
Map<Integer, Set<UUID>> uniqueJoins = new HashMap<>();
Function<Long, Integer> function = Formatters.dayOfYear();
public int toAverageUniqueJoinsPerDay() {
return MutatorFunctions.average(uniqueJoinsPerDay());
}
for (Session session : sessions) {
Optional<UUID> uuidValue = session.getValue(SessionKeys.UUID);
if (!uuidValue.isPresent()) {
continue;
}
UUID uuid = uuidValue.get();
int day = function.apply(session.getUnsafe(SessionKeys.START));
public TreeMap<Long, Integer> uniqueJoinsPerDay() {
TreeMap<Long, List<Session>> byStartOfDay = toDateHoldersMutator().groupByStartOfDay();
uniqueJoins.computeIfAbsent(day, computedDay -> new HashSet<>());
uniqueJoins.get(day).add(uuid);
TreeMap<Long, Integer> uniqueJoins = new TreeMap<>();
for (Map.Entry<Long, List<Session>> entry : byStartOfDay.entrySet()) {
uniqueJoins.put(
entry.getKey(),
new SessionsMutator(entry.getValue()).toUniquePlayers()
);
}
int total = (int) uniqueJoins.values().stream().mapToInt(Set::size).count();
int numberOfDays = uniqueJoins.size();
return uniqueJoins;
}
if (numberOfDays == 0) {
return 0;
}
return total / numberOfDays;
public int toUniquePlayers() {
return (int) sessions.stream()
.map(session -> session.getUnsafe(SessionKeys.UUID))
.distinct()
.count();
}
public int count() {

View File

@ -18,6 +18,7 @@ import com.djrapitops.plan.utilities.html.Html;
import com.djrapitops.plugin.api.TimeAmount;
import java.util.ArrayList;
import java.util.Optional;
/**
* Server Health analysis mutator.
@ -59,8 +60,9 @@ public class HealthInformation extends AbstractHealthInfo {
PlayersOnlineResolver onlineResolver = analysisContainer.getUnsafe(AnalysisKeys.PLAYERS_ONLINE_RESOLVER);
double avgOnlineOnRegister = newPlayersMonth.registerDates().stream()
.mapToInt(date -> onlineResolver.getOnlineOn(date).orElse(-1))
.filter(value -> value != -1)
.map(onlineResolver::getOnlineOn)
.filter(Optional::isPresent)
.mapToInt(Optional::get)
.average().orElse(0);
if (avgOnlineOnRegister >= 1) {
notes.add("<p>" + Html.GREEN_THUMB.parse() + " New Players have players to play with when they join ("