mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2024-11-02 16:59:42 +01:00
commit
e34f2f773f
@ -112,7 +112,7 @@
|
||||
<dependency>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.2.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Geo IP -->
|
||||
|
@ -14,6 +14,7 @@ import com.djrapitops.plugin.api.utility.log.DebugLog;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import com.djrapitops.plugin.settings.ColorScheme;
|
||||
import com.google.inject.Inject;
|
||||
import org.bstats.sponge.Metrics;
|
||||
import org.slf4j.Logger;
|
||||
import org.spongepowered.api.config.ConfigDir;
|
||||
import org.spongepowered.api.event.Listener;
|
||||
@ -24,9 +25,12 @@ import org.spongepowered.api.plugin.Plugin;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
|
||||
@Plugin(id = "plan", name = "Plan", version = "4.4.3", description = "Player Analytics Plugin by Rsl1122", authors = {"Rsl1122"})
|
||||
@Plugin(id = "plan", name = "Plan", version = "4.4.4", description = "Player Analytics Plugin by Rsl1122", authors = {"Rsl1122"})
|
||||
public class PlanSponge extends SpongePlugin implements PlanPlugin {
|
||||
|
||||
@Inject
|
||||
private Metrics metrics;
|
||||
|
||||
@Inject
|
||||
private Logger logger;
|
||||
|
||||
@ -58,7 +62,7 @@ public class PlanSponge extends SpongePlugin implements PlanPlugin {
|
||||
locale = system.getLocaleSystem().getLocale();
|
||||
system.enable();
|
||||
|
||||
new BStatsSponge().registerMetrics();
|
||||
new BStatsSponge(metrics).registerMetrics();
|
||||
|
||||
Log.info(locale.getString(PluginLang.ENABLED));
|
||||
} catch (AbstractMethodError e) {
|
||||
|
@ -4,6 +4,7 @@ import com.djrapitops.plan.PlanPlugin;
|
||||
import com.djrapitops.plan.command.commands.*;
|
||||
import com.djrapitops.plan.command.commands.manage.ManageConDebugCommand;
|
||||
import com.djrapitops.plan.command.commands.manage.ManageRawDataCommand;
|
||||
import com.djrapitops.plan.command.commands.manage.ManageUninstalledCommand;
|
||||
import com.djrapitops.plan.system.locale.Locale;
|
||||
import com.djrapitops.plan.system.locale.lang.DeepHelpLang;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
@ -44,6 +45,7 @@ public class PlanBungeeCommand extends TreeCmdNode {
|
||||
new ManageConDebugCommand(plugin),
|
||||
new ManageRawDataCommand(plugin),
|
||||
new BungeeSetupToggleCommand(plugin),
|
||||
new ManageUninstalledCommand(plugin),
|
||||
new ReloadCommand(plugin),
|
||||
new DisableCommand(plugin),
|
||||
new StatusCommand<>(plugin, Permissions.MANAGE.getPermission(), plugin.getColorScheme()),
|
||||
|
@ -154,11 +154,11 @@ public class Session extends DataContainer implements DateHolder {
|
||||
}
|
||||
|
||||
public void setWorldTimes(WorldTimes worldTimes) {
|
||||
putRawData(SessionKeys.WORLD_TIMES, worldTimes);
|
||||
this.worldTimes = worldTimes;
|
||||
}
|
||||
|
||||
public void setPlayerKills(List<PlayerKill> playerKills) {
|
||||
putRawData(SessionKeys.PLAYER_KILLS, playerKills);
|
||||
this.playerKills = playerKills;
|
||||
}
|
||||
|
||||
public boolean isFetchedFromDB() {
|
||||
@ -182,14 +182,8 @@ public class Session extends DataContainer implements DateHolder {
|
||||
getValue(SessionKeys.END).orElse(-1L).equals(session.getValue(SessionKeys.END).orElse(-1L)) &&
|
||||
mobKills == session.mobKills &&
|
||||
deaths == session.deaths &&
|
||||
Objects.equals(
|
||||
getValue(SessionKeys.WORLD_TIMES).orElse(null),
|
||||
session.getValue(SessionKeys.WORLD_TIMES).orElse(null)
|
||||
) &&
|
||||
Objects.equals(
|
||||
getValue(SessionKeys.PLAYER_KILLS).orElse(new ArrayList<>()),
|
||||
session.getValue(SessionKeys.PLAYER_KILLS).orElse(new ArrayList<>())
|
||||
);
|
||||
Objects.equals(playerKills, session.playerKills) &&
|
||||
Objects.equals(worldTimes, session.worldTimes);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -205,7 +199,7 @@ public class Session extends DataContainer implements DateHolder {
|
||||
return worldTimes;
|
||||
}
|
||||
|
||||
private List<PlayerKill> getPlayerKills() {
|
||||
public List<PlayerKill> getPlayerKills() {
|
||||
return playerKills;
|
||||
}
|
||||
|
||||
@ -231,7 +225,6 @@ public class Session extends DataContainer implements DateHolder {
|
||||
}
|
||||
|
||||
Map<String, Long> playtimePerAlias = worldTimes.getPlaytimePerAlias();
|
||||
long total = worldTimes.getTotal();
|
||||
|
||||
long longest = 0;
|
||||
String theWorld = "-";
|
||||
@ -244,8 +237,25 @@ public class Session extends DataContainer implements DateHolder {
|
||||
}
|
||||
}
|
||||
|
||||
long total = worldTimes.getTotal();
|
||||
// Prevent arithmetic error if 0
|
||||
if (total <= 0) {
|
||||
total = -1;
|
||||
}
|
||||
double quotient = longest * 1.0 / total;
|
||||
|
||||
return theWorld + " (" + Formatters.percentage().apply(quotient) + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Session{" +
|
||||
"sessionStart=" + sessionStart +
|
||||
", worldTimes=" + worldTimes +
|
||||
", playerKills=" + playerKills +
|
||||
", mobKills=" + mobKills +
|
||||
", deaths=" + deaths +
|
||||
", afkTime=" + afkTime +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ public class PingMutator {
|
||||
int max = -1;
|
||||
for (Ping ping : pings) {
|
||||
Integer value = ping.getMax();
|
||||
if (value < 0 || 8000 < value) {
|
||||
if (value <= 0 || 4000 < value) {
|
||||
continue;
|
||||
}
|
||||
if (value > max) {
|
||||
@ -67,7 +67,7 @@ public class PingMutator {
|
||||
int min = -1;
|
||||
for (Ping ping : pings) {
|
||||
Integer value = ping.getMin();
|
||||
if (value < 0 || 8000 < value) {
|
||||
if (value <= 0 || 4000 < value) {
|
||||
continue;
|
||||
}
|
||||
if (value < min || min == -1) {
|
||||
@ -80,7 +80,7 @@ public class PingMutator {
|
||||
|
||||
public double average() {
|
||||
return pings.stream().mapToDouble(Ping::getAverage)
|
||||
.filter(value -> value >= 0 && value <= 8000)
|
||||
.filter(value -> value > 0 && value <= 4000)
|
||||
.average().orElse(-1);
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import com.djrapitops.plan.data.store.containers.DataContainer;
|
||||
import com.djrapitops.plan.data.store.keys.CommonKeys;
|
||||
import com.djrapitops.plan.data.store.keys.SessionKeys;
|
||||
import com.djrapitops.plan.data.time.WorldTimes;
|
||||
import com.djrapitops.plan.utilities.analysis.Median;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
@ -142,13 +143,8 @@ public class SessionsMutator {
|
||||
}
|
||||
|
||||
public long toMedianSessionLength() {
|
||||
List<Long> sessionLengths = sessions.stream().map(Session::getLength)
|
||||
.sorted()
|
||||
.collect(Collectors.toList());
|
||||
if (sessionLengths.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
return sessionLengths.get(sessionLengths.size() / 2);
|
||||
List<Long> sessionLengths = sessions.stream().map(Session::getLength).collect(Collectors.toList());
|
||||
return (long) Median.forLong(sessionLengths).calculate();
|
||||
}
|
||||
|
||||
public int toAverageUniqueJoinsPerDay() {
|
||||
@ -200,5 +196,4 @@ public class SessionsMutator {
|
||||
return toPlayerDeathList().size();
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -170,8 +170,11 @@ public class WorldTimes {
|
||||
}
|
||||
|
||||
public Map<String, Long> getPlaytimePerAlias() {
|
||||
Map<String, Long> playtimePerWorld = getWorldTimes() // WorldTimes Map<String, GMTimes>
|
||||
.entrySet().stream()
|
||||
if (times.isEmpty()) {
|
||||
return new HashMap<>();
|
||||
}
|
||||
|
||||
Map<String, Long> playtimePerWorld = times.entrySet().stream() // WorldTimes Map<String, GMTimes>
|
||||
.collect(Collectors.toMap(
|
||||
Map.Entry::getKey,
|
||||
entry -> entry.getValue().getTotal() // GMTimes.getTotal
|
||||
|
@ -7,9 +7,6 @@ package com.djrapitops.plan.system.cache;
|
||||
import com.djrapitops.plan.api.exceptions.EnableException;
|
||||
import com.djrapitops.plan.system.PlanSystem;
|
||||
import com.djrapitops.plan.system.SubSystem;
|
||||
import com.djrapitops.plugin.api.TimeAmount;
|
||||
import com.djrapitops.plugin.task.AbsRunnable;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
import com.djrapitops.plugin.utilities.Verify;
|
||||
|
||||
/**
|
||||
@ -21,7 +18,6 @@ public class CacheSystem implements SubSystem {
|
||||
|
||||
private final DataCache dataCache;
|
||||
private final GeolocationCache geolocationCache;
|
||||
private final DataContainerCache dataContainerCache;
|
||||
|
||||
public CacheSystem(PlanSystem system) {
|
||||
this(new DataCache(system), system);
|
||||
@ -30,7 +26,6 @@ public class CacheSystem implements SubSystem {
|
||||
protected CacheSystem(DataCache dataCache, PlanSystem system) {
|
||||
this.dataCache = dataCache;
|
||||
geolocationCache = new GeolocationCache(() -> system.getLocaleSystem().getLocale());
|
||||
dataContainerCache = new DataContainerCache();
|
||||
}
|
||||
|
||||
public static CacheSystem getInstance() {
|
||||
@ -43,19 +38,11 @@ public class CacheSystem implements SubSystem {
|
||||
public void enable() throws EnableException {
|
||||
dataCache.enable();
|
||||
geolocationCache.enable();
|
||||
|
||||
RunnableFactory.createNew("DataContainer cache clean task", new AbsRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
dataContainerCache.clear();
|
||||
}
|
||||
}).runTaskTimerAsynchronously(TimeAmount.MINUTE.ticks(), TimeAmount.MINUTE.ms());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
geolocationCache.clearCache();
|
||||
dataContainerCache.clear();
|
||||
}
|
||||
|
||||
public DataCache getDataCache() {
|
||||
@ -66,7 +53,4 @@ public class CacheSystem implements SubSystem {
|
||||
return geolocationCache;
|
||||
}
|
||||
|
||||
public DataContainerCache getDataContainerCache() {
|
||||
return dataContainerCache;
|
||||
}
|
||||
}
|
||||
|
@ -1,67 +0,0 @@
|
||||
package com.djrapitops.plan.system.cache;
|
||||
|
||||
import com.djrapitops.plan.data.store.Key;
|
||||
import com.djrapitops.plan.data.store.containers.AnalysisContainer;
|
||||
import com.djrapitops.plan.data.store.containers.DataContainer;
|
||||
import com.djrapitops.plan.data.store.containers.PlayerContainer;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plugin.api.TimeAmount;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Cache to aid Bungee in case SQL is causing cpu thread starvation, leading to mysql connection drops.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class DataContainerCache extends DataContainer {
|
||||
|
||||
public DataContainerCache() {
|
||||
super(TimeAmount.SECOND.ms() * 10L);
|
||||
}
|
||||
|
||||
public PlayerContainer getPlayerContainer(UUID uuid) {
|
||||
return getAndCacheSupplier(Keys.playerContainer(uuid), Suppliers.playerContainer(uuid));
|
||||
}
|
||||
|
||||
public AnalysisContainer getAnalysisContainer(UUID serverUUID) {
|
||||
return getAndCacheSupplier(Keys.analysisContainer(serverUUID), Suppliers.analysisContainer(serverUUID));
|
||||
}
|
||||
|
||||
private <T> T getAndCacheSupplier(Key<T> key, Supplier<T> ifNotPresent) {
|
||||
if (!supports(key)) {
|
||||
putSupplier(key, ifNotPresent);
|
||||
}
|
||||
return getUnsafe(key);
|
||||
}
|
||||
|
||||
private static class Keys {
|
||||
static Key<AnalysisContainer> analysisContainer(UUID serverUUID) {
|
||||
return new Key<>(AnalysisContainer.class, "ANALYSIS_CONTAINER:" + serverUUID);
|
||||
}
|
||||
|
||||
static Key<PlayerContainer> playerContainer(UUID uuid) {
|
||||
return new Key<>(PlayerContainer.class, "PLAYER_CONTAINER:" + uuid);
|
||||
}
|
||||
|
||||
private Keys() {
|
||||
// Static utility class
|
||||
}
|
||||
}
|
||||
|
||||
private static class Suppliers {
|
||||
static Supplier<AnalysisContainer> analysisContainer(UUID serverUUID) {
|
||||
return () -> new AnalysisContainer(Database.getActive().fetch().getServerContainer(serverUUID));
|
||||
}
|
||||
|
||||
static Supplier<PlayerContainer> playerContainer(UUID uuid) {
|
||||
return () -> Database.getActive().fetch().getPlayerContainer(uuid);
|
||||
}
|
||||
|
||||
private Suppliers() {
|
||||
// Static utility class
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package com.djrapitops.plan.system.database.databases.sql;
|
||||
|
||||
import com.djrapitops.plan.PlanPlugin;
|
||||
import com.djrapitops.plan.system.database.databases.sql.patches.Patch;
|
||||
import com.djrapitops.plan.system.locale.Locale;
|
||||
import com.djrapitops.plan.system.locale.lang.PluginLang;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import com.djrapitops.plugin.task.AbsRunnable;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Task that is in charge on patching the database when the database enables.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class PatchTask extends AbsRunnable {
|
||||
|
||||
private final Patch[] patches;
|
||||
private final Supplier<Locale> locale;
|
||||
|
||||
public PatchTask(Patch[] patches, Supplier<Locale> locale) {
|
||||
this.patches = patches;
|
||||
this.locale = locale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
boolean didApply = applyPatches();
|
||||
Log.info(locale.get().getString(
|
||||
didApply ? PluginLang.DB_APPLIED_PATCHES : PluginLang.DB_APPLIED_PATCHES_ALREADY
|
||||
));
|
||||
} catch (Exception e) {
|
||||
Log.error("----------------------------------------------------");
|
||||
Log.error(locale.get().getString(PluginLang.ENABLE_FAIL_DB_PATCH));
|
||||
Log.error("----------------------------------------------------");
|
||||
Log.toLog(this.getClass(), e);
|
||||
PlanPlugin.getInstance().onDisable();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean applyPatches() {
|
||||
boolean didApply = false;
|
||||
for (Patch patch : patches) {
|
||||
if (!patch.hasBeenApplied()) {
|
||||
String patchName = patch.getClass().getSimpleName();
|
||||
Log.info(locale.get().getString(PluginLang.DB_APPLY_PATCH, patchName));
|
||||
patch.apply();
|
||||
didApply = true;
|
||||
}
|
||||
}
|
||||
return didApply;
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
package com.djrapitops.plan.system.database.databases.sql;
|
||||
|
||||
import com.djrapitops.plan.PlanPlugin;
|
||||
import com.djrapitops.plan.api.exceptions.database.DBInitException;
|
||||
import com.djrapitops.plan.api.exceptions.database.DBOpException;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
@ -157,31 +156,12 @@ public abstract class SQLDB extends Database {
|
||||
new VersionTableRemovalPatch(this)
|
||||
};
|
||||
|
||||
RunnableFactory.createNew("Database Patch", new AbsRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
boolean applied = false;
|
||||
for (Patch patch : patches) {
|
||||
if (!patch.hasBeenApplied()) {
|
||||
String patchName = patch.getClass().getSimpleName();
|
||||
Log.info(locale.get().getString(PluginLang.DB_APPLY_PATCH, patchName));
|
||||
patch.apply();
|
||||
applied = true;
|
||||
}
|
||||
}
|
||||
Log.info(locale.get().getString(
|
||||
applied ? PluginLang.DB_APPLIED_PATCHES : PluginLang.DB_APPLIED_PATCHES_ALREADY
|
||||
));
|
||||
} catch (Exception e) {
|
||||
Log.error("----------------------------------------------------");
|
||||
Log.error(locale.get().getString(PluginLang.ENABLE_FAIL_DB_PATCH));
|
||||
Log.error("----------------------------------------------------");
|
||||
Log.toLog(this.getClass(), e);
|
||||
PlanPlugin.getInstance().onDisable();
|
||||
}
|
||||
}
|
||||
}).runTaskLaterAsynchronously(TimeAmount.SECOND.ticks() * 5L);
|
||||
try {
|
||||
RunnableFactory.createNew("Database Patch", new PatchTask(patches, locale))
|
||||
.runTaskLaterAsynchronously(TimeAmount.SECOND.ticks() * 5L);
|
||||
} catch (Exception ignore) {
|
||||
// Task failed to register because plugin is being disabled
|
||||
}
|
||||
} catch (DBOpException e) {
|
||||
throw new DBInitException("Failed to set-up Database", e);
|
||||
}
|
||||
|
@ -9,9 +9,11 @@ import com.djrapitops.plan.data.store.mutators.PlayersMutator;
|
||||
import com.djrapitops.plan.data.store.mutators.SessionsMutator;
|
||||
import com.djrapitops.plan.data.store.objects.DateObj;
|
||||
import com.djrapitops.plan.data.time.WorldTimes;
|
||||
import com.djrapitops.plan.system.cache.SessionCache;
|
||||
import com.djrapitops.plan.system.database.databases.operation.FetchOperations;
|
||||
import com.djrapitops.plan.system.database.databases.sql.SQLDB;
|
||||
import com.djrapitops.plan.system.info.server.Server;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plugin.api.TimeAmount;
|
||||
|
||||
import java.util.*;
|
||||
@ -84,7 +86,13 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
|
||||
|
||||
// Calculating getters
|
||||
container.putSupplier(ServerKeys.OPERATORS, () -> PlayersMutator.forContainer(container).operators());
|
||||
container.putSupplier(ServerKeys.SESSIONS, () -> PlayersMutator.forContainer(container).getSessions());
|
||||
container.putSupplier(ServerKeys.SESSIONS, () -> {
|
||||
List<Session> sessions = PlayersMutator.forContainer(container).getSessions();
|
||||
if (serverUUID.equals(ServerInfo.getServerUUID())) {
|
||||
sessions.addAll(SessionCache.getActiveSessions().values());
|
||||
}
|
||||
return sessions;
|
||||
});
|
||||
container.putSupplier(ServerKeys.PLAYER_KILLS, () -> SessionsMutator.forContainer(container).toPlayerKillList());
|
||||
container.putSupplier(ServerKeys.PLAYER_KILL_COUNT, () -> container.getUnsafe(ServerKeys.PLAYER_KILLS).size());
|
||||
container.putSupplier(ServerKeys.MOB_KILL_COUNT, () -> SessionsMutator.forContainer(container).toMobKillCount());
|
||||
|
@ -117,7 +117,7 @@ public class KillsTable extends UserIDTable {
|
||||
UUID victim = UUID.fromString(uuidS);
|
||||
long date = set.getLong(Col.DATE.get());
|
||||
String weapon = set.getString(Col.WEAPON.get());
|
||||
session.getUnsafe(SessionKeys.PLAYER_KILLS).add(new PlayerKill(victim, weapon, date));
|
||||
session.getPlayerKills().add(new PlayerKill(victim, weapon, date));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -286,7 +286,7 @@ public class KillsTable extends UserIDTable {
|
||||
for (Session session : sessions) {
|
||||
int sessionID = session.getUnsafe(SessionKeys.DB_ID);
|
||||
// Every kill
|
||||
for (PlayerKill kill : session.getUnsafe(SessionKeys.PLAYER_KILLS)) {
|
||||
for (PlayerKill kill : session.getPlayerKills()) {
|
||||
UUID victim = kill.getVictim();
|
||||
long date = kill.getDate();
|
||||
String weapon = kill.getWeapon();
|
||||
|
@ -113,7 +113,7 @@ public class SessionsTable extends UserIDTable {
|
||||
}
|
||||
|
||||
db.getWorldTimesTable().saveWorldTimes(uuid, sessionID, session.getUnsafe(SessionKeys.WORLD_TIMES));
|
||||
db.getKillsTable().savePlayerKills(uuid, sessionID, session.getUnsafe(SessionKeys.PLAYER_KILLS));
|
||||
db.getKillsTable().savePlayerKills(uuid, sessionID, session.getPlayerKills());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -144,6 +144,7 @@ public class ConnectionOut {
|
||||
|
||||
post.setHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||
post.setHeader("charset", "UTF-8");
|
||||
post.setHeader("Connection", "close");
|
||||
|
||||
byte[] toSend = parameters.getBytes();
|
||||
post.setEntity(new ByteArrayEntity(toSend));
|
||||
|
@ -9,7 +9,7 @@ import com.djrapitops.plan.api.exceptions.connection.InternalErrorException;
|
||||
import com.djrapitops.plan.api.exceptions.connection.WebException;
|
||||
import com.djrapitops.plan.api.exceptions.database.DBOpException;
|
||||
import com.djrapitops.plan.data.store.containers.AnalysisContainer;
|
||||
import com.djrapitops.plan.system.cache.CacheSystem;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.info.InfoSystem;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plan.system.webserver.response.DefaultResponses;
|
||||
@ -79,7 +79,7 @@ public class GenerateAnalysisPageRequest extends InfoRequestWithVariables implem
|
||||
try {
|
||||
runningAnalysis = true;
|
||||
UUID serverUUID = ServerInfo.getServerUUID();
|
||||
AnalysisContainer analysisContainer = CacheSystem.getInstance().getDataContainerCache().getAnalysisContainer(serverUUID);
|
||||
AnalysisContainer analysisContainer = new AnalysisContainer(Database.getActive().fetch().getServerContainer(serverUUID));
|
||||
return new AnalysisPage(analysisContainer).toHtml();
|
||||
} catch (DBOpException e) {
|
||||
if (!e.getCause().getMessage().contains("Connection is closed")) {
|
||||
|
@ -12,6 +12,8 @@ import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||
import org.bukkit.event.player.PlayerEvent;
|
||||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
@ -27,14 +29,24 @@ public class AFKListener implements Listener {
|
||||
// Static so that /reload does not cause afk tracking to fail.
|
||||
public static final AFKTracker AFK_TRACKER = new AFKTracker();
|
||||
|
||||
private final Map<UUID, Boolean> ignorePermissionInfo;
|
||||
|
||||
public AFKListener() {
|
||||
ignorePermissionInfo = new HashMap<>();
|
||||
}
|
||||
|
||||
private void event(PlayerEvent event) {
|
||||
try {
|
||||
Player player = event.getPlayer();
|
||||
UUID uuid = player.getUniqueId();
|
||||
long time = System.currentTimeMillis();
|
||||
|
||||
if (player.hasPermission(Permissions.IGNORE_AFK.getPermission())) {
|
||||
boolean ignored = ignorePermissionInfo.getOrDefault(uuid, player.hasPermission(Permissions.IGNORE_AFK.getPermission()));
|
||||
if (ignored) {
|
||||
AFK_TRACKER.hasIgnorePermission(uuid);
|
||||
ignorePermissionInfo.put(uuid, true);
|
||||
} else {
|
||||
ignorePermissionInfo.put(uuid, false);
|
||||
}
|
||||
|
||||
AFK_TRACKER.performedAction(uuid, time);
|
||||
|
@ -15,8 +15,8 @@ import com.djrapitops.plan.system.webserver.cache.PageId;
|
||||
import com.djrapitops.plan.system.webserver.cache.ResponseCache;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
|
||||
import net.md_5.bungee.api.event.PostLoginEvent;
|
||||
import net.md_5.bungee.api.event.ServerDisconnectEvent;
|
||||
import net.md_5.bungee.api.event.ServerSwitchEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
@ -53,7 +53,7 @@ public class PlayerOnlineListener implements Listener {
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onLogout(ServerDisconnectEvent event) {
|
||||
public void onLogout(PlayerDisconnectEvent event) {
|
||||
try {
|
||||
ProxiedPlayer player = event.getPlayer();
|
||||
UUID uuid = player.getUniqueId();
|
||||
|
@ -32,7 +32,7 @@ public class PlayerPageUpdateProcessor implements Runnable {
|
||||
cancel();
|
||||
}
|
||||
}
|
||||
}).runTaskLaterAsynchronously(TimeAmount.SECOND.ticks() * 20);
|
||||
}).runTaskLaterAsynchronously(TimeAmount.SECOND.ticks() * 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,10 +9,12 @@ import com.djrapitops.plan.data.store.objects.DateObj;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plan.system.processing.CriticalRunnable;
|
||||
import com.djrapitops.plan.utilities.analysis.Median;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.OptionalInt;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Processes 60s values of a Ping list.
|
||||
@ -37,30 +39,35 @@ public class PingInsertProcessor implements CriticalRunnable {
|
||||
long lastDate = history.get(history.size() - 1).getDate();
|
||||
OptionalInt max = history.stream()
|
||||
.mapToInt(DateObj::getValue)
|
||||
.filter(i -> i >= 0)
|
||||
.filter(i -> i > 0 && i < 4000)
|
||||
.max();
|
||||
|
||||
if (!max.isPresent()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int minValue = history.stream()
|
||||
.mapToInt(DateObj::getValue)
|
||||
.filter(i -> i >= 0)
|
||||
.min().orElse(-1);
|
||||
int minValue = getMinValue(history);
|
||||
|
||||
double avgValue = history.stream()
|
||||
.mapToInt(DateObj::getValue)
|
||||
.filter(i -> i >= 0)
|
||||
.average().orElse(-1);
|
||||
int meanValue = getMeanValue(history);
|
||||
|
||||
int maxValue = max.getAsInt();
|
||||
|
||||
Ping ping = new Ping(lastDate, ServerInfo.getServerUUID(),
|
||||
minValue,
|
||||
maxValue,
|
||||
avgValue);
|
||||
meanValue);
|
||||
|
||||
Database.getActive().save().ping(uuid, ping);
|
||||
}
|
||||
|
||||
int getMinValue(List<DateObj<Integer>> history) {
|
||||
return history.stream()
|
||||
.mapToInt(DateObj::getValue)
|
||||
.filter(i -> i > 0 && i < 4000)
|
||||
.min().orElse(-1);
|
||||
}
|
||||
|
||||
int getMeanValue(List<DateObj<Integer>> history) {
|
||||
return (int) Median.forInt(history.stream().map(DateObj::getValue).collect(Collectors.toList())).calculate();
|
||||
}
|
||||
}
|
||||
|
@ -52,6 +52,8 @@ public enum Settings {
|
||||
AFK_THRESHOLD_MINUTES("Data.AFKThresholdMinutes"),
|
||||
KEEP_LOGS_DAYS("Plugin.KeepLogsForXDays"),
|
||||
KEEP_INACTIVE_PLAYERS_DAYS("Data.KeepInactivePlayerDataForDays"),
|
||||
PING_SERVER_ENABLE_DELAY("Data.Ping.ServerEnableDelaySeconds"),
|
||||
PING_PLAYER_LOGIN_DELAY("Data.Ping.PlayerLoginDelaySeconds"),
|
||||
|
||||
// String
|
||||
DEBUG("Plugin.Debug"),
|
||||
|
@ -174,7 +174,9 @@ public class NetworkSettings {
|
||||
AFK_THRESHOLD_MINUTES,
|
||||
DATA_GEOLOCATIONS,
|
||||
KEEP_LOGS_DAYS,
|
||||
KEEP_INACTIVE_PLAYERS_DAYS
|
||||
KEEP_INACTIVE_PLAYERS_DAYS,
|
||||
PING_SERVER_ENABLE_DELAY,
|
||||
PING_PLAYER_LOGIN_DELAY
|
||||
};
|
||||
Log.debug("NetworkSettings: Adding Config Values..");
|
||||
for (Settings setting : sameStrings) {
|
||||
|
@ -5,10 +5,12 @@
|
||||
package com.djrapitops.plan.system.tasks;
|
||||
|
||||
import com.djrapitops.plan.Plan;
|
||||
import com.djrapitops.plan.system.settings.Settings;
|
||||
import com.djrapitops.plan.system.tasks.server.BukkitTPSCountTimer;
|
||||
import com.djrapitops.plan.system.tasks.server.PaperTPSCountTimer;
|
||||
import com.djrapitops.plan.system.tasks.server.PingCountTimer;
|
||||
import com.djrapitops.plugin.api.Check;
|
||||
import com.djrapitops.plugin.api.TimeAmount;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
@ -33,8 +35,9 @@ public class BukkitTaskSystem extends ServerTaskSystem {
|
||||
try {
|
||||
PingCountTimer pingCountTimer = new PingCountTimer();
|
||||
((Plan) plugin).registerListener(pingCountTimer);
|
||||
long startDelay = TimeAmount.SECOND.ticks() * (long) Settings.PING_SERVER_ENABLE_DELAY.getNumber();
|
||||
RunnableFactory.createNew("PingCountTimer", pingCountTimer)
|
||||
.runTaskTimer(20L, PingCountTimer.PING_INTERVAL);
|
||||
.runTaskTimer(startDelay, PingCountTimer.PING_INTERVAL);
|
||||
} catch (ExceptionInInitializerError | NoClassDefFoundError ignore) {
|
||||
// Running CraftBukkit
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ package com.djrapitops.plan.system.tasks.server;
|
||||
import com.djrapitops.plan.data.store.objects.DateObj;
|
||||
import com.djrapitops.plan.system.processing.Processing;
|
||||
import com.djrapitops.plan.system.processing.processors.player.PingInsertProcessor;
|
||||
import com.djrapitops.plan.system.settings.Settings;
|
||||
import com.djrapitops.plan.utilities.java.Reflection;
|
||||
import com.djrapitops.plugin.api.TimeAmount;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
@ -160,7 +161,7 @@ public class PingCountTimer extends AbsRunnable implements Listener {
|
||||
addPlayer(player);
|
||||
}
|
||||
}
|
||||
}).runTaskLater(TimeAmount.SECOND.ticks() * 10L);
|
||||
}).runTaskLater(TimeAmount.SECOND.ticks() * (long) Settings.PING_PLAYER_LOGIN_DELAY.getNumber());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
|
@ -1,6 +1,6 @@
|
||||
package com.djrapitops.plan.system.webserver.response.pages;
|
||||
|
||||
import com.djrapitops.plan.system.cache.CacheSystem;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@ -12,6 +12,6 @@ import java.util.UUID;
|
||||
public class RawPlayerDataResponse extends RawDataResponse {
|
||||
|
||||
public RawPlayerDataResponse(UUID uuid) {
|
||||
super(CacheSystem.getInstance().getDataContainerCache().getPlayerContainer(uuid));
|
||||
super(Database.getActive().fetch().getPlayerContainer(uuid));
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package com.djrapitops.plan.system.webserver.response.pages;
|
||||
|
||||
import com.djrapitops.plan.system.cache.CacheSystem;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@ -12,6 +12,6 @@ import java.util.UUID;
|
||||
public class RawServerDataResponse extends RawDataResponse {
|
||||
|
||||
public RawServerDataResponse(UUID serverUUID) {
|
||||
super(CacheSystem.getInstance().getDataContainerCache().getAnalysisContainer(serverUUID).getServerContainer());
|
||||
super(Database.getActive().fetch().getServerContainer(serverUUID));
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package com.djrapitops.plan.utilities.analysis;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Math utility for calculating the median from Integer values.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class Median {
|
||||
|
||||
private final List<Long> values;
|
||||
private int size;
|
||||
|
||||
private Median(Collection<Integer> values, int b) {
|
||||
this(values.stream().map(i -> (long) i).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
private Median(List<Long> values) {
|
||||
this.values = values;
|
||||
Collections.sort(values);
|
||||
size = values.size();
|
||||
}
|
||||
|
||||
public static Median forInt(Collection<Integer> integers) {
|
||||
return new Median(integers, 0);
|
||||
}
|
||||
|
||||
public static Median forLong(List<Long> longs) {
|
||||
return new Median(longs);
|
||||
}
|
||||
|
||||
public double calculate() {
|
||||
if (values.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
if (size % 2 == 0) {
|
||||
return calculateEven();
|
||||
} else {
|
||||
return calculateOdd();
|
||||
}
|
||||
}
|
||||
|
||||
private double calculateEven() {
|
||||
int half = size / 2;
|
||||
double x1 = values.get(half);
|
||||
double x2 = values.get(half - 1);
|
||||
return (x1 + x2) / 2;
|
||||
}
|
||||
|
||||
private double calculateOdd() {
|
||||
int half = size / 2;
|
||||
return (double) values.get(half);
|
||||
}
|
||||
}
|
@ -2,13 +2,10 @@ package com.djrapitops.plan.utilities.html.pages;
|
||||
|
||||
import com.djrapitops.plan.PlanPlugin;
|
||||
import com.djrapitops.plan.data.container.Session;
|
||||
import com.djrapitops.plan.data.store.CachingSupplier;
|
||||
import com.djrapitops.plan.data.store.Key;
|
||||
import com.djrapitops.plan.data.store.keys.SessionKeys;
|
||||
import com.djrapitops.plan.data.store.mutators.formatting.Formatter;
|
||||
import com.djrapitops.plan.data.store.mutators.formatting.Formatters;
|
||||
import com.djrapitops.plan.data.store.objects.DateHolder;
|
||||
import com.djrapitops.plan.system.cache.CacheSystem;
|
||||
import com.djrapitops.plan.system.cache.SessionCache;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.info.connection.ConnectionLog;
|
||||
@ -32,7 +29,6 @@ import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.RuntimeMXBean;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.*;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Html parsing for the Debug page.
|
||||
@ -68,7 +64,6 @@ public class DebugPage implements Page {
|
||||
StringBuilder content = new StringBuilder();
|
||||
appendResponseCache(content);
|
||||
appendSessionCache(content);
|
||||
appendDataContainerCache(content);
|
||||
return content.toString();
|
||||
}
|
||||
|
||||
@ -110,36 +105,6 @@ public class DebugPage implements Page {
|
||||
}
|
||||
}
|
||||
|
||||
private void appendDataContainerCache(StringBuilder content) {
|
||||
try {
|
||||
content.append("<pre>### DataContainer Cache:<br><br>");
|
||||
|
||||
content.append("Key | Is Cached | Cache Time <br>")
|
||||
.append("-- | -- | -- <br>");
|
||||
Formatter<Long> timeStamp = Formatters.yearLongValue();
|
||||
Set<Map.Entry<Key, Supplier>> dataContainers = CacheSystem.getInstance().getDataContainerCache().getMap().entrySet();
|
||||
if (dataContainers.isEmpty()) {
|
||||
content.append("Empty");
|
||||
}
|
||||
for (Map.Entry<Key, Supplier> entry : dataContainers) {
|
||||
String keyName = entry.getKey().getKeyName();
|
||||
Supplier supplier = entry.getValue();
|
||||
if (supplier instanceof CachingSupplier) {
|
||||
CachingSupplier cachingSupplier = (CachingSupplier) supplier;
|
||||
boolean isCached = cachingSupplier.isCached();
|
||||
String cacheText = isCached ? "Yes" : "No";
|
||||
String cacheTime = isCached ? timeStamp.apply(cachingSupplier.getCacheTime()) : "-";
|
||||
content.append(keyName).append(" | ").append(cacheText).append(" | ").append(cacheTime).append("<br>");
|
||||
} else {
|
||||
content.append(keyName).append(" | ").append("Non-caching Supplier").append(" | ").append("-").append("<br>");
|
||||
}
|
||||
}
|
||||
content.append("</pre>");
|
||||
} catch (Exception e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private String createConfigContent() {
|
||||
StringBuilder content = new StringBuilder();
|
||||
appendConfig(content);
|
||||
|
@ -14,7 +14,6 @@ import com.djrapitops.plan.data.store.mutators.formatting.Formatter;
|
||||
import com.djrapitops.plan.data.store.mutators.formatting.Formatters;
|
||||
import com.djrapitops.plan.data.store.mutators.formatting.PlaceholderReplacer;
|
||||
import com.djrapitops.plan.data.time.WorldTimes;
|
||||
import com.djrapitops.plan.system.cache.CacheSystem;
|
||||
import com.djrapitops.plan.system.cache.SessionCache;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
@ -60,7 +59,7 @@ public class InspectPage implements Page {
|
||||
}
|
||||
Benchmark.start("Inspect Parse, Fetch");
|
||||
Database db = Database.getActive();
|
||||
PlayerContainer container = CacheSystem.getInstance().getDataContainerCache().getPlayerContainer(uuid);
|
||||
PlayerContainer container = Database.getActive().fetch().getPlayerContainer(uuid);
|
||||
if (!container.getValue(PlayerKeys.REGISTERED).isPresent()) {
|
||||
throw new IllegalStateException("Player is not registered");
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ public class SessionAccordion extends AbstractAccordion {
|
||||
sessions.sort(new DateHolderRecentComparator());
|
||||
|
||||
int i = 0;
|
||||
for (Session session : sessions) {
|
||||
for (Session session : new ArrayList<>(sessions)) {
|
||||
if (i >= maxSessions) {
|
||||
break;
|
||||
}
|
||||
|
@ -5,18 +5,22 @@ import com.djrapitops.plan.system.info.connection.ConnectionSystem;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import org.bstats.sponge.Metrics;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.io.Serializable;
|
||||
|
||||
public class BStatsSponge {
|
||||
|
||||
@Inject
|
||||
private Metrics metrics;
|
||||
private final Metrics metrics;
|
||||
|
||||
public BStatsSponge(Metrics metrics) {
|
||||
this.metrics = metrics;
|
||||
}
|
||||
|
||||
public void registerMetrics() {
|
||||
Log.logDebug("Enable", "Enabling bStats Metrics.");
|
||||
if (metrics != null) {
|
||||
registerConfigSettingGraphs();
|
||||
} else {
|
||||
Log.debug("Metrics not injected properly.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
name: Plan
|
||||
author: Rsl1122
|
||||
main: com.djrapitops.plan.PlanBungee
|
||||
version: 4.4.3
|
||||
version: 4.4.4
|
@ -67,6 +67,9 @@ Data:
|
||||
LogUnknownCommands: false
|
||||
CombineCommandAliases: true
|
||||
Geolocations: true
|
||||
Ping:
|
||||
ServerEnableDelaySeconds: 300
|
||||
PlayerLoginDelaySeconds: 30
|
||||
KeepInactivePlayerDataForDays: 180
|
||||
# -----------------------------------------------------
|
||||
Customization:
|
||||
|
@ -81,6 +81,9 @@ Data:
|
||||
LogUnknownCommands: false
|
||||
CombineCommandAliases: true
|
||||
Geolocations: true
|
||||
Ping:
|
||||
ServerEnableDelaySeconds: 300
|
||||
PlayerLoginDelaySeconds: 30
|
||||
KeepInactivePlayerDataForDays: 180
|
||||
# -----------------------------------------------------
|
||||
Customization:
|
||||
|
@ -1,7 +1,7 @@
|
||||
name: Plan
|
||||
author: Rsl1122
|
||||
main: com.djrapitops.plan.Plan
|
||||
version: 4.4.3
|
||||
version: 4.4.4
|
||||
softdepend:
|
||||
- EssentialsX
|
||||
- Towny
|
||||
@ -19,6 +19,7 @@ softdepend:
|
||||
- ProtocolSupport
|
||||
- Kingdoms
|
||||
- RedProtect
|
||||
- AdvancedBan
|
||||
|
||||
commands:
|
||||
plan:
|
||||
|
@ -1148,9 +1148,9 @@
|
||||
<script src="js/admin.js"></script>
|
||||
|
||||
<!-- FullCalendar -->
|
||||
<link rel='stylesheet' href='../plugins/fullcalendar/fullcalendar.min.css'/>
|
||||
<script src='../plugins/momentjs/moment.js'></script>
|
||||
<script src='../plugins/fullcalendar/fullcalendar.min.js'></script>
|
||||
<link rel='stylesheet' href='plugins/fullcalendar/fullcalendar.min.css'/>
|
||||
<script src='plugins/momentjs/moment.js'></script>
|
||||
<script src='plugins/fullcalendar/fullcalendar.min.js'></script>
|
||||
|
||||
<!-- Plan Charts -->
|
||||
<script src="js/charts/playerGraph.js"></script>
|
||||
|
@ -1,10 +1,7 @@
|
||||
package com.djrapitops.plan.system.cache;
|
||||
|
||||
import com.djrapitops.plan.data.container.Session;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.*;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import utilities.TestConstants;
|
||||
import utilities.mocks.SystemMockUtil;
|
||||
@ -36,6 +33,11 @@ public class SessionCacheTest {
|
||||
sessionCache.cacheSession(uuid, session);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
SessionCache.clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAtomity() {
|
||||
SessionCache reloaded = new SessionCache(null);
|
||||
@ -43,4 +45,16 @@ public class SessionCacheTest {
|
||||
assertTrue(cachedSession.isPresent());
|
||||
assertEquals(session, cachedSession.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBungeeReCaching() {
|
||||
SessionCache cache = new BungeeDataCache(null);
|
||||
cache.cacheSession(uuid, session);
|
||||
Session expected = new Session(uuid, 0, "", "");
|
||||
cache.cacheSession(uuid, expected);
|
||||
|
||||
Optional<Session> result = SessionCache.getCachedSession(uuid);
|
||||
assertTrue(result.isPresent());
|
||||
assertEquals(expected, result.get());
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
package com.djrapitops.plan.system.processing.processors.player;
|
||||
|
||||
import com.djrapitops.plan.data.store.objects.DateObj;
|
||||
import com.djrapitops.plan.utilities.analysis.Median;
|
||||
import com.djrapitops.plugin.api.TimeAmount;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import utilities.RandomData;
|
||||
import utilities.TestConstants;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Test for {@link PingInsertProcessor}.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class PingInsertProcessorTest {
|
||||
|
||||
private List<DateObj<Integer>> testPing;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
testPing = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < TimeAmount.MINUTE.ms(); i += TimeAmount.SECOND.ms() * 2L) {
|
||||
testPing.add(new DateObj<>(i, RandomData.randomInt(1, 4000)));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMedian() {
|
||||
List<Integer> collect = testPing.stream().map(DateObj::getValue).sorted().collect(Collectors.toList());
|
||||
System.out.println(collect);
|
||||
int expected = (int) Median.forInt(collect).calculate();
|
||||
int result = new PingInsertProcessor(TestConstants.PLAYER_ONE_UUID, new ArrayList<>()).getMeanValue(testPing);
|
||||
System.out.println(result);
|
||||
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMedianSingleEntry() {
|
||||
int expected = 50;
|
||||
int result = new PingInsertProcessor(TestConstants.PLAYER_ONE_UUID, new ArrayList<>()).getMeanValue(
|
||||
Collections.singletonList(new DateObj<>(0, expected))
|
||||
);
|
||||
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMedianEmpty() {
|
||||
int expected = -1;
|
||||
int result = new PingInsertProcessor(TestConstants.PLAYER_ONE_UUID, new ArrayList<>()).getMeanValue(
|
||||
Collections.emptyList()
|
||||
);
|
||||
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
package com.djrapitops.plan.utilities.analysis;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Tests for {@link Median}.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class MedianTest {
|
||||
|
||||
@Test
|
||||
public void simpleOdd() {
|
||||
List<Integer> testValues = Arrays.asList(1, 3, 3, 6, 7, 8, 9);
|
||||
Collections.shuffle(testValues);
|
||||
double expected = 6;
|
||||
double result = Median.forInt(testValues).calculate();
|
||||
|
||||
assertEquals(expected, result, 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleEven() {
|
||||
List<Integer> testValues = Arrays.asList(1, 2, 3, 4, 5, 6, 8, 9);
|
||||
Collections.shuffle(testValues);
|
||||
double expected = 4.5;
|
||||
double result = Median.forInt(testValues).calculate();
|
||||
|
||||
assertEquals(expected, result, 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void empty() {
|
||||
double expected = -1;
|
||||
double result = Median.forInt(Collections.emptyList()).calculate();
|
||||
|
||||
assertEquals(expected, result, 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singleValue() {
|
||||
double expected = 50;
|
||||
double result = Median.forInt(Collections.singletonList((int) expected)).calculate();
|
||||
|
||||
assertEquals(expected, result, 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void twoValues() {
|
||||
List<Integer> testValues = Arrays.asList(1, 2);
|
||||
double expected = 1.5;
|
||||
double result = Median.forInt(testValues).calculate();
|
||||
|
||||
assertEquals(expected, result, 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void overflowOdd() {
|
||||
List<Integer> testValues = Arrays.asList(Integer.MIN_VALUE, 2, Integer.MAX_VALUE);
|
||||
double expected = 2;
|
||||
double result = Median.forInt(testValues).calculate();
|
||||
|
||||
assertEquals(expected, result, 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void overflowEven() {
|
||||
List<Integer> testValues = Arrays.asList(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
|
||||
double expected = -0.5;
|
||||
double result = Median.forInt(testValues).calculate();
|
||||
|
||||
assertEquals(expected, result, 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void overflowEven2() {
|
||||
List<Integer> testValues = Arrays.asList(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
|
||||
double expected = Integer.MAX_VALUE;
|
||||
double result = Median.forInt(testValues).calculate();
|
||||
|
||||
assertEquals(expected, result, 0.01);
|
||||
}
|
||||
|
||||
}
|
@ -129,7 +129,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.gmail.nossr50</groupId>
|
||||
<artifactId>mcmmo</artifactId>
|
||||
<artifactId>mcMMO</artifactId>
|
||||
<version>1.5.07</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
@ -161,7 +161,7 @@
|
||||
<dependency>
|
||||
<groupId>net.kaikk.mc</groupId>
|
||||
<artifactId>GriefPreventionPlus</artifactId>
|
||||
<version>RELEASE</version>
|
||||
<version>13.3</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -230,6 +230,12 @@
|
||||
<version>6.549</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>me.leoko</groupId>
|
||||
<artifactId>advancedban</artifactId>
|
||||
<version>2.1.5</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
|
@ -6,6 +6,7 @@ import com.djrapitops.plugin.api.Check;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import com.djrapitops.pluginbridge.plan.aac.AdvancedAntiCheatHook;
|
||||
import com.djrapitops.pluginbridge.plan.advancedachievements.AdvancedAchievementsHook;
|
||||
import com.djrapitops.pluginbridge.plan.advancedban.AdvancedBanHook;
|
||||
import com.djrapitops.pluginbridge.plan.askyblock.ASkyBlockHook;
|
||||
import com.djrapitops.pluginbridge.plan.banmanager.BanManagerHook;
|
||||
import com.djrapitops.pluginbridge.plan.buycraft.BuyCraftHook;
|
||||
@ -64,13 +65,16 @@ public class Bridge {
|
||||
}
|
||||
|
||||
private static Hook[] getBungeeHooks(HookHandler h) {
|
||||
return new Hook[0];
|
||||
return new Hook[]{
|
||||
new AdvancedBanHook(h)
|
||||
};
|
||||
}
|
||||
|
||||
private static Hook[] getBukkitHooks(HookHandler h) {
|
||||
return new Hook[]{
|
||||
new AdvancedAntiCheatHook(h),
|
||||
new AdvancedAchievementsHook(h),
|
||||
new AdvancedBanHook(h),
|
||||
new ASkyBlockHook(h),
|
||||
new BanManagerHook(h),
|
||||
new BuyCraftHook(h),
|
||||
|
@ -2,9 +2,6 @@ package com.djrapitops.pluginbridge.plan;
|
||||
|
||||
import com.djrapitops.plan.data.plugin.HookHandler;
|
||||
import com.djrapitops.plan.data.plugin.PluginData;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import static org.bukkit.plugin.java.JavaPlugin.getPlugin;
|
||||
|
||||
/**
|
||||
* Abstract class for easy hooking of plugins.
|
||||
@ -35,11 +32,9 @@ public abstract class Hook {
|
||||
public Hook(String plugin, HookHandler hookHandler) {
|
||||
this.hookHandler = hookHandler;
|
||||
try {
|
||||
Class<?> givenClass = Class.forName(plugin);
|
||||
Class<? extends JavaPlugin> pluginClass = (Class<? extends JavaPlugin>) givenClass;
|
||||
JavaPlugin hookedPlugin = getPlugin(pluginClass);
|
||||
enabled = hookedPlugin.isEnabled();
|
||||
} catch (NoClassDefFoundError | NoSuchFieldError | NoSuchMethodError | Exception e) {
|
||||
Class.forName(plugin);
|
||||
enabled = true;
|
||||
} catch (Exception e) {
|
||||
enabled = false;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Licence is provided in the jar as license.yml also here:
|
||||
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
|
||||
*/
|
||||
package com.djrapitops.pluginbridge.plan.advancedban;
|
||||
|
||||
import com.djrapitops.plan.api.PlanAPI;
|
||||
import com.djrapitops.plan.data.element.AnalysisContainer;
|
||||
import com.djrapitops.plan.data.element.InspectContainer;
|
||||
import com.djrapitops.plan.data.plugin.ContainerSize;
|
||||
import com.djrapitops.plan.data.plugin.PluginData;
|
||||
import com.djrapitops.plan.data.store.keys.AnalysisKeys;
|
||||
import com.djrapitops.plan.utilities.FormatUtils;
|
||||
import com.djrapitops.plan.utilities.html.Html;
|
||||
import com.djrapitops.plan.utilities.html.HtmlUtils;
|
||||
import com.djrapitops.plan.utilities.html.icon.Color;
|
||||
import com.djrapitops.plan.utilities.html.icon.Family;
|
||||
import com.djrapitops.plan.utilities.html.icon.Icon;
|
||||
import com.djrapitops.plan.utilities.html.icon.Icons;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
import me.leoko.advancedban.manager.PunishmentManager;
|
||||
import me.leoko.advancedban.manager.UUIDManager;
|
||||
import me.leoko.advancedban.utils.Punishment;
|
||||
import me.leoko.advancedban.utils.PunishmentType;
|
||||
|
||||
/**
|
||||
* PluginData for AdvancedBan plugin.
|
||||
*
|
||||
* @author Vankka
|
||||
*/
|
||||
public class AdvancedBanData extends PluginData {
|
||||
public AdvancedBanData() {
|
||||
super(ContainerSize.THIRD, "AdvancedBan");
|
||||
setPluginIcon(Icons.BANNED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InspectContainer getPlayerData(UUID uuid, InspectContainer inspectContainer) {
|
||||
String abUuid = uuid.toString().replace("-", "");
|
||||
|
||||
if (uuid.version() == 3) { // Cracked / Offline UUID
|
||||
return inspectContainer;
|
||||
}
|
||||
|
||||
Punishment ban = PunishmentManager.get().getBan(abUuid);
|
||||
Punishment mute = PunishmentManager.get().getMute(abUuid);
|
||||
long warnings = PunishmentManager.get().getWarns(abUuid).stream().filter(warning -> !warning.isExpired()).count();
|
||||
|
||||
inspectContainer.addValue(getWithIcon("Banned", Icons.BANNED), ban != null ? "Yes" : "No");
|
||||
inspectContainer.addValue(getWithIcon("Muted", Icon.called("bell-slash").of(Color.DEEP_ORANGE)), mute != null ? "Yes" : "No");
|
||||
inspectContainer.addValue(getWithIcon("Warnings", Icon.called("flag").of(Color.YELLOW)), warnings);
|
||||
|
||||
if (ban != null) {
|
||||
String operator = ban.getOperator();
|
||||
String link = Html.LINK.parse(PlanAPI.getInstance().getPlayerInspectPageLink(operator), operator);
|
||||
String reason = HtmlUtils.swapColorsToSpan(ban.getReason());
|
||||
long start = ban.getStart();
|
||||
String end = FormatUtils.formatTimeStampYear(ban.getEnd());
|
||||
|
||||
if (ban.getType() == PunishmentType.BAN || ban.getType() == PunishmentType.IP_BAN) { // Permanent
|
||||
end = "Permanent ban";
|
||||
}
|
||||
|
||||
if (operator.equals("CONSOLE")) {
|
||||
link = "CONSOLE";
|
||||
}
|
||||
|
||||
inspectContainer.addValue(" " + getWithIcon("Operator", Icon.called("user").of(Color.RED)), link);
|
||||
inspectContainer.addValue(" " + getWithIcon("Date", Icon.called("calendar").of(Color.RED).of(Family.REGULAR)), FormatUtils.formatTimeStampYear(start));
|
||||
inspectContainer.addValue(" " + getWithIcon("Ends", Icon.called("calendar-check").of(Color.RED).of(Family.REGULAR)), end);
|
||||
inspectContainer.addValue(" " + getWithIcon("Reason", Icon.called("comment").of(Color.RED).of(Family.REGULAR)), reason);
|
||||
}
|
||||
|
||||
if (mute != null) {
|
||||
String operator = mute.getOperator();
|
||||
String link = Html.LINK.parse(PlanAPI.getInstance().getPlayerInspectPageLink(operator), operator);
|
||||
String reason = HtmlUtils.swapColorsToSpan(mute.getReason());
|
||||
long start = mute.getStart();
|
||||
String end = FormatUtils.formatTimeStampYear(mute.getEnd());
|
||||
|
||||
if (mute.getType() == PunishmentType.MUTE) { // Permanent
|
||||
end = "Permanent mute";
|
||||
}
|
||||
|
||||
if (operator.equals("CONSOLE")) {
|
||||
link = "CONSOLE";
|
||||
}
|
||||
|
||||
inspectContainer.addValue(" " + getWithIcon("Operator", Icon.called("user").of(Color.DEEP_ORANGE)), link);
|
||||
inspectContainer.addValue(" " + getWithIcon("Date", Icon.called("calendar").of(Color.DEEP_ORANGE).of(Family.REGULAR)), FormatUtils.formatTimeStampYear(start));
|
||||
inspectContainer.addValue(" " + getWithIcon("Ends", Icon.called("calendar-check").of(Color.DEEP_ORANGE).of(Family.REGULAR)), end);
|
||||
inspectContainer.addValue(" " + getWithIcon("Reason", Icon.called("comment").of(Color.DEEP_ORANGE).of(Family.REGULAR)), reason);
|
||||
}
|
||||
|
||||
return inspectContainer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnalysisContainer getServerData(Collection<UUID> uuids, AnalysisContainer analysisContainer) {
|
||||
return analysisContainer;
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Licence is provided in the jar as license.yml also here:
|
||||
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
|
||||
*/
|
||||
package com.djrapitops.pluginbridge.plan.advancedban;
|
||||
|
||||
import com.djrapitops.pluginbridge.plan.Hook;
|
||||
import com.djrapitops.plan.data.plugin.HookHandler;
|
||||
|
||||
/**
|
||||
* Hook for AdvancedBan plugin.
|
||||
*
|
||||
* @author Vankka
|
||||
*/
|
||||
public class AdvancedBanHook extends Hook {
|
||||
public AdvancedBanHook(HookHandler hookHandler) {
|
||||
super("me.leoko.advancedban.Universal", hookHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hook() throws NoClassDefFoundError {
|
||||
if (enabled) {
|
||||
addPluginDataSource(new AdvancedBanData());
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user