TPS collection, array generation. API methods, 3rd party speedups.

- Deprecated Condition, will be removed
This commit is contained in:
Rsl1122 2017-06-22 13:01:29 +03:00
parent 9bbb0b49c3
commit c17c1c5171
42 changed files with 776 additions and 64 deletions

View File

@ -19,6 +19,11 @@ public class Log {
Plan.getPluginInstance().getPluginLogger().info(message);
}
/**
* Sends a message to the console with the chatcolors.
*
* @param message Message to send.
*/
public static void infoColor(String message) {
Plan.getInstance().getPluginLogger().infoColor(message);
}
@ -71,6 +76,11 @@ public class Log {
Plan.getInstance().getPluginLogger().toLog(message, filename);
}
/**
* Used to get the name for the error log file.
*
* @return Name of the error log file.
*/
public static String getErrorsFilename() {
return Plan.getInstance().getPluginLogger().getErrorsFilename();
}

View File

@ -38,7 +38,7 @@ public enum Phrase {
NOTIFY_DISABLED_GMLISTENER(ChatColor.YELLOW + "Gamemode change listener disabled, Gm times info inaccurate."),
NOTIFY_DISABLED_COMMANDLISTENER(ChatColor.YELLOW + "Command usage listener disabled."),
NOTIFY_DISABLED_DEATHLISTENER(ChatColor.YELLOW + "Death listener disabled, player & mob kills not recorded."),
//
//
CACHE_SAVETASK_DISABLED("Attempted to schedule data for save after task was shut down."),
CACHE_GETTASK_DISABLED("Attempted to schedule data grab after task was shut down."),
CACHE_CLEARTASK_DISABLED("Attempted to schedule data for clear after task was shut down."),
@ -74,7 +74,7 @@ public enum Phrase {
ANALYSIS_FAIL_NO_PLAYERS(ANALYSIS + "Analysis failed, no known players."),
ANALYSIS_FAIL_NO_DATA(ANALYSIS + "Analysis failed, no data in the database."),
ANALYSIS_BEGIN_ANALYSIS(ANALYSIS + "Data Fetched (REPLACE0 users, took REPLACE1ms), beginning Analysis of data.."),
ANALYSIS_THIRD_PARTY(ANALYSIS+"Analyzing additional data sources (3rd party)"),
ANALYSIS_THIRD_PARTY(ANALYSIS + "Analyzing additional data sources (3rd party)"),
ANALYSIS_COMPLETE(ANALYSIS + "Analysis Complete. (took REPLACE0ms) REPLACE1"),
DATA_CORRUPTION_WARN("Some data might be corrupted: " + REPLACE0),
//
@ -115,9 +115,9 @@ public enum Phrase {
CMD_MANAGE_HELP_HEADER(CMD_FOOTER + "" + COLOR_MAIN.color() + " Player Analytics - Managment Help"),
CMD_MANAGE_STATUS_HEADER(CMD_FOOTER + "" + COLOR_MAIN.color() + " Player Analytics - Database status"),
CMD_MANAGE_STATUS_ACTIVE_DB(CMD_BALL + "" + COLOR_MAIN.color() + " Active Database: " + COLOR_SEC.color() + "REPLACE0"),
CMD_MANAGE_STATUS_QUEUE_SAVE(CMD_BALL + "" + COLOR_MAIN.color() + " Save Queue Size: " + COLOR_SEC.color() + "REPLACE0/"+Settings.PROCESS_SAVE_LIMIT.getNumber()),
CMD_MANAGE_STATUS_QUEUE_GET(CMD_BALL + "" + COLOR_MAIN.color() + " Get Queue Size: " + COLOR_SEC.color() + "REPLACE0/"+Settings.PROCESS_GET_LIMIT.getNumber()),
CMD_MANAGE_STATUS_QUEUE_CLEAR(CMD_BALL + "" + COLOR_MAIN.color() + " Clear Queue Size: " + COLOR_SEC.color() + "REPLACE0/"+Settings.PROCESS_CLEAR_LIMIT.getNumber()),
CMD_MANAGE_STATUS_QUEUE_SAVE(CMD_BALL + "" + COLOR_MAIN.color() + " Save Queue Size: " + COLOR_SEC.color() + "REPLACE0/" + Settings.PROCESS_SAVE_LIMIT.getNumber()),
CMD_MANAGE_STATUS_QUEUE_GET(CMD_BALL + "" + COLOR_MAIN.color() + " Get Queue Size: " + COLOR_SEC.color() + "REPLACE0/" + Settings.PROCESS_GET_LIMIT.getNumber()),
CMD_MANAGE_STATUS_QUEUE_CLEAR(CMD_BALL + "" + COLOR_MAIN.color() + " Clear Queue Size: " + COLOR_SEC.color() + "REPLACE0/" + Settings.PROCESS_CLEAR_LIMIT.getNumber()),
CMD_MANAGE_STATUS_QUEUE_PROCESS(CMD_BALL + "" + COLOR_MAIN.color() + " Process Queue Size: " + COLOR_SEC.color() + "REPLACE0/20000"),
CMD_CLICK_ME("Click Me"),
CMD_LINK(COLOR_SEC.color() + " " + BALL + COLOR_MAIN.color() + " Link: " + COLOR_TER.color()),

View File

@ -37,6 +37,7 @@ import main.java.com.djrapitops.plan.api.API;
import main.java.com.djrapitops.plan.command.PlanCommand;
import main.java.com.djrapitops.plan.data.additional.HookHandler;
import main.java.com.djrapitops.plan.data.cache.*;
import main.java.com.djrapitops.plan.data.handling.TPSCountTimer;
import main.java.com.djrapitops.plan.data.listeners.*;
import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.database.databases.*;
@ -120,6 +121,7 @@ public class Plan extends RslPlugin<Plan> {
this.inspectCache = new InspectCacheHandler(this);
this.analysisCache = new AnalysisCacheHandler(this);
registerListeners();
new TPSCountTimer(this).runTaskTimer(1000, 20);
getCommand("plan").setExecutor(new PlanCommand(this));
@ -402,6 +404,13 @@ public class Plan extends RslPlugin<Plan> {
Log.info("Using locale: " + usingLocale);
}
/**
* Used to get the object storing server variables that are constant after
* boot.
*
* @return ServerVariableHolder
* @see ServerVariableHolder
*/
public ServerVariableHolder getVariable() {
return variable;
}
@ -421,6 +430,11 @@ public class Plan extends RslPlugin<Plan> {
return INSTANCE.api;
}
/**
* Used to get the plugin instance singleton.
*
* @return this object.
*/
public static Plan getInstance() {
return (Plan) getPluginInstance();
}

View File

@ -11,18 +11,33 @@ import org.bukkit.Server;
*/
public class ServerVariableHolder {
private int maxPlayers;
private String ip;
private final int maxPlayers;
private final String ip;
/**
* Constructor, grabs the variables.
*
* @param server instance the plugin is running on.
*/
public ServerVariableHolder(Server server) {
maxPlayers = server.getMaxPlayers();
ip = server.getIp();
}
/**
* Maximum amount of players defined in server.properties
*
* @return number.
*/
public int getMaxPlayers() {
return maxPlayers;
}
/**
* Ip string in server.properties
*
* @return the ip.
*/
public String getIp() {
return ip;
}

View File

@ -4,7 +4,10 @@ import com.djrapitops.javaplugin.utilities.UUIDFetcher;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.function.Function;
import java.util.stream.Collectors;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.AnalysisData;
import main.java.com.djrapitops.plan.data.UserData;
@ -182,8 +185,8 @@ public class API {
}
/**
* Run's the analysis with the current data in the cache and fetches rest from
* the database.
* Run's the analysis with the current data in the cache and fetches rest
* from the database.
*
* Starts a new Asyncronous task to run the analysis.
*/
@ -245,12 +248,12 @@ public class API {
public UUID playerNameToUUID(String playerName) throws Exception {
return UUIDFetcher.getUUIDOf(playerName);
}
/**
* Get the saved UUIDs in the database.
*
*
* Should be called from async thread.
*
*
* @return Collection of UUIDs that can be found in the database.
* @throws SQLException If database error occurs.
* @since 3.4.2
@ -258,14 +261,14 @@ public class API {
public Collection<UUID> getSavedUUIDs() throws SQLException {
return plugin.getDB().getSavedUUIDs();
}
/**
* Get the saved UserData in the database for a collection of UUIDs.
*
*
* Will not contain data for UUIDs not found in the database.
*
*
* Should be called from async thread.
*
*
* @param uuids Collection of UUIDs that can be found in the database.
* @return List of all Data in the database.
* @throws SQLException If database error occurs.
@ -274,4 +277,32 @@ public class API {
public List<UserData> getUserDataOfUsers(Collection<UUID> uuids) throws SQLException {
return plugin.getDB().getUserDataForUUIDS(uuids);
}
/**
* Get the cached UserData objects in the InspectCache.
*
* This can be used with PluginData objects safely to get the data for all
* users in Plan database, because all data is InspectCached before analysis
* begins.
*
* @return List of all Data in the InspectCache.
* @since 3.5.0
*/
public List<UserData> getInspectCachedUserData() {
return plugin.getInspectCache().getCachedUserData();
}
/**
* Get the cached UserData objects in the InspectCache in a Map form.
*
* This can be used with PluginData objects safely to get the data for all
* users in Plan database, because all data is InspectCached before analysis
* begins.
*
* @return Map of all Data in the InspectCache with UUID of the player as the key.
* @since 3.5.0
*/
public Map<UUID, UserData> getInspectCachedUserDataMap() {
return getInspectCachedUserData().stream().collect(Collectors.toMap(UserData::getUuid, Function.identity()));
}
}

View File

@ -1,27 +1,43 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package main.java.com.djrapitops.plan.command;
/**
* Container class for boolean and a string.
*
* @author Rsl1122
* @since 3.4.3
* @deprecated Stupid idea.
*/
@Deprecated
public class Condition {
final private String failMsg;
final private boolean pass;
/**
* Constructor.
* @param pass Did the condition pass?
* @param failMsg Message to send if the condition failed.
*/
@Deprecated
public Condition(boolean pass, String failMsg) {
this.failMsg = failMsg;
this.pass = pass;
}
/**
*
* @return
*/
@Deprecated
public String getFailMsg() {
return failMsg;
}
/**
*
* @return
*/
@Deprecated
public boolean pass() {
return pass;
}

View File

@ -15,6 +15,11 @@ import org.bukkit.OfflinePlayer;
*/
public class ConditionUtils {
/**
* Check if the plugin can display the data.
*
* @return true/false
*/
public static boolean pluginHasViewCapability() {
final boolean usingAlternativeIP = Settings.SHOW_ALTERNATIVE_IP.isTrue();
final boolean webserverIsOn = Settings.WEBSERVER_ENABLED.isTrue();
@ -22,6 +27,13 @@ public class ConditionUtils {
return webserverIsOn || usingAlternativeIP || usingTextUI;
}
/**
* Get the uuid of a playername. Same as UUIDUtility
*
* @param playerName name of player.
* @return UUID
* @see UUIDUtility
*/
public static UUID getUUID(String playerName) {
try {
return UUIDUtility.getUUIDOf(playerName);
@ -30,10 +42,22 @@ public class ConditionUtils {
}
}
/**
* Check if uuid is not null.
*
* @param uuid UUID
* @return is the uuid null?
*/
public static boolean uuidIsValid(UUID uuid) {
return uuid != null;
}
/**
* Check if the player has played.
*
* @param uuid UUID of player
* @return has the player played before?
*/
public static boolean playerHasPlayed(UUID uuid) {
if (!uuidIsValid(uuid)) {
return false;

View File

@ -12,7 +12,7 @@ import org.bukkit.command.CommandSender;
/**
* This subcommand is used to view the version and the database type in use.
*
*
* @author Rsl1122
* @since 2.0.0
*/
@ -26,7 +26,7 @@ public class InfoCommand extends SubCommand {
* @param plugin Current instance of Plan
*/
public InfoCommand(Plan plugin) {
super("info", CommandType.CONSOLE,Permissions.INFO.getPermission(), Phrase.CMD_USG_INFO + "");
super("info", CommandType.CONSOLE, Permissions.INFO.getPermission(), Phrase.CMD_USG_INFO + "");
this.plugin = plugin;
}

View File

@ -45,7 +45,7 @@ public class ManageRemoveCommand extends SubCommand {
String playerName = MiscUtils.getPlayerName(args, sender, Permissions.MANAGE);
(new RslBukkitRunnable<Plan>("DBRemoveTask "+playerName) {
(new RslBukkitRunnable<Plan>("DBRemoveTask " + playerName) {
@Override
public void run() {
UUID uuid;

View File

@ -928,58 +928,114 @@ public class AnalysisData {
this.playtimeDistributionData = playtimeDistributionData;
}
/**
*
* @return
*/
public int getAvgUniqJoins() {
return avgUniqJoins;
}
/**
*
* @return
*/
public int getAvgUniqJoinsDay() {
return avgUniqJoinsDay;
}
/**
*
* @return
*/
public int getAvgUniqJoinsWeek() {
return avgUniqJoinsWeek;
}
/**
*
* @return
*/
public int getAvgUniqJoinsMonth() {
return avgUniqJoinsMonth;
}
/**
*
* @param avgUniqJoins
*/
public void setAvgUniqJoins(int avgUniqJoins) {
this.avgUniqJoins = avgUniqJoins;
}
/**
*
* @param avgUniqJoinsDay
*/
public void setAvgUniqJoinsDay(int avgUniqJoinsDay) {
this.avgUniqJoinsDay = avgUniqJoinsDay;
}
/**
*
* @param avgUniqJoinsWeek
*/
public void setAvgUniqJoinsWeek(int avgUniqJoinsWeek) {
this.avgUniqJoinsWeek = avgUniqJoinsWeek;
}
/**
*
* @param avgUniqJoinsMonth
*/
public void setAvgUniqJoinsMonth(int avgUniqJoinsMonth) {
this.avgUniqJoinsMonth = avgUniqJoinsMonth;
}
/**
*
* @return
*/
public int getUniqueJoinsDay() {
return uniqueJoinsDay;
}
/**
*
* @param uniqueJoinsDay
*/
public void setUniqueJoinsDay(int uniqueJoinsDay) {
this.uniqueJoinsDay = uniqueJoinsDay;
}
/**
*
* @return
*/
public int getUniqueJoinsWeek() {
return uniqueJoinsWeek;
}
/**
*
* @param uniqueJoinsWeek
*/
public void setUniqueJoinsWeek(int uniqueJoinsWeek) {
this.uniqueJoinsWeek = uniqueJoinsWeek;
}
/**
*
* @return
*/
public int getUniqueJoinsMonth() {
return uniqueJoinsMonth;
}
/**
*
* @param uniqueJoinsMonth
*/
public void setUniqueJoinsMonth(int uniqueJoinsMonth) {
this.uniqueJoinsMonth = uniqueJoinsMonth;
}

View File

@ -95,6 +95,15 @@ public class KillData {
}
return true;
}
@Override
public int hashCode() {
int hash = 3;
hash = 89 * hash + Objects.hashCode(this.victim);
hash = 89 * hash + (int) (this.date ^ (this.date >>> 32));
hash = 89 * hash + Objects.hashCode(this.weapon);
return hash;
}
}

View File

@ -370,10 +370,19 @@ public class RawAnalysisData {
return sessiondata;
}
/**
*
* @return
*/
public Map<UUID, List<SessionData>> getSortedSessionData() {
return sortedSessionData;
}
/**
*
* @param uuid
* @param sessions
*/
public void addSessions(UUID uuid, List<SessionData> sessions) {
sessiondata.addAll(sessions);
sortedSessionData.put(uuid, sessions);

View File

@ -8,7 +8,7 @@ package main.java.com.djrapitops.plan.data;
*/
public class SessionData {
private long sessionStart;
private final long sessionStart;
private long sessionEnd;
/**
@ -32,6 +32,10 @@ public class SessionData {
this.sessionEnd = sessionEnd;
}
/**
* Constructor for copying the object.
* @param s SessionData to copy.
*/
public SessionData(SessionData s) {
this.sessionStart = s.getSessionStart();
this.sessionEnd = s.getSessionEnd();
@ -108,4 +112,12 @@ public class SessionData {
}
return true;
}
@Override
public int hashCode() {
int hash = 3;
hash = 97 * hash + (int) (this.sessionStart ^ (this.sessionStart >>> 32));
hash = 97 * hash + (int) (this.sessionEnd ^ (this.sessionEnd >>> 32));
return hash;
}
}

View File

@ -12,25 +12,86 @@ package main.java.com.djrapitops.plan.data;
* @since 3.5.0
*/
public class TPS {
private final long date;
private final double tps;
private final int players;
/**
* Constructor.
*
* @param date time of the average calculation.
* @param tps average tps for the last minute.
* @param players average players for the last minute.
*/
public TPS(long date, double tps, int players) {
this.date = date;
this.tps = tps;
this.players = players;
}
/**
* Get the time of the average calculation.
*
* @return epoch ms.
*/
public long getDate() {
return date;
}
/**
* Get the average tps for the minute.
*
* @return 0-20 double
*/
public double getTps() {
return tps;
}
/**
* Get the average players for the minute.
*
* @return Players online.
*/
public int getPlayers() {
return players;
}
@Override
public int hashCode() {
int hash = 3;
hash = 97 * hash + (int) (this.date ^ (this.date >>> 32));
hash = 97 * hash + (int) (Double.doubleToLongBits(this.tps) ^ (Double.doubleToLongBits(this.tps) >>> 32));
hash = 97 * hash + this.players;
return hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final TPS other = (TPS) obj;
if (this.date != other.date) {
return false;
}
if (Double.doubleToLongBits(this.tps) != Double.doubleToLongBits(other.tps)) {
return false;
}
if (this.players != other.players) {
return false;
}
return true;
}
@Override
public String toString() {
return "TPS{" + date + "|" + tps + "|" + players+'}';
}
}

View File

@ -63,6 +63,10 @@ public class AnalysisCacheHandler {
return (cache != null);
}
/**
*
* @return
*/
public boolean isAnalysisBeingRun() {
return analysis.isAnalysisBeingRun();
}

View File

@ -10,6 +10,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Phrase;
import main.java.com.djrapitops.plan.Plan;
@ -26,6 +28,7 @@ import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.utilities.Benchmark;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
import main.java.com.djrapitops.plan.utilities.NewPlayerCreator;
import main.java.com.djrapitops.plan.utilities.analysis.MathUtils;
import main.java.com.djrapitops.plan.utilities.comparators.HandlingInfoTimeComparator;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
@ -51,6 +54,7 @@ public class DataCacheHandler extends LocationCache {
// Cache
private final HashMap<UUID, UserData> dataCache;
private Map<String, Integer> commandUse;
private List<List<TPS>> unsavedTPSHistory;
// Plan
private final Plan plugin;
@ -63,7 +67,7 @@ public class DataCacheHandler extends LocationCache {
private DataCacheGetQueue getTask;
// Variables
private int timesSaved;
/**
* Class Constructor.
@ -81,14 +85,13 @@ public class DataCacheHandler extends LocationCache {
startQueues();
timesSaved = 0;
commandUse = new HashMap<>();
if (!getCommandUseFromDb()) {
Log.error(Phrase.DB_FAILURE_DISABLE + "");
plugin.getServer().getPluginManager().disablePlugin(plugin);
return;
}
unsavedTPSHistory = new ArrayList<>();
startAsyncPeriodicSaveTask();
}
@ -137,16 +140,23 @@ public class DataCacheHandler extends LocationCache {
clearAfterXsaves = configValue;
}
RslTask asyncPeriodicCacheSaveTask = new RslBukkitRunnable<Plan>("PeriodicCacheSaveTask") {
private int timesSaved = 0;
@Override
public void run() {
DataCacheHandler handler = Plan.getInstance().getHandler();
handler.saveHandlerDataToCache();
handler.saveCachedUserData();
if (timesSaved % clearAfterXsaves == 0) {
handler.clearCache();
try {
DataCacheHandler handler = Plan.getInstance().getHandler();
handler.saveHandlerDataToCache();
handler.saveCachedUserData();
if (timesSaved % clearAfterXsaves == 0) {
handler.clearCache();
}
saveCommandUse();
saveUnsavedTPSHistory();
timesSaved++;
} catch (Exception e) {
Log.toLog(this.getClass().getName() + "(" + this.getTaskName() + ")", e);
}
saveCommandUse();
timesSaved++;
}
}.runTaskTimerAsynchronously(60 * 20 * minutes, 60 * 20 * minutes);
}
@ -281,6 +291,7 @@ public class DataCacheHandler extends LocationCache {
} catch (SQLException e) {
Log.toLog(this.getClass().getName(), e);
}
saveUnsavedTPSHistory();
try {
db.close();
} catch (SQLException e) {
@ -341,6 +352,34 @@ public class DataCacheHandler extends LocationCache {
}
}
public void saveUnsavedTPSHistory() {
List<TPS> averages = calculateAverageTpsForEachMinute();
if (averages.isEmpty()) {
return;
}
try {
db.getTpsTable().saveTPSData(averages);
} catch (SQLException ex) {
Log.toLog(this.getClass().getName(), ex);
}
}
private List<TPS> calculateAverageTpsForEachMinute() {
final List<TPS> averages = new ArrayList<>();
ArrayList<List<TPS>> copy = new ArrayList<>(unsavedTPSHistory);
if (copy.isEmpty()) {
return new ArrayList<>();
}
for (List<TPS> history : copy) {
final long lastdate = history.get(history.size() - 1).getDate();
final double averageTPS = MathUtils.averageDouble(history.stream().map(t -> t.getTps()));
final int averagePlayersOnline = (int) MathUtils.averageInt(history.stream().map(t -> t.getPlayers()));
averages.add(new TPS(lastdate, averageTPS, averagePlayersOnline));
}
unsavedTPSHistory.removeAll(copy);
return averages;
}
/**
* Refreshes the calculations for all online players with ReloadInfo.
*/
@ -499,19 +538,39 @@ public class DataCacheHandler extends LocationCache {
commandUse.put(command, commandUse.get(command) + 1);
}
/**
*
* @return
*/
public DataCacheSaveQueue getSaveTask() {
return saveTask;
}
/**
*
* @return
*/
public DataCacheClearQueue getClearTask() {
return clearTask;
}
/**
*
* @return
*/
public DataCacheProcessQueue getProcessTask() {
return processTask;
}
/**
*
* @return
*/
public DataCacheGetQueue getGetTask() {
return getTask;
}
public void addTPSLastMinute(List<TPS> history) {
unsavedTPSHistory.add(history);
}
}

View File

@ -0,0 +1,57 @@
package main.java.com.djrapitops.plan.data.handling;
import com.djrapitops.javaplugin.task.RslBukkitRunnable;
import java.util.ArrayList;
import java.util.List;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.TPS;
import main.java.com.djrapitops.plan.data.cache.DataCacheHandler;
/**
* Class responsible for calculating TPS every second.
*
* @author Rsl1122
*/
public class TPSCountTimer extends RslBukkitRunnable<Plan> {
private long lastCheck;
private final Plan plugin;
private final DataCacheHandler handler;
private final List<TPS> history;
public TPSCountTimer(Plan plugin) {
super("TPSCountTimer");
lastCheck = -1;
this.handler = plugin.getHandler();
this.plugin = plugin;
history = new ArrayList<>();
}
@Override
public void run() {
long now = System.nanoTime();
long diff = now - lastCheck;
lastCheck = now;
if (diff > now) { // First run's diff = now + 1, no calc possible.
return;
}
TPS tps = calculateTPS(diff, now);
history.add(tps);
if (history.size() >= 60) {
handler.addTPSLastMinute(history);
history.clear();
}
}
public TPS calculateTPS(long diff, long tpsDate) {
long expectedDiff = 1000000000L; // 1 000 000 000 ns / 1 s
long difference = diff - expectedDiff;
if (difference < 1000000) { // If less than 1 millisecond it is forgiven.
difference = 0;
}
double tpsN = 20 - ((difference / expectedDiff) * 20);
int playersOnline = plugin.getServer().getOnlinePlayers().size();
TPS tps = new TPS(tpsDate / 1000000L, tpsN, playersOnline);
return tps;
}
}

View File

@ -12,13 +12,44 @@ package main.java.com.djrapitops.plan.data.handling.info;
*/
public enum InfoType {
/**
*
*/
CHAT,
/**
*
*/
DEATH,
/**
*
*/
KILL,
/**
*
*/
GM,
/**
*
*/
LOGIN,
/**
*
*/
LOGOUT,
/**
*
*/
KICK,
/**
*
*/
RELOAD,
/**
* Used for events registered with the API.

View File

@ -1,29 +1,42 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package main.java.com.djrapitops.plan.database;
/**
* Class to contain objects in the batches.
*
* @author Rsl1122
* @since 3.4.3
* @param <T>
* @param <T> Object stored.
*/
public class Container<T> {
private T object;
private int id;
private final T object;
private final int id;
/**
* Constructor for the object.
*
* @param object Object to place inside the container.
* @param id UserID related to the object.
*/
public Container(T object, int id) {
this.object = object;
this.id = id;
}
/**
* Get the object in the container.
*
* @return object.
*/
public T getObject() {
return object;
}
/**
* Get the UserID related to the object.
*
* @return userID
*/
public int getId() {
return id;
}

View File

@ -12,6 +12,7 @@ import java.util.Map;
import java.util.Map.Entry;
/**
* Class containing static utility methods used by the Database classes.
*
* @author Rsl1122
* @since 3.4.3
@ -20,6 +21,14 @@ public class DBUtils {
private static final int BATCH_SIZE = 2048;
/**
* Splits a collection of objects into lists with the size defined by
* BATCH_SIZE.
*
* @param <T> Object type
* @param objects Collection of the objects.
// * @return Lists with max size of BATCH_SIZE.
*/
public static <T> List<List<T>> splitIntoBatches(Collection<T> objects) {
List<List<T>> batches = new ArrayList<>();
@ -39,6 +48,12 @@ public class DBUtils {
return batches;
}
/**
*
* @param <T>
* @param objects
* @return
*/
public static <T> List<List<Container<T>>> splitIntoBatchesId(Map<Integer, List<T>> objects) {
List<List<Container<T>>> wrappedBatches = new ArrayList<>();

View File

@ -336,6 +336,11 @@ public abstract class Database {
return commandUseTable;
}
/**
* Used to get the tps table.
*
* @return Table representing plan_tps
*/
public TPSTable getTpsTable() {
return tpsTable;
}

View File

@ -54,6 +54,7 @@ public abstract class SQLDB extends Database {
nicknamesTable = new NicknamesTable(this, usingMySQL);
commandUseTable = new CommandUseTable(this, usingMySQL);
versionTable = new VersionTable(this, usingMySQL);
tpsTable = new TPSTable(this, usingMySQL);
startConnectionPingTask(plugin);
}

View File

@ -111,6 +111,12 @@ public class LocationsTable extends Table {
}
}
/**
*
* @param worlds
* @return
* @throws SQLException
*/
public Map<Integer, List<Location>> getAllLocations(Map<String, World> worlds) throws SQLException {
Benchmark.start("Get Locations Multiple");
PreparedStatement statement = null;

View File

@ -256,6 +256,10 @@ public class SessionsTable extends Table {
}
}
/**
*
* @throws SQLException
*/
public void clean() throws SQLException {
Map<Integer, Integer> loginTimes = db.getUsersTable().getLoginTimes();
Map<Integer, List<SessionData>> allSessions = getSessionData(loginTimes.keySet());

View File

@ -24,6 +24,11 @@ public class TPSTable extends Table {
private final String columnTPS;
private final String columnPlayers;
/**
*
* @param db
* @param usingMySQL
*/
public TPSTable(SQLDB db, boolean usingMySQL) {
super("plan_tps", db, usingMySQL);
columnDate = "date";
@ -47,6 +52,11 @@ public class TPSTable extends Table {
}
}
/**
*
* @return
* @throws SQLException
*/
public List<TPS> getTPSData() throws SQLException {
Benchmark.start("Get TPS");
List<TPS> data = new ArrayList<>();
@ -69,6 +79,11 @@ public class TPSTable extends Table {
}
}
/**
*
* @param data
* @throws SQLException
*/
public void saveTPSData(List<TPS> data) throws SQLException {
List<List<TPS>> batches = DBUtils.splitIntoBatches(data);
for (List<TPS> batch : batches) {
@ -104,6 +119,10 @@ public class TPSTable extends Table {
}
}
/**
*
* @throws SQLException
*/
public void clean() throws SQLException {
PreparedStatement statement = null;
try {

View File

@ -128,6 +128,12 @@ public abstract class Table {
}
}
/**
*
* @param <T>
* @param objects
* @return
*/
protected <T> List<List<Container<T>>> splitIntoBatches(Map<Integer, List<T>> objects) {
return DBUtils.splitIntoBatchesId(objects);
}

View File

@ -848,6 +848,11 @@ public class UsersTable extends Table {
}
}
/**
*
* @return
* @throws SQLException
*/
public Map<Integer, Integer> getLoginTimes() throws SQLException {
Benchmark.start("Get Logintimes");
PreparedStatement statement = null;
@ -876,6 +881,12 @@ public class UsersTable extends Table {
return columnID;
}
/**
*
* @param playername
* @return
* @throws SQLException
*/
public UUID getUuidOf(String playername) throws SQLException {
PreparedStatement statement = null;
ResultSet set = null;
@ -895,6 +906,11 @@ public class UsersTable extends Table {
}
}
/**
*
* @param uuids
* @return
*/
public Map<Integer, Long> getLoginTimes(Collection<UUID> uuids) {
//TODO
return new HashMap<>();

View File

@ -0,0 +1,32 @@
package main.java.com.djrapitops.plan.ui.graphs;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import main.java.com.djrapitops.plan.data.TPS;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
import main.java.com.djrapitops.plan.utilities.comparators.TPSComparator;
/**
*
* @author Rsl1122
* @since 3.5.0
*/
public class TPSGraphCreator {
public static String[] generateDataArray(List<TPS> tpsData, long scale) {
long now = MiscUtils.getTime();
List<TPS> filtered = filterTPS(tpsData, now-scale);
Collections.sort(filtered, new TPSComparator());
List<Long> dates = filtered.stream().map(t -> t.getDate()).collect(Collectors.toList());
List<Double> tps = filtered.stream().map(t -> t.getTps()).collect(Collectors.toList());
List<Integer> players = filtered.stream().map(t -> t.getPlayers()).collect(Collectors.toList());
return new String[]{dates.toString(), tps.toString(), players.toString()};
}
private static List<TPS> filterTPS(List<TPS> tpsData, long nowMinusScale) {
return tpsData.stream()
.filter(t -> t != null)
.filter(t -> t.getDate() >= nowMinusScale)
.collect(Collectors.toList());
}
}

View File

@ -39,10 +39,20 @@ public class FormatUtils {
return FormattingUtils.formatTimeStamp(epochMs);
}
/**
*
* @param epochMs
* @return
*/
public static String formatTimeStampSecond(long epochMs) {
return FormattingUtils.formatTimeStampSecond(epochMs);
}
/**
*
* @param epochMs
* @return
*/
public static String formatTimeStampYear(long epochMs) {
return FormattingUtils.formatTimeStampYear(epochMs);
}

View File

@ -49,6 +49,10 @@ public class HtmlUtils {
return html;
}
/**
*
* @return
*/
public static String getServerAnalysisUrlWithProtocol() {
return Settings.LINK_PROTOCOL.toString()+":"+getServerAnalysisUrl();
}
@ -69,6 +73,11 @@ public class HtmlUtils {
return url;
}
/**
*
* @param playerName
* @return
*/
public static String getInspectUrlWithProtocol(String playerName) {
return Settings.LINK_PROTOCOL.toString()+":"+getInspectUrl(playerName);
}

View File

@ -82,6 +82,11 @@ public class ManageUtils {
return true;
}
/**
*
* @param sessions
* @return
*/
public static boolean containsCombinable(List<SessionData> sessions) {
return containsCombinable(sessions, 5000);
}
@ -95,6 +100,12 @@ public class ManageUtils {
.anyMatch((Long start) -> (Math.abs(s.getSessionEnd() - start) < threshold)));
}
/**
*
* @param sessions
* @param loginTimes
* @return
*/
public static List<SessionData> combineSessions(List<SessionData> sessions, Integer loginTimes) {
return combineSessions(sessions, loginTimes, 5000);
}

View File

@ -428,6 +428,10 @@ public class Analysis {
return replaceMap;
}
/**
*
* @return
*/
public boolean isAnalysisBeingRun() {
return taskId != -1;
}

View File

@ -226,6 +226,12 @@ public class AnalysisUtils {
return source.parseContainer("", "Exception during calculation.");
}
/**
*
* @param sessions
* @param scale
* @return
*/
public static Integer getUniqueJoins(Map<UUID, List<SessionData>> sessions, long scale) {
long now = MiscUtils.getTime();
long nowMinusScale = now - scale;
@ -242,6 +248,12 @@ public class AnalysisUtils {
return uniqueJoins.size();
}
/**
*
* @param sessions
* @param scale
* @return
*/
public static Integer getUniqueJoinsPerDay(Map<UUID, List<SessionData>> sessions, long scale) {
Map<Integer, Set<UUID>> uniqueJoins = new HashMap<>();
long now = MiscUtils.getTime();
@ -269,6 +281,11 @@ public class AnalysisUtils {
return total / size;
}
/**
*
* @param sessionStarts
* @return
*/
public static List<int[]> getDaysAndHours(List<Long> sessionStarts) {
List<int[]> daysAndHours = sessionStarts.stream().map((Long start) -> {
Calendar day = Calendar.getInstance();

View File

@ -22,6 +22,11 @@ import main.java.com.djrapitops.plan.utilities.PlaceholderUtils;
*/
public class ExportUtility {
/**
*
* @return
* @throws IOException
*/
public static File getFolder() throws IOException {
String path = Settings.ANALYSIS_EXPORT_PATH.toString();
if (path.contains(":")) {
@ -40,6 +45,12 @@ public class ExportUtility {
return folder;
}
/**
*
* @param plugin
* @param analysisData
* @param rawData
*/
public static void export(Plan plugin, AnalysisData analysisData, List<UserData> rawData) {
if (!Settings.ANALYSIS_EXPORT.isTrue()) {
return;
@ -61,12 +72,24 @@ public class ExportUtility {
}
}
/**
*
* @param folder
* @return
*/
public static File getPlayersFolder(File folder) {
File playersFolder = new File(folder, "player");
playersFolder.mkdirs();
return playersFolder;
}
/**
*
* @param userData
* @param playersFolder
* @throws FileNotFoundException
* @throws IOException
*/
public static void writeInspectHtml(UserData userData, File playersFolder) throws FileNotFoundException, IOException {
if (!Settings.ANALYSIS_EXPORT.isTrue()) {
return;
@ -82,6 +105,13 @@ public class ExportUtility {
Files.write(inspectHtmlFile.toPath(), Arrays.asList(inspectHtml));
}
/**
*
* @param analysisData
* @param serverFolder
* @throws FileNotFoundException
* @throws IOException
*/
public static void writeAnalysisHtml(AnalysisData analysisData, File serverFolder) throws FileNotFoundException, IOException {
if (!Settings.ANALYSIS_EXPORT.isTrue()) {
return;

View File

@ -25,6 +25,11 @@ import org.bukkit.World;
*/
public class LocationAnalysis {
/**
*
* @param data
* @param db
*/
public static void performAnalysis(AnalysisData data, Database db) {
Benchmark.start("Location Analysis");
try {
@ -45,6 +50,12 @@ public class LocationAnalysis {
Benchmark.stop("Location Analysis");
}
/**
*
* @param freqPoints
* @param allPoints
* @return
*/
public static Map<Point, Object> cluster(Collection<Point> freqPoints, Collection<Point> allPoints) {
Benchmark.start("LocAnalysis cluster");
allPoints.removeAll(freqPoints);
@ -55,6 +66,11 @@ public class LocationAnalysis {
return new HashMap<>();
}
/**
*
* @param points
* @return
*/
public static Set<Point> getFrequentPoints(Map<Point, Integer> points) {
Benchmark.start("LocAnalysis getFrequentPoints");
if (points.isEmpty()) {
@ -66,6 +82,11 @@ public class LocationAnalysis {
return freqPoints;
}
/**
*
* @param locations
* @return
*/
public static Map<String, Map<Point, Integer>> getWorldPoints(Collection<Location> locations) {
Benchmark.start("LocAnalysis getWorldPoints");
Map<String, Map<Point, Integer>> pointMap = new HashMap<>();
@ -89,6 +110,12 @@ public class LocationAnalysis {
return pointMap;
}
/**
*
* @param one
* @param two
* @return
*/
public static double distance(Point one, Point two) {
return Math.hypot(one.getX() - two.getX(), one.getY() - one.getY());
}

View File

@ -14,15 +14,28 @@ public class Point {
final private int x;
final private int y;
/**
*
* @param x
* @param y
*/
public Point(int x, int y) {
this.x = x;
this.y = y;
}
/**
*
* @return
*/
public int getX() {
return x;
}
/**
*
* @return
*/
public int getY() {
return y;
}

View File

@ -0,0 +1,18 @@
package main.java.com.djrapitops.plan.utilities.comparators;
import java.util.Comparator;
import main.java.com.djrapitops.plan.data.TPS;
/**
*
* @author Rsl1122
* @since 3.5.0
*/
public class TPSComparator implements Comparator<TPS>{
@Override
public int compare(TPS o1, TPS o2) {
return Long.compare(o1.getDate(), o2.getDate());
}
}

View File

@ -18,10 +18,23 @@ import main.java.com.djrapitops.plan.database.Database;
*/
public class UUIDUtility {
/**
*
* @param playername
* @return
* @throws Exception
*/
public static UUID getUUIDOf(String playername) throws Exception {
return getUUIDOf(playername, Plan.getInstance().getDB());
}
/**
*
* @param playername
* @param db
* @return
* @throws Exception
*/
public static UUID getUUIDOf(String playername, Database db) throws Exception {
UUID uuid = null;
try {

View File

@ -75,6 +75,9 @@ public class FormatUtilsTest {
assertEquals(expResult, result);
}
/**
*
*/
@Test
public void testFormatTimeStampYear() {
long epochZero = 0L;

View File

@ -30,15 +30,26 @@ public class ManageUtilsTest {
private int threshold = 5000;
/**
*
*/
public ManageUtilsTest() {
}
/**
*
* @throws IOException
* @throws Exception
*/
@Before
public void setUp() throws IOException, Exception {
TestInit t = new TestInit();
assertTrue("Not set up", t.setUp());
}
/**
*
*/
@Test
public void testContainsCombinable() {
List<SessionData> data = new ArrayList<>();
@ -48,6 +59,9 @@ public class ManageUtilsTest {
assertTrue(ManageUtils.containsCombinable(data));
}
/**
*
*/
@Test
public void testContainsCombinableFalse() {
List<SessionData> data = new ArrayList<>();
@ -56,6 +70,9 @@ public class ManageUtilsTest {
assertTrue(!ManageUtils.containsCombinable(data));
}
/**
*
*/
@Test
public void testContainsCombinableFalse2() {
List<SessionData> data = new ArrayList<>();
@ -64,6 +81,9 @@ public class ManageUtilsTest {
assertTrue(!ManageUtils.containsCombinable(data));
}
/**
*
*/
@Test
public void testContainsCombinableFalse3() {
List<SessionData> data = new ArrayList<>();
@ -72,6 +92,9 @@ public class ManageUtilsTest {
assertTrue(!ManageUtils.containsCombinable(data));
}
/**
*
*/
@Test
public void testCombineSessions() {
List<SessionData> data = new ArrayList<>();
@ -83,6 +106,9 @@ public class ManageUtilsTest {
assertEquals(exp, get);
}
/**
*
*/
@Test
public void testCombineSessions2() {
List<SessionData> data = new ArrayList<>();
@ -95,6 +121,9 @@ public class ManageUtilsTest {
assertEquals(exp, get);
}
/**
*
*/
@Test
public void testCombineSessions3() {
List<SessionData> data = new ArrayList<>();
@ -108,6 +137,9 @@ public class ManageUtilsTest {
assertEquals(exp2, result.get(1));
}
/**
*
*/
@Test
public void testCombineSessions4() {
List<SessionData> data = new ArrayList<>();
@ -122,6 +154,9 @@ public class ManageUtilsTest {
assertEquals(exp2, result.get(1));
}
/**
*
*/
@Test
public void testCombineSessions5() {
List<SessionData> data = new ArrayList<>();

View File

@ -2,17 +2,14 @@ package com.djrapitops.pluginbridge.plan.advancedachievements;
import com.hm.achievement.api.AdvancedAchievementsAPI;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Map;
import java.util.UUID;
import java.util.function.Function;
import java.util.stream.Collectors;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.additional.AnalysisType;
import main.java.com.djrapitops.plan.data.additional.PluginData;
import main.java.com.djrapitops.plan.ui.Html;
import main.java.com.djrapitops.plan.utilities.HtmlUtils;
import static org.bukkit.Bukkit.getOfflinePlayers;
import org.bukkit.OfflinePlayer;
/**
* PluginData class for AdvancedAchievements-plugin.
@ -50,26 +47,26 @@ public class AdvancedAchievementsTable extends PluginData {
@Override
public String getHtmlReplaceValue(String modifierPrefix, UUID uuidUnused) {
StringBuilder html = new StringBuilder();
Map<UUID, OfflinePlayer> offlinePlayers = Arrays.stream(getOfflinePlayers()).filter(p -> p.hasPlayedBefore()).collect(Collectors.toMap(p -> p.getUniqueId(), Function.identity()));
if (offlinePlayers.isEmpty()) {
Map<UUID, UserData> cachedUserData = Plan.getPlanAPI().getInspectCachedUserDataMap();
if (cachedUserData.isEmpty()) {
html.append(Html.TABLELINE_2.parse("No Players.", ""));
} else if (aaAPI.getAdvancedAchievementsVersionCode() >= 520) {
Map<UUID, Integer> achievementsMap = aaAPI.getPlayersTotalAchievements();
for (UUID uuid : achievementsMap.keySet()) {
OfflinePlayer p = offlinePlayers.get(uuid);
if (p == null) {
UserData uData = cachedUserData.get(uuid);
if (uData == null) {
continue;
}
String inspectUrl = HtmlUtils.getInspectUrl(p.getName());
String inspectUrl = HtmlUtils.getInspectUrl(uData.getName());
int achievements = achievementsMap.get(uuid);
html.append(Html.TABLELINE_2.parse(Html.LINK.parse(inspectUrl, p.getName()), achievements+""));
html.append(Html.TABLELINE_2.parse(Html.LINK.parse(inspectUrl, uData.getName()), achievements+""));
}
} else {
for (OfflinePlayer p : offlinePlayers.values()) {
String inspectUrl = HtmlUtils.getInspectUrl(p.getName());
String achievements = aaAPI.getPlayerTotalAchievements(p.getUniqueId()) + "";
html.append(Html.TABLELINE_2.parse(Html.LINK.parse(inspectUrl, p.getName()), achievements));
}
cachedUserData.values().stream().forEach((uData) -> {
String inspectUrl = HtmlUtils.getInspectUrl(uData.getName());
String achievements = aaAPI.getPlayerTotalAchievements(uData.getUuid()) + "";
html.append(Html.TABLELINE_2.parse(Html.LINK.parse(inspectUrl, uData.getName()), achievements));
});
}
return parseContainer("", html.toString());
}

View File

@ -10,6 +10,7 @@ import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.additional.AnalysisType;
import main.java.com.djrapitops.plan.data.additional.PluginData;
import main.java.com.djrapitops.plan.ui.Html;
@ -44,9 +45,8 @@ public class JobsAnalysisJobTable extends PluginData {
@Override
public String getHtmlReplaceValue(String modifierPrefix, UUID uuid) {
PlayerManager pm = Jobs.getPlayerManager();
List<List<JobProgression>> players = Arrays.stream(getOfflinePlayers())
.filter(p -> p != null)
.map(p -> pm.getPlayerInfo(p.getUniqueId()))
List<List<JobProgression>> players = Plan.getPlanAPI().getInspectCachedUserData().stream()
.map(p -> pm.getPlayerInfo(p.getUuid()))
.filter(i -> i != null)
.map(i -> pm.getJobsPlayerOffline(i))
.map(p -> p.getJobProgression())