Skip to content

Commit 2fd7ee9

Browse files
committed
Add NEW_PLAYER_PER_DAY_AVERAGE datapoint
1 parent edf7d40 commit 2fd7ee9

6 files changed

Lines changed: 136 additions & 4 deletions

File tree

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

Lines changed: 2 additions & 0 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_PLAYERS_AVERAGE("See New players average -datapoint of servers"),
154+
DATA_NETWORK_NEW_PLAYERS_AVERAGE("See New players average -datapoint of network"),
153155
DATA_SERVER_NEW_PLAYER_RETENTION("See New player retention -datapoint of servers"),
154156
DATA_NETWORK_NEW_PLAYER_RETENTION("See New player retention -datapoint of network"),
155157
DATA_PLAYER_SESSION_COUNT("See Session count -datapoint of players"),

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ public enum DatapointType {
5959
UNIQUE_PLAYERS_AVERAGE(UniquePlayersPerDayAverage.class, DatapointCacheKey.SESSION),
6060
NEW_PLAYER_RETENTION(NewPlayerRetention.class, DatapointCacheKey.SESSION),
6161
TPS_LOW_SPIKES(TPSLowSpikes.class, DatapointCacheKey.TPS),
62-
DOWNTIME(Downtime.class, DatapointCacheKey.TPS);
62+
DOWNTIME(Downtime.class, DatapointCacheKey.TPS),
63+
NEW_PLAYERS_AVERAGE(NewPlayersPerDayAverage.class, DatapointCacheKey.SESSION);
6364

6465
private final Class<? extends Datapoint<?>> datapointClass;
6566
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
@@ -153,4 +153,8 @@ public interface DatapointModule {
153153
@Binds
154154
@IntoSet
155155
Datapoint<?> bindDowntime(Downtime downtime);
156+
157+
@Binds
158+
@IntoSet
159+
Datapoint<?> bindNewPlayersPerDayAverage(NewPlayersPerDayAverage newPlayersPerDayAverage);
156160
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
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.delivery.web.resolver.exception.BadRequestException;
25+
import com.djrapitops.plan.settings.config.PlanConfig;
26+
import com.djrapitops.plan.storage.database.DBSystem;
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 players average per day.
35+
* <p>
36+
* Average is computed using the timezone configured in the config,
37+
* splitting day at midnight and counting new players each day,
38+
* and then averaging the number.
39+
*
40+
* @author AuroraLS3
41+
*/
42+
@Singleton
43+
public class NewPlayersPerDayAverage implements Datapoint<Integer> {
44+
45+
private final PlanConfig config;
46+
private final DBSystem dbSystem;
47+
48+
@Inject
49+
public NewPlayersPerDayAverage(PlanConfig config, DBSystem dbSystem) {
50+
this.config = config;
51+
this.dbSystem = dbSystem;
52+
}
53+
54+
@Override
55+
public SupportedFilters[] getSupportedFilters() {
56+
return SupportedFilters.noPlayer();
57+
}
58+
59+
@Override
60+
public Optional<Integer> getValue(GenericFilter filter) {
61+
if (filter.getPlayerUUID().isPresent()) {
62+
throw new BadRequestException("NEW_PLAYERS_AVERAGE does not support player parameter");
63+
}
64+
65+
if (!filter.getServerUUIDs().isEmpty()) {
66+
return Optional.of(dbSystem.getDatabase().query(PlayerCountQueries.averageNewPlayerCount(
67+
filter.getAfter(), filter.getBefore(), config.getTimeZone().getOffset(filter.getBefore()), filter.getServerUUIDs())
68+
));
69+
}
70+
71+
return Optional.of(dbSystem.getDatabase().query(PlayerCountQueries.averageNewPlayerCount(
72+
filter.getAfter(), filter.getBefore(), config.getTimeZone().getOffset(filter.getBefore()))
73+
));
74+
}
75+
76+
@Override
77+
public WebPermission getPermission(GenericFilter filter) {
78+
if (filter.getPlayerUUID().isPresent()) {
79+
return WebPermission.DATA_PLAYER;
80+
} else if (!filter.getServerUUIDs().isEmpty()) {
81+
return WebPermission.DATA_SERVER_NEW_PLAYERS_AVERAGE;
82+
} else {
83+
return WebPermission.DATA_NETWORK_NEW_PLAYERS_AVERAGE;
84+
}
85+
}
86+
87+
@Override
88+
public DatapointType getType() {
89+
return DatapointType.NEW_PLAYERS_AVERAGE;
90+
}
91+
}

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

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -424,23 +424,54 @@ public static Query<NavigableMap<Long, Integer>> hourlyNewPlayerCounts(long afte
424424
}
425425

426426
public static Query<Integer> averageNewPlayerCount(long after, long before, long timeZoneOffset, ServerUUID serverUUID) {
427+
return averageUniquePlayerCount(after, before, timeZoneOffset, List.of(serverUUID));
428+
}
429+
430+
public static Query<Integer> averageNewPlayerCount(long after, long before, long timeZoneOffset) {
431+
return database -> {
432+
Sql sql = database.getSql();
433+
String selectNewPlayersQuery = SELECT +
434+
"date," +
435+
"COUNT(1) as " + PLAYER_COUNT +
436+
FROM + "(" + SELECT +
437+
sql.dateToEpochSecond(sql.dateToDayStamp(sql.epochSecondToDate('(' + UserInfoTable.REGISTERED + "+?)/1000"))) +
438+
"*1000 as date" +
439+
FROM + UsersTable.TABLE_NAME + " t" +
440+
WHERE + UsersTable.REGISTERED + "<=?" +
441+
AND + UsersTable.REGISTERED + ">=?" +
442+
") q1" +
443+
GROUP_BY + "date";
444+
String selectAverage = SELECT + "AVG(" + PLAYER_COUNT + ") as average" + FROM + '(' + selectNewPlayersQuery + ") q1";
445+
446+
return database.queryOptional(selectAverage,
447+
set -> (int) set.getDouble("average"),
448+
timeZoneOffset, before, after)
449+
.orElse(0);
450+
};
451+
}
452+
453+
public static Query<Integer> averageNewPlayerCount(long after, long before, long timeZoneOffset, List<ServerUUID> serverUUIDs) {
427454
return database -> {
428455
Sql sql = database.getSql();
429456
String selectNewPlayersQuery = SELECT +
457+
"date," +
458+
"COUNT(DISTINCT(" + UserInfoTable.USER_ID + ")) as " + PLAYER_COUNT +
459+
FROM + "(" + SELECT +
430460
sql.dateToEpochSecond(sql.dateToDayStamp(sql.epochSecondToDate('(' + UserInfoTable.REGISTERED + "+?)/1000"))) +
431461
"*1000 as date," +
432-
"COUNT(1) as " + PLAYER_COUNT +
462+
UserInfoTable.USER_ID +
433463
FROM + UserInfoTable.TABLE_NAME + " t" +
434464
INNER_JOIN + ServerTable.TABLE_NAME + " s ON s." + ServerTable.ID + "=t." + UserInfoTable.SERVER_ID +
435465
WHERE + UserInfoTable.REGISTERED + "<=?" +
436466
AND + UserInfoTable.REGISTERED + ">=?" +
437-
AND + "s." + ServerTable.SERVER_UUID + "=?" +
467+
AND + "s." + ServerTable.SERVER_UUID + " IN (" + ServerTable.uuids(serverUUIDs) + ")" +
468+
") q1" +
438469
GROUP_BY + "date";
439470
String selectAverage = SELECT + "AVG(" + PLAYER_COUNT + ") as average" + FROM + '(' + selectNewPlayersQuery + ") q1";
440471

441472
return database.queryOptional(selectAverage,
442473
set -> (int) set.getDouble("average"),
443-
timeZoneOffset, before, after, serverUUID.toString())
474+
timeZoneOffset, before, after)
444475
.orElse(0);
445476
};
446477
}

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
@@ -211,6 +211,9 @@ static Stream<Arguments> testCases() {
211211
Arguments.of("/v1/datapoint?type=NEW_PLAYERS", WebPermission.DATA_NETWORK_NEW_PLAYERS, 200, 403),
212212
Arguments.of("/v1/datapoint?type=NEW_PLAYERS&server=" + TestConstants.SERVER_UUID_STRING, WebPermission.DATA_SERVER_NEW_PLAYERS, 200, 403),
213213
Arguments.of("/v1/datapoint?type=NEW_PLAYERS&player=" + TestConstants.PLAYER_ONE_UUID_STRING, WebPermission.DATA_PLAYER, 400, 403),
214+
Arguments.of("/v1/datapoint?type=NEW_PLAYERS_AVERAGE", WebPermission.DATA_NETWORK_NEW_PLAYERS_AVERAGE, 200, 403),
215+
Arguments.of("/v1/datapoint?type=NEW_PLAYERS_AVERAGE&server=" + TestConstants.SERVER_UUID_STRING, WebPermission.DATA_SERVER_NEW_PLAYERS_AVERAGE, 200, 403),
216+
Arguments.of("/v1/datapoint?type=NEW_PLAYERS_AVERAGE&player=" + TestConstants.PLAYER_ONE_UUID_STRING, WebPermission.DATA_PLAYER, 400, 403),
214217
Arguments.of("/v1/datapoint?type=NEW_PLAYER_RETENTION", WebPermission.DATA_NETWORK_NEW_PLAYER_RETENTION, 200, 403),
215218
Arguments.of("/v1/datapoint?type=NEW_PLAYER_RETENTION&server=" + TestConstants.SERVER_UUID_STRING, WebPermission.DATA_SERVER_NEW_PLAYER_RETENTION, 200, 403),
216219
Arguments.of("/v1/datapoint?type=NEW_PLAYER_RETENTION&player=" + TestConstants.PLAYER_ONE_UUID_STRING, WebPermission.DATA_PLAYER, 400, 403),

0 commit comments

Comments
 (0)