Skip to content

Commit f19db4d

Browse files
committed
Add PLAYTIME_PER_DAY_AVERAGE datapoint
1 parent 2fd7ee9 commit f19db4d

6 files changed

Lines changed: 180 additions & 25 deletions

File tree

Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/auth/WebPermission.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,9 @@ public enum WebPermission implements Supplier<String>, Lang {
125125
DATA_PLAYER_PLAYTIME("See Playtime datapoint of players"),
126126
DATA_SERVER_PLAYTIME("See Playtime datapoint of servers"),
127127
DATA_NETWORK_PLAYTIME("See Playtime datapoint of network"),
128+
DATA_PLAYER_PLAYTIME_PER_DAY_AVERAGE("See Average playtime per day -datapoint of players"),
129+
DATA_SERVER_PLAYTIME_PER_DAY_AVERAGE("See Average playtime per day -datapoint of servers"),
130+
DATA_NETWORK_PLAYTIME_PER_DAY_AVERAGE("See Average playtime per day -datapoint of network"),
128131
DATA_PLAYER_AFK_TIME("See AFK datapoint of players"),
129132
DATA_SERVER_AFK_TIME("See AFK datapoint of servers"),
130133
DATA_NETWORK_AFK_TIME("See AFK datapoint of network"),

Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/json/datapoint/DatapointType.java

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -29,38 +29,40 @@
2929
* @author AuroraLS3
3030
*/
3131
public enum DatapointType {
32-
PLAYTIME(Playtime.class, DatapointCacheKey.SESSION),
33-
WORLD_PIE(WorldPie.class, DatapointCacheKey.SESSION),
3432
AFK_TIME(AfkTime.class, DatapointCacheKey.SESSION),
3533
AFK_TIME_PERCENTAGE(AfkTimePercentage.class, DatapointCacheKey.SESSION),
36-
SERVER_OCCUPIED(ServerOccupied.class, DatapointCacheKey.SESSION, DatapointCacheKey.TPS),
34+
CHUNKS_AVERAGE(ChunksAverage.class, DatapointCacheKey.TPS),
35+
CPU_AVERAGE(CPUAverage.class, DatapointCacheKey.TPS),
36+
DEATHS(Deaths.class, DatapointCacheKey.SESSION),
37+
DOWNTIME(Downtime.class, DatapointCacheKey.TPS),
38+
ENTITIES_AVERAGE(EntitiesAverage.class, DatapointCacheKey.TPS),
39+
MOB_KILLS(MobKills.class, DatapointCacheKey.SESSION),
3740
MOST_ACTIVE_GAME_MODE(MostActiveGameMode.class, DatapointCacheKey.SESSION),
3841
MOST_ACTIVE_WORLD(MostActiveWorld.class, DatapointCacheKey.SESSION),
39-
SERVER_PIE(ServerPie.class, DatapointCacheKey.SESSION),
40-
UNIQUE_PLAYERS_COUNT(UniquePlayersCount.class, DatapointCacheKey.SESSION),
42+
MSPT_AVERAGE(MSPTAverage.class, DatapointCacheKey.TPS),
4143
NEW_PLAYERS(NewPlayers.class, DatapointCacheKey.SESSION),
44+
NEW_PLAYERS_AVERAGE(NewPlayersPerDayAverage.class, DatapointCacheKey.SESSION),
45+
NEW_PLAYER_RETENTION(NewPlayerRetention.class, DatapointCacheKey.SESSION),
46+
PLAYERS_ONLINE(PlayersOnlineCurrent.class, DatapointCacheKey.TPS),
47+
PLAYERS_ONLINE_AVERAGE(PlayersOnlineAverage.class, DatapointCacheKey.TPS),
48+
PLAYERS_ONLINE_PEAK(PlayersOnlinePeak.class, DatapointCacheKey.TPS),
49+
PLAYER_KILLS(PlayerKills.class, DatapointCacheKey.SESSION),
50+
PLAYTIME(Playtime.class, DatapointCacheKey.SESSION),
51+
PLAYTIME_PER_DAY_AVERAGE(PlaytimePerDayAverage.class, DatapointCacheKey.SESSION),
52+
PLAYTIME_PER_PLAYER_AVERAGE(PlaytimePerPlayerAverage.class, DatapointCacheKey.SESSION),
53+
RAM_AVERAGE(RAMAverage.class, DatapointCacheKey.TPS),
4254
REGULAR_PLAYERS(RegularPlayers.class, DatapointCacheKey.SESSION),
55+
SERVER_OCCUPIED(ServerOccupied.class, DatapointCacheKey.SESSION, DatapointCacheKey.TPS),
56+
SERVER_PIE(ServerPie.class, DatapointCacheKey.SESSION),
4357
SESSION_COUNT(SessionCount.class, DatapointCacheKey.SESSION),
4458
SESSION_LENGTH_AVERAGE(SessionLengthAverage.class, DatapointCacheKey.SESSION),
45-
PLAYTIME_PER_PLAYER_AVERAGE(PlaytimePerPlayerAverage.class, DatapointCacheKey.SESSION),
46-
PLAYERS_ONLINE_PEAK(PlayersOnlinePeak.class, DatapointCacheKey.TPS),
47-
PLAYERS_ONLINE(PlayersOnlineCurrent.class, DatapointCacheKey.TPS),
48-
UPTIME_CURRENT(UptimeCurrent.class),
49-
MOB_KILLS(MobKills.class, DatapointCacheKey.SESSION),
50-
PLAYER_KILLS(PlayerKills.class, DatapointCacheKey.SESSION),
51-
DEATHS(Deaths.class, DatapointCacheKey.SESSION),
52-
PLAYERS_ONLINE_AVERAGE(PlayersOnlineAverage.class, DatapointCacheKey.TPS),
5359
TPS_AVERAGE(TPSAverage.class, DatapointCacheKey.TPS),
54-
MSPT_AVERAGE(MSPTAverage.class, DatapointCacheKey.TPS),
55-
CPU_AVERAGE(CPUAverage.class, DatapointCacheKey.TPS),
56-
RAM_AVERAGE(RAMAverage.class, DatapointCacheKey.TPS),
57-
ENTITIES_AVERAGE(EntitiesAverage.class, DatapointCacheKey.TPS),
58-
CHUNKS_AVERAGE(ChunksAverage.class, DatapointCacheKey.TPS),
59-
UNIQUE_PLAYERS_AVERAGE(UniquePlayersPerDayAverage.class, DatapointCacheKey.SESSION),
60-
NEW_PLAYER_RETENTION(NewPlayerRetention.class, DatapointCacheKey.SESSION),
6160
TPS_LOW_SPIKES(TPSLowSpikes.class, DatapointCacheKey.TPS),
62-
DOWNTIME(Downtime.class, DatapointCacheKey.TPS),
63-
NEW_PLAYERS_AVERAGE(NewPlayersPerDayAverage.class, DatapointCacheKey.SESSION);
61+
UNIQUE_PLAYERS_AVERAGE(UniquePlayersPerDayAverage.class, DatapointCacheKey.SESSION),
62+
UNIQUE_PLAYERS_COUNT(UniquePlayersCount.class, DatapointCacheKey.SESSION),
63+
UPTIME_CURRENT(UptimeCurrent.class),
64+
WORLD_PIE(WorldPie.class, DatapointCacheKey.SESSION),
65+
;
6466

6567
private final Class<? extends Datapoint<?>> datapointClass;
6668
private final DatapointCacheKey[] cacheKeys;

Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/json/datapoint/types/DatapointModule.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,4 +157,8 @@ public interface DatapointModule {
157157
@Binds
158158
@IntoSet
159159
Datapoint<?> bindNewPlayersPerDayAverage(NewPlayersPerDayAverage newPlayersPerDayAverage);
160+
161+
@Binds
162+
@IntoSet
163+
Datapoint<?> bindPlaytimePerDayAverage(PlaytimePerDayAverage playtimePerDayAverage);
160164
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* This file is part of Player Analytics (Plan).
3+
*
4+
* Plan is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU Lesser General Public License v3 as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* Plan is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU Lesser General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU Lesser General Public License
15+
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
16+
*/
17+
package com.djrapitops.plan.delivery.rendering.json.datapoint.types;
18+
19+
import com.djrapitops.plan.delivery.domain.auth.WebPermission;
20+
import com.djrapitops.plan.delivery.domain.datatransfer.GenericFilter;
21+
import com.djrapitops.plan.delivery.rendering.json.datapoint.Datapoint;
22+
import com.djrapitops.plan.delivery.rendering.json.datapoint.DatapointType;
23+
import com.djrapitops.plan.delivery.rendering.json.datapoint.SupportedFilters;
24+
import com.djrapitops.plan.settings.config.PlanConfig;
25+
import com.djrapitops.plan.storage.database.DBSystem;
26+
import com.djrapitops.plan.storage.database.queries.objects.SessionQueries;
27+
28+
import javax.inject.Inject;
29+
import javax.inject.Singleton;
30+
import java.util.Optional;
31+
import java.util.UUID;
32+
33+
/**
34+
* Playtime per day average datapoint.
35+
* <p>
36+
* Playtime is grouped in buckets by date based on timeszone defined in config, and then averaged.
37+
*
38+
* @author AuroraLS3
39+
*/
40+
@Singleton
41+
public class PlaytimePerDayAverage implements Datapoint<Long> {
42+
43+
private final PlanConfig config;
44+
private final DBSystem dbSystem;
45+
46+
@Inject
47+
public PlaytimePerDayAverage(PlanConfig config, DBSystem dbSystem) {
48+
this.config = config;
49+
this.dbSystem = dbSystem;
50+
}
51+
52+
@Override
53+
public Optional<Long> getValue(GenericFilter filter) {
54+
Optional<UUID> player = filter.getPlayerUUID();
55+
if (player.isPresent()) {
56+
return Optional.of(dbSystem.getDatabase().query(SessionQueries.averagePlaytimePerDay(
57+
filter.getAfter(), filter.getBefore(), config.getTimeZone().getOffset(filter.getBefore()), player.get(), filter.getServerUUIDs())
58+
));
59+
}
60+
61+
if (!filter.getServerUUIDs().isEmpty()) {
62+
return Optional.of(dbSystem.getDatabase().query(SessionQueries.averagePlaytimePerDay(
63+
filter.getAfter(), filter.getBefore(), config.getTimeZone().getOffset(filter.getBefore()), filter.getServerUUIDs())
64+
));
65+
}
66+
67+
return Optional.of(dbSystem.getDatabase().query(SessionQueries.averagePlaytimePerDay(
68+
filter.getAfter(), filter.getBefore(), config.getTimeZone().getOffset(filter.getBefore()))
69+
));
70+
}
71+
72+
@Override
73+
public FormatType getFormatType() {
74+
return FormatType.TIME_AMOUNT;
75+
}
76+
77+
@Override
78+
public WebPermission getPermission(GenericFilter filter) {
79+
if (filter.getPlayerUUID().isPresent()) {
80+
return WebPermission.DATA_PLAYER_PLAYTIME_PER_DAY_AVERAGE;
81+
} else if (!filter.getServerUUIDs().isEmpty()) {
82+
return WebPermission.DATA_SERVER_PLAYTIME_PER_DAY_AVERAGE;
83+
} else {
84+
return WebPermission.DATA_NETWORK_PLAYTIME_PER_DAY_AVERAGE;
85+
}
86+
}
87+
88+
@Override
89+
public DatapointType getType() {
90+
return DatapointType.PLAYTIME_PER_DAY_AVERAGE;
91+
}
92+
93+
@Override
94+
public SupportedFilters[] getSupportedFilters() {
95+
return SupportedFilters.all();
96+
}
97+
}

Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/objects/SessionQueries.java

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -728,18 +728,29 @@ public NavigableMap<Long, Long> processResults(ResultSet set) throws SQLExceptio
728728
};
729729
}
730730

731+
public static Query<Long> averagePlaytimePerDay(long after, long before, long timeZoneOffset) {
732+
return averagePlaytimePerDay(after, before, timeZoneOffset, List.of());
733+
}
734+
731735
public static Query<Long> averagePlaytimePerDay(long after, long before, long timeZoneOffset, ServerUUID serverUUID) {
736+
return averagePlaytimePerDay(after, before, timeZoneOffset, List.of(serverUUID));
737+
}
738+
739+
public static Query<Long> averagePlaytimePerDay(long after, long before, long timeZoneOffset, List<ServerUUID> serverUUIDs) {
732740
return database -> {
733741
Sql sql = database.getSql();
734742
String selectPlaytimePerDay = SELECT +
743+
"date,SUM(playtime) as playtime" +
744+
FROM + "(" + SELECT +
735745
sql.dateToEpochSecond(sql.dateToDayStamp(sql.epochSecondToDate('(' + SessionsTable.SESSION_START + "+?)/1000"))) +
736746
"*1000 as date," +
737-
"SUM(" + SessionsTable.SESSION_END + '-' + SessionsTable.SESSION_START + ") as playtime" +
747+
SessionsTable.SESSION_END + '-' + SessionsTable.SESSION_START + " as playtime" +
738748
FROM + SessionsTable.TABLE_NAME + " t" +
739749
INNER_JOIN + ServerTable.TABLE_NAME + " s ON s." + ServerTable.ID + "=t." + SessionsTable.SERVER_ID +
740750
WHERE + SessionsTable.SESSION_END + "<=?" +
741751
AND + SessionsTable.SESSION_START + ">=?" +
742-
AND + "s." + ServerTable.SERVER_UUID + "=?" +
752+
(serverUUIDs.isEmpty() ? "" : AND + "s." + ServerTable.SERVER_UUID + " IN (" + ServerTable.uuids(serverUUIDs) + ")") +
753+
") q1" +
743754
GROUP_BY + "date";
744755
String selectAverage = SELECT + "AVG(playtime) as average" + FROM + '(' + selectPlaytimePerDay + ") q1";
745756

@@ -749,7 +760,42 @@ public void prepare(PreparedStatement statement) throws SQLException {
749760
statement.setLong(1, timeZoneOffset);
750761
statement.setLong(2, before);
751762
statement.setLong(3, after);
752-
statement.setString(4, serverUUID.toString());
763+
}
764+
765+
@Override
766+
public Long processResults(ResultSet set) throws SQLException {
767+
return set.next() ? (long) set.getDouble("average") : 0;
768+
}
769+
});
770+
};
771+
}
772+
773+
public static Query<Long> averagePlaytimePerDay(long after, long before, long timeZoneOffset, UUID playerUUID, List<ServerUUID> serverUUIDs) {
774+
return database -> {
775+
Sql sql = database.getSql();
776+
String selectPlaytimePerDay = SELECT +
777+
"date,SUM(playtime) as playtime" +
778+
FROM + "(" + SELECT +
779+
sql.dateToEpochSecond(sql.dateToDayStamp(sql.epochSecondToDate('(' + SessionsTable.SESSION_START + "+?)/1000"))) +
780+
"*1000 as date," +
781+
SessionsTable.SESSION_END + '-' + SessionsTable.SESSION_START + " as playtime" +
782+
FROM + SessionsTable.TABLE_NAME + " t" +
783+
INNER_JOIN + ServerTable.TABLE_NAME + " s ON s." + ServerTable.ID + "=t." + SessionsTable.SERVER_ID +
784+
WHERE + SessionsTable.SESSION_END + "<=?" +
785+
AND + SessionsTable.SESSION_START + ">=?" +
786+
AND + SessionsTable.USER_ID + "=" + UsersTable.SELECT_USER_ID +
787+
(serverUUIDs.isEmpty() ? "" : AND + "s." + ServerTable.SERVER_UUID + " IN (" + ServerTable.uuids(serverUUIDs) + ")") +
788+
") q1" +
789+
GROUP_BY + "date";
790+
String selectAverage = SELECT + "AVG(playtime) as average" + FROM + '(' + selectPlaytimePerDay + ") q1";
791+
792+
return database.query(new QueryStatement<Long>(selectAverage, 100) {
793+
@Override
794+
public void prepare(PreparedStatement statement) throws SQLException {
795+
statement.setLong(1, timeZoneOffset);
796+
statement.setLong(2, before);
797+
statement.setLong(3, after);
798+
statement.setString(4, playerUUID.toString());
753799
}
754800

755801
@Override

Plan/common/src/test/java/com/djrapitops/plan/delivery/webserver/AccessControlTest.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,9 @@ static Stream<Arguments> testCases() {
181181
Arguments.of("/v1/datapoint?type=PLAYTIME", WebPermission.DATA_NETWORK_PLAYTIME, 200, 403),
182182
Arguments.of("/v1/datapoint?type=PLAYTIME&server=" + TestConstants.SERVER_UUID_STRING, WebPermission.DATA_SERVER_PLAYTIME, 200, 403),
183183
Arguments.of("/v1/datapoint?type=PLAYTIME&player=" + TestConstants.PLAYER_ONE_UUID_STRING, WebPermission.DATA_PLAYER_PLAYTIME, 200, 403),
184+
Arguments.of("/v1/datapoint?type=PLAYTIME_PER_DAY_AVERAGE", WebPermission.DATA_NETWORK_PLAYTIME_PER_DAY_AVERAGE, 200, 403),
185+
Arguments.of("/v1/datapoint?type=PLAYTIME_PER_DAY_AVERAGE&server=" + TestConstants.SERVER_UUID_STRING, WebPermission.DATA_SERVER_PLAYTIME_PER_DAY_AVERAGE, 200, 403),
186+
Arguments.of("/v1/datapoint?type=PLAYTIME_PER_DAY_AVERAGE&player=" + TestConstants.PLAYER_ONE_UUID_STRING, WebPermission.DATA_PLAYER_PLAYTIME_PER_DAY_AVERAGE, 200, 403),
184187
Arguments.of("/v1/datapoint?type=AFK_TIME", WebPermission.DATA_NETWORK_AFK_TIME, 200, 403),
185188
Arguments.of("/v1/datapoint?type=AFK_TIME&server=" + TestConstants.SERVER_UUID_STRING, WebPermission.DATA_SERVER_AFK_TIME, 200, 403),
186189
Arguments.of("/v1/datapoint?type=AFK_TIME&player=" + TestConstants.PLAYER_ONE_UUID_STRING, WebPermission.DATA_PLAYER_AFK_TIME, 200, 403),

0 commit comments

Comments
 (0)