Skip to content

Commit fd8588c

Browse files
committed
Add NEW_PLAYER_RETENTION Datapoint
1 parent 2f3d07f commit fd8588c

12 files changed

Lines changed: 118 additions & 19 deletions

File tree

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ public enum WebPermission implements Supplier<String>, Lang {
150150
DATA_NETWORK_REGULAR_PLAYERS("See Regular players -datapoint of network"),
151151
DATA_SERVER_NEW_PLAYERS("See New players -datapoint of servers"),
152152
DATA_NETWORK_NEW_PLAYERS("See New players -datapoint of network"),
153+
DATA_SERVER_NEW_PLAYER_RETENTION("See New player retention -datapoint of servers"),
154+
DATA_NETWORK_NEW_PLAYER_RETENTION("See New player retention -datapoint of network"),
153155
DATA_PLAYER_SESSION_COUNT("See Session count -datapoint of players"),
154156
DATA_SERVER_SESSION_COUNT("See Session count -datapoint of servers"),
155157
DATA_NETWORK_SESSION_COUNT("See Session count -datapoint of network"),
@@ -160,8 +162,8 @@ public enum WebPermission implements Supplier<String>, Lang {
160162
DATA_NETWORK_PLAYTIME_PER_PLAYER_AVERAGE("See Average playtime per player -datapoint of network"),
161163
DATA_SERVER_PLAYERS_ONLINE_PEAK("See Player online peak -datapoint of servers"),
162164
DATA_NETWORK_PLAYERS_ONLINE_PEAK("See Player online peak -datapoint of network"),
163-
DATA_SERVER_PLAYERS_ONLINE("See Players online -datapoint of servers"),
164-
DATA_NETWORK_PLAYERS_ONLINE("See Players online -datapoint of network"),
165+
DATA_SERVER_PLAYERS_ONLINE_CURRENT("See Players online -datapoint of servers"),
166+
DATA_NETWORK_PLAYERS_ONLINE_CURRENT("See Players online -datapoint of network"),
165167
DATA_SERVER_UPTIME_CURRENT("See Current uptime -datapoint of servers"),
166168
DATA_NETWORK_UPTIME_CURRENT("See Current uptime -datapoint of network"),
167169
DATA_PLAYER_MOB_KILLS("See Mob kills -datapoint of players"),

Plan/common/src/main/java/com/djrapitops/plan/delivery/export/ServerPageExporter.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ public void exportJSON(Path toDirectory, ServerUUID serverUUID) throws IOExcepti
170170
datapointType + DatapointType.UPTIME_CURRENT + server,
171171
datapointType + DatapointType.TPS_AVERAGE + afterMillis + TimeUnit.DAYS.toMillis(7) + server,
172172
datapointType + DatapointType.UNIQUE_PLAYERS_AVERAGE + afterMillis + TimeUnit.DAYS.toMillis(7) + server,
173+
datapointType + DatapointType.NEW_PLAYER_RETENTION + afterMillis + TimeUnit.DAYS.toMillis(7) + server,
173174
// Week comparison
174175
datapointType + DatapointType.UNIQUE_PLAYERS_COUNT + afterMillis + TimeUnit.DAYS.toMillis(14) + beforeMillis + TimeUnit.DAYS.toMillis(7L) + server,
175176
datapointType + DatapointType.NEW_PLAYERS + afterMillis + TimeUnit.DAYS.toMillis(14) + beforeMillis + TimeUnit.DAYS.toMillis(7L) + server,

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public enum DatapointType {
4444
SESSION_LENGTH_AVERAGE(SessionLengthAverage.class, DatapointCacheKey.SESSION),
4545
PLAYTIME_PER_PLAYER_AVERAGE(PlaytimePerPlayerAverage.class, DatapointCacheKey.SESSION),
4646
PLAYERS_ONLINE_PEAK(PlayersOnlinePeak.class, DatapointCacheKey.TPS),
47-
PLAYERS_ONLINE(PlayersOnline.class, DatapointCacheKey.TPS),
47+
PLAYERS_ONLINE(PlayersOnlineCurrent.class, DatapointCacheKey.TPS),
4848
UPTIME_CURRENT(UptimeCurrent.class),
4949
MOB_KILLS(MobKills.class, DatapointCacheKey.SESSION),
5050
PLAYER_KILLS(PlayerKills.class, DatapointCacheKey.SESSION),
@@ -56,7 +56,8 @@ public enum DatapointType {
5656
RAM_AVERAGE(RAMAverage.class, DatapointCacheKey.TPS),
5757
ENTITIES_AVERAGE(EntitiesAverage.class, DatapointCacheKey.TPS),
5858
CHUNKS_AVERAGE(ChunksAverage.class, DatapointCacheKey.TPS),
59-
UNIQUE_PLAYERS_AVERAGE(UniquePlayersPerDayAverage.class, DatapointCacheKey.SESSION);
59+
UNIQUE_PLAYERS_AVERAGE(UniquePlayersPerDayAverage.class, DatapointCacheKey.SESSION),
60+
NEW_PLAYER_RETENTION(NewPlayerRetention.class, DatapointCacheKey.SESSION);
6061

6162
private final Class<? extends Datapoint<?>> datapointClass;
6263
private final DatapointCacheKey[] cacheKeys;

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ public interface DatapointModule {
9696

9797
@Binds
9898
@IntoSet
99-
Datapoint<?> bindPlayersOnline(PlayersOnline playersOnline);
99+
Datapoint<?> bindPlayersOnline(PlayersOnlineCurrent playersOnlineCurrent);
100100

101101
@Binds
102102
@IntoSet
@@ -140,5 +140,9 @@ public interface DatapointModule {
140140

141141
@Binds
142142
@IntoSet
143-
Datapoint<?> bindUniquePlayersAveragePerDay(UniquePlayersPerDayAverage uniquePlayersPerDayAverage);
143+
Datapoint<?> bindUniquePlayersPerDayAverage(UniquePlayersPerDayAverage uniquePlayersPerDayAverage);
144+
145+
@Binds
146+
@IntoSet
147+
Datapoint<?> bindNewPlayerRetention(NewPlayerRetention newPlayerRetention);
144148
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
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.OutOf;
20+
import com.djrapitops.plan.delivery.domain.auth.WebPermission;
21+
import com.djrapitops.plan.delivery.domain.datatransfer.GenericFilter;
22+
import com.djrapitops.plan.delivery.rendering.json.datapoint.Datapoint;
23+
import com.djrapitops.plan.delivery.rendering.json.datapoint.DatapointType;
24+
import com.djrapitops.plan.delivery.web.resolver.exception.BadRequestException;
25+
import com.djrapitops.plan.storage.database.DBSystem;
26+
import com.djrapitops.plan.storage.database.Database;
27+
import com.djrapitops.plan.storage.database.queries.analysis.PlayerCountQueries;
28+
29+
import javax.inject.Inject;
30+
import javax.inject.Singleton;
31+
import java.util.Optional;
32+
33+
/**
34+
* Datapoint for New player retention.
35+
* <p>
36+
* New player retention is calculated by checking if a player registered within the timeframe,
37+
* and played within the latter half of the timeframe.
38+
*
39+
* @author AuroraLS3
40+
*/
41+
@Singleton
42+
public class NewPlayerRetention implements Datapoint<OutOf> {
43+
44+
private final DBSystem dbSystem;
45+
46+
@Inject
47+
public NewPlayerRetention(DBSystem dbSystem) {this.dbSystem = dbSystem;}
48+
49+
@Override
50+
public Optional<OutOf> getValue(GenericFilter filter) {
51+
if (filter.getPlayerUUID().isPresent()) {
52+
throw new BadRequestException("NEW_PLAYER_RETENTION does not support player parameter");
53+
}
54+
55+
Database db = dbSystem.getDatabase();
56+
int new7d = db.query(PlayerCountQueries.newPlayerCount(filter.getAfter(), filter.getBefore(), filter.getServerUUIDs()));
57+
int retained7d = db.query(PlayerCountQueries.retainedPlayerCount(filter.getAfter(), filter.getBefore(), filter.getServerUUIDs()));
58+
return Optional.of(new OutOf(retained7d, new7d, FormatType.NONE));
59+
}
60+
61+
@Override
62+
public WebPermission getPermission(GenericFilter filter) {
63+
if (filter.getPlayerUUID().isPresent()) {
64+
return WebPermission.DATA_PLAYER;
65+
} else if (!filter.getServerUUIDs().isEmpty()) {
66+
return WebPermission.DATA_SERVER_NEW_PLAYER_RETENTION;
67+
} else {
68+
return WebPermission.DATA_NETWORK_NEW_PLAYER_RETENTION;
69+
}
70+
}
71+
72+
@Override
73+
public DatapointType getType() {
74+
return DatapointType.NEW_PLAYER_RETENTION;
75+
}
76+
77+
@Override
78+
public FormatType getFormatType() {
79+
return FormatType.SPECIAL;
80+
}
81+
}

Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/json/datapoint/types/PlayersOnline.java renamed to Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/json/datapoint/types/PlayersOnlineCurrent.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,14 @@
4040
* @author AuroraLS3
4141
*/
4242
@Singleton
43-
public class PlayersOnline implements Datapoint<Integer> {
43+
public class PlayersOnlineCurrent implements Datapoint<Integer> {
4444

4545
private final DBSystem dbSystem;
4646
private final ServerInfo serverInfo;
4747
private final ServerSensor<?> serverSensor;
4848

4949
@Inject
50-
public PlayersOnline(DBSystem dbSystem, ServerInfo serverInfo, ServerSensor<?> serverSensor) {
50+
public PlayersOnlineCurrent(DBSystem dbSystem, ServerInfo serverInfo, ServerSensor<?> serverSensor) {
5151
this.dbSystem = dbSystem;
5252
this.serverInfo = serverInfo;
5353
this.serverSensor = serverSensor;
@@ -95,9 +95,9 @@ public WebPermission getPermission(GenericFilter filter) {
9595
if (filter.getPlayerUUID().isPresent()) {
9696
return WebPermission.DATA_PLAYER;
9797
} else if (!filter.getServerUUIDs().isEmpty()) {
98-
return WebPermission.DATA_SERVER_PLAYERS_ONLINE;
98+
return WebPermission.DATA_SERVER_PLAYERS_ONLINE_CURRENT;
9999
} else {
100-
return WebPermission.DATA_NETWORK_PLAYERS_ONLINE;
100+
return WebPermission.DATA_NETWORK_PLAYERS_ONLINE_CURRENT;
101101
}
102102
}
103103

Plan/common/src/main/java/com/djrapitops/plan/settings/theme/ThemeVal.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public enum ThemeVal {
5353
WHITE("Colors.Extra.White", "#fff"),
5454

5555
GRAPH_PUNCHCARD("GraphColors.PunchCard", "#222"),
56-
GRAPH_PLAYERS_ONLINE("GraphColors.PlayersOnline", "#1E90FF"),
56+
GRAPH_PLAYERS_ONLINE("GraphColors.PlayersOnlineCurrent", "#1E90FF"),
5757
GRAPH_TPS_HIGH("GraphColors.TPS.High", "#267F00"),
5858
GRAPH_TPS_MED("GraphColors.TPS.Medium", "#e5cc12"),
5959
GRAPH_TPS_LOW("GraphColors.TPS.Low", "#b74343"),

Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/analysis/PlayerCountQueries.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,10 @@ public static Query<Integer> averageNewPlayerCount(long after, long before, long
446446
}
447447

448448
public static Query<Integer> retainedPlayerCount(long after, long before, ServerUUID serverUUID) {
449+
return retainedPlayerCount(after, before, List.of(serverUUID));
450+
}
451+
452+
public static Query<Integer> retainedPlayerCount(long after, long before, List<ServerUUID> serverUUIDs) {
449453
String selectUniqueUUIDs = SELECT + DISTINCT + "s." + SessionsTable.USER_ID +
450454
FROM + SessionsTable.TABLE_NAME + " s" +
451455
INNER_JOIN + UserInfoTable.TABLE_NAME + " ux" +
@@ -456,7 +460,7 @@ public static Query<Integer> retainedPlayerCount(long after, long before, Server
456460
AND + UserInfoTable.REGISTERED + "<=?" +
457461
AND + SessionsTable.SESSION_START + ">=?" +
458462
AND + SessionsTable.SESSION_END + "<=?" +
459-
AND + "se." + ServerTable.SERVER_UUID + "=?";
463+
(serverUUIDs.isEmpty() ? "" : AND + "se." + ServerTable.SERVER_UUID + " IN (" + ServerTable.uuids(serverUUIDs) + ')');
460464

461465
return new QueryStatement<>(selectUniqueUUIDs) {
462466
@Override
@@ -468,7 +472,6 @@ public void prepare(PreparedStatement statement) throws SQLException {
468472
long half = before - (before - after) / 2;
469473
statement.setLong(3, half);
470474
statement.setLong(4, before);
471-
statement.setString(5, serverUUID.toString());
472475
}
473476

474477
@Override

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,9 @@ static Stream<Arguments> testCases() {
210210
Arguments.of("/v1/datapoint?type=NEW_PLAYERS", WebPermission.DATA_NETWORK_NEW_PLAYERS, 200, 403),
211211
Arguments.of("/v1/datapoint?type=NEW_PLAYERS&server=" + TestConstants.SERVER_UUID_STRING, WebPermission.DATA_SERVER_NEW_PLAYERS, 200, 403),
212212
Arguments.of("/v1/datapoint?type=NEW_PLAYERS&player=" + TestConstants.PLAYER_ONE_UUID_STRING, WebPermission.DATA_PLAYER, 400, 403),
213+
Arguments.of("/v1/datapoint?type=NEW_PLAYER_RETENTION", WebPermission.DATA_NETWORK_NEW_PLAYER_RETENTION, 200, 403),
214+
Arguments.of("/v1/datapoint?type=NEW_PLAYER_RETENTION&server=" + TestConstants.SERVER_UUID_STRING, WebPermission.DATA_SERVER_NEW_PLAYER_RETENTION, 200, 403),
215+
Arguments.of("/v1/datapoint?type=NEW_PLAYER_RETENTION&player=" + TestConstants.PLAYER_ONE_UUID_STRING, WebPermission.DATA_PLAYER, 400, 403),
213216
Arguments.of("/v1/datapoint?type=SESSION_COUNT", WebPermission.DATA_NETWORK_SESSION_COUNT, 200, 403),
214217
Arguments.of("/v1/datapoint?type=SESSION_COUNT&server=" + TestConstants.SERVER_UUID_STRING, WebPermission.DATA_SERVER_SESSION_COUNT, 200, 403),
215218
Arguments.of("/v1/datapoint?type=SESSION_COUNT&player=" + TestConstants.PLAYER_ONE_UUID_STRING, WebPermission.DATA_PLAYER_SESSION_COUNT, 200, 403),
@@ -222,8 +225,8 @@ static Stream<Arguments> testCases() {
222225
Arguments.of("/v1/datapoint?type=PLAYERS_ONLINE_PEAK", WebPermission.DATA_NETWORK_PLAYERS_ONLINE_PEAK, 200, 403),
223226
Arguments.of("/v1/datapoint?type=PLAYERS_ONLINE_PEAK&server=" + TestConstants.SERVER_UUID_STRING, WebPermission.DATA_SERVER_PLAYERS_ONLINE_PEAK, 200, 403),
224227
Arguments.of("/v1/datapoint?type=PLAYERS_ONLINE_PEAK&player=" + TestConstants.PLAYER_ONE_UUID_STRING, WebPermission.DATA_PLAYER, 400, 403),
225-
Arguments.of("/v1/datapoint?type=PLAYERS_ONLINE", WebPermission.DATA_NETWORK_PLAYERS_ONLINE, 200, 403),
226-
Arguments.of("/v1/datapoint?type=PLAYERS_ONLINE&server=" + TestConstants.SERVER_UUID_STRING, WebPermission.DATA_SERVER_PLAYERS_ONLINE, 200, 403),
228+
Arguments.of("/v1/datapoint?type=PLAYERS_ONLINE", WebPermission.DATA_NETWORK_PLAYERS_ONLINE_CURRENT, 200, 403),
229+
Arguments.of("/v1/datapoint?type=PLAYERS_ONLINE&server=" + TestConstants.SERVER_UUID_STRING, WebPermission.DATA_SERVER_PLAYERS_ONLINE_CURRENT, 200, 403),
227230
Arguments.of("/v1/datapoint?type=PLAYERS_ONLINE&player=" + TestConstants.PLAYER_ONE_UUID_STRING, WebPermission.DATA_PLAYER, 400, 403),
228231
Arguments.of("/v1/datapoint?type=UPTIME_CURRENT", WebPermission.DATA_NETWORK_UPTIME_CURRENT, 200, 403),
229232
Arguments.of("/v1/datapoint?type=UPTIME_CURRENT&server=" + TestConstants.SERVER_UUID_STRING, WebPermission.DATA_SERVER_UPTIME_CURRENT, 200, 403),

Plan/react/dashboard/src/components/datapoint/QueryDatapoint.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ const FormattedOutOf = ({outOf}: { outOf: OutOf }) => {
4545
return (
4646
<>
4747
<Format value={outOf.value} formatType={outOf.formatType}/>
48+
{' / '}
49+
<Format value={outOf.max} formatType={outOf.formatType}/>
4850
{' '}({formatDecimals(outOf.percentage * 100)}%)
4951
</>
5052
)

0 commit comments

Comments
 (0)