NetworkContainer, Improved PerServer data fetching for large numbers of players

This commit is contained in:
Rsl1122 2018-06-24 12:43:29 +03:00
parent fc4942b59b
commit e65106382b
8 changed files with 227 additions and 168 deletions

View File

@ -1,25 +1,32 @@
package com.djrapitops.plan.data.store; package com.djrapitops.plan.data.store;
import com.djrapitops.plugin.api.TimeAmount;
import java.util.function.Supplier; import java.util.function.Supplier;
/** /**
* Caching layer between Supplier and caller. * Caching layer between Supplier and caller.
* *
* Refreshes the value if 30 seconds have passed since the last call.
*
* @author Rsl1122 * @author Rsl1122
*/ */
public class CachingSupplier<T> implements Supplier<T> { public class CachingSupplier<T> implements Supplier<T> {
private final Supplier<T> original; private final Supplier<T> original;
private T cachedValue; private T cachedValue;
private long cacheTime;
public CachingSupplier(Supplier<T> original) { public CachingSupplier(Supplier<T> original) {
this.original = original; this.original = original;
cacheTime = 0L;
} }
@Override @Override
public T get() { public T get() {
if (cachedValue == null) { if (cachedValue == null || System.currentTimeMillis() - cacheTime > TimeAmount.SECOND.ms() * 30L) {
cachedValue = original.get(); cachedValue = original.get();
cacheTime = System.currentTimeMillis();
} }
return cachedValue; return cachedValue;
} }

View File

@ -3,6 +3,7 @@ package com.djrapitops.plan.data.store.mutators;
import com.djrapitops.plan.data.container.Session; import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.data.store.containers.DataContainer; import com.djrapitops.plan.data.store.containers.DataContainer;
import com.djrapitops.plan.data.store.containers.PerServerContainer; import com.djrapitops.plan.data.store.containers.PerServerContainer;
import com.djrapitops.plan.data.store.keys.PerServerKeys;
import com.djrapitops.plan.data.store.keys.PlayerKeys; import com.djrapitops.plan.data.store.keys.PlayerKeys;
import com.djrapitops.plan.data.time.WorldTimes; import com.djrapitops.plan.data.time.WorldTimes;
@ -22,9 +23,13 @@ public class PerServerDataMutator {
this.data = data; this.data = data;
} }
public static PerServerDataMutator forContainer(DataContainer container) {
return new PerServerDataMutator(container.getValue(PlayerKeys.PER_SERVER).orElse(new PerServerContainer()));
}
public List<Session> flatMapSessions() { public List<Session> flatMapSessions() {
return data.values().stream() return data.values().stream()
.map(container -> container.getUnsafe(PlayerKeys.SESSIONS)) .map(container -> container.getUnsafe(PerServerKeys.SESSIONS))
.flatMap(Collection::stream) .flatMap(Collection::stream)
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
@ -33,7 +38,7 @@ public class PerServerDataMutator {
WorldTimes total = new WorldTimes(new HashMap<>()); WorldTimes total = new WorldTimes(new HashMap<>());
for (DataContainer container : data.values()) { for (DataContainer container : data.values()) {
WorldTimes worldTimes = container.getUnsafe(PlayerKeys.WORLD_TIMES); WorldTimes worldTimes = container.getUnsafe(PerServerKeys.WORLD_TIMES);
total.add(worldTimes); total.add(worldTimes);
} }
@ -43,7 +48,7 @@ public class PerServerDataMutator {
public Map<UUID, WorldTimes> worldTimesPerServer() { public Map<UUID, WorldTimes> worldTimesPerServer() {
Map<UUID, WorldTimes> timesMap = new HashMap<>(); Map<UUID, WorldTimes> timesMap = new HashMap<>();
for (Map.Entry<UUID, DataContainer> entry : data.entrySet()) { for (Map.Entry<UUID, DataContainer> entry : data.entrySet()) {
timesMap.put(entry.getKey(), entry.getValue().getUnsafe(PlayerKeys.WORLD_TIMES)); timesMap.put(entry.getKey(), entry.getValue().getUnsafe(PerServerKeys.WORLD_TIMES));
} }
return timesMap; return timesMap;
} }
@ -53,9 +58,7 @@ public class PerServerDataMutator {
UUID maxServer = null; UUID maxServer = null;
for (Map.Entry<UUID, DataContainer> entry : data.entrySet()) { for (Map.Entry<UUID, DataContainer> entry : data.entrySet()) {
long total = entry.getValue().getValue(PlayerKeys.WORLD_TIMES) long total = SessionsMutator.forContainer(entry.getValue()).toPlaytime();
.orElse(new WorldTimes(new HashMap<>()))
.getTotal();
if (total > max) { if (total > max) {
max = total; max = total;
maxServer = entry.getKey(); maxServer = entry.getKey();
@ -68,7 +71,7 @@ public class PerServerDataMutator {
public Map<UUID, List<Session>> sessionsPerServer() { public Map<UUID, List<Session>> sessionsPerServer() {
Map<UUID, List<Session>> sessionMap = new HashMap<>(); Map<UUID, List<Session>> sessionMap = new HashMap<>();
for (Map.Entry<UUID, DataContainer> entry : data.entrySet()) { for (Map.Entry<UUID, DataContainer> entry : data.entrySet()) {
sessionMap.put(entry.getKey(), entry.getValue().getUnsafe(PlayerKeys.SESSIONS)); sessionMap.put(entry.getKey(), entry.getValue().getUnsafe(PerServerKeys.SESSIONS));
} }
return sessionMap; return sessionMap;
} }

View File

@ -204,4 +204,9 @@ public class PlayersMutator {
.filter(Objects::nonNull) .filter(Objects::nonNull)
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
public List<PlayerContainer> operators() {
return players.stream()
.filter(player -> player.getValue(PlayerKeys.OPERATOR).orElse(false)).collect(Collectors.toList());
}
} }

View File

@ -32,7 +32,7 @@ public class PlaceholderReplacer extends HashMap<String, Serializable> implement
} }
} }
public <T> void addPlaceholderFrom(DataContainer container, Formatter<T> formatter, PlaceholderKey<T> key) { public <T> void addAllPlaceholderFrom(DataContainer container, Formatter<T> formatter, PlaceholderKey<T> key) {
if (!container.supports(key)) { if (!container.supports(key)) {
return; return;
} }
@ -45,7 +45,7 @@ public class PlaceholderReplacer extends HashMap<String, Serializable> implement
public <T> void addPlaceholdersFrom(DataContainer container, Formatter<T> formatter, PlaceholderKey<T>... keys) { public <T> void addPlaceholdersFrom(DataContainer container, Formatter<T> formatter, PlaceholderKey<T>... keys) {
for (PlaceholderKey<T> key : keys) { for (PlaceholderKey<T> key : keys) {
addPlaceholderFrom(container, formatter, key); addAllPlaceholderFrom(container, formatter, key);
} }
} }

View File

@ -5,6 +5,7 @@ import com.djrapitops.plan.data.container.GeoInfo;
import com.djrapitops.plan.data.container.Session; import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.data.container.TPS; import com.djrapitops.plan.data.container.TPS;
import com.djrapitops.plan.data.container.UserInfo; import com.djrapitops.plan.data.container.UserInfo;
import com.djrapitops.plan.data.store.containers.NetworkContainer;
import com.djrapitops.plan.data.store.containers.PlayerContainer; import com.djrapitops.plan.data.store.containers.PlayerContainer;
import com.djrapitops.plan.data.store.containers.ServerContainer; import com.djrapitops.plan.data.store.containers.ServerContainer;
import com.djrapitops.plan.system.info.server.Server; import com.djrapitops.plan.system.info.server.Server;
@ -13,14 +14,60 @@ import java.util.*;
public interface FetchOperations { public interface FetchOperations {
// Profiles /**
* Used to get a NetworkContainer, some limitations apply to values returned by DataContainer keys.
* <p>
* Limitations:
* - Bungee ServerContainer does not support: ServerKeys WORLD_TIMES, PLAYER_KILLS, PLAYER_KILL_COUNT
* - Bungee ServerContainer ServerKeys.TPS only contains playersOnline values
* - NetworkKeys.PLAYERS PlayerContainers:
* - do not support: PlayerKeys WORLD_TIMES, PLAYER_KILLS, PLAYER_KILL_COUNT
* - PlayerKeys.PER_SERVER does not support: PerServerKeys WORLD_TIMES, PLAYER_KILLS, PLAYER_KILL_COUNT
* <p>
* Blocking methods are not called until DataContainer getter methods are called.
*
* @return a new NetworkContainer.
*/
NetworkContainer getNetworkContainer();
/**
* Used to get a ServerContainer, some limitations apply to values returned by DataContainer keys.
* <p>
* Limitations:
* - ServerKeys.PLAYERS PlayerContainers PlayerKeys.PER_SERVER only contains information about the queried server.
* <p>
* Blocking methods are not called until DataContainer getter methods are called.
*
* @param serverUUID UUID of the Server.
* @return a new ServerContainer.
*/
ServerContainer getServerContainer(UUID serverUUID); ServerContainer getServerContainer(UUID serverUUID);
// UUIDs /**
* Used to get PlayerContainers of all players on the network, some limitations apply to DataContainer keys.
* <p>
* Limitations:
* - PlayerContainers do not support: PlayerKeys WORLD_TIMES, PLAYER_KILLS, PLAYER_KILL_COUNT
* - PlayerContainers PlayerKeys.PER_SERVER does not support: PerServerKeys WORLD_TIMES, PLAYER_KILLS, PLAYER_KILL_COUNT
* <p>
* Blocking methods are not called until DataContainer getter methods are called.
*
* @return a list of PlayerContainers in Plan database.
*/
List<PlayerContainer> getAllPlayerContainers();
/**
* Used to get a PlayerContainer of a specific player.
* <p>
* Blocking methods are not called until DataContainer getter methods are called.
*
* @param uuid UUID of the player.
* @return a new PlayerContainer.
*/
PlayerContainer getPlayerContainer(UUID uuid); PlayerContainer getPlayerContainer(UUID uuid);
// UUIDs
Set<UUID> getSavedUUIDs(); Set<UUID> getSavedUUIDs();
Set<UUID> getSavedUUIDs(UUID server); Set<UUID> getSavedUUIDs(UUID server);
@ -47,22 +94,8 @@ public interface FetchOperations {
List<TPS> getTPSData(UUID serverUUID); List<TPS> getTPSData(UUID serverUUID);
List<TPS> getNetworkOnlineData();
List<Long> getRegisterDates();
Optional<TPS> getAllTimePeak(UUID serverUUID);
Optional<TPS> getPeakPlayerCount(UUID serverUUID, long afterDate);
Map<UUID, Map<UUID, List<Session>>> getSessionsWithNoExtras(); Map<UUID, Map<UUID, List<Session>>> getSessionsWithNoExtras();
Map<UUID, Map<UUID, List<Session>>> getSessionsAndExtras();
Set<String> getWorldNames(UUID serverUuid);
List<String> getNicknamesOfPlayerOnServer(UUID uuid, UUID serverUUID);
Map<UUID, UserInfo> getUsers(); Map<UUID, UserInfo> getUsers();
Map<UUID, Long> getLastSeenForAllPlayers(); Map<UUID, Long> getLastSeenForAllPlayers();
@ -79,13 +112,8 @@ public interface FetchOperations {
List<WebUser> getWebUsers(); List<WebUser> getWebUsers();
Map<Integer, String> getServerNamesByID();
Map<UUID, Map<UUID, List<Session>>> getSessionsInLastMonth();
List<Server> getServers(); List<Server> getServers();
List<UUID> getServerUUIDs(); List<UUID> getServerUUIDs();
List<String> getNetworkGeolocations();
} }

View File

@ -5,10 +5,7 @@ import com.djrapitops.plan.data.container.GeoInfo;
import com.djrapitops.plan.data.container.Session; import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.data.container.TPS; import com.djrapitops.plan.data.container.TPS;
import com.djrapitops.plan.data.container.UserInfo; import com.djrapitops.plan.data.container.UserInfo;
import com.djrapitops.plan.data.store.containers.DataContainer; import com.djrapitops.plan.data.store.containers.*;
import com.djrapitops.plan.data.store.containers.PerServerContainer;
import com.djrapitops.plan.data.store.containers.PlayerContainer;
import com.djrapitops.plan.data.store.containers.ServerContainer;
import com.djrapitops.plan.data.store.keys.PerServerKeys; import com.djrapitops.plan.data.store.keys.PerServerKeys;
import com.djrapitops.plan.data.store.keys.PlayerKeys; import com.djrapitops.plan.data.store.keys.PlayerKeys;
import com.djrapitops.plan.data.store.keys.ServerKeys; import com.djrapitops.plan.data.store.keys.ServerKeys;
@ -23,7 +20,6 @@ import com.djrapitops.plan.system.info.server.Server;
import com.djrapitops.plugin.api.TimeAmount; import com.djrapitops.plugin.api.TimeAmount;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
public class SQLFetchOps extends SQLOps implements FetchOperations { public class SQLFetchOps extends SQLOps implements FetchOperations {
@ -31,6 +27,27 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
super(db); super(db);
} }
@Override
public NetworkContainer getNetworkContainer() {
return new NetworkContainer(getBungeeServerContainer());
}
private ServerContainer getBungeeServerContainer() {
Optional<Server> bungeeInfo = serverTable.getBungeeInfo();
if (!bungeeInfo.isPresent()) {
return new ServerContainer();
}
ServerContainer container = getServerContainer(bungeeInfo.get().getUuid());
container.putSupplier(ServerKeys.PLAYERS, this::getAllPlayerContainers);
container.putSupplier(ServerKeys.TPS, tpsTable::getNetworkOnlineData);
container.putSupplier(ServerKeys.WORLD_TIMES, null); // Additional Session information not supported
container.putSupplier(ServerKeys.PLAYER_KILLS, null);
container.putSupplier(ServerKeys.PLAYER_KILL_COUNT, null);
return container;
}
@Override @Override
public ServerContainer getServerContainer(UUID serverUUID) { public ServerContainer getServerContainer(UUID serverUUID) {
ServerContainer container = new ServerContainer(); ServerContainer container = new ServerContainer();
@ -68,8 +85,7 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
container.putSupplier(ServerKeys.WORLD_TIMES, () -> worldTimesTable.getWorldTimesOfServer(serverUUID)); container.putSupplier(ServerKeys.WORLD_TIMES, () -> worldTimesTable.getWorldTimesOfServer(serverUUID));
// Calculating getters // Calculating getters
container.putSupplier(ServerKeys.OPERATORS, () -> container.getUnsafe(ServerKeys.PLAYERS).stream() container.putSupplier(ServerKeys.OPERATORS, () -> PlayersMutator.forContainer(container).operators());
.filter(player -> player.getValue(PlayerKeys.OPERATOR).orElse(false)).collect(Collectors.toList()));
container.putSupplier(ServerKeys.SESSIONS, () -> PlayersMutator.forContainer(container).getSessions()); container.putSupplier(ServerKeys.SESSIONS, () -> PlayersMutator.forContainer(container).getSessions());
container.putSupplier(ServerKeys.PLAYER_KILLS, SessionsMutator.forContainer(container)::toPlayerKillList); container.putSupplier(ServerKeys.PLAYER_KILLS, SessionsMutator.forContainer(container)::toPlayerKillList);
container.putSupplier(ServerKeys.PLAYER_KILL_COUNT, container.getUnsafe(ServerKeys.PLAYER_KILLS)::size); container.putSupplier(ServerKeys.PLAYER_KILL_COUNT, container.getUnsafe(ServerKeys.PLAYER_KILLS)::size);
@ -92,6 +108,10 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
killsTable.addKillsToSessions(map); killsTable.addKillsToSessions(map);
worldTimesTable.addWorldTimesToSessions(map); worldTimesTable.addWorldTimesToSessions(map);
Map<UUID, List<UserInfo>> serverUserInfos = Collections.singletonMap(serverUUID, serverUserInfo);
Map<UUID, Map<UUID, List<Session>>> serverSessions = Collections.singletonMap(serverUUID, sessions);
Map<UUID, PerServerContainer> perServerInfo = getPerServerData(serverSessions, serverUserInfos);
for (UserInfo userInfo : serverUserInfo) { for (UserInfo userInfo : serverUserInfo) {
PlayerContainer container = new PlayerContainer(); PlayerContainer container = new PlayerContainer();
UUID uuid = userInfo.getUuid(); UUID uuid = userInfo.getUuid();
@ -102,7 +122,7 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
container.putRawData(PlayerKeys.KICK_COUNT, timesKicked.get(uuid)); container.putRawData(PlayerKeys.KICK_COUNT, timesKicked.get(uuid));
container.putSupplier(PlayerKeys.GEO_INFO, () -> geoInfo.get(uuid)); container.putSupplier(PlayerKeys.GEO_INFO, () -> geoInfo.get(uuid));
container.putSupplier(PlayerKeys.NICKNAMES, () -> nicknamesTable.getNicknameInformation(uuid)); container.putSupplier(PlayerKeys.NICKNAMES, () -> nicknamesTable.getNicknameInformation(uuid));
container.putSupplier(PlayerKeys.PER_SERVER, () -> getPerServerData(uuid)); container.putSupplier(PlayerKeys.PER_SERVER, () -> perServerInfo.get(uuid));
container.putRawData(PlayerKeys.BANNED, userInfo.isBanned()); container.putRawData(PlayerKeys.BANNED, userInfo.isBanned());
container.putRawData(PlayerKeys.OPERATOR, userInfo.isOperator()); container.putRawData(PlayerKeys.OPERATOR, userInfo.isOperator());
@ -134,6 +154,95 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
return containers; return containers;
} }
@Override
public List<PlayerContainer> getAllPlayerContainers() {
List<PlayerContainer> containers = new ArrayList<>();
Map<UUID, UserInfo> users = usersTable.getUsers();
Map<UUID, Integer> timesKicked = usersTable.getAllTimesKicked();
Map<UUID, List<GeoInfo>> geoInfo = geoInfoTable.getAllGeoInfo();
Map<UUID, Map<UUID, List<Session>>> sessions = sessionsTable.getAllSessions(false);
Map<UUID, List<UserInfo>> allUserInfo = userInfoTable.getAllUserInfo();
Map<UUID, PerServerContainer> perServerInfo = getPerServerData(sessions, allUserInfo);
for (UserInfo userInfo : users.values()) {
PlayerContainer container = new PlayerContainer();
UUID uuid = userInfo.getUuid();
container.putRawData(PlayerKeys.UUID, uuid);
container.putRawData(PlayerKeys.REGISTERED, userInfo.getRegistered());
container.putRawData(PlayerKeys.NAME, userInfo.getName());
container.putRawData(PlayerKeys.KICK_COUNT, timesKicked.get(uuid));
container.putSupplier(PlayerKeys.GEO_INFO, () -> geoInfo.get(uuid));
container.putSupplier(PlayerKeys.NICKNAMES, () -> nicknamesTable.getNicknameInformation(uuid));
container.putSupplier(PlayerKeys.PER_SERVER, () -> perServerInfo.get(uuid));
container.putSupplier(PlayerKeys.SESSIONS, () -> {
List<Session> playerSessions = PerServerDataMutator.forContainer(container).flatMapSessions();
container.getValue(PlayerKeys.ACTIVE_SESSION).ifPresent(playerSessions::add);
return playerSessions;
}
);
// Calculating getters
container.putSupplier(PlayerKeys.LAST_SEEN, SessionsMutator.forContainer(container)::toLastSeen);
container.putSupplier(PlayerKeys.MOB_KILL_COUNT, SessionsMutator.forContainer(container)::toMobKillCount);
container.putSupplier(PlayerKeys.DEATH_COUNT, SessionsMutator.forContainer(container)::toDeathCount);
containers.add(container);
}
return containers;
}
private Map<UUID, PerServerContainer> getPerServerData(Map<UUID, Map<UUID, List<Session>>> sessions, Map<UUID, List<UserInfo>> allUserInfo) {
Map<UUID, PerServerContainer> perServerContainers = new HashMap<>();
for (Map.Entry<UUID, List<UserInfo>> entry : allUserInfo.entrySet()) {
UUID serverUUID = entry.getKey();
List<UserInfo> serverUserInfo = entry.getValue();
for (UserInfo userInfo : serverUserInfo) {
UUID uuid = userInfo.getUuid();
PerServerContainer perServerContainer = perServerContainers.getOrDefault(uuid, new PerServerContainer());
DataContainer container = perServerContainer.getOrDefault(serverUUID, new DataContainer());
container.putRawData(PlayerKeys.REGISTERED, userInfo.getRegistered());
container.putRawData(PlayerKeys.BANNED, userInfo.isBanned());
container.putRawData(PlayerKeys.OPERATOR, userInfo.isOperator());
perServerContainer.put(serverUUID, container);
perServerContainers.put(uuid, perServerContainer);
}
}
for (Map.Entry<UUID, Map<UUID, List<Session>>> entry : sessions.entrySet()) {
UUID serverUUID = entry.getKey();
Map<UUID, List<Session>> serverUserSessions = entry.getValue();
for (Map.Entry<UUID, List<Session>> sessionEntry : serverUserSessions.entrySet()) {
UUID uuid = sessionEntry.getKey();
PerServerContainer perServerContainer = perServerContainers.getOrDefault(uuid, new PerServerContainer());
DataContainer container = perServerContainer.getOrDefault(serverUUID, new DataContainer());
List<Session> serverSessions = sessionEntry.getValue();
container.putRawData(PerServerKeys.SESSIONS, serverSessions);
container.putSupplier(PerServerKeys.LAST_SEEN, SessionsMutator.forContainer(container)::toLastSeen);
container.putSupplier(PerServerKeys.WORLD_TIMES, SessionsMutator.forContainer(container)::toTotalWorldTimes);
container.putSupplier(PerServerKeys.PLAYER_KILLS, SessionsMutator.forContainer(container)::toPlayerKillList);
container.putSupplier(PerServerKeys.PLAYER_KILL_COUNT, container.getUnsafe(PerServerKeys.PLAYER_KILLS)::size);
container.putSupplier(PerServerKeys.MOB_KILL_COUNT, SessionsMutator.forContainer(container)::toMobKillCount);
container.putSupplier(PerServerKeys.DEATH_COUNT, SessionsMutator.forContainer(container)::toDeathCount);
perServerContainer.put(serverUUID, container);
perServerContainers.put(uuid, perServerContainer);
}
}
return perServerContainers;
}
@Override @Override
public PlayerContainer getPlayerContainer(UUID uuid) { public PlayerContainer getPlayerContainer(UUID uuid) {
PlayerContainer container = new PlayerContainer(); PlayerContainer container = new PlayerContainer();
@ -242,51 +351,11 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
return tpsTable.getTPSData(serverUUID); return tpsTable.getTPSData(serverUUID);
} }
@Override
public List<TPS> getNetworkOnlineData() {
return tpsTable.getNetworkOnlineData();
}
@Override
public List<Long> getRegisterDates() {
return usersTable.getRegisterDates();
}
@Override
public Optional<TPS> getAllTimePeak(UUID serverUUID) {
return tpsTable.getAllTimePeak(serverUUID);
}
@Override
public Optional<TPS> getPeakPlayerCount(UUID serverUUID, long afterDate) {
return tpsTable.getPeakPlayerCount(serverUUID, afterDate);
}
@Override @Override
public Map<UUID, Map<UUID, List<Session>>> getSessionsWithNoExtras() { public Map<UUID, Map<UUID, List<Session>>> getSessionsWithNoExtras() {
return sessionsTable.getAllSessions(false); return sessionsTable.getAllSessions(false);
} }
@Override
public Map<UUID, Map<UUID, List<Session>>> getSessionsAndExtras() {
return sessionsTable.getAllSessions(true);
}
@Override
public Map<UUID, Map<UUID, List<Session>>> getSessionsInLastMonth() {
return sessionsTable.getSessionInLastMonth();
}
@Override
public Set<String> getWorldNames(UUID serverUuid) {
return worldTable.getWorldNames(serverUuid);
}
@Override
public List<String> getNicknamesOfPlayerOnServer(UUID uuid, UUID serverUUID) {
return nicknamesTable.getNicknames(uuid, serverUUID);
}
@Override @Override
public Map<UUID, UserInfo> getUsers() { public Map<UUID, UserInfo> getUsers() {
return usersTable.getUsers(); return usersTable.getUsers();
@ -342,11 +411,6 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
return securityTable.getUsers(); return securityTable.getUsers();
} }
@Override
public Map<Integer, String> getServerNamesByID() {
return serverTable.getServerNamesByID();
}
@Override @Override
public List<Server> getServers() { public List<Server> getServers() {
Map<UUID, Server> bukkitServers = getBukkitServers(); Map<UUID, Server> bukkitServers = getBukkitServers();
@ -364,8 +428,4 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
return serverTable.getServerUUIDs(); return serverTable.getServerUUIDs();
} }
@Override
public List<String> getNetworkGeolocations() {
return geoInfoTable.getNetworkGeolocations();
}
} }

View File

@ -5,30 +5,15 @@
package com.djrapitops.plan.system.webserver.pages.parsing; package com.djrapitops.plan.system.webserver.pages.parsing;
import com.djrapitops.plan.api.exceptions.ParseException; import com.djrapitops.plan.api.exceptions.ParseException;
import com.djrapitops.plan.data.container.Session; import com.djrapitops.plan.data.store.containers.NetworkContainer;
import com.djrapitops.plan.data.container.TPS; import com.djrapitops.plan.data.store.mutators.formatting.PlaceholderReplacer;
import com.djrapitops.plan.data.store.mutators.formatting.Formatters;
import com.djrapitops.plan.system.database.databases.Database; import com.djrapitops.plan.system.database.databases.Database;
import com.djrapitops.plan.system.info.server.ServerInfo;
import com.djrapitops.plan.system.settings.Settings;
import com.djrapitops.plan.system.settings.theme.Theme;
import com.djrapitops.plan.system.settings.theme.ThemeVal;
import com.djrapitops.plan.system.update.VersionCheckSystem;
import com.djrapitops.plan.system.webserver.response.cache.PageId; import com.djrapitops.plan.system.webserver.response.cache.PageId;
import com.djrapitops.plan.system.webserver.response.cache.ResponseCache; import com.djrapitops.plan.system.webserver.response.cache.ResponseCache;
import com.djrapitops.plan.system.webserver.response.pages.parts.NetworkPageContent; import com.djrapitops.plan.system.webserver.response.pages.parts.NetworkPageContent;
import com.djrapitops.plan.utilities.MiscUtils;
import com.djrapitops.plan.utilities.analysis.AnalysisUtils;
import com.djrapitops.plan.utilities.file.FileUtil; import com.djrapitops.plan.utilities.file.FileUtil;
import com.djrapitops.plan.utilities.html.HtmlUtils;
import com.djrapitops.plan.utilities.html.graphs.WorldMap;
import com.djrapitops.plan.utilities.html.graphs.line.OnlineActivityGraph;
import com.djrapitops.plugin.api.TimeAmount;
import java.util.List; import static com.djrapitops.plan.data.store.keys.NetworkKeys.*;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
/** /**
* Html String parser for /network page. * Html String parser for /network page.
@ -40,76 +25,26 @@ public class NetworkPage extends Page {
@Override @Override
public String toHtml() throws ParseException { public String toHtml() throws ParseException {
try { try {
UUID serverUUID = ServerInfo.getServerUUID();
long now = System.currentTimeMillis();
Database database = Database.getActive(); Database database = Database.getActive();
List<TPS> networkOnlineData = database.fetch().getNetworkOnlineData(); NetworkContainer networkContainer = database.fetch().getNetworkContainer();
List<String> geolocations = database.fetch().getNetworkGeolocations();
peakTimes(serverUUID, now, database);
uniquePlayers(now, database);
addValue("timeZone", MiscUtils.getTimeZoneOffsetHours());
addValue("networkName", Settings.BUNGEE_NETWORK_NAME.toString());
addValue("version", VersionCheckSystem.getCurrentVersion());
addValue("playersOnlineSeries", new OnlineActivityGraph(networkOnlineData).toHighChartsSeries());
addValue("playersGraphColor", Theme.getValue(ThemeVal.GRAPH_PLAYERS_ONLINE));
addValue("worldMapColLow", Theme.getValue(ThemeVal.WORLD_MAP_LOW));
addValue("worldMapColHigh", Theme.getValue(ThemeVal.WORLD_MAP_HIGH));
addValue("playersOnline", ServerInfo.getServerProperties().getOnlinePlayers());
addValue("playersTotal", database.count().getNetworkPlayerCount());
addValue("geoMapSeries", new WorldMap(geolocations).toHighChartsSeries());
List<Long> registerDates = database.fetch().getRegisterDates();
addValue("playersNewDay", AnalysisUtils.getNewPlayers(registerDates, TimeAmount.DAY.ms(), now));
addValue("playersNewWeek", AnalysisUtils.getNewPlayers(registerDates, TimeAmount.WEEK.ms(), now));
addValue("playersNewMonth", AnalysisUtils.getNewPlayers(registerDates, TimeAmount.MONTH.ms(), now));
PlaceholderReplacer placeholderReplacer = new PlaceholderReplacer();
placeholderReplacer.addAllPlaceholdersFrom(networkContainer,
VERSION, NETWORK_NAME, TIME_ZONE,
PLAYERS_ONLINE_SERIES, PLAYERS_TOTAL, PLAYERS_GRAPH_COLOR,
REFRESH_TIME_F, RECENT_PEAK_TIME_F, ALL_TIME_PEAK_TIME_F,
PLAYERS_ALL_TIME_PEAK, PLAYERS_RECENT_PEAK,
PLAYERS_DAY, PLAYERS_WEEK, PLAYERS_MONTH,
PLAYERS_NEW_DAY, PLAYERS_NEW_WEEK, PLAYERS_NEW_MONTH,
WORLD_MAP_SERIES, WORLD_MAP_HIGH_COLOR, WORLD_MAP_LOW_COLOR
);
NetworkPageContent networkPageContent = (NetworkPageContent) NetworkPageContent networkPageContent = (NetworkPageContent)
ResponseCache.loadResponse(PageId.NETWORK_CONTENT.id(), NetworkPageContent::new); ResponseCache.loadResponse(PageId.NETWORK_CONTENT.id(), NetworkPageContent::new);
addValue("tabContentServers", networkPageContent.getContents()); addValue("tabContentServers", networkPageContent.getContents());
return HtmlUtils.replacePlaceholders(FileUtil.getStringFromResource("web/network.html"), placeHolders); return placeholderReplacer.apply(FileUtil.getStringFromResource("web/network.html"));
} catch (Exception e) { } catch (Exception e) {
throw new ParseException(e); throw new ParseException(e);
} }
} }
private void uniquePlayers(long now, Database db) {
Map<UUID, Map<UUID, List<Session>>> allSessions = db.fetch().getSessionsInLastMonth();
Map<UUID, List<Session>> userSessions = AnalysisUtils.sortSessionsByUser(allSessions);
long dayAgo = now - TimeAmount.DAY.ms();
long weekAgo = now - TimeAmount.WEEK.ms();
long monthAgo = now - TimeAmount.MONTH.ms();
addValue("playersUniqueDay", AnalysisUtils.getUniquePlayers(userSessions, dayAgo));
addValue("playersUniqueWeek", AnalysisUtils.getUniquePlayers(userSessions, weekAgo));
addValue("playersUniqueMonth", AnalysisUtils.getUniquePlayers(userSessions, monthAgo));
}
private void peakTimes(UUID serverUUID, long now, Database db) {
Optional<TPS> allTimePeak = db.fetch().getAllTimePeak(serverUUID);
Optional<TPS> lastPeak = db.fetch().getPeakPlayerCount(serverUUID, now - TimeAmount.DAY.ms() * 2L);
if (allTimePeak.isPresent()) {
TPS tps = allTimePeak.get();
addValue("bestPeakTime", Formatters.year().apply(tps));
addValue("playersBestPeak", tps.getPlayers());
} else {
addValue("bestPeakTime", "No Data");
addValue("playersBestPeak", "");
}
if (lastPeak.isPresent()) {
TPS tps = lastPeak.get();
addValue("lastPeakTime", Formatters.year().apply(tps));
addValue("playersLastPeak", tps.getPlayers());
} else {
addValue("lastPeakTime", "No Data");
addValue("playersLastPeak", "");
}
}
} }

View File

@ -12,9 +12,11 @@ import com.djrapitops.plan.data.WebUser;
import com.djrapitops.plan.data.container.*; import com.djrapitops.plan.data.container.*;
import com.djrapitops.plan.data.store.Key; import com.djrapitops.plan.data.store.Key;
import com.djrapitops.plan.data.store.containers.AnalysisContainer; import com.djrapitops.plan.data.store.containers.AnalysisContainer;
import com.djrapitops.plan.data.store.containers.NetworkContainer;
import com.djrapitops.plan.data.store.containers.PlayerContainer; import com.djrapitops.plan.data.store.containers.PlayerContainer;
import com.djrapitops.plan.data.store.containers.ServerContainer; import com.djrapitops.plan.data.store.containers.ServerContainer;
import com.djrapitops.plan.data.store.keys.AnalysisKeys; import com.djrapitops.plan.data.store.keys.AnalysisKeys;
import com.djrapitops.plan.data.store.keys.NetworkKeys;
import com.djrapitops.plan.data.store.keys.PlayerKeys; import com.djrapitops.plan.data.store.keys.PlayerKeys;
import com.djrapitops.plan.data.store.keys.ServerKeys; import com.djrapitops.plan.data.store.keys.ServerKeys;
import com.djrapitops.plan.data.store.objects.Nickname; import com.djrapitops.plan.data.store.objects.Nickname;
@ -1124,4 +1126,23 @@ public class SQLiteTest {
assertTrue("Some keys are not supported by AnalysisContainer: AnalysisKeys." + unsupported.toString(), unsupported.isEmpty()); assertTrue("Some keys are not supported by AnalysisContainer: AnalysisKeys." + unsupported.toString(), unsupported.isEmpty());
} }
@Test
public void networkContainerSupportsAllNetworkKeys() throws IllegalAccessException, UnsupportedEncodingException, NoSuchAlgorithmException {
serverContainerSupportsAllServerKeys();
NetworkContainer networkContainer = db.fetch().getNetworkContainer();
List<String> unsupported = new ArrayList<>();
for (Field field : NetworkKeys.class.getDeclaredFields()) {
if (!Modifier.isPublic(field.getModifiers())) {
continue;
}
Key key = (Key) field.get(null);
if (!networkContainer.supports(key)) {
unsupported.add(field.getName());
}
}
assertTrue("Some keys are not supported by NetworkContainer: NetworkKeys." + unsupported.toString(), unsupported.isEmpty());
}
} }