Playtime & Sessions per day queries

This commit is contained in:
Rsl1122 2019-08-14 08:35:22 +03:00
parent 7a2636f5b2
commit 63c2db3cb2
11 changed files with 195 additions and 62 deletions

View File

@ -141,7 +141,7 @@ public class NetworkContainer extends DynamicDataContainer {
config.get(TimeSettings.ACTIVE_PLAY_THRESHOLD), config.get(TimeSettings.ACTIVE_PLAY_THRESHOLD),
config.get(TimeSettings.ACTIVE_LOGIN_THRESHOLD), config.get(TimeSettings.ACTIVE_LOGIN_THRESHOLD),
formatters.timeAmount(), formatters.decimals(), formatters.percentage(), formatters.timeAmount(), formatters.decimals(), formatters.percentage(),
config.get(TimeSettings.USE_SERVER_TIME) ? TimeZone.getDefault() : TimeZone.getTimeZone("GMT") config.getTimeZone()
)); ));
putCachingSupplier(NetworkKeys.HEALTH_INDEX, () -> getUnsafe(healthInformation).getServerHealth()); putCachingSupplier(NetworkKeys.HEALTH_INDEX, () -> getUnsafe(healthInformation).getServerHealth());
putCachingSupplier(NetworkKeys.HEALTH_NOTES, () -> getUnsafe(healthInformation).toHtml()); putCachingSupplier(NetworkKeys.HEALTH_NOTES, () -> getUnsafe(healthInformation).toHtml());

View File

@ -19,6 +19,7 @@ package com.djrapitops.plan.db;
import com.djrapitops.plan.api.exceptions.database.DBInitException; import com.djrapitops.plan.api.exceptions.database.DBInitException;
import com.djrapitops.plan.db.access.Query; import com.djrapitops.plan.db.access.Query;
import com.djrapitops.plan.db.access.transactions.Transaction; import com.djrapitops.plan.db.access.transactions.Transaction;
import com.djrapitops.plan.db.sql.parsing.Sql;
import java.util.concurrent.Future; import java.util.concurrent.Future;
@ -67,6 +68,10 @@ public interface Database {
*/ */
DBType getType(); DBType getType();
default Sql getSql() {
return getType().getSql();
}
State getState(); State getState();
enum State { enum State {

View File

@ -79,7 +79,7 @@ public class PlayerCountQueries {
*/ */
public static Query<NavigableMap<Long, Integer>> uniquePlayerCounts(long after, long before, long timeZoneOffset, UUID serverUUID) { public static Query<NavigableMap<Long, Integer>> uniquePlayerCounts(long after, long before, long timeZoneOffset, UUID serverUUID) {
return database -> { return database -> {
Sql sql = database.getType().getSql(); Sql sql = database.getSql();
String selectUniquePlayersPerDay = SELECT + String selectUniquePlayersPerDay = SELECT +
sql.dateToEpochSecond(sql.dateToDayStamp(sql.epochSecondToDate('(' + SessionsTable.SESSION_START + "+?)/1000"))) + sql.dateToEpochSecond(sql.dateToDayStamp(sql.epochSecondToDate('(' + SessionsTable.SESSION_START + "+?)/1000"))) +
"*1000 as date," + "*1000 as date," +
@ -113,7 +113,7 @@ public class PlayerCountQueries {
public static Query<Integer> averageUniquePlayerCount(long after, long before, long timeZoneOffset, UUID serverUUID) { public static Query<Integer> averageUniquePlayerCount(long after, long before, long timeZoneOffset, UUID serverUUID) {
return database -> { return database -> {
Sql sql = database.getType().getSql(); Sql sql = database.getSql();
String selectUniquePlayersPerDay = SELECT + String selectUniquePlayersPerDay = SELECT +
sql.dateToEpochSecond(sql.dateToDayStamp(sql.epochSecondToDate('(' + SessionsTable.SESSION_START + "+?)/1000"))) + sql.dateToEpochSecond(sql.dateToDayStamp(sql.epochSecondToDate('(' + SessionsTable.SESSION_START + "+?)/1000"))) +
"*1000 as date," + "*1000 as date," +
@ -163,7 +163,7 @@ public class PlayerCountQueries {
*/ */
public static Query<NavigableMap<Long, Integer>> newPlayerCounts(long after, long before, long timeZoneOffset, UUID serverUUID) { public static Query<NavigableMap<Long, Integer>> newPlayerCounts(long after, long before, long timeZoneOffset, UUID serverUUID) {
return database -> { return database -> {
Sql sql = database.getType().getSql(); Sql sql = database.getSql();
String selectNewPlayersQuery = SELECT + String selectNewPlayersQuery = SELECT +
sql.dateToEpochSecond(sql.dateToDayStamp(sql.epochSecondToDate('(' + UserInfoTable.REGISTERED + "+?)/1000"))) + sql.dateToEpochSecond(sql.dateToDayStamp(sql.epochSecondToDate('(' + UserInfoTable.REGISTERED + "+?)/1000"))) +
"*1000 as date," + "*1000 as date," +
@ -197,7 +197,7 @@ public class PlayerCountQueries {
public static Query<Integer> averageNewPlayerCount(long after, long before, long timeZoneOffset, UUID serverUUID) { public static Query<Integer> averageNewPlayerCount(long after, long before, long timeZoneOffset, UUID serverUUID) {
return database -> { return database -> {
Sql sql = database.getType().getSql(); Sql sql = database.getSql();
String selectNewPlayersQuery = SELECT + String selectNewPlayersQuery = SELECT +
sql.dateToEpochSecond(sql.dateToDayStamp(sql.epochSecondToDate('(' + UserInfoTable.REGISTERED + "+?)/1000"))) + sql.dateToEpochSecond(sql.dateToDayStamp(sql.epochSecondToDate('(' + UserInfoTable.REGISTERED + "+?)/1000"))) +
"*1000 as date," + "*1000 as date," +

View File

@ -26,6 +26,7 @@ import com.djrapitops.plan.data.time.WorldTimes;
import com.djrapitops.plan.db.access.Query; import com.djrapitops.plan.db.access.Query;
import com.djrapitops.plan.db.access.QueryAllStatement; import com.djrapitops.plan.db.access.QueryAllStatement;
import com.djrapitops.plan.db.access.QueryStatement; import com.djrapitops.plan.db.access.QueryStatement;
import com.djrapitops.plan.db.sql.parsing.Sql;
import com.djrapitops.plan.db.sql.tables.*; import com.djrapitops.plan.db.sql.tables.*;
import com.djrapitops.plan.utilities.comparators.DateHolderRecentComparator; import com.djrapitops.plan.utilities.comparators.DateHolderRecentComparator;
@ -370,6 +371,40 @@ public class SessionQueries {
}; };
} }
public static Query<NavigableMap<Long, Integer>> sessionCountPerDay(long after, long before, long timeZoneOffset, UUID serverUUID) {
return database -> {
Sql sql = database.getSql();
String selectSessionsPerDay = SELECT +
sql.dateToEpochSecond(sql.dateToDayStamp(sql.epochSecondToDate('(' + SessionsTable.SESSION_START + "+?)/1000"))) +
"*1000 as date," +
"COUNT(1) as session_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>>(selectSessionsPerDay, 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("session_count"));
}
return uniquePerDay;
}
});
};
}
public static Query<Long> playtime(long after, long before, UUID serverUUID) { public static Query<Long> playtime(long after, long before, UUID serverUUID) {
String sql = SELECT + "SUM(" + SessionsTable.SESSION_END + '-' + SessionsTable.SESSION_START + ") as playtime" + String sql = SELECT + "SUM(" + SessionsTable.SESSION_END + '-' + SessionsTable.SESSION_START + ") as playtime" +
FROM + SessionsTable.TABLE_NAME + FROM + SessionsTable.TABLE_NAME +
@ -391,6 +426,71 @@ public class SessionQueries {
}; };
} }
public static Query<NavigableMap<Long, Long>> playtimePerDay(long after, long before, long timeZoneOffset, UUID serverUUID) {
return database -> {
Sql sql = database.getSql();
String selectPlaytimePerDay = SELECT +
sql.dateToEpochSecond(sql.dateToDayStamp(sql.epochSecondToDate('(' + SessionsTable.SESSION_START + "+?)/1000"))) +
"*1000 as date," +
"SUM(" + SessionsTable.SESSION_END + '-' + SessionsTable.SESSION_START + ") as playtime" +
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, Long>>(selectPlaytimePerDay, 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, Long> processResults(ResultSet set) throws SQLException {
NavigableMap<Long, Long> uniquePerDay = new TreeMap<>();
while (set.next()) {
uniquePerDay.put(set.getLong("date"), set.getLong("playtime"));
}
return uniquePerDay;
}
});
};
}
public static Query<Long> averagePlaytimePerDay(long after, long before, long timeZoneOffset, UUID serverUUID) {
return database -> {
Sql sql = database.getSql();
String selectPlaytimePerDay = SELECT +
sql.dateToEpochSecond(sql.dateToDayStamp(sql.epochSecondToDate('(' + SessionsTable.SESSION_START + "+?)/1000"))) +
"*1000 as date," +
"SUM(" + SessionsTable.SESSION_END + '-' + SessionsTable.SESSION_START + ") as playtime" +
FROM + SessionsTable.TABLE_NAME +
WHERE + SessionsTable.SESSION_END + "<=?" +
AND + SessionsTable.SESSION_START + ">=?" +
AND + SessionsTable.SERVER_UUID + "=?" +
GROUP_BY + "date";
String selectAverage = SELECT + "AVG(playtime) as average" + FROM + '(' + selectPlaytimePerDay + ") q1";
return database.query(new QueryStatement<Long>(selectAverage, 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 Long processResults(ResultSet set) throws SQLException {
return set.next() ? set.getLong("average") : 0;
}
});
};
}
public static Query<Long> afkTime(long after, long before, UUID serverUUID) { public static Query<Long> afkTime(long after, long before, UUID serverUUID) {
String sql = SELECT + "SUM(" + SessionsTable.AFK_TIME + ") as afk_time" + String sql = SELECT + "SUM(" + SessionsTable.AFK_TIME + ") as afk_time" +
FROM + SessionsTable.TABLE_NAME + FROM + SessionsTable.TABLE_NAME +

View File

@ -67,7 +67,7 @@ public class GraphJSONParser {
this.config = config; this.config = config;
this.dbSystem = dbSystem; this.dbSystem = dbSystem;
this.graphs = graphs; this.graphs = graphs;
this.timeZone = config.get(TimeSettings.USE_SERVER_TIME) ? TimeZone.getDefault() : TimeZone.getTimeZone("GMT"); this.timeZone = config.getTimeZone();
} }
public String performanceGraphJSON(UUID serverUUID) { public String performanceGraphJSON(UUID serverUUID) {
@ -121,10 +121,18 @@ public class GraphJSONParser {
NavigableMap<Long, Integer> newPerDay = db.query( NavigableMap<Long, Integer> newPerDay = db.query(
PlayerCountQueries.newPlayerCounts(twoYearsAgo, now, timeZone.getOffset(now), serverUUID) PlayerCountQueries.newPlayerCounts(twoYearsAgo, now, timeZone.getOffset(now), serverUUID)
); );
NavigableMap<Long, Long> playtimePerDay = db.query(
SessionQueries.playtimePerDay(twoYearsAgo, now, timeZone.getOffset(now), serverUUID)
);
NavigableMap<Long, Integer> sessionsPerDay = db.query(
SessionQueries.sessionCountPerDay(twoYearsAgo, now, timeZone.getOffset(now), serverUUID)
);
return "{\"data\":" + return "{\"data\":" +
graphs.calendar().serverCalendar( graphs.calendar().serverCalendar(
uniquePerDay, uniquePerDay,
newPerDay newPerDay,
playtimePerDay,
sessionsPerDay
).toCalendarSeries() + ).toCalendarSeries() +
",\"firstDay\":" + 1 + '}'; ",\"firstDay\":" + 1 + '}';
} }

View File

@ -29,7 +29,6 @@ import com.djrapitops.plan.db.access.queries.objects.UserInfoQueries;
import com.djrapitops.plan.system.database.DBSystem; import com.djrapitops.plan.system.database.DBSystem;
import com.djrapitops.plan.system.settings.config.PlanConfig; import com.djrapitops.plan.system.settings.config.PlanConfig;
import com.djrapitops.plan.system.settings.paths.DisplaySettings; import com.djrapitops.plan.system.settings.paths.DisplaySettings;
import com.djrapitops.plan.system.settings.paths.TimeSettings;
import com.djrapitops.plan.utilities.formatting.Formatter; import com.djrapitops.plan.utilities.formatting.Formatter;
import com.djrapitops.plan.utilities.formatting.Formatters; import com.djrapitops.plan.utilities.formatting.Formatters;
@ -66,7 +65,7 @@ public class OnlineActivityOverviewJSONParser implements TabJSONParser<Map<Strin
timeAmountFormatter = formatters.timeAmount(); timeAmountFormatter = formatters.timeAmount();
decimalFormatter = formatters.decimals(); decimalFormatter = formatters.decimals();
percentageFormatter = formatters.percentage(); percentageFormatter = formatters.percentage();
this.timeZone = config.get(TimeSettings.USE_SERVER_TIME) ? TimeZone.getDefault() : TimeZone.getTimeZone("GMT"); this.timeZone = config.getTimeZone();
} }
public Map<String, Object> createJSONAsMap(UUID serverUUID) { public Map<String, Object> createJSONAsMap(UUID serverUUID) {
@ -146,16 +145,15 @@ public class OnlineActivityOverviewJSONParser implements TabJSONParser<Map<Strin
numbers.put("playtime_7d", timeAmountFormatter.apply(playtimeWeek)); numbers.put("playtime_7d", timeAmountFormatter.apply(playtimeWeek));
numbers.put("playtime_24h", timeAmountFormatter.apply(playtimeDay)); numbers.put("playtime_24h", timeAmountFormatter.apply(playtimeDay));
// TODO numbers.put("playtime_30d_avg", timeAmountFormatter.apply(db.query(SessionQueries.averagePlaytimePerDay(monthAgo, now, timeZoneOffset, serverUUID))));
numbers.put("playtime_30d_avg", timeAmountFormatter.apply(-1L));
numbers.put("playtime_30d_avg_trend", new Trend( numbers.put("playtime_30d_avg_trend", new Trend(
-1, db.query(SessionQueries.averagePlaytimePerDay(monthAgo, halfMonthAgo, timeZoneOffset, serverUUID)),
-1, db.query(SessionQueries.averagePlaytimePerDay(halfMonthAgo, now, timeZoneOffset, serverUUID)),
false, false,
timeAmountFormatter timeAmountFormatter
)); ));
numbers.put("playtime_7d_avg", timeAmountFormatter.apply(-1L)); numbers.put("playtime_7d_avg", timeAmountFormatter.apply(db.query(SessionQueries.averagePlaytimePerDay(weekAgo, now, timeZoneOffset, serverUUID))));
numbers.put("playtime_24h_avg", timeAmountFormatter.apply(-1L)); numbers.put("playtime_24h_avg", timeAmountFormatter.apply(db.query(SessionQueries.playtime(dayAgo, now, serverUUID))));
Long sessionsMonth = db.query(SessionQueries.sessionCount(monthAgo, now, serverUUID)); Long sessionsMonth = db.query(SessionQueries.sessionCount(monthAgo, now, serverUUID));
Long sessionsWeek = db.query(SessionQueries.sessionCount(weekAgo, now, serverUUID)); Long sessionsWeek = db.query(SessionQueries.sessionCount(weekAgo, now, serverUUID));

View File

@ -75,7 +75,7 @@ public class ServerOverviewJSONParser implements TabJSONParser<Map<String, Objec
timeAmount = formatters.timeAmount(); timeAmount = formatters.timeAmount();
decimals = formatters.decimals(); decimals = formatters.decimals();
percentage = formatters.percentage(); percentage = formatters.percentage();
this.timeZone = config.get(TimeSettings.USE_SERVER_TIME) ? TimeZone.getDefault() : TimeZone.getTimeZone("GMT"); this.timeZone = config.getTimeZone();
} }
public Map<String, Object> createJSONAsMap(UUID serverUUID) { public Map<String, Object> createJSONAsMap(UUID serverUUID) {

View File

@ -121,6 +121,10 @@ public class PlanConfig extends Config {
set(setting.getPath(), value); set(setting.getPath(), value);
} }
public TimeZone getTimeZone() {
return get(TimeSettings.USE_SERVER_TIME) ? TimeZone.getDefault() : TimeZone.getTimeZone("GMT");
}
public PluginsConfigSection getPluginsConfigSection() { public PluginsConfigSection getPluginsConfigSection() {
return pluginsConfigSection; return pluginsConfigSection;
} }

View File

@ -18,14 +18,13 @@ package com.djrapitops.plan.utilities.html.graphs.calendar;
import com.djrapitops.plan.data.store.containers.PlayerContainer; import com.djrapitops.plan.data.store.containers.PlayerContainer;
import com.djrapitops.plan.system.settings.config.PlanConfig; import com.djrapitops.plan.system.settings.config.PlanConfig;
import com.djrapitops.plan.system.settings.paths.TimeSettings;
import com.djrapitops.plan.system.settings.theme.Theme; import com.djrapitops.plan.system.settings.theme.Theme;
import com.djrapitops.plan.utilities.formatting.Formatters; import com.djrapitops.plan.utilities.formatting.Formatters;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import java.util.NavigableMap;
import java.util.SortedMap; import java.util.SortedMap;
import java.util.TimeZone;
/** /**
* Factory class for different objects representing HTML calendars. * Factory class for different objects representing HTML calendars.
@ -53,18 +52,20 @@ public class CalendarFactory {
return new PlayerCalendar( return new PlayerCalendar(
player, player,
formatters.timeAmount(), formatters.yearLong(), formatters.iso8601NoClockLong(), theme, formatters.timeAmount(), formatters.yearLong(), formatters.iso8601NoClockLong(), theme,
config.get(TimeSettings.USE_SERVER_TIME) ? TimeZone.getDefault() : TimeZone.getTimeZone("GMT") config.getTimeZone()
); );
} }
public ServerCalendar serverCalendar( public ServerCalendar serverCalendar(
SortedMap<Long, Integer> uniquePerDay, SortedMap<Long, Integer> uniquePerDay,
SortedMap<Long, Integer> newPerDay SortedMap<Long, Integer> newPerDay,
SortedMap<Long, Long> playtimePerDay,
NavigableMap<Long, Integer> sessionsPerDay
) { ) {
return new ServerCalendar( return new ServerCalendar(
uniquePerDay, newPerDay, uniquePerDay, newPerDay, playtimePerDay, sessionsPerDay,
formatters.iso8601NoClockLong(), formatters.timeAmount(), theme, formatters.iso8601NoClockLong(), formatters.timeAmount(), theme,
config.get(TimeSettings.USE_SERVER_TIME) ? TimeZone.getDefault() : TimeZone.getTimeZone("GMT") config.getTimeZone()
); );
} }
} }

View File

@ -20,7 +20,10 @@ import com.djrapitops.plan.system.settings.theme.Theme;
import com.djrapitops.plan.system.settings.theme.ThemeVal; import com.djrapitops.plan.system.settings.theme.ThemeVal;
import com.djrapitops.plan.utilities.formatting.Formatter; import com.djrapitops.plan.utilities.formatting.Formatter;
import java.util.*; import java.util.Map;
import java.util.NavigableMap;
import java.util.SortedMap;
import java.util.TimeZone;
/** /**
* Utility for creating FullCalendar calendar event array on Player page. * Utility for creating FullCalendar calendar event array on Player page.
@ -40,7 +43,10 @@ public class ServerCalendar {
private final TimeZone timeZone; private final TimeZone timeZone;
ServerCalendar( ServerCalendar(
SortedMap<Long, Integer> uniquePerDay, SortedMap<Long, Integer> newPerDay, SortedMap<Long, Integer> uniquePerDay,
SortedMap<Long, Integer> newPerDay,
SortedMap<Long, Long> playtimePerDay,
NavigableMap<Long, Integer> sessionsPerDay,
Formatter<Long> iso8601Formatter, Formatter<Long> iso8601Formatter,
Formatter<Long> timeAmountFormatter, Formatter<Long> timeAmountFormatter,
Theme theme, Theme theme,
@ -50,8 +56,8 @@ public class ServerCalendar {
this.newPerDay = newPerDay; this.newPerDay = newPerDay;
this.iso8601Formatter = iso8601Formatter; this.iso8601Formatter = iso8601Formatter;
this.timeAmountFormatter = timeAmountFormatter; this.timeAmountFormatter = timeAmountFormatter;
sessionsPerDay = new TreeMap<>(); // TODO this.sessionsPerDay = sessionsPerDay;
playtimePerDay = new TreeMap<>(); // TODO this.playtimePerDay = playtimePerDay;
this.theme = theme; this.theme = theme;
this.timeZone = timeZone; this.timeZone = timeZone;
} }
@ -60,57 +66,45 @@ public class ServerCalendar {
StringBuilder series = new StringBuilder("["); StringBuilder series = new StringBuilder("[");
series.append("{\"title\": \"badcode\",\"start\":0}"); series.append("{\"title\": \"badcode\",\"start\":0}");
appendSessionRelatedData(series); appendTimeZoneOffsetData(series);
appendRegistered(series);
return series.append("]").toString(); return series.append("]").toString();
} }
private void appendRegistered(StringBuilder series) { private void appendTimeZoneOffsetData(StringBuilder series) {
Map<String, Integer> registeredByDay = getRegisteredByDay(); // Has a timezone offset
appendUniquePlayers(series);
appendNewPlayers(series);
appendSessionCounts(series);
appendPlaytime(series);
}
for (Map.Entry<String, Integer> entry : registeredByDay.entrySet()) { private void appendNewPlayers(StringBuilder series) {
Integer newPlayers = entry.getValue(); for (Map.Entry<Long, Integer> entry : newPerDay.entrySet()) {
int newPlayers = entry.getValue();
if (newPlayers <= 0) { if (newPlayers <= 0) {
continue; continue;
} }
String day = entry.getKey(); Long key = entry.getKey();
String day = iso8601Formatter.apply(key - timeZone.getOffset(key));// Remove the timezone offset since Calendar uses UTC
series.append(",{\"title\": \"New: ").append(newPlayers) series.append(",{\"title\": \"New: ").append(newPlayers)
.append("\",\"start\":\"").append(day) .append("\",\"start\":\"").append(day)
.append("\",\"color\": \"").append(theme.getValue(ThemeVal.LIGHT_GREEN)).append('"') .append("\",\"color\": \"").append(theme.getValue(ThemeVal.LIGHT_GREEN)).append('"')
.append("}"); .append("}");
} }
} }
private void appendSessionRelatedData(StringBuilder series) { private void appendUniquePlayers(StringBuilder series) {
// Has a timezone offset
for (Map.Entry<Long, Integer> entry : uniquePerDay.entrySet()) { for (Map.Entry<Long, Integer> entry : uniquePerDay.entrySet()) {
if (entry.getValue() <= 0) { long uniquePlayers = entry.getValue();
if (uniquePlayers <= 0) {
continue; continue;
} }
Long key = entry.getKey(); Long key = entry.getKey();
String day = iso8601Formatter.apply(key - timeZone.getOffset(entry.getKey()));// Remove the timezone offset since Calendar uses UTC String day = iso8601Formatter.apply(key - timeZone.getOffset(key));// Remove the timezone offset since Calendar uses UTC
Integer sessionCount = sessionsPerDay.getOrDefault(key, 0);
Long playtime = playtimePerDay.getOrDefault(key, 0L);
long uniquePlayers = entry.getValue();
if (playtime > 0) {
series.append(",{\"title\": \"Playtime: ").append(timeAmountFormatter.apply(playtime))
.append("\",\"start\":\"").append(day)
.append("\",\"color\": \"").append(theme.getValue(ThemeVal.GREEN)).append('"')
.append("}");
}
if (sessionCount > 0) {
series.append(",{\"title\": \"Sessions: ").append(sessionCount)
.append("\",\"start\":\"").append(day)
.append("\",\"color\": \"").append(theme.getValue(ThemeVal.TEAL)).append('"')
.append("}");
}
series.append(",{\"title\": \"Unique: ").append(uniquePlayers) series.append(",{\"title\": \"Unique: ").append(uniquePlayers)
.append("\",\"start\":\"").append(day) .append("\",\"start\":\"").append(day)
@ -119,12 +113,35 @@ public class ServerCalendar {
} }
} }
private Map<String, Integer> getRegisteredByDay() { private void appendPlaytime(StringBuilder series) {
Map<String, Integer> registeredByDay = new HashMap<>(); for (Map.Entry<Long, Long> entry : playtimePerDay.entrySet()) {
for (Map.Entry<Long, Integer> entry : newPerDay.entrySet()) { long playtime = entry.getValue();
String day = iso8601Formatter.apply(entry.getKey()); if (playtime <= 0) {
registeredByDay.put(day, entry.getValue()); continue;
}
Long key = entry.getKey();
String day = iso8601Formatter.apply(key - timeZone.getOffset(key));// Remove the timezone offset since Calendar uses UTC
series.append(",{\"title\": \"Playtime: ").append(timeAmountFormatter.apply(playtime))
.append("\",\"start\":\"").append(day)
.append("\",\"color\": \"").append(theme.getValue(ThemeVal.GREEN)).append('"')
.append("}");
}
}
private void appendSessionCounts(StringBuilder series) {
for (Map.Entry<Long, Integer> entry : sessionsPerDay.entrySet()) {
int sessionCount = entry.getValue();
if (sessionCount <= 0) {
continue;
}
Long key = entry.getKey();
String day = iso8601Formatter.apply(key - timeZone.getOffset(key));// Remove the timezone offset since Calendar uses UTC
series.append(",{\"title\": \"Sessions: ").append(sessionCount)
.append("\",\"start\":\"").append(day)
.append("\",\"color\": \"").append(theme.getValue(ThemeVal.TEAL)).append('"')
.append("}");
} }
return registeredByDay;
} }
} }

View File

@ -454,7 +454,7 @@
</tr> </tr>
<tr> <tr>
<td><i class="col-green far fa-fw fa-clock"></i> Average Playtime / <td><i class="col-green far fa-fw fa-clock"></i> Average Playtime /
Player Day
</td> </td>
<td id="data_playtime_30d_avg"></td> <td id="data_playtime_30d_avg"></td>
<td id="data_playtime_7d_avg"></td> <td id="data_playtime_7d_avg"></td>