mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2024-12-15 05:41:51 +08:00
Rewrote Unique player and new player counters for #560
This commit is contained in:
parent
9369a863b2
commit
0549ce32f5
@ -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() {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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() {
|
||||
|
@ -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 ("
|
||||
|
Loading…
Reference in New Issue
Block a user