mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2025-03-12 22:59:26 +01:00
Unique players / day query
This commit is contained in:
parent
01fb2debb6
commit
cb626145fe
@ -17,11 +17,9 @@
|
||||
package com.djrapitops.plan.data.store.mutators;
|
||||
|
||||
import com.djrapitops.plan.utilities.html.graphs.line.Point;
|
||||
import com.djrapitops.plugin.utilities.Verify;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NavigableMap;
|
||||
import java.util.TimeZone;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MutatorFunctions {
|
||||
@ -38,6 +36,32 @@ public class MutatorFunctions {
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static NavigableMap<Long, Integer> addMissing(NavigableMap<Long, Integer> points, long accuracy, Integer replacement) {
|
||||
if (Verify.isEmpty(points)) return points;
|
||||
|
||||
NavigableMap<Long, Integer> filled = new TreeMap<>();
|
||||
Long lastX = null;
|
||||
for (Map.Entry<Long, Integer> point : points.entrySet()) {
|
||||
long date = point.getKey();
|
||||
|
||||
if (lastX != null && date - lastX > accuracy) {
|
||||
addMissing(lastX, date, filled, accuracy, replacement);
|
||||
}
|
||||
lastX = date;
|
||||
filled.put(point.getKey(), point.getValue());
|
||||
}
|
||||
|
||||
return filled;
|
||||
}
|
||||
|
||||
private static void addMissing(long from, long to, NavigableMap<Long, Integer> points, long accuracy, Integer replacement) {
|
||||
long iterate = from;
|
||||
while (iterate < to) {
|
||||
points.put(iterate, replacement);
|
||||
iterate += accuracy;
|
||||
}
|
||||
}
|
||||
|
||||
public static int average(Map<Long, Integer> map) {
|
||||
return (int) map.values().stream()
|
||||
.mapToInt(i -> i)
|
||||
|
@ -18,12 +18,15 @@ package com.djrapitops.plan.db.access.queries.analysis;
|
||||
|
||||
import com.djrapitops.plan.db.access.Query;
|
||||
import com.djrapitops.plan.db.access.QueryStatement;
|
||||
import com.djrapitops.plan.db.sql.parsing.Sql;
|
||||
import com.djrapitops.plan.db.sql.tables.SessionsTable;
|
||||
import com.djrapitops.plan.db.sql.tables.UserInfoTable;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.NavigableMap;
|
||||
import java.util.TreeMap;
|
||||
import java.util.UUID;
|
||||
|
||||
import static com.djrapitops.plan.db.sql.parsing.Sql.*;
|
||||
@ -65,6 +68,49 @@ public class PlayerCountQueries {
|
||||
return queryPlayerCount(sql, after, before, serverUUID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a EpochMs - Count map of unique players on a server.
|
||||
*
|
||||
* @param after After epoch ms
|
||||
* @param before Before epoch ms
|
||||
* @param timeZoneOffset Offset from {@link java.util.TimeZone#getOffset(long)}, applied to the dates before grouping.
|
||||
* @param serverUUID UUID of the Plan server
|
||||
* @return Map: Epoch ms (Accuracy of a day) - How many unique players played that day
|
||||
*/
|
||||
public static Query<NavigableMap<Long, Integer>> uniquePlayerCounts(long after, long before, long timeZoneOffset, UUID serverUUID) {
|
||||
return database -> {
|
||||
Sql sql = database.getType().getSql();
|
||||
String selectUniquePlayersPerDay = SELECT +
|
||||
sql.dateToEpochSecond(sql.dateToDayStamp(sql.epochSecondToDate('(' + SessionsTable.SESSION_START + "+?)/1000"))) +
|
||||
"*1000 as date," +
|
||||
"COUNT(DISTINCT " + SessionsTable.USER_UUID + ") as player_count" +
|
||||
FROM + SessionsTable.TABLE_NAME +
|
||||
WHERE + SessionsTable.SESSION_END + "<=?" +
|
||||
AND + SessionsTable.SESSION_START + ">=?" +
|
||||
AND + SessionsTable.SERVER_UUID + "=?" +
|
||||
GROUP_BY + "date";
|
||||
|
||||
return database.query(new QueryStatement<NavigableMap<Long, Integer>>(selectUniquePlayersPerDay, 100) {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
statement.setLong(1, timeZoneOffset);
|
||||
statement.setLong(2, before);
|
||||
statement.setLong(3, after);
|
||||
statement.setString(4, serverUUID.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigableMap<Long, Integer> processResults(ResultSet set) throws SQLException {
|
||||
NavigableMap<Long, Integer> uniquePerDay = new TreeMap<>();
|
||||
while (set.next()) {
|
||||
uniquePerDay.put(set.getLong("date"), set.getInt("player_count"));
|
||||
}
|
||||
return uniquePerDay;
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
public static Query<Integer> newPlayerCount(long after, long before, UUID serverUUID) {
|
||||
String sql = SELECT + "COUNT(" + UserInfoTable.USER_UUID + ") as player_count" +
|
||||
FROM + UserInfoTable.TABLE_NAME +
|
||||
|
@ -17,13 +17,20 @@
|
||||
package com.djrapitops.plan.system.json;
|
||||
|
||||
import com.djrapitops.plan.data.container.Ping;
|
||||
import com.djrapitops.plan.data.store.mutators.*;
|
||||
import com.djrapitops.plan.data.store.mutators.MutatorFunctions;
|
||||
import com.djrapitops.plan.data.store.mutators.PingMutator;
|
||||
import com.djrapitops.plan.data.store.mutators.PlayersMutator;
|
||||
import com.djrapitops.plan.data.store.mutators.TPSMutator;
|
||||
import com.djrapitops.plan.data.store.objects.DateMap;
|
||||
import com.djrapitops.plan.data.time.WorldTimes;
|
||||
import com.djrapitops.plan.db.Database;
|
||||
import com.djrapitops.plan.db.access.queries.analysis.ActivityIndexQueries;
|
||||
import com.djrapitops.plan.db.access.queries.analysis.PlayerCountQueries;
|
||||
import com.djrapitops.plan.db.access.queries.containers.ServerPlayerContainersQuery;
|
||||
import com.djrapitops.plan.db.access.queries.objects.*;
|
||||
import com.djrapitops.plan.db.access.queries.objects.GeoInfoQueries;
|
||||
import com.djrapitops.plan.db.access.queries.objects.PingQueries;
|
||||
import com.djrapitops.plan.db.access.queries.objects.TPSQueries;
|
||||
import com.djrapitops.plan.db.access.queries.objects.WorldTimesQueries;
|
||||
import com.djrapitops.plan.system.database.DBSystem;
|
||||
import com.djrapitops.plan.system.settings.config.PlanConfig;
|
||||
import com.djrapitops.plan.system.settings.paths.TimeSettings;
|
||||
@ -86,13 +93,20 @@ public class GraphJSONParser {
|
||||
public String uniqueAndNewGraphJSON(UUID serverUUID) {
|
||||
Database db = dbSystem.getDatabase();
|
||||
LineGraphFactory lineGraphs = graphs.line();
|
||||
SessionsMutator sessionsMutator = new SessionsMutator(db.query(SessionQueries.fetchSessionsOfServerFlat(serverUUID)))
|
||||
.filterSessionsBetween(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(180L), System.currentTimeMillis());
|
||||
long now = System.currentTimeMillis();
|
||||
long halfYearAgo = now - TimeUnit.DAYS.toMillis(180L);
|
||||
NavigableMap<Long, Integer> uniquePerDay = db.query(
|
||||
PlayerCountQueries.uniquePlayerCounts(halfYearAgo, now, timeZone.getOffset(now), serverUUID)
|
||||
);
|
||||
PlayersMutator playersMutator = new PlayersMutator(db.query(new ServerPlayerContainersQuery(serverUUID)))
|
||||
.filterRegisteredBetween(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(180L), System.currentTimeMillis());
|
||||
.filterRegisteredBetween(halfYearAgo, now);
|
||||
|
||||
return "{\"uniquePlayers\":" +
|
||||
lineGraphs.lineGraph(MutatorFunctions.toPointsWithRemovedOffset(sessionsMutator.uniqueJoinsPerDay(timeZone), timeZone)).toHighChartsSeries() +
|
||||
lineGraphs.lineGraph(
|
||||
MutatorFunctions.toPointsWithRemovedOffset(
|
||||
MutatorFunctions.addMissing(uniquePerDay, TimeUnit.DAYS.toMillis(1L), 0),
|
||||
timeZone
|
||||
)).toHighChartsSeries() +
|
||||
",\"newPlayers\":" +
|
||||
lineGraphs.lineGraph(MutatorFunctions.toPointsWithRemovedOffset(playersMutator.newPerDay(timeZone), timeZone)).toHighChartsSeries() +
|
||||
'}';
|
||||
@ -100,14 +114,17 @@ public class GraphJSONParser {
|
||||
|
||||
public String serverCalendarJSON(UUID serverUUID) {
|
||||
Database db = dbSystem.getDatabase();
|
||||
SessionsMutator sessionsMutator = new SessionsMutator(db.query(SessionQueries.fetchSessionsOfServerFlat(serverUUID)))
|
||||
.filterSessionsBetween(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(730L), System.currentTimeMillis());
|
||||
long now = System.currentTimeMillis();
|
||||
long twoYearsAgo = now - TimeUnit.DAYS.toMillis(730L);
|
||||
NavigableMap<Long, Integer> uniquePerDay = db.query(
|
||||
PlayerCountQueries.uniquePlayerCounts(twoYearsAgo, now, timeZone.getOffset(now), serverUUID)
|
||||
);
|
||||
PlayersMutator playersMutator = new PlayersMutator(db.query(new ServerPlayerContainersQuery(serverUUID)));
|
||||
|
||||
return "{\"data\":" +
|
||||
graphs.calendar().serverCalendar(
|
||||
playersMutator,
|
||||
sessionsMutator.uniqueJoinsPerDay(timeZone),
|
||||
uniquePerDay,
|
||||
playersMutator.newPerDay(timeZone)
|
||||
).toCalendarSeries() +
|
||||
",\"firstDay\":" + 1 + '}';
|
||||
|
@ -25,8 +25,8 @@ import com.djrapitops.plan.utilities.formatting.Formatters;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TimeZone;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* Factory class for different objects representing HTML calendars.
|
||||
@ -60,8 +60,8 @@ public class CalendarFactory {
|
||||
|
||||
public ServerCalendar serverCalendar(
|
||||
PlayersMutator mutator,
|
||||
TreeMap<Long, Integer> uniquePerDay,
|
||||
TreeMap<Long, Integer> newPerDay
|
||||
SortedMap<Long, Integer> uniquePerDay,
|
||||
SortedMap<Long, Integer> newPerDay
|
||||
) {
|
||||
return new ServerCalendar(
|
||||
mutator, uniquePerDay, newPerDay,
|
||||
|
@ -33,8 +33,8 @@ import java.util.*;
|
||||
public class ServerCalendar {
|
||||
|
||||
private final PlayersMutator mutator;
|
||||
private final TreeMap<Long, Integer> uniquePerDay;
|
||||
private final TreeMap<Long, Integer> newPerDay;
|
||||
private final SortedMap<Long, Integer> uniquePerDay;
|
||||
private final SortedMap<Long, Integer> newPerDay;
|
||||
|
||||
private final Formatter<Long> iso8601Formatter;
|
||||
private final Formatter<Long> timeAmountFormatter;
|
||||
@ -42,7 +42,7 @@ public class ServerCalendar {
|
||||
private final TimeZone timeZone;
|
||||
|
||||
ServerCalendar(
|
||||
PlayersMutator mutator, TreeMap<Long, Integer> uniquePerDay, TreeMap<Long, Integer> newPerDay,
|
||||
PlayersMutator mutator, SortedMap<Long, Integer> uniquePerDay, SortedMap<Long, Integer> newPerDay,
|
||||
Formatter<Long> iso8601Formatter,
|
||||
Formatter<Long> timeAmountFormatter,
|
||||
Theme theme,
|
||||
|
Loading…
Reference in New Issue
Block a user