diff --git a/.gitignore b/.gitignore index f5eafe026..fa2c58164 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,7 @@ /Plan/target/ /Plan/temporaryTestFolder/ /Debugger/nbproject/private/ -/PlanDebugger/ \ No newline at end of file +/PlanDebugger/ +/ProjectHelper/nbproject/private/ +/ProjectHelper/nbproject/ +/ProjectHelper/target/ \ No newline at end of file diff --git a/Plan/pom.xml b/Plan/pom.xml index 0bc9a57c9..c51aa7f18 100644 --- a/Plan/pom.xml +++ b/Plan/pom.xml @@ -3,10 +3,10 @@ 4.0.0 com.djrapitops Plan - 3.1.1 + 3.2.0 jar - @@ -149,7 +149,15 @@ org.apache.maven.plugins maven-jar-plugin - 2.6 + 2.6 + + + **/test/* + **/*/test/* + **/*/test.* + **/test/**/* + + org.pitest @@ -162,6 +170,8 @@ test.java.main.java.com.djrapitops.plan.* + 1000 + true @@ -173,6 +183,14 @@ checkstyle.xml + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.4 + + test.* + + diff --git a/Plan/src/main/java/com/djrapitops/plan/Log.java b/Plan/src/main/java/com/djrapitops/plan/Log.java index 0202572c3..524490e76 100644 --- a/Plan/src/main/java/com/djrapitops/plan/Log.java +++ b/Plan/src/main/java/com/djrapitops/plan/Log.java @@ -5,8 +5,8 @@ import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.Collection; -import java.util.Date; import main.java.com.djrapitops.plan.utilities.FormatUtils; +import main.java.com.djrapitops.plan.utilities.MiscUtils; /** * This class manages the messages going to the Bukkit's Logger. @@ -99,7 +99,7 @@ public class Log { } FileWriter fw = new FileWriter(log, true); try (PrintWriter pw = new PrintWriter(fw)) { - String timestamp = FormatUtils.formatTimeStamp(new Date().getTime() + ""); + String timestamp = FormatUtils.formatTimeStamp(MiscUtils.getTime()); pw.println("[" + timestamp + "] " + message); pw.flush(); } diff --git a/Plan/src/main/java/com/djrapitops/plan/Phrase.java b/Plan/src/main/java/com/djrapitops/plan/Phrase.java index 87b0c7ff1..8169e7518 100644 --- a/Plan/src/main/java/com/djrapitops/plan/Phrase.java +++ b/Plan/src/main/java/com/djrapitops/plan/Phrase.java @@ -79,6 +79,7 @@ public enum Phrase { ERROR_WEBSERVER_OFF_INSPECT(ChatColor.YELLOW + "" + PREFIX + "This command can be only used if webserver/planlite is enabled on this server."), ERROR_LOGGED("Caught " + REPLACE0 + ". It has been logged to the Errors.txt"), ERROR_SESSIONDATA_INITIALIZATION("Player's session was initialized in a wrong way! (" + REPLACE0 + ")"), + ERROR_ANALYSIS_FETCH_FAIL("Failed to fetch data for Analysis, Exception occurred."), // CMD_FOOTER(COLOR_TER.color() + "" + ARROWS_RIGHT), MANAGE_ERROR_INCORRECT_PLUGIN(ChatColor.RED + "" + PREFIX + "Plugin not supported: "), diff --git a/Plan/src/main/java/com/djrapitops/plan/Plan.java b/Plan/src/main/java/com/djrapitops/plan/Plan.java index 07b1c5937..897f81c00 100644 --- a/Plan/src/main/java/com/djrapitops/plan/Plan.java +++ b/Plan/src/main/java/com/djrapitops/plan/Plan.java @@ -26,7 +26,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URL; -import java.util.Date; import java.util.HashSet; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -209,7 +208,7 @@ public class Plan extends JavaPlugin { public void run() { if (!analysisCache.isCached()) { analysisCache.updateCache(); - } else if (new Date().getTime() - analysisCache.getData().getRefreshDate() > 60000) { + } else if (MiscUtils.getTime() - analysisCache.getData().getRefreshDate() > 60000) { analysisCache.updateCache(); } } diff --git a/Plan/src/main/java/com/djrapitops/plan/Settings.java b/Plan/src/main/java/com/djrapitops/plan/Settings.java index 6464aa5f4..218e5d0e2 100644 --- a/Plan/src/main/java/com/djrapitops/plan/Settings.java +++ b/Plan/src/main/java/com/djrapitops/plan/Settings.java @@ -68,6 +68,7 @@ public enum Settings { HIDE_TOWNS("Customization.Plugins.Towny.HideTowns"); private final String configPath; + private Boolean value; private Settings(String path) { this.configPath = path; @@ -79,9 +80,16 @@ public enum Settings { * @return Boolean value of the config setting, false if not boolean. */ public boolean isTrue() { + if (value != null) { + return value; + } return Plan.getInstance().getConfig().getBoolean(configPath); } + public void setValue(Boolean value) { + this.value = value; + } + /** * If the settings is a String, this method should be used. * diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/AnalyzeCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/AnalyzeCommand.java index 8ebdfd453..fe22cea15 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/AnalyzeCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/AnalyzeCommand.java @@ -1,6 +1,5 @@ package main.java.com.djrapitops.plan.command.commands; -import java.util.Date; import main.java.com.djrapitops.plan.Permissions; import main.java.com.djrapitops.plan.Phrase; import main.java.com.djrapitops.plan.Plan; @@ -10,6 +9,7 @@ import main.java.com.djrapitops.plan.command.SubCommand; import main.java.com.djrapitops.plan.data.cache.AnalysisCacheHandler; import main.java.com.djrapitops.plan.ui.TextUI; import main.java.com.djrapitops.plan.utilities.HtmlUtils; +import main.java.com.djrapitops.plan.utilities.MiscUtils; import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; @@ -56,7 +56,7 @@ public class AnalyzeCommand extends SubCommand { plugin.getServer().getScheduler().cancelTask(bootAnID); } analysisCache.updateCache(); - } else if (new Date().getTime() - analysisCache.getData().getRefreshDate() > 60000) { + } else if (MiscUtils.getTime() - analysisCache.getData().getRefreshDate() > 60000) { analysisCache.updateCache(); } diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/QuickAnalyzeCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/QuickAnalyzeCommand.java index c54ffb978..7a89c9a59 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/QuickAnalyzeCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/QuickAnalyzeCommand.java @@ -1,6 +1,5 @@ package main.java.com.djrapitops.plan.command.commands; -import java.util.Date; import main.java.com.djrapitops.plan.Permissions; import main.java.com.djrapitops.plan.Phrase; import main.java.com.djrapitops.plan.Plan; @@ -8,6 +7,7 @@ import main.java.com.djrapitops.plan.command.CommandType; import main.java.com.djrapitops.plan.command.SubCommand; import main.java.com.djrapitops.plan.data.cache.AnalysisCacheHandler; import main.java.com.djrapitops.plan.ui.TextUI; +import main.java.com.djrapitops.plan.utilities.MiscUtils; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.scheduler.BukkitRunnable; @@ -45,7 +45,7 @@ public class QuickAnalyzeCommand extends SubCommand { plugin.getServer().getScheduler().cancelTask(bootAnID); } analysisCache.updateCache(); - } else if (new Date().getTime() - analysisCache.getData().getRefreshDate() > 60000) { + } else if (MiscUtils.getTime() - analysisCache.getData().getRefreshDate() > 60000) { analysisCache.updateCache(); } diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageImportCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageImportCommand.java index 5e4e02680..a41a0aece 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageImportCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageImportCommand.java @@ -4,17 +4,20 @@ import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.UUID; +import java.util.stream.Collectors; import main.java.com.djrapitops.plan.Permissions; import main.java.com.djrapitops.plan.Phrase; import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.command.CommandType; import main.java.com.djrapitops.plan.command.SubCommand; -import main.java.com.djrapitops.plan.data.importing.Importer; -import main.java.com.djrapitops.plan.data.importing.OnTimeImporter; +import main.java.com.djrapitops.plan.data.handling.importing.ImportUtils; +import main.java.com.djrapitops.plan.data.handling.importing.Importer; import main.java.com.djrapitops.plan.utilities.ManageUtils; import org.bukkit.Bukkit; +import static org.bukkit.Bukkit.getOfflinePlayers; import org.bukkit.OfflinePlayer; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; @@ -23,9 +26,9 @@ import org.bukkit.scheduler.BukkitTask; /** * This manage subcommand is used to import data from 3rd party plugins. - * + * * Supported plugins (v3.0.0) : OnTime - * + * * @author Rsl1122 * @since 2.3.0 */ @@ -57,10 +60,9 @@ public class ManageImportCommand extends SubCommand { sender.sendMessage(Phrase.MANAGE_ERROR_INCORRECT_PLUGIN + importFromPlugin); return true; } - HashMap importPlugins = new HashMap<>(); - importPlugins.put("ontime", new OnTimeImporter(plugin)); + Map importPlugins = ImportUtils.getImporters(); - if (!importPlugins.get(importFromPlugin).isEnabled()) { + if (!importPlugins.keySet().contains(importFromPlugin) || !ImportUtils.isPluginEnabled(importFromPlugin)) { sender.sendMessage(Phrase.MANAGE_ERROR_PLUGIN_NOT_ENABLED + importFromPlugin); return true; } @@ -70,20 +72,18 @@ public class ManageImportCommand extends SubCommand { return true; } + final Importer importer = importPlugins.get(importFromPlugin); // Header - sender.sendMessage(Phrase.MANAGE_IMPORTING + ""); - Set uuids = new HashSet<>(); - for (OfflinePlayer p : Bukkit.getOfflinePlayers()) { - uuids.add(p.getUniqueId()); - } - HashMap numbericData = importPlugins.get(importFromPlugin).grabNumericData(uuids); BukkitTask asyncImportTask = new BukkitRunnable() { @Override public void run() { - if (importFromPlugin.equals("ontime")) { - if (ManageUtils.importOnTime(numbericData, plugin)) { - sender.sendMessage(Phrase.MANAGE_SUCCESS + ""); - } + sender.sendMessage(Phrase.MANAGE_IMPORTING + ""); + List uuids = Arrays.stream(getOfflinePlayers()).map(p -> p.getUniqueId()).collect(Collectors.toList()); + if (importer.importData(uuids)) { + sender.sendMessage(Phrase.MANAGE_SUCCESS + ""); + } else { + sender.sendMessage(Phrase.MANAGE_PROCESS_FAIL + ""); + } this.cancel(); } diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageRemoveCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageRemoveCommand.java index 9bb773cee..5737869f4 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageRemoveCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageRemoveCommand.java @@ -76,7 +76,7 @@ public class ManageRemoveCommand extends SubCommand { public void run() { sender.sendMessage(Phrase.MANAGE_PROCESS_START.parse()); try { - plugin.getHandler().scheludeForClear(uuid); + plugin.getHandler().getDataCache().remove(uuid); if (plugin.getDB().removeAccount(uuid.toString())) { sender.sendMessage(Phrase.MANAGE_REMOVE_SUCCESS.parse(playerName, plugin.getDB().getConfigName())); } else { diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageRestoreCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageRestoreCommand.java index 41b8fc639..aa7dad922 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageRestoreCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageRestoreCommand.java @@ -99,6 +99,9 @@ public class ManageRestoreCommand extends SubCommand { return; } if (ManageUtils.clearAndCopy(copyToDB, backupDB, uuids)) { + if (copyToDB.getConfigName().equals(plugin.getDB().getConfigName())) { + plugin.getHandler().getCommandUseFromDb(); + } sender.sendMessage(Phrase.MANAGE_COPY_SUCCESS.toString()); } else { sender.sendMessage(Phrase.MANAGE_PROCESS_FAIL.toString()); diff --git a/Plan/src/main/java/com/djrapitops/plan/data/AnalysisData.java b/Plan/src/main/java/com/djrapitops/plan/data/AnalysisData.java index 21238d27b..c8d36f603 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/AnalysisData.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/AnalysisData.java @@ -37,6 +37,9 @@ public class AnalysisData { private String recentPlayers; private String sortablePlayersTable; private String[] playersDataArray; + private String punchCardData; + private String[] sessionDistributionData; + private String[] playtimeDistributionData; private int newPlayersMonth; private int newPlayersWeek; @@ -81,6 +84,9 @@ public class AnalysisData { geomapCountries = Html.ERROR_NOT_SET + ""; geomapZ = Html.ERROR_NOT_SET + ""; geomapCodes = Html.ERROR_NOT_SET + ""; + punchCardData = "[]"; + sessionDistributionData = new String[]{"[]", "[]"}; + playtimeDistributionData = new String[]{"[]", "[]"}; playersDataArray = new String[]{"[0]", "[\"No data\"]", "[0]", "[\"No data\"]", "[0]", "[\"No data\"]"}; genderData = new int[]{0, 0, 0}; additionalDataReplaceMap = new HashMap<>(); @@ -878,4 +884,28 @@ public class AnalysisData { public void setGenderData(int[] genderData) { this.genderData = genderData; } + + public String getPunchCardData() { + return punchCardData; + } + + public void setPunchCardData(String punchCardData) { + this.punchCardData = punchCardData; + } + + public String[] getSessionDistributionData() { + return sessionDistributionData; + } + + public void setSessionDistributionData(String[] sessionDistributionData) { + this.sessionDistributionData = sessionDistributionData; + } + + public String[] getPlaytimeDistributionData() { + return playtimeDistributionData; + } + + public void setPlaytimeDistributionData(String[] playtimeDistributionData) { + this.playtimeDistributionData = playtimeDistributionData; + } } diff --git a/Plan/src/main/java/com/djrapitops/plan/data/KillData.java b/Plan/src/main/java/com/djrapitops/plan/data/KillData.java index e0b2b0e4f..1d2030b24 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/KillData.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/KillData.java @@ -1,5 +1,6 @@ package main.java.com.djrapitops.plan.data; +import java.util.Objects; import java.util.UUID; /** @@ -65,4 +66,35 @@ public class KillData { public int getVictimUserID() { return victimUserID; } + + @Override + public String toString() { + return "{victim:" + victim + "|victimUserID:" + victimUserID + "|date:" + date + "|weapon:" + weapon + '}'; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final KillData other = (KillData) obj; + if (this.date != other.date) { + return false; + } + if (!Objects.equals(this.weapon, other.weapon)) { + return false; + } + if (!Objects.equals(this.victim, other.victim)) { + return false; + } + return true; + } + + } diff --git a/Plan/src/main/java/com/djrapitops/plan/data/additional/PluginData.java b/Plan/src/main/java/com/djrapitops/plan/data/additional/PluginData.java index c5721ac25..a6dc4fcdd 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/additional/PluginData.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/additional/PluginData.java @@ -148,7 +148,7 @@ public abstract class PluginData { * @see AnalysisType */ public final String parseContainer(String modifier, String contents) { - return "
" + Html.FONT_AWESOME_ICON.parse(icon) + modifier + prefix + contents + suffix + "
"; + return "
" + Html.FONT_AWESOME_ICON.parse(icon) + " " + modifier + prefix + contents + suffix + "
"; } /** diff --git a/Plan/src/main/java/com/djrapitops/plan/data/additional/factions/FactionsMaxPower.java b/Plan/src/main/java/com/djrapitops/plan/data/additional/factions/FactionsMaxPower.java index 1abe6a6f5..a85107a5a 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/additional/factions/FactionsMaxPower.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/additional/factions/FactionsMaxPower.java @@ -25,6 +25,7 @@ public class FactionsMaxPower extends PluginData { public FactionsMaxPower() { super("Factions", "maxpower"); super.setPrefix("Max Power: "); + super.setIcon("bolt"); } @Override diff --git a/Plan/src/main/java/com/djrapitops/plan/data/additional/ontime/OntimeRefer.java b/Plan/src/main/java/com/djrapitops/plan/data/additional/ontime/OntimeRefer.java index 6b58fdb37..8dfd8bcb9 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/additional/ontime/OntimeRefer.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/additional/ontime/OntimeRefer.java @@ -25,7 +25,7 @@ public class OntimeRefer extends PluginData { * Class Constructor, sets the parameters of the PluginData object. */ public OntimeRefer() { - super("OnTime", "refer", AnalysisType.INT_TOTAL, AnalysisType.INT_AVG); + super("OnTime", "refer", AnalysisType.LONG_TOTAL, AnalysisType.LONG_AVG); super.setAnalysisOnly(false); super.setIcon("commenting-o"); super.setPrefix("Referrals All Time: "); @@ -49,12 +49,12 @@ public class OntimeRefer extends PluginData { public Serializable getValue(UUID uuid) { OfflinePlayer offlinePlayer = getOfflinePlayer(uuid); if (!offlinePlayer.hasPlayedBefore()) { - return 0; + return -1L; } String name = offlinePlayer.getName(); long referTotal = OnTimeAPI.getPlayerTimeData(name, OnTimeAPI.data.TOTALREFER); if (referTotal == -1) { - return 0; + return -1L; } return referTotal; } diff --git a/Plan/src/main/java/com/djrapitops/plan/data/additional/ontime/OntimeReferMonth.java b/Plan/src/main/java/com/djrapitops/plan/data/additional/ontime/OntimeReferMonth.java index 90b199d94..d525f1310 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/additional/ontime/OntimeReferMonth.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/additional/ontime/OntimeReferMonth.java @@ -25,7 +25,7 @@ public class OntimeReferMonth extends PluginData { * Class Constructor, sets the parameters of the PluginData object. */ public OntimeReferMonth() { - super("OnTime", "refer_30d", AnalysisType.INT_TOTAL); + super("OnTime", "refer_30d", AnalysisType.LONG_TOTAL); super.setAnalysisOnly(false); super.setIcon("commenting-o"); super.setPrefix("Referrals Last 30d: "); @@ -49,12 +49,12 @@ public class OntimeReferMonth extends PluginData { public Serializable getValue(UUID uuid) { OfflinePlayer offlinePlayer = getOfflinePlayer(uuid); if (!offlinePlayer.hasPlayedBefore()) { - return 0; + return -1L; } String name = offlinePlayer.getName(); long referTotal = OnTimeAPI.getPlayerTimeData(name, OnTimeAPI.data.MONTHREFER); if (referTotal == -1) { - return 0; + return -1L; } return referTotal; } diff --git a/Plan/src/main/java/com/djrapitops/plan/data/additional/ontime/OntimeReferWeek.java b/Plan/src/main/java/com/djrapitops/plan/data/additional/ontime/OntimeReferWeek.java index 6b33b2a97..402f21218 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/additional/ontime/OntimeReferWeek.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/additional/ontime/OntimeReferWeek.java @@ -25,7 +25,7 @@ public class OntimeReferWeek extends PluginData { * Class Constructor, sets the parameters of the PluginData object. */ public OntimeReferWeek() { - super("OnTime", "refer_7d", AnalysisType.INT_TOTAL); + super("OnTime", "refer_7d", AnalysisType.LONG_TOTAL); super.setAnalysisOnly(false); super.setIcon("commenting-o"); super.setPrefix("Referrals Last 7d: "); @@ -49,12 +49,12 @@ public class OntimeReferWeek extends PluginData { public Serializable getValue(UUID uuid) { OfflinePlayer offlinePlayer = getOfflinePlayer(uuid); if (!offlinePlayer.hasPlayedBefore()) { - return 0; + return -1L; } String name = offlinePlayer.getName(); long referTotal = OnTimeAPI.getPlayerTimeData(name, OnTimeAPI.data.WEEKREFER); if (referTotal == -1) { - return 0; + return -1L; } return referTotal; } diff --git a/Plan/src/main/java/com/djrapitops/plan/data/additional/ontime/OntimeVotes.java b/Plan/src/main/java/com/djrapitops/plan/data/additional/ontime/OntimeVotes.java index 217b3c47a..cd838d215 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/additional/ontime/OntimeVotes.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/additional/ontime/OntimeVotes.java @@ -25,7 +25,7 @@ public class OntimeVotes extends PluginData { * Class Constructor, sets the parameters of the PluginData object. */ public OntimeVotes() { - super("OnTime", "votes", AnalysisType.INT_TOTAL, AnalysisType.INT_AVG); + super("OnTime", "votes", AnalysisType.LONG_TOTAL, AnalysisType.LONG_AVG); super.setAnalysisOnly(false); super.setIcon("check"); super.setPrefix("Votes All Time: "); @@ -49,12 +49,12 @@ public class OntimeVotes extends PluginData { public Serializable getValue(UUID uuid) { OfflinePlayer offlinePlayer = getOfflinePlayer(uuid); if (!offlinePlayer.hasPlayedBefore()) { - return 0; + return -1L; } String name = offlinePlayer.getName(); long votesTotal = OnTimeAPI.getPlayerTimeData(name, OnTimeAPI.data.TOTALVOTE); if (votesTotal == -1) { - return 0; + return -1L; } return votesTotal; } diff --git a/Plan/src/main/java/com/djrapitops/plan/data/additional/ontime/OntimeVotesMonth.java b/Plan/src/main/java/com/djrapitops/plan/data/additional/ontime/OntimeVotesMonth.java index 8f5d43761..581e9641e 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/additional/ontime/OntimeVotesMonth.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/additional/ontime/OntimeVotesMonth.java @@ -25,7 +25,7 @@ public class OntimeVotesMonth extends PluginData { * Class Constructor, sets the parameters of the PluginData object. */ public OntimeVotesMonth() { - super("OnTime", "votes_30d", AnalysisType.INT_TOTAL); + super("OnTime", "votes_30d", AnalysisType.LONG_TOTAL); super.setAnalysisOnly(false); super.setIcon("check"); super.setPrefix("Votes Last 30d: "); @@ -49,12 +49,12 @@ public class OntimeVotesMonth extends PluginData { public Serializable getValue(UUID uuid) { OfflinePlayer offlinePlayer = getOfflinePlayer(uuid); if (!offlinePlayer.hasPlayedBefore()) { - return 0; + return -1L; } String name = offlinePlayer.getName(); long votesTotal = OnTimeAPI.getPlayerTimeData(name, OnTimeAPI.data.MONTHVOTE); if (votesTotal == -1) { - return 0; + return -1L; } return votesTotal; } diff --git a/Plan/src/main/java/com/djrapitops/plan/data/additional/ontime/OntimeVotesWeek.java b/Plan/src/main/java/com/djrapitops/plan/data/additional/ontime/OntimeVotesWeek.java index fad9ba38b..c0a6b0541 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/additional/ontime/OntimeVotesWeek.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/additional/ontime/OntimeVotesWeek.java @@ -25,7 +25,7 @@ public class OntimeVotesWeek extends PluginData { * Class Constructor, sets the parameters of the PluginData object. */ public OntimeVotesWeek() { - super("OnTime", "votes_7d", AnalysisType.INT_TOTAL); + super("OnTime", "votes_7d", AnalysisType.LONG_TOTAL); super.setAnalysisOnly(false); super.setIcon("check"); super.setPrefix("Votes Last 7d: "); @@ -49,12 +49,12 @@ public class OntimeVotesWeek extends PluginData { public Serializable getValue(UUID uuid) { OfflinePlayer offlinePlayer = getOfflinePlayer(uuid); if (!offlinePlayer.hasPlayedBefore()) { - return 0; + return -1L; } String name = offlinePlayer.getName(); long votesTotal = OnTimeAPI.getPlayerTimeData(name, OnTimeAPI.data.WEEKVOTE); if (votesTotal == -1) { - return 0; + return -1L; } return votesTotal; } diff --git a/Plan/src/main/java/com/djrapitops/plan/data/additional/towny/TownyTable.java b/Plan/src/main/java/com/djrapitops/plan/data/additional/towny/TownyTable.java index d9aa41b79..2b19fdf16 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/additional/towny/TownyTable.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/additional/towny/TownyTable.java @@ -1,6 +1,7 @@ package main.java.com.djrapitops.plan.data.additional.towny; import com.massivecraft.factions.entity.MPlayer; +import com.palmergames.bukkit.towny.object.Resident; import com.palmergames.bukkit.towny.object.Town; import java.io.Serializable; import java.util.List; @@ -46,8 +47,17 @@ public class TownyTable extends PluginData { html.append(Html.TABLELINE_4.parse(Html.TOWN_NO_TOWNS.parse(), "", "", "")); } else { for (Town t : towns) { + if (t == null) { + continue; + } String name = t.getName(); - String mayor = t.getMayor().getName(); + Resident mayorR = t.getMayor(); + String mayor; + if (mayorR != null) { + mayor = mayorR.getName(); + } else { + mayor = "None"; + } String residents = t.getNumResidents() + ""; String land = t.getPurchasedBlocks() + ""; String leaderPage = Html.LINK.parse(HtmlUtils.getInspectUrl(mayor), mayor); diff --git a/Plan/src/main/java/com/djrapitops/plan/data/additional/vault/EconomyBalance.java b/Plan/src/main/java/com/djrapitops/plan/data/additional/vault/EconomyBalance.java index f5d25c77e..5d39ae420 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/additional/vault/EconomyBalance.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/additional/vault/EconomyBalance.java @@ -41,16 +41,16 @@ public class EconomyBalance extends PluginData { @Override public String getHtmlReplaceValue(String modifierPrefix, UUID uuid) { OfflinePlayer p = getOfflinePlayer(uuid); - if (p.hasPlayedBefore()) { - parseContainer(modifierPrefix, this.econ.getBalance(p) + ""); + if (this.econ.hasAccount(p)) { + return parseContainer(modifierPrefix, this.econ.getBalance(p) + ""); } - return ""; + return parseContainer(modifierPrefix, "0"); } @Override public Serializable getValue(UUID uuid) { OfflinePlayer p = getOfflinePlayer(uuid); - if (p.hasPlayedBefore()) { + if (this.econ.hasAccount(p)) { return this.econ.getBalance(p); } return -1; diff --git a/Plan/src/main/java/com/djrapitops/plan/data/cache/DataCacheHandler.java b/Plan/src/main/java/com/djrapitops/plan/data/cache/DataCacheHandler.java index 9aaba93a6..656cc4cf4 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/cache/DataCacheHandler.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/cache/DataCacheHandler.java @@ -4,7 +4,6 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -22,6 +21,7 @@ import main.java.com.djrapitops.plan.data.handling.info.HandlingInfo; import main.java.com.djrapitops.plan.data.handling.info.LogoutInfo; import main.java.com.djrapitops.plan.data.handling.info.ReloadInfo; import main.java.com.djrapitops.plan.database.Database; +import main.java.com.djrapitops.plan.utilities.MiscUtils; import main.java.com.djrapitops.plan.utilities.NewPlayerCreator; import main.java.com.djrapitops.plan.utilities.comparators.HandlingInfoTimeComparator; import org.bukkit.Bukkit; @@ -37,8 +37,8 @@ import static org.bukkit.Bukkit.getOfflinePlayer; * This class is the main processing class that initializes Save, Clear, Process * and Get queue and Starts the asyncronous save task. * - * It is used to store commanduse, locations, active sessions and UserData objects - * in memory. + * It is used to store commanduse, locations, active sessions and UserData + * objects in memory. * * It's methods can be used to access all the data it stores and to clear them. * @@ -49,7 +49,7 @@ public class DataCacheHandler extends LocationCache { // Cache private final HashMap dataCache; - private HashMap commandUse; + private Map commandUse; // Plan private final Plan plugin; @@ -245,7 +245,7 @@ public class DataCacheHandler extends LocationCache { * If processTask has unprocessed information, it will be processed. */ public void saveCacheOnDisable() { - long time = new Date().getTime(); + long time = MiscUtils.getTime(); Log.debug("SaveCacheOnDisable! " + time); saveTask.stop(); getTask.stop(); @@ -269,8 +269,16 @@ public class DataCacheHandler extends LocationCache { data.addAll(dataCache.values()); Log.debug("SAVING, DataCache size: " + dataCache.keySet().size()); try { - db.saveMultipleUserData(data); db.saveCommandUse(commandUse); + } catch (SQLException e) { + Log.toLog(this.getClass().getName(), e); + } + try { + db.saveMultipleUserData(data); + } catch (SQLException e) { + Log.toLog(this.getClass().getName(), e); + } + try { db.close(); } catch (SQLException e) { Log.toLog(this.getClass().getName(), e); @@ -339,7 +347,7 @@ public class DataCacheHandler extends LocationCache { } private void saveHandlerDataToCache(Player player) { - long time = new Date().getTime(); + long time = MiscUtils.getTime(); UUID uuid = player.getUniqueId(); addToPool(new ReloadInfo(uuid, time, player.getAddress().getAddress(), player.isBanned(), player.getDisplayName(), player.getGameMode())); } diff --git a/Plan/src/main/java/com/djrapitops/plan/data/cache/InspectCacheHandler.java b/Plan/src/main/java/com/djrapitops/plan/data/cache/InspectCacheHandler.java index 5e38fa2c9..f4275be78 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/cache/InspectCacheHandler.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/cache/InspectCacheHandler.java @@ -1,9 +1,16 @@ package main.java.com.djrapitops.plan.data.cache; +import java.sql.SQLException; +import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; import java.util.UUID; +import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.data.UserData; +import main.java.com.djrapitops.plan.database.Database; /** * This class stores UserData objects used for displaying the Html pages. @@ -46,6 +53,24 @@ public class InspectCacheHandler { handler.getUserDataForProcessing(cacher, uuid, false); } + public void cacheAllUserData(Database db) throws SQLException { + Set cachedUserData = handler.getDataCache().keySet(); + for (UUID uuid : cachedUserData) { + cache(uuid); + } + Set savedUUIDs = new HashSet<>(); + try { + savedUUIDs = db.getUsersTable().getSavedUUIDs(); + } catch (SQLException ex) { + Log.toLog(this.getClass().getName(), ex); + } + savedUUIDs.removeAll(cachedUserData); + List userDataForUUIDS = db.getUserDataForUUIDS(savedUUIDs); + for (UserData uData : userDataForUUIDS) { + cache.put(uData.getUuid(), uData); + } + } + /** * Checks the cache for UserData matching UUID. * @@ -65,4 +90,8 @@ public class InspectCacheHandler { public boolean isCached(UUID uuid) { return cache.containsKey(uuid); } + + public List getCachedUserData() { + return new ArrayList<>(cache.values()); + } } diff --git a/Plan/src/main/java/com/djrapitops/plan/data/cache/SessionCache.java b/Plan/src/main/java/com/djrapitops/plan/data/cache/SessionCache.java index cef050429..6f30cf298 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/cache/SessionCache.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/cache/SessionCache.java @@ -1,12 +1,12 @@ package main.java.com.djrapitops.plan.data.cache; -import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.UUID; import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.data.SessionData; import main.java.com.djrapitops.plan.data.UserData; +import main.java.com.djrapitops.plan.utilities.MiscUtils; /** * This class is used to store active sessions of players in memory. @@ -31,7 +31,7 @@ public class SessionCache { * @param uuid UUID of the player. */ public void startSession(UUID uuid) { - long now = new Date().getTime(); + long now = MiscUtils.getTime(); Log.debug(uuid + ": Starting a session: " + now); SessionData session = new SessionData(now); activeSessions.put(uuid, session); @@ -45,7 +45,7 @@ public class SessionCache { public void endSession(UUID uuid) { SessionData currentSession = activeSessions.get(uuid); if (currentSession != null) { - long now = new Date().getTime(); + long now = MiscUtils.getTime(); Log.debug(uuid + ": Ending a session: " + now); currentSession.endSession(now); } diff --git a/Plan/src/main/java/com/djrapitops/plan/data/cache/queue/DataCacheSaveQueue.java b/Plan/src/main/java/com/djrapitops/plan/data/cache/queue/DataCacheSaveQueue.java index 49678a9af..a8793bf12 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/cache/queue/DataCacheSaveQueue.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/cache/queue/DataCacheSaveQueue.java @@ -133,7 +133,7 @@ class SaveConsumer implements Runnable { UUID uuid = data.getUuid(); Log.debug(uuid + ": Saving: " + uuid); try { - db.saveUserData(uuid, data); + db.saveUserData(data); data.stopAccessing(); Log.debug(uuid + ": Saved!"); if (data.shouldClearAfterSave()) { diff --git a/Plan/src/main/java/com/djrapitops/plan/data/handling/importing/ImportUtils.java b/Plan/src/main/java/com/djrapitops/plan/data/handling/importing/ImportUtils.java new file mode 100644 index 000000000..5abbd37f3 --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/data/handling/importing/ImportUtils.java @@ -0,0 +1,26 @@ +/* + * 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.data.handling.importing; + +import java.util.HashMap; +import java.util.Map; +import static org.bukkit.Bukkit.getPluginManager; + +/** + * + * @author Risto + */ +public class ImportUtils { + public static boolean isPluginEnabled(String pluginName) { + return getPluginManager().isPluginEnabled(pluginName); + } + + public static Map getImporters() { + Map importers = new HashMap<>(); + importers.put("ontime", new OnTimeImporter()); + return importers; + } +} diff --git a/Plan/src/main/java/com/djrapitops/plan/data/handling/importing/Importer.java b/Plan/src/main/java/com/djrapitops/plan/data/handling/importing/Importer.java new file mode 100644 index 000000000..ce3298320 --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/data/handling/importing/Importer.java @@ -0,0 +1,53 @@ +package main.java.com.djrapitops.plan.data.handling.importing; + +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Set; +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.Plan; +import main.java.com.djrapitops.plan.data.cache.DataCacheHandler; +import main.java.com.djrapitops.plan.data.handling.info.HandlingInfo; +import main.java.com.djrapitops.plan.database.Database; +import static org.bukkit.Bukkit.getOfflinePlayer; +import org.bukkit.OfflinePlayer; + +/** + * + * @author Rsl1122 + */ +public abstract class Importer { + + public Importer() { + + } + + public boolean importData(Collection uuids) { + Plan plan = Plan.getInstance(); + DataCacheHandler handler = plan.getHandler(); + Database db = plan.getDB(); + Set saved; + try { + saved = db.getSavedUUIDs(); + } catch (SQLException ex) { + Log.toLog(this.getClass().getName(), ex); + return false; + } + List unSaved = new ArrayList<>(uuids); + unSaved.removeAll(saved); + for (UUID uuid : unSaved) { + OfflinePlayer player = getOfflinePlayer(uuid); + handler.newPlayer(player); + } + for (UUID uuid : uuids) { + handler.addToPool(importData(uuid)); + } + return true; + } + + public abstract HandlingInfo importData(UUID uuid); +} diff --git a/Plan/src/main/java/com/djrapitops/plan/data/handling/importing/OnTimeImporter.java b/Plan/src/main/java/com/djrapitops/plan/data/handling/importing/OnTimeImporter.java new file mode 100644 index 000000000..502dc7e6b --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/data/handling/importing/OnTimeImporter.java @@ -0,0 +1,49 @@ +package main.java.com.djrapitops.plan.data.handling.importing; + +import java.util.HashMap; +import java.util.Set; +import java.util.UUID; +import main.java.com.djrapitops.plan.data.UserData; +import main.java.com.djrapitops.plan.data.handling.info.HandlingInfo; +import main.java.com.djrapitops.plan.data.handling.info.InfoType; +import me.edge209.OnTime.OnTimeAPI; +import me.edge209.OnTime.OnTimeAPI.data; +import org.bukkit.Bukkit; +import static org.bukkit.Bukkit.getOfflinePlayer; +import org.bukkit.GameMode; +import org.bukkit.OfflinePlayer; + +/** + * + * @author Rsl1122 + */ +public class OnTimeImporter extends Importer { + + /** + * + */ + public OnTimeImporter() { + } + + @Override + public HandlingInfo importData(UUID uuid) { + OfflinePlayer p = getOfflinePlayer(uuid); + Long playTime = OnTimeAPI.getPlayerTimeData(p.getName(), OnTimeAPI.data.TOTALPLAY); + return new HandlingInfo(uuid, InfoType.OTHER, 0L) { + @Override + public boolean process(UserData uData) { + if (uuid != uData.getUuid()) { + return false; + } + if (playTime > uData.getPlayTime()) { + uData.setPlayTime(playTime); + uData.setLastGamemode(GameMode.SURVIVAL); + uData.setAllGMTimes(playTime, 0, 0, 0); + uData.setLastGmSwapTime(playTime); + } + return true; + } + }; + + } +} diff --git a/Plan/src/main/java/com/djrapitops/plan/data/importing/Importer.java b/Plan/src/main/java/com/djrapitops/plan/data/importing/Importer.java deleted file mode 100644 index bbbb491a5..000000000 --- a/Plan/src/main/java/com/djrapitops/plan/data/importing/Importer.java +++ /dev/null @@ -1,26 +0,0 @@ - -package main.java.com.djrapitops.plan.data.importing; - -import java.util.HashMap; -import java.util.Set; -import java.util.UUID; - -/** - * - * @author Rsl1122 - */ -public interface Importer { - - /** - * - * @param uuids - * @return - */ - public HashMap grabNumericData(Set uuids); - - /** - * - * @return - */ - public boolean isEnabled(); -} diff --git a/Plan/src/main/java/com/djrapitops/plan/data/importing/OnTimeImporter.java b/Plan/src/main/java/com/djrapitops/plan/data/importing/OnTimeImporter.java deleted file mode 100644 index 4fe405925..000000000 --- a/Plan/src/main/java/com/djrapitops/plan/data/importing/OnTimeImporter.java +++ /dev/null @@ -1,55 +0,0 @@ -package main.java.com.djrapitops.plan.data.importing; - -import java.util.HashMap; -import java.util.Set; -import java.util.UUID; -import main.java.com.djrapitops.plan.Plan; -import me.edge209.OnTime.OnTimeAPI; -import org.bukkit.Bukkit; -import org.bukkit.OfflinePlayer; - -/** - * - * @author Rsl1122 - */ -public class OnTimeImporter implements Importer { - - private final Plan plugin; - private boolean enabled; - - /** - * - * @param plugin - */ - public OnTimeImporter(Plan plugin) { - this.plugin = plugin; - this.enabled = Bukkit.getPluginManager().isPluginEnabled("OnTime"); - } - - /** - * - * @param uuids - * @return - */ - @Override - public HashMap grabNumericData(Set uuids) { - HashMap onTimeData = new HashMap<>(); - for (OfflinePlayer p : Bukkit.getOfflinePlayers()) { - Long playTime = OnTimeAPI.getPlayerTimeData(p.getName(), OnTimeAPI.data.TOTALPLAY); - if (playTime != -1) { - UUID uuid = p.getUniqueId(); - onTimeData.put(uuid, playTime); - } - } - return onTimeData; - } - - /** - * - * @return - */ - @Override - public boolean isEnabled() { - return enabled; - } -} diff --git a/Plan/src/main/java/com/djrapitops/plan/data/listeners/PlanCommandPreprocessListener.java b/Plan/src/main/java/com/djrapitops/plan/data/listeners/PlanCommandPreprocessListener.java index c3d3141d5..ca45864be 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/listeners/PlanCommandPreprocessListener.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/listeners/PlanCommandPreprocessListener.java @@ -1,5 +1,6 @@ package main.java.com.djrapitops.plan.data.listeners; +import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.Permissions; import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.data.cache.DataCacheHandler; @@ -39,6 +40,7 @@ public class PlanCommandPreprocessListener implements Listener { return; } if (Permissions.IGNORE_COMMANDUSE.userHasThisPermission(event.getPlayer())) { + Log.debug("Ignored command, player had ignore permission."); return; } handler.handleCommand(event.getMessage().split(" ")[0]); diff --git a/Plan/src/main/java/com/djrapitops/plan/data/listeners/PlanDeathEventListener.java b/Plan/src/main/java/com/djrapitops/plan/data/listeners/PlanDeathEventListener.java index bacadf7be..203cd1129 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/listeners/PlanDeathEventListener.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/listeners/PlanDeathEventListener.java @@ -1,10 +1,10 @@ package main.java.com.djrapitops.plan.data.listeners; -import java.util.Date; import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.data.cache.DataCacheHandler; import main.java.com.djrapitops.plan.data.handling.info.DeathInfo; import main.java.com.djrapitops.plan.data.handling.info.KillInfo; +import main.java.com.djrapitops.plan.utilities.MiscUtils; import org.bukkit.Material; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; @@ -40,7 +40,7 @@ public class PlanDeathEventListener implements Listener { */ @EventHandler(priority = EventPriority.MONITOR) public void onDeath(EntityDeathEvent event) { - long time = new Date().getTime(); + long time = MiscUtils.getTime(); LivingEntity dead = event.getEntity(); Player killer = dead.getKiller(); boolean killerIsPlayer = killer != null; diff --git a/Plan/src/main/java/com/djrapitops/plan/data/listeners/PlanGamemodeChangeListener.java b/Plan/src/main/java/com/djrapitops/plan/data/listeners/PlanGamemodeChangeListener.java index a80fad15b..f0a286aed 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/listeners/PlanGamemodeChangeListener.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/listeners/PlanGamemodeChangeListener.java @@ -1,9 +1,9 @@ package main.java.com.djrapitops.plan.data.listeners; -import java.util.Date; import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.data.cache.DataCacheHandler; import main.java.com.djrapitops.plan.data.handling.info.GamemodeInfo; +import main.java.com.djrapitops.plan.utilities.MiscUtils; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -42,6 +42,6 @@ public class PlanGamemodeChangeListener implements Listener { return; } Player p = event.getPlayer(); - handler.addToPool(new GamemodeInfo(p.getUniqueId(), new Date().getTime(), event.getNewGameMode())); + handler.addToPool(new GamemodeInfo(p.getUniqueId(), MiscUtils.getTime(), event.getNewGameMode())); } } diff --git a/Plan/src/main/java/com/djrapitops/plan/data/listeners/PlanPlayerListener.java b/Plan/src/main/java/com/djrapitops/plan/data/listeners/PlanPlayerListener.java index 66cb41cd2..6258902e2 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/listeners/PlanPlayerListener.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/listeners/PlanPlayerListener.java @@ -1,6 +1,5 @@ package main.java.com.djrapitops.plan.data.listeners; -import java.util.Date; import java.util.UUID; import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.Plan; @@ -9,6 +8,7 @@ import main.java.com.djrapitops.plan.data.cache.DataCacheHandler; import main.java.com.djrapitops.plan.data.handling.info.KickInfo; import main.java.com.djrapitops.plan.data.handling.info.LoginInfo; import main.java.com.djrapitops.plan.data.handling.info.LogoutInfo; +import main.java.com.djrapitops.plan.utilities.MiscUtils; import main.java.com.djrapitops.plan.utilities.NewPlayerCreator; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -60,7 +60,7 @@ public class PlanPlayerListener implements Listener { BukkitTask asyncNewPlayerCheckTask = new BukkitRunnable() { @Override public void run() { - LoginInfo loginInfo = new LoginInfo(uuid, new Date().getTime(), player.getAddress().getAddress(), player.isBanned(), player.getDisplayName(), player.getGameMode(), 1); + LoginInfo loginInfo = new LoginInfo(uuid, MiscUtils.getTime(), player.getAddress().getAddress(), player.isBanned(), player.getDisplayName(), player.getGameMode(), 1); boolean isNewPlayer = !plugin.getDB().wasSeenBefore(uuid); if (isNewPlayer) { UserData newUserData = NewPlayerCreator.createNewPlayer(player); @@ -90,7 +90,7 @@ public class PlanPlayerListener implements Listener { UUID uuid = player.getUniqueId(); handler.endSession(uuid); Log.debug(uuid + ": PlayerQuitEvent"); - handler.addToPool(new LogoutInfo(uuid, new Date().getTime(), player.isBanned(), player.getGameMode(), handler.getSession(uuid))); + handler.addToPool(new LogoutInfo(uuid, MiscUtils.getTime(), player.isBanned(), player.getGameMode(), handler.getSession(uuid))); handler.saveCachedData(uuid); Log.debug(uuid + ": PlayerQuitEvent_END"); } @@ -110,7 +110,7 @@ public class PlanPlayerListener implements Listener { Player player = event.getPlayer(); UUID uuid = player.getUniqueId(); handler.endSession(uuid); - handler.addToPool(new LogoutInfo(uuid, new Date().getTime(), player.isBanned(), player.getGameMode(), handler.getSession(uuid))); + handler.addToPool(new LogoutInfo(uuid, MiscUtils.getTime(), player.isBanned(), player.getGameMode(), handler.getSession(uuid))); handler.addToPool(new KickInfo(uuid)); handler.saveCachedData(uuid); } diff --git a/Plan/src/main/java/com/djrapitops/plan/database/Database.java b/Plan/src/main/java/com/djrapitops/plan/database/Database.java index d59a337b0..34a58e74d 100644 --- a/Plan/src/main/java/com/djrapitops/plan/database/Database.java +++ b/Plan/src/main/java/com/djrapitops/plan/database/Database.java @@ -5,9 +5,17 @@ import java.util.*; import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.data.UserData; import main.java.com.djrapitops.plan.data.cache.DBCallableProcessor; +import main.java.com.djrapitops.plan.database.tables.CommandUseTable; +import main.java.com.djrapitops.plan.database.tables.GMTimesTable; +import main.java.com.djrapitops.plan.database.tables.IPsTable; +import main.java.com.djrapitops.plan.database.tables.KillsTable; +import main.java.com.djrapitops.plan.database.tables.LocationsTable; +import main.java.com.djrapitops.plan.database.tables.NicknamesTable; +import main.java.com.djrapitops.plan.database.tables.SessionsTable; +import main.java.com.djrapitops.plan.database.tables.UsersTable; +import main.java.com.djrapitops.plan.database.tables.VersionTable; import org.bukkit.Location; import org.bukkit.World; -import org.bukkit.configuration.ConfigurationSection; /** * Abstract class representing a Database. @@ -16,7 +24,16 @@ import org.bukkit.configuration.ConfigurationSection; */ public abstract class Database { - private final Plan plugin; + protected final Plan plugin; + protected UsersTable usersTable; + protected GMTimesTable gmTimesTable; + protected KillsTable killsTable; + protected LocationsTable locationsTable; + protected NicknamesTable nicknamesTable; + protected SessionsTable sessionsTable; + protected IPsTable ipsTable; + protected CommandUseTable commandUseTable; + protected VersionTable versionTable; /** * Super constructor. @@ -39,141 +56,255 @@ public abstract class Database { } /** + * Used to give Database processors to call with UserData after they have + * been fetched from the database. * - * @param uuid - * @param processors - * @throws SQLException + * This method is a shortcut method for multiple parameters. + * + * @param uuid UUID of the player. + * @param processors Processors to call with the UserData after the fetch is + * complete. + * @throws SQLException If a database error occurs. */ public void giveUserDataToProcessors(UUID uuid, DBCallableProcessor... processors) throws SQLException { - List coll = new ArrayList<>(); - coll.addAll(Arrays.asList(processors)); - giveUserDataToProcessors(uuid, coll); + giveUserDataToProcessors(uuid, Arrays.asList(processors)); } /** + * Used to give Database processors to call with UserData after they have + * been fetched from the database. * - * @param uuid - * @param processors - * @throws SQLException + * @param uuid UUID of the player. + * @param processors Processors to call with the UserData after the fetch is + * complete. + * @throws SQLException If a database error occurs. */ public abstract void giveUserDataToProcessors(UUID uuid, Collection processors) throws SQLException; - /** - * - * @param uuid - * @param data - * @throws SQLException - */ - public abstract void saveUserData(UUID uuid, UserData data) throws SQLException; + public abstract List getUserDataForUUIDS(Collection uuids) throws SQLException; /** + * Used to save UserData object of a user. * - * @param data - * @throws SQLException + * @param uuid UUID of the player + * @param data UserData of the Player. + * @throws SQLException If a database error occurs. + * @deprecated Separate UUID no longer required. */ - public abstract void saveMultipleUserData(List data) throws SQLException; + @Deprecated + public void saveUserData(UUID uuid, UserData data) throws SQLException { + if (uuid.equals(data.getUuid())) { + saveUserData(data); + } + } /** + * Used to save UserData object of a user. * - * @param uuid - * @return + * @param data UserData of the Player. + * @throws SQLException If a database error occurs. + */ + public abstract void saveUserData(UserData data) throws SQLException; + + /** + * Used to save UserData object of multiple users. + * + * @param data Collection of UserData objects. + * @throws SQLException If a database error occurs. + */ + public abstract void saveMultipleUserData(Collection data) throws SQLException; + + /** + * Check if the user is saved in the database. + * + * @param uuid UUID of the user. + * @return true/false */ public abstract boolean wasSeenBefore(UUID uuid); /** - * + * Cleans the database of excess data. */ public abstract void clean(); /** + * Used to get the name of the database type. * - * @return + * @return SQLite/MySQL */ public abstract String getName(); /** + * Used to get the config name of the database type. * - * @return + * @return sqlite/mysql */ public String getConfigName() { return getName().toLowerCase().replace(" ", ""); } /** + * Used to get the database schema version. * - * @return - */ - public ConfigurationSection getConfigSection() { - return plugin.getConfig().getConfigurationSection(getConfigName()); - } - - /** - * - * @return @throws SQLException + * @return Integer starting from 0, incremented by one when schema is + * updated. + * @throws SQLException If a database error occurs. */ public abstract int getVersion() throws SQLException; /** + * Used to set the database schema version. * - * @param version - * @throws SQLException + * @param version Integer starting from 0, incremented by one when schema is + * updated. + * @throws SQLException If a database error occurs. */ public abstract void setVersion(int version) throws SQLException; /** + * Closes the database & it's resources. * - * @throws SQLException + * @throws SQLException If a database error occurs. */ public abstract void close() throws SQLException; /** + * Removes all data related to an account from the database. * - * @param uuid - * @return - * @throws SQLException + * @param uuid UUID of the account. + * @return Success of the removal. + * @throws SQLException If a database error occurs. */ public abstract boolean removeAccount(String uuid) throws SQLException; /** + * Used to clear all data from the database. * - * @return @throws SQLException + * Uses DELETE * FROM table. + * + * @return Success of removal. + * @throws SQLException If a database error occurs. */ public abstract boolean removeAllData() throws SQLException; /** + * Used to save CommandUse map. * * @param data - * @throws SQLException - * @throws NullPointerException + * @throws SQLException If a database error occurs. + * @throws NullPointerException If the database has not initialized tables. */ - public abstract void saveCommandUse(HashMap data) throws SQLException, NullPointerException; + @Deprecated + public void saveCommandUse(Map data) throws SQLException, NullPointerException { + commandUseTable.saveCommandUse(data); + } /** * - * @return @throws SQLException + * @return @throws SQLException If a database error occurs. */ - public abstract Set getSavedUUIDs() throws SQLException; + public Set getSavedUUIDs() throws SQLException { + return usersTable.getSavedUUIDs(); + } /** * - * @return @throws SQLException + * @return @throws SQLException If a database error occurs. */ - public abstract HashMap getCommandUse() throws SQLException; + @Deprecated + public Map getCommandUse() throws SQLException { + return commandUseTable.getCommandUse(); + } /** * * @param uuid * @return - * @throws SQLException + * @throws SQLException If a database error occurs. */ - public abstract int getUserId(String uuid) throws SQLException; + @Deprecated + public int getUserId(String uuid) throws SQLException { + return usersTable.getUserId(uuid); + } /** * * @param userId * @param worlds * @return - * @throws SQLException + * @throws SQLException If a database error occurs. */ - public abstract List getLocations(String userId, HashMap worlds) throws SQLException; + @Deprecated + public List getLocations(String userId, HashMap worlds) throws SQLException { + return getLocations(Integer.parseInt(userId), worlds); + } + + @Deprecated + public List getLocations(int userId, HashMap worlds) throws SQLException { + return locationsTable.getLocations(userId, worlds); + } + + /** + * + * @return + */ + public UsersTable getUsersTable() { + return usersTable; + } + + /** + * + * @return + */ + public SessionsTable getSessionsTable() { + return sessionsTable; + } + + /** + * + * @return + */ + public GMTimesTable getGmTimesTable() { + return gmTimesTable; + } + + /** + * + * @return + */ + public KillsTable getKillsTable() { + return killsTable; + } + + /** + * + * @return + */ + public LocationsTable getLocationsTable() { + return locationsTable; + } + + /** + * + * @return + */ + public IPsTable getIpsTable() { + return ipsTable; + } + + /** + * + * @return + */ + public NicknamesTable getNicknamesTable() { + return nicknamesTable; + } + + /** + * + * @return + */ + public CommandUseTable getCommandUseTable() { + return commandUseTable; + } } diff --git a/Plan/src/main/java/com/djrapitops/plan/database/databases/SQLDB.java b/Plan/src/main/java/com/djrapitops/plan/database/databases/SQLDB.java index 7064ca348..4023dbc26 100644 --- a/Plan/src/main/java/com/djrapitops/plan/database/databases/SQLDB.java +++ b/Plan/src/main/java/com/djrapitops/plan/database/databases/SQLDB.java @@ -3,6 +3,7 @@ package main.java.com.djrapitops.plan.database.databases; import java.net.InetAddress; import java.sql.Connection; import java.sql.SQLException; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -10,16 +11,16 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; +import java.util.function.Function; +import java.util.stream.Collectors; import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.data.*; import main.java.com.djrapitops.plan.data.cache.DBCallableProcessor; import main.java.com.djrapitops.plan.database.Database; import main.java.com.djrapitops.plan.database.tables.*; -import main.java.com.djrapitops.plan.utilities.UUIDFetcher; import org.bukkit.GameMode; import org.bukkit.Location; -import org.bukkit.World; import org.bukkit.scheduler.BukkitRunnable; import static org.bukkit.Bukkit.getOfflinePlayer; @@ -35,16 +36,6 @@ public abstract class SQLDB extends Database { private Connection connection; - private final UsersTable usersTable; - private final GMTimesTable gmTimesTable; - private final KillsTable killsTable; - private final LocationsTable locationsTable; - private final NicknamesTable nicknamesTable; - private final SessionsTable sessionsTable; - private final IPsTable ipsTable; - private final CommandUseTable commandUseTable; - private final VersionTable versionTable; - /** * * @param plugin @@ -77,7 +68,7 @@ public abstract class SQLDB extends Database { */ public void startConnectionPingTask(Plan plugin) throws IllegalArgumentException, IllegalStateException { // Maintains Connection. - (new BukkitRunnable() { + new BukkitRunnable() { @Override public void run() { try { @@ -88,7 +79,7 @@ public abstract class SQLDB extends Database { connection = getNewConnection(); } } - }).runTaskTimerAsynchronously(plugin, 60 * 20, 60 * 20); + }.runTaskTimerAsynchronously(plugin, 60 * 20, 60 * 20); } /** @@ -124,13 +115,22 @@ public abstract class SQLDB extends Database { newDatabase = false; } catch (Exception e) { } - versionTable.createTable(); + if (!versionTable.createTable()) { + Log.error("Failed to create table: " + versionTable.getTableName()); + return false; + } if (newDatabase) { Log.info("New Database created."); setVersion(3); } for (Table table : getAllTables()) { - table.createTable(); + if (!table.createTable()) { + Log.error("Failed to create table: " + table.getTableName()); + return false; + } + } + if (!newDatabase && getVersion() < 3) { + setVersion(3); } } return true; @@ -196,55 +196,13 @@ public abstract class SQLDB extends Database { @Override public boolean wasSeenBefore(UUID uuid) { try { - return getUserId(uuid.toString()) != -1; + return usersTable.getUserId(uuid.toString()) != -1; } catch (SQLException e) { Log.toLog(this.getClass().getName(), e); return false; } } - /** - * - * @param uuid - * @return - * @throws SQLException - */ - @Override - public int getUserId(String uuid) throws SQLException { - return usersTable.getUserId(uuid); - } - - /** - * - * @return @throws SQLException - */ - @Override - public Set getSavedUUIDs() throws SQLException { - return usersTable.getSavedUUIDs(); - } - - /** - * - * @param commandUse - * @throws SQLException - * @throws NullPointerException - */ - @Override - @Deprecated - public void saveCommandUse(HashMap commandUse) throws SQLException, NullPointerException { - commandUseTable.saveCommandUse(commandUse); - } - - /** - * - * @return @throws SQLException - */ - @Override - @Deprecated - public HashMap getCommandUse() throws SQLException { - return commandUseTable.getCommandUse(); - } - /** * * @param uuid @@ -259,7 +217,7 @@ public abstract class SQLDB extends Database { Log.toLog(this.getClass().getName(), e); return false; } - int userId = getUserId(uuid); + int userId = usersTable.getUserId(uuid); if (userId == -1) { return false; } @@ -295,7 +253,7 @@ public abstract class SQLDB extends Database { UserData data = new UserData(getOfflinePlayer(uuid), new DemographicsData()); usersTable.addUserInformationToUserData(data); - int userId = getUserId(uuid.toString()); + int userId = usersTable.getUserId(uuid); List nicknames = nicknamesTable.getNicknames(userId); data.addNicknames(nicknames); @@ -316,43 +274,42 @@ public abstract class SQLDB extends Database { } } - @Deprecated - private HashMap getGMTimes(int userId) throws SQLException { - return gmTimesTable.getGMTimes(userId); - } - - @Deprecated - private List getIPAddresses(int userId) throws SQLException { - return ipsTable.getIPAddresses(userId); - } - - @Deprecated - private List getNicknames(int userId) throws SQLException { - return nicknamesTable.getNicknames(userId); - } - @Override - @Deprecated - public List getLocations(String userId, HashMap worlds) throws SQLException { - return getLocations(Integer.parseInt(userId), worlds); - } - - /** - * - * @param userId - * @param worlds - * @return - * @throws SQLException - * @deprecated - */ - @Deprecated - public List getLocations(int userId, HashMap worlds) throws SQLException { - return locationsTable.getLocations(userId, worlds); - } - - @Deprecated - private List getPlayerKills(int userId) throws SQLException { - return killsTable.getPlayerKills(userId); + public List getUserDataForUUIDS(Collection uuids) throws SQLException { + if (uuids == null || uuids.isEmpty()) { + return new ArrayList<>(); + } + Map userIds = usersTable.getAllUserIds(); + List data = new ArrayList<>(); + for (UUID uuid : uuids) { + if (!userIds.keySet().contains(uuid)) { + continue; + } + UserData uData = new UserData(getOfflinePlayer(uuid), new DemographicsData()); + data.add(uData); + } + if (data.isEmpty()) { + return data; + } + usersTable.addUserInformationToUserData(data); + Map idUuidRel = userIds.entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey)); + List ids = userIds.entrySet().stream().filter(e -> uuids.contains(e.getKey())).map(e -> e.getValue()).collect(Collectors.toList()); + Log.debug("Ids: "+ids); + Map> nicknames = nicknamesTable.getNicknames(ids); + Map> ipList = ipsTable.getIPList(ids); + Map> playerKills = killsTable.getPlayerKills(ids, idUuidRel); + Map> sessionData = sessionsTable.getSessionData(ids); + Log.debug("Sizes: U:"+uuids.size()+" D:"+data.size()+" I:"+userIds.size()+" N:"+nicknames.size()+" I:"+ipList.size()+" K:"+playerKills.size()+" S:"+sessionData.size()); + for (UserData uData : data) { + UUID uuid = uData.getUuid(); + Integer id = userIds.get(uuid); + uData.addIpAddresses(ipList.get(id)); + uData.addNicknames(nicknames.get(id)); + uData.addSessions(sessionData.get(id)); + uData.setPlayerKills(playerKills.get(id)); + uData.setGmTimes(gmTimesTable.getGMTimes(id)); + } + return data; } /** @@ -361,7 +318,7 @@ public abstract class SQLDB extends Database { * @throws SQLException */ @Override - public void saveMultipleUserData(List data) throws SQLException { + public void saveMultipleUserData(Collection data) throws SQLException { checkConnection(); if (data.isEmpty()) { return; @@ -369,45 +326,61 @@ public abstract class SQLDB extends Database { Set exceptions = new HashSet<>(); List saveLast = usersTable.saveUserDataInformationBatch(data); data.removeAll(saveLast); - for (UserData uData : data) { - if (uData == null) { + // Transform to map + Map userDatas = data.stream().collect(Collectors.toMap(UserData::getUuid, Function.identity())); + // Get UserIDs + Map userIds = usersTable.getAllUserIds(); + // Empty dataset + Map> locations = new HashMap<>(); + Map> nicknames = new HashMap<>(); + Map lastNicks = new HashMap<>(); + Map> ips = new HashMap<>(); + Map> kills = new HashMap<>(); + Map uuids = userIds.entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey)); + Map> sessions = new HashMap<>(); + Map> gmTimes = new HashMap<>(); + // Put to dataset + for (UUID uuid : userDatas.keySet()) { + Integer id = userIds.get(uuid); + UserData uData = userDatas.get(uuid); + if (id == -1) { + saveLast.add(uData); + Log.debug("User not seen before, saving last: "+uuid); continue; } - UUID uuid = uData.getUuid(); - if (uuid == null) { - try { - uData.setUuid(UUIDFetcher.getUUIDOf(uData.getName())); - if (uData.getUuid() == null) { - continue; - } - } catch (Exception ex) { - continue; - } - } uData.access(); - try { - int userId = getUserId(uData.getUuid().toString()); - sessionsTable.saveSessionData(userId, uData.getSessions()); - saveAdditionalLocationsList(userId, uData.getLocations()); - saveNickList(userId, uData.getNicknames(), uData.getLastNick()); - saveIPList(userId, uData.getIps()); - savePlayerKills(userId, uData.getPlayerKills()); - saveGMTimes(userId, uData.getGmTimes()); - } catch (Exception e) { - exceptions.add(e); - } - uData.stopAccessing(); + locations.put(id, new ArrayList<>(uData.getLocations())); + nicknames.put(id, new HashSet<>(uData.getNicknames())); + lastNicks.put(id, uData.getLastNick()); + ips.put(id, new HashSet<>(uData.getIps())); + kills.put(id, new ArrayList<>(uData.getPlayerKills())); + sessions.put(id, new ArrayList<>(uData.getSessions())); + gmTimes.put(id, uData.getGmTimes()); } - for (UserData userData : saveLast) { - UUID uuid = userData.getUuid(); - if (uuid == null) { - continue; + // Save + locationsTable.saveAdditionalLocationsLists(locations); + nicknamesTable.saveNickLists(nicknames, lastNicks); + ipsTable.saveIPList(ips); + killsTable.savePlayerKills(kills, uuids); + sessionsTable.saveSessionData(sessions); + for (Integer id : gmTimes.keySet()) { + gmTimesTable.saveGMTimes(id, gmTimes.get(id)); + } + for (Integer id : locations.keySet()) { + UUID uuid = uuids.get(id); + if (uuid != null) { + UserData uData = userDatas.get(uuid); + if (uData != null) { + uData.stopAccessing(); + } } + } + // Save leftovers + for (UserData userData : saveLast) { try { - saveUserData(uuid, userData); - } catch (SQLException e) { + saveUserData(userData); + } catch (SQLException | NullPointerException e) { exceptions.add(e); - } catch (NullPointerException e) { } } if (!exceptions.isEmpty()) { @@ -418,12 +391,15 @@ public abstract class SQLDB extends Database { /** * - * @param uuid * @param data * @throws SQLException */ @Override - public void saveUserData(UUID uuid, UserData data) throws SQLException { + public void saveUserData(UserData data) throws SQLException { + if (data == null) { + return; + } + UUID uuid = data.getUuid(); if (uuid == null) { return; } @@ -431,12 +407,12 @@ public abstract class SQLDB extends Database { Log.debug("DB_Save: " + data); data.access(); usersTable.saveUserDataInformation(data); - int userId = getUserId(uuid.toString()); - sessionsTable.saveSessionData(userId, data.getSessions()); + int userId = usersTable.getUserId(uuid.toString()); + sessionsTable.saveSessionData(userId, new ArrayList<>(data.getSessions())); locationsTable.saveAdditionalLocationsList(userId, data.getLocations()); - nicknamesTable.saveNickList(userId, data.getNicknames(), data.getLastNick()); - ipsTable.saveIPList(userId, data.getIps()); - killsTable.savePlayerKills(userId, data.getPlayerKills()); + nicknamesTable.saveNickList(userId, new HashSet<>(data.getNicknames()), data.getLastNick()); + ipsTable.saveIPList(userId, new HashSet<>(data.getIps())); + killsTable.savePlayerKills(userId, new ArrayList<>(data.getPlayerKills())); gmTimesTable.saveGMTimes(userId, data.getGmTimes()); data.stopAccessing(); } @@ -550,68 +526,4 @@ public abstract class SQLDB extends Database { public Connection getConnection() { return connection; } - - /** - * - * @return - */ - public UsersTable getUsersTable() { - return usersTable; - } - - /** - * - * @return - */ - public SessionsTable getSessionsTable() { - return sessionsTable; - } - - /** - * - * @return - */ - public GMTimesTable getGmTimesTable() { - return gmTimesTable; - } - - /** - * - * @return - */ - public KillsTable getKillsTable() { - return killsTable; - } - - /** - * - * @return - */ - public LocationsTable getLocationsTable() { - return locationsTable; - } - - /** - * - * @return - */ - public IPsTable getIpsTable() { - return ipsTable; - } - - /** - * - * @return - */ - public NicknamesTable getNicknamesTable() { - return nicknamesTable; - } - - /** - * - * @return - */ - public CommandUseTable getCommandUseTable() { - return commandUseTable; - } } diff --git a/Plan/src/main/java/com/djrapitops/plan/database/tables/CommandUseTable.java b/Plan/src/main/java/com/djrapitops/plan/database/tables/CommandUseTable.java index 152fcfa7a..483f8b5dd 100644 --- a/Plan/src/main/java/com/djrapitops/plan/database/tables/CommandUseTable.java +++ b/Plan/src/main/java/com/djrapitops/plan/database/tables/CommandUseTable.java @@ -4,6 +4,7 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.HashMap; +import java.util.Map; import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.database.databases.SQLDB; @@ -48,11 +49,10 @@ public class CommandUseTable extends Table { /** * - * @return - * @throws SQLException + * @return @throws SQLException */ - public HashMap getCommandUse() throws SQLException { - HashMap commandUse = new HashMap<>(); + public Map getCommandUse() throws SQLException { + Map commandUse = new HashMap<>(); PreparedStatement statement = null; ResultSet set = null; try { @@ -74,34 +74,37 @@ public class CommandUseTable extends Table { * @throws SQLException * @throws NullPointerException */ - public void saveCommandUse(HashMap data) throws SQLException, NullPointerException { + public void saveCommandUse(Map data) throws SQLException, NullPointerException { if (data.isEmpty()) { return; } PreparedStatement statement = null; try { - removeAllData(); + if (!removeAllData()) { + Log.debug("CommandUse Table clear failed."); + } statement = prepareStatement("INSERT INTO " + tableName + " (" + columnCommand + ", " + columnTimesUsed + ") VALUES (?, ?)"); boolean commitRequired = false; for (String key : data.keySet()) { + Integer amount = data.get(key); +// Log.debug("Saving Command: "+key+" "+amount); if (key.length() > 20) { continue; } statement.setString(1, key); - statement.setInt(2, data.get(key)); + statement.setInt(2, amount); statement.addBatch(); commitRequired = true; } - if (commitRequired) { + Log.debug("CommandUse: Executing batch, size: "+data.size()); statement.executeBatch(); } } finally { close(statement); } } - } diff --git a/Plan/src/main/java/com/djrapitops/plan/database/tables/IPsTable.java b/Plan/src/main/java/com/djrapitops/plan/database/tables/IPsTable.java index c79b048b5..bbef11193 100644 --- a/Plan/src/main/java/com/djrapitops/plan/database/tables/IPsTable.java +++ b/Plan/src/main/java/com/djrapitops/plan/database/tables/IPsTable.java @@ -6,7 +6,11 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.database.databases.SQLDB; @@ -136,4 +140,74 @@ public class IPsTable extends Table { close(statement); } } + + public Map> getIPList(Collection ids) throws SQLException { + if (ids == null || ids.isEmpty()) { + return new HashMap<>(); + } + PreparedStatement statement = null; + ResultSet set = null; + try { + statement = prepareStatement("SELECT * FROM " + tableName); + set = statement.executeQuery(); + Map> ips = new HashMap<>(); + for (Integer id : ids) { + ips.put(id, new HashSet<>()); + } + while (set.next()) { + Integer id = set.getInt(columnUserID); + if (!ids.contains(id)) { + Log.debug("Ips-Ids did not contain: " + id); + continue; + } + try { + ips.get(id).add(InetAddress.getByName(set.getString(columnIP))); + } catch (UnknownHostException e) { + } + } + return ips; + } finally { + close(set); + close(statement); + } + } + + public void saveIPList(Map> ips) throws SQLException { + if (ips == null || ips.isEmpty()) { + return; + } + Map> saved = getIPList(ips.keySet()); + PreparedStatement statement = null; + try { + statement = prepareStatement("INSERT INTO " + tableName + " (" + + columnUserID + ", " + + columnIP + + ") VALUES (?, ?)"); + boolean commitRequired = false; + for (Integer id : ips.keySet()) { + Set ipAddresses = ips.get(id); + Set s = saved.get(id); + if (s != null) { + ipAddresses.removeAll(s); + } + if (ipAddresses.isEmpty()) { + continue; + } + for (InetAddress ip : ipAddresses) { + if (ip == null) { + continue; + } + statement.setInt(1, id); + statement.setString(2, ip.getHostAddress()); + statement.addBatch(); + commitRequired = true; + } + } + if (commitRequired) { + statement.executeBatch(); + } + } finally { + close(statement); + } + } } diff --git a/Plan/src/main/java/com/djrapitops/plan/database/tables/KillsTable.java b/Plan/src/main/java/com/djrapitops/plan/database/tables/KillsTable.java index 3a6797e3d..94bb70146 100644 --- a/Plan/src/main/java/com/djrapitops/plan/database/tables/KillsTable.java +++ b/Plan/src/main/java/com/djrapitops/plan/database/tables/KillsTable.java @@ -4,7 +4,10 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.UUID; import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.data.KillData; @@ -147,4 +150,78 @@ public class KillsTable extends Table { close(statement); } } + + public Map> getPlayerKills(Collection ids, Map uuids) throws SQLException { + if (ids == null || ids.isEmpty()) { + return new HashMap<>(); + } + + PreparedStatement statement = null; + ResultSet set = null; + try { + Map> kills = new HashMap<>(); + statement = prepareStatement("SELECT * FROM " + tableName); + set = statement.executeQuery(); + for (Integer id : ids) { + kills.put(id, new ArrayList<>()); + } + while (set.next()) { + int killerID = set.getInt(columnKillerUserID); + int victimID = set.getInt(columnVictimUserID); + if (!ids.contains(killerID)) { + Log.debug("Kills-Ids did not contain: " + killerID); + continue; + } + UUID victimUUID = uuids.get(victimID); + kills.get(killerID).add(new KillData(victimUUID, victimID, set.getString(columnWeapon), set.getLong(columnDate))); + } + return kills; + } finally { + close(set); + close(statement); + } + } + + public void savePlayerKills(Map> kills, Map uuids) throws SQLException { + if (kills == null || kills.isEmpty()) { + Log.debug("Save multiple - Kills was empty."); + return; + } + Map> saved = getPlayerKills(kills.keySet(), uuids); + + PreparedStatement statement = null; + try { + statement = prepareStatement("INSERT INTO " + tableName + " (" + + columnKillerUserID + ", " + + columnVictimUserID + ", " + + columnWeapon + ", " + + columnDate + + ") VALUES (?, ?, ?, ?)"); + boolean commitRequired = false; + for (Integer id : kills.keySet()) { + List playerKills = kills.get(id); + List s = saved.get(id); + Log.debug("Saving:" + playerKills + " Saved: " + s); + if (s != null) { + playerKills.removeAll(s); + } + for (KillData kill : playerKills) { + if (kill == null) { + continue; + } + statement.setInt(1, id); + statement.setInt(2, kill.getVictimUserID()); + statement.setString(3, kill.getWeapon()); + statement.setLong(4, kill.getDate()); + statement.addBatch(); + commitRequired = true; + } + if (commitRequired) { + statement.executeBatch(); + } + } + } finally { + close(statement); + } + } } diff --git a/Plan/src/main/java/com/djrapitops/plan/database/tables/LocationsTable.java b/Plan/src/main/java/com/djrapitops/plan/database/tables/LocationsTable.java index 4291af1b7..e2a2c1811 100644 --- a/Plan/src/main/java/com/djrapitops/plan/database/tables/LocationsTable.java +++ b/Plan/src/main/java/com/djrapitops/plan/database/tables/LocationsTable.java @@ -6,6 +6,7 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Map; import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.database.databases.SQLDB; import org.bukkit.Location; @@ -132,13 +133,13 @@ public class LocationsTable extends Table { if (location == null) { continue; } - statement.setInt(1, userId); - statement.setInt(2, (int) location.getBlockX()); - statement.setInt(3, (int) location.getBlockZ()); World world = location.getWorld(); if (world == null) { continue; } + statement.setInt(1, userId); + statement.setInt(2, (int) location.getBlockX()); + statement.setInt(3, (int) location.getBlockZ()); statement.setString(4, world.getName()); statement.addBatch(); commitRequired = true; @@ -150,4 +151,43 @@ public class LocationsTable extends Table { close(statement); } } + + public void saveAdditionalLocationsLists(Map> locations) throws SQLException { + if (locations == null || locations.isEmpty()) { + return; + } + PreparedStatement statement = null; + try { + statement = prepareStatement("INSERT INTO " + tableName + " (" + + columnUserID + ", " + + columnCoordinatesX + ", " + + columnCoordinatesZ + ", " + + columnWorld + + ") VALUES (?, ?, ?, ?)"); + boolean commitRequired = false; + for (Integer id : locations.keySet()) { + List newLocations = locations.get(id); + if (newLocations == null || newLocations.isEmpty()) { + continue; + } + for (Location location : newLocations) { + World world = location.getWorld(); + if (world == null) { + continue; + } + statement.setInt(1, id); + statement.setInt(2, (int) location.getBlockX()); + statement.setInt(3, (int) location.getBlockZ()); + statement.setString(4, world.getName()); + statement.addBatch(); + commitRequired = true; + } + } + if (commitRequired) { + statement.executeBatch(); + } + } finally { + close(statement); + } + } } diff --git a/Plan/src/main/java/com/djrapitops/plan/database/tables/NicknamesTable.java b/Plan/src/main/java/com/djrapitops/plan/database/tables/NicknamesTable.java index 81e13f3f5..8720dedb6 100644 --- a/Plan/src/main/java/com/djrapitops/plan/database/tables/NicknamesTable.java +++ b/Plan/src/main/java/com/djrapitops/plan/database/tables/NicknamesTable.java @@ -4,7 +4,10 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Set; import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.database.databases.SQLDB; @@ -164,4 +167,88 @@ public class NicknamesTable extends Table { close(statement); } } + + public Map> getNicknames(Collection ids) throws SQLException { + if (ids == null || ids.isEmpty()) { + return new HashMap<>(); + } + + PreparedStatement statement = null; + ResultSet set = null; + try { + Map> nicks = new HashMap<>(); + Map lastNicks = new HashMap<>(); + for (Integer id : ids) { + nicks.put(id, new ArrayList<>()); + } + statement = prepareStatement("SELECT * FROM " + tableName); + set = statement.executeQuery(); + while (set.next()) { + + Integer id = set.getInt(columnUserID); + if (!ids.contains(id)) { + Log.debug("Nicknames-Ids did not contain: " + id); + continue; + } + String nickname = set.getString(columnNick); + if (nickname.isEmpty()) { + continue; + } + nicks.get(id).add(nickname); + if (set.getBoolean(columnCurrent)) { + lastNicks.put(id, nickname); + } + } + for (Integer id : lastNicks.keySet()) { + String lastNick = lastNicks.get(id); + List list = nicks.get(id); + list.remove(lastNick); + list.add(lastNick); + } + + return nicks; + } finally { + close(set); + close(statement); + } + } + + public void saveNickLists(Map> nicknames, Map lastNicks) throws SQLException { + if (nicknames == null || nicknames.isEmpty()) { + return; + } + Map> saved = getNicknames(nicknames.keySet()); + PreparedStatement statement = null; + try { + boolean commitRequired = false; + statement = prepareStatement("INSERT INTO " + tableName + " (" + + columnUserID + ", " + + columnCurrent + ", " + + columnNick + + ") VALUES (?, ?, ?)"); + for (Integer id : nicknames.keySet()) { + Set newNicks = nicknames.get(id); + String lastNick = lastNicks.get(id); + List s = saved.get(id); + if (s != null) { + newNicks.removeAll(s); + } + if (newNicks.isEmpty()) { + continue; + } + for (String name : newNicks) { + statement.setInt(1, id); + statement.setInt(2, (name.equals(lastNick)) ? 1 : 0); + statement.setString(3, name); + statement.addBatch(); + commitRequired = true; + } + } + if (commitRequired) { + statement.executeBatch(); + } + } finally { + close(statement); + } + } } diff --git a/Plan/src/main/java/com/djrapitops/plan/database/tables/SessionsTable.java b/Plan/src/main/java/com/djrapitops/plan/database/tables/SessionsTable.java index 311a418bb..5687894e5 100644 --- a/Plan/src/main/java/com/djrapitops/plan/database/tables/SessionsTable.java +++ b/Plan/src/main/java/com/djrapitops/plan/database/tables/SessionsTable.java @@ -4,7 +4,10 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Map; import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.data.SessionData; import main.java.com.djrapitops.plan.database.databases.SQLDB; @@ -142,4 +145,79 @@ public class SessionsTable extends Table { close(statement); } } + + public Map> getSessionData(Collection ids) throws SQLException { + if (ids == null || ids.isEmpty()) { + return new HashMap<>(); + } + PreparedStatement statement = null; + ResultSet set = null; + try { + Map> sessions = new HashMap<>(); + statement = prepareStatement("SELECT * FROM " + tableName); + set = statement.executeQuery(); + for (Integer id : ids) { + sessions.put(id, new ArrayList<>()); + } + while (set.next()) { + Integer id = set.getInt(columnUserID); + if (!ids.contains(id)) { + Log.debug("Session-Ids did not contain: " + id); + continue; + } + sessions.get(id).add(new SessionData(set.getLong(columnSessionStart), set.getLong(columnSessionEnd))); + } + set.close(); + statement.close(); + + return sessions; + } finally { + close(set); + close(statement); + } + } + + public void saveSessionData(Map> sessions) throws SQLException { + if (sessions == null || sessions.isEmpty()) { + return; + } + Map> saved = getSessionData(sessions.keySet()); + PreparedStatement statement = null; + try { + statement = prepareStatement("INSERT INTO " + tableName + " (" + + columnUserID + ", " + + columnSessionStart + ", " + + columnSessionEnd + + ") VALUES (?, ?, ?)"); + + boolean commitRequired = false; + for (Integer id : sessions.keySet()) { + List sessionList = sessions.get(id); + List s = saved.get(id); + if (s != null) { + sessionList.removeAll(s); + } + if (sessionList.isEmpty()) { + continue; + } + for (SessionData session : sessionList) { + long end = session.getSessionEnd(); + long start = session.getSessionStart(); + if (end < start) { + continue; + } + statement.setInt(1, id); + statement.setLong(2, start); + statement.setLong(3, end); + statement.addBatch(); + commitRequired = true; + } + } + if (commitRequired) { + statement.executeBatch(); + } + } finally { + close(statement); + } + } } diff --git a/Plan/src/main/java/com/djrapitops/plan/database/tables/UsersTable.java b/Plan/src/main/java/com/djrapitops/plan/database/tables/UsersTable.java index a22dea4f9..f9922f4ba 100644 --- a/Plan/src/main/java/com/djrapitops/plan/database/tables/UsersTable.java +++ b/Plan/src/main/java/com/djrapitops/plan/database/tables/UsersTable.java @@ -4,15 +4,21 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.UUID; +import java.util.function.Function; +import java.util.stream.Collectors; import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.api.Gender; import main.java.com.djrapitops.plan.data.UserData; import main.java.com.djrapitops.plan.database.databases.SQLDB; import main.java.com.djrapitops.plan.utilities.UUIDFetcher; +import me.edge209.OnTime.OnTimeAPI.data; import org.bukkit.GameMode; /** @@ -172,8 +178,7 @@ public class UsersTable extends Table { /** * - * @return - * @throws SQLException + * @return @throws SQLException */ public Set getSavedUUIDs() throws SQLException { PreparedStatement statement = null; @@ -253,6 +258,37 @@ public class UsersTable extends Table { close(statement); } } + + public void addUserInformationToUserData(List data) throws SQLException { + PreparedStatement statement = null; + ResultSet set = null; + try { + Map userDatas = data.stream().collect(Collectors.toMap(UserData::getUuid, Function.identity())); + statement = prepareStatement("SELECT * FROM " + tableName); + set = statement.executeQuery(); + while (set.next()) { + String uuidS = set.getString(columnUUID); + UUID uuid = UUID.fromString(uuidS); + if (!userDatas.keySet().contains(uuid)) { + continue; + } + UserData uData = userDatas.get(uuid); + uData.getDemData().setAge(set.getInt(columnDemAge)); + uData.getDemData().setGender(Gender.parse(set.getString(columnDemGender))); + uData.getDemData().setGeoLocation(set.getString(columnDemGeoLocation)); + uData.setLastGamemode(GameMode.valueOf(set.getString(columnLastGM))); + uData.setLastGmSwapTime(set.getLong(columnLastGMSwapTime)); + uData.setPlayTime(set.getLong(columnPlayTime)); + uData.setLoginTimes(set.getInt(columnLoginTimes)); + uData.setLastPlayed(set.getLong(columnLastPlayed)); + uData.setDeaths(set.getInt(columnDeaths)); + uData.setMobKills(set.getInt(columnMobKills)); + } + } finally { + close(set); + close(statement); + } + } /** * @@ -343,7 +379,7 @@ public class UsersTable extends Table { * @return * @throws SQLException */ - public List saveUserDataInformationBatch(List data) throws SQLException { + public List saveUserDataInformationBatch(Collection data) throws SQLException { PreparedStatement statement = null; try { List saveLast = new ArrayList<>(); @@ -418,6 +454,47 @@ public class UsersTable extends Table { } } + public Map getUserIds(Collection uuids) throws SQLException { + PreparedStatement statement = null; + ResultSet set = null; + try { + Map ids = new HashMap<>(); + statement = prepareStatement("SELECT " + columnUUID + ", " + columnID + " FROM " + tableName); + set = statement.executeQuery(); + while (set.next()) { + String uuidS = set.getString(columnUUID); + UUID uuid = UUID.fromString(uuidS); + if (!uuids.contains(uuid)) { + continue; + } + ids.put(uuid, set.getInt(columnID)); + } + return ids; + } finally { + close(set); + close(statement); + } + } + + public Map getAllUserIds() throws SQLException { + PreparedStatement statement = null; + ResultSet set = null; + try { + Map ids = new HashMap<>(); + statement = prepareStatement("SELECT " + columnUUID + ", " + columnID + " FROM " + tableName); + set = statement.executeQuery(); + while (set.next()) { + String uuidS = set.getString(columnUUID); + UUID uuid = UUID.fromString(uuidS); + ids.put(uuid, set.getInt(columnID)); + } + return ids; + } finally { + close(set); + close(statement); + } + } + /** * * @return diff --git a/Plan/src/main/java/com/djrapitops/plan/ui/Html.java b/Plan/src/main/java/com/djrapitops/plan/ui/Html.java index f56676ff3..25173faf2 100644 --- a/Plan/src/main/java/com/djrapitops/plan/ui/Html.java +++ b/Plan/src/main/java/com/djrapitops/plan/ui/Html.java @@ -34,6 +34,7 @@ public enum Html { COLOR_f(""), // FONT_AWESOME_ICON(""), + MINOTAR_SMALL_IMG("\"""), SPAN("" + REPLACE0 + ""), BUTTON("" + REPLACE1 + ""), BUTTON_CLASS("class=\"button\""), diff --git a/Plan/src/main/java/com/djrapitops/plan/ui/TextUI.java b/Plan/src/main/java/com/djrapitops/plan/ui/TextUI.java index 572d6c90c..81ccaf774 100644 --- a/Plan/src/main/java/com/djrapitops/plan/ui/TextUI.java +++ b/Plan/src/main/java/com/djrapitops/plan/ui/TextUI.java @@ -9,6 +9,8 @@ import main.java.com.djrapitops.plan.data.cache.AnalysisCacheHandler; import main.java.com.djrapitops.plan.data.cache.InspectCacheHandler; import main.java.com.djrapitops.plan.utilities.AnalysisUtils; import main.java.com.djrapitops.plan.utilities.FormatUtils; +import main.java.com.djrapitops.plan.utilities.MathUtils; +import main.java.com.djrapitops.plan.utilities.MiscUtils; import org.bukkit.ChatColor; /** @@ -24,6 +26,7 @@ public class TextUI { */ public static String[] getInspectMessages(UUID uuid) { InspectCacheHandler inspectCache = Plan.getInstance().getInspectCache(); + long now = MiscUtils.getTime(); if (!inspectCache.isCached(uuid)) { return new String[]{"Error has occurred, please retry."}; } @@ -31,17 +34,17 @@ public class TextUI { ChatColor main = Phrase.COLOR_MAIN.color(); ChatColor sec = Phrase.COLOR_SEC.color(); ChatColor ter = Phrase.COLOR_TER.color(); - boolean active = AnalysisUtils.isActive(d.getLastPlayed(), d.getPlayTime(), d.getLoginTimes()); + boolean active = AnalysisUtils.isActive(now, d.getLastPlayed(), d.getPlayTime(), d.getLoginTimes()); boolean banned = d.isBanned(); boolean online = d.isOnline(); String ball = sec + " " + Phrase.BALL + main; return new String[]{ sec + " " + Phrase.BALL + (banned ? ChatColor.DARK_RED + " Banned" : ter + (active ? " Active" : " Inactive")) + (online ? ChatColor.GREEN + " Online" : ChatColor.RED + " Offline"), - ball + " Registered: " + sec + FormatUtils.formatTimeStamp(d.getRegistered() + ""), - ball + " Last seen: " + sec + FormatUtils.formatTimeStamp(d.getLastPlayed() + ""), - ball + " Playtime: " + sec + FormatUtils.formatTimeAmount(d.getPlayTime() + ""), + ball + " Registered: " + sec + FormatUtils.formatTimeStamp(d.getRegistered()), + ball + " Last seen: " + sec + FormatUtils.formatTimeStamp(d.getLastPlayed()), + ball + " Playtime: " + sec + FormatUtils.formatTimeAmount(d.getPlayTime()), ball + " Login times: " + sec + d.getLoginTimes(), - ball + " Average session length: " + sec + FormatUtils.formatTimeAmount(AnalysisUtils.average(AnalysisUtils.transformSessionDataToLengths(d.getSessions())) + ""), + ball + " Average session length: " + sec + FormatUtils.formatTimeAmount(MathUtils.averageLong(AnalysisUtils.transformSessionDataToLengths(d.getSessions()))), ball + " Kills: " + sec + d.getPlayerKills().size() + main + " Mobs: " + sec + d.getMobKills() + main + " Deaths: " + sec + d.getDeaths(), ball + " Geolocation: " + sec + d.getDemData().getGeoLocation() }; @@ -66,8 +69,8 @@ public class TextUI { ball + " Active: " + sec + d.getActive() + main + " Inactive: " + sec + d.getInactive() + main + " Single join: " + sec + d.getJoinleaver() + main + " Banned: " + sec + d.getBanned(), ball + " New Players 24h: " + sec + d.getNewPlayersDay() + main + " 7d: " + sec + d.getNewPlayersWeek() + main + " 30d: " + sec + d.getNewPlayersMonth(), "", - ball + " Total Playtime: " + sec + FormatUtils.formatTimeAmount(d.getTotalPlayTime() + "") + main + " Player Avg: " + sec + FormatUtils.formatTimeAmount(d.getAveragePlayTime() + ""), - ball + " Average Session Length: " + sec + FormatUtils.formatTimeAmount(d.getSessionAverage() + ""), + ball + " Total Playtime: " + sec + FormatUtils.formatTimeAmount(d.getTotalPlayTime()) + main + " Player Avg: " + sec + FormatUtils.formatTimeAmount(d.getAveragePlayTime()), + ball + " Average Session Length: " + sec + FormatUtils.formatTimeAmount(d.getSessionAverage()), ball + " Total Logintimes: " + sec + d.getTotalLoginTimes(), ball + " Kills: " + sec + d.getTotalPlayerKills() + main + " Mobs: " + sec + d.getTotalMobKills() + main + " Deaths: " + sec + d.getTotalDeaths() }; diff --git a/Plan/src/main/java/com/djrapitops/plan/ui/graphs/PlayerActivityGraphCreator.java b/Plan/src/main/java/com/djrapitops/plan/ui/graphs/PlayerActivityGraphCreator.java index 16ae2e769..bd69f94fa 100644 --- a/Plan/src/main/java/com/djrapitops/plan/ui/graphs/PlayerActivityGraphCreator.java +++ b/Plan/src/main/java/com/djrapitops/plan/ui/graphs/PlayerActivityGraphCreator.java @@ -47,7 +47,7 @@ public class PlayerActivityGraphCreator { if (lastSavedPValue != lastPValue || i - lastSaveI > (scale / (long) 75)) { lastSaveI = i; - labels.add("\"" + FormatUtils.formatTimeStamp(i + "") + "\""); + labels.add("\"" + FormatUtils.formatTimeStamp(i) + "\""); lastSavedPValue = lastPValue; playersOnline.add(lastPValue); } diff --git a/Plan/src/main/java/com/djrapitops/plan/ui/graphs/PunchCardGraphCreator.java b/Plan/src/main/java/com/djrapitops/plan/ui/graphs/PunchCardGraphCreator.java new file mode 100644 index 000000000..26758512f --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/ui/graphs/PunchCardGraphCreator.java @@ -0,0 +1,138 @@ +/* + * 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.ui.graphs; + +import java.util.Arrays; +import java.util.Calendar; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; +import main.java.com.djrapitops.plan.Log; +import main.java.com.djrapitops.plan.data.SessionData; + +/** + * + * @author Rsl1122 + */ +public class PunchCardGraphCreator { + + public static String generateDataArray(Collection data) { + // Initialize dataset + List sessionStarts = getSessionStarts(data); + List daysAndHours = getDaysAndHours(sessionStarts); + int[][] dataArray = createDataArray(daysAndHours); + int big = findBiggestValue(dataArray); + int[][] scaled = scale(dataArray, big); + StringBuilder arrayBuilder = buildString(scaled); + return arrayBuilder.toString(); + } + + private static StringBuilder buildString(int[][] scaled) { + StringBuilder arrayBuilder = new StringBuilder(); + arrayBuilder.append("["); + arrayBuilder.append("{").append("x:").append(-1).append(", y:").append(-1).append(", r:").append(1).append("}"); + arrayBuilder.append(","); + arrayBuilder.append("{").append("x:").append(25).append(", y:").append(7).append(", r:").append(1).append("}"); + arrayBuilder.append(","); + for (int i = 0; i < 7; i++) { + for (int j = 0; j < 24; j++) { + int value = scaled[i][j]; + if (value == 0) { + continue; + } + arrayBuilder.append("{").append("x:").append(j).append(", y:").append(i).append(", r:").append(value).append("}"); + if (!(i == 6 && j == 23)) { + arrayBuilder.append(","); + } + } + } + arrayBuilder.append("]"); + return arrayBuilder; + } + + private static int[][] createDataArray(List daysAndHours) { + int[][] dataArray = createEmptyArray(); + for (int[] dAndH : daysAndHours) { + int d = dAndH[0]; + int h = dAndH[1]; + dataArray[d][h] = dataArray[d][h] + 1; + } + return dataArray; + } + + private static List getDaysAndHours(List sessionStarts) { + List daysAndHours = sessionStarts.stream().map(start -> { + Calendar day = Calendar.getInstance(); + day.setTimeInMillis(start); + int hourOfDay = day.get(Calendar.HOUR_OF_DAY); + + int dayOfWeek = day.get(Calendar.DAY_OF_WEEK) - 2; + if (hourOfDay == 24) { + hourOfDay = 0; + dayOfWeek += 1; + } + if (dayOfWeek > 6) { + dayOfWeek = 0; + } + if (dayOfWeek < 0) { + dayOfWeek = 6; + } + return new int[]{dayOfWeek, hourOfDay}; + }).collect(Collectors.toList()); + return daysAndHours; + } + + private static List getSessionStarts(Collection data) { + List sessionStarts = data.stream() + .filter(s -> s != null) + .filter(s -> s.isValid()) + .map(s -> s.getSessionStart()) + .sorted() + .collect(Collectors.toList()); + return sessionStarts; + } + + private static int[][] createEmptyArray() { + int[][] dataArray = new int[7][24]; + for (int i = 0; i < 7; i++) { + for (int j = 0; j < 24; j++) { + dataArray[i][j] = 0; + } + } + return dataArray; + } + + private static int findBiggestValue(int[][] dataArray) { + int highest = 1; + for (int i = 0; i < 7; i++) { + for (int j = 0; j < 24; j++) { + int num = dataArray[i][j]; + if (num > highest) { + highest = num; + } + } + } + return highest; + } + + private static int[][] scale(int[][] dataArray, int big) { + + int[][] scaled = new int[7][24]; + for (int i = 0; i < 7; i++) { + Log.debug("Scaling: " + Arrays.toString(dataArray[i]) + " | " + big); + for (int j = 0; j < 24; j++) { + int value = (int) ((dataArray[i][j] * 10.0) / big); + if (value != 0) { + value += 4; + } + scaled[i][j] = value; + } + Log.debug(" Scaled: " + Arrays.toString(scaled[i])); + } + + return scaled; + } +} diff --git a/Plan/src/main/java/com/djrapitops/plan/ui/graphs/SessionLengthDistributionGraphCreator.java b/Plan/src/main/java/com/djrapitops/plan/ui/graphs/SessionLengthDistributionGraphCreator.java new file mode 100644 index 000000000..f313e74d4 --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/ui/graphs/SessionLengthDistributionGraphCreator.java @@ -0,0 +1,98 @@ +/* + * 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.ui.graphs; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import main.java.com.djrapitops.plan.data.SessionData; +import main.java.com.djrapitops.plan.utilities.AnalysisUtils; +import main.java.com.djrapitops.plan.utilities.MathUtils; + +/** + * + * @author Risto + */ +public class SessionLengthDistributionGraphCreator { + + public static String[] generateDataArraySessions(Collection data) { + List lengths = AnalysisUtils.transformSessionDataToLengths(data); + return generateDataArray(lengths); + } + + public static String[] generateDataArray(Collection lengths) { + Map values = getValues(lengths); + Map scaled = scale(values); + StringBuilder arrayBuilder = buildString(scaled); + StringBuilder labelBuilder = buildLabels(scaled); + return new String[]{arrayBuilder.toString(), labelBuilder.toString()}; + } + + private static StringBuilder buildString(Map scaled) { + StringBuilder arrayBuilder = new StringBuilder(); + arrayBuilder.append("["); + + long big = MathUtils.getBiggestLong(scaled.keySet()); + for (long key = 0; key <= big; key++) { + Integer value = scaled.get(key); + if (value == null) { + continue; + } + arrayBuilder.append(value); + if (key != big) { + arrayBuilder.append(", "); + } + } + arrayBuilder.append("]"); + return arrayBuilder; + } + + private static StringBuilder buildLabels(Map scaled) { + StringBuilder arrayBuilder = new StringBuilder(); + arrayBuilder.append("["); + + long big = MathUtils.getBiggestLong(scaled.keySet()); + for (long key = 0; key <= big; key++) { + Integer value = scaled.get(key); + if (value == null) { + continue; + } + arrayBuilder.append("\'").append(key - 5).append(" - ").append(key).append(" min").append("\'"); + if (key != big) { + arrayBuilder.append(", "); + } + } + arrayBuilder.append("]"); + return arrayBuilder; + } + + private static Map getValues(Collection lengths) { + List unused = new ArrayList<>(lengths); + Map values = new HashMap<>(); + long lengthInMinutes = 5; + while (!unused.isEmpty()) { + long length = lengthInMinutes * 60 * 1000; + List lessThan = unused.stream().filter(l -> l < length).collect(Collectors.toList()); + values.put(lengthInMinutes, lessThan.size()); + unused.removeAll(lessThan); + lengthInMinutes += 5; + } + return values; + } + + private static Map scale(Map values) { + Map scaled = new HashMap<>(); + int total = MathUtils.sumInt(values.values().stream().map(i -> (Serializable) i)); + for (long key : values.keySet()) { + scaled.put(key, (int) ((1.0 * values.get(key) / total) * 100)); + } + return scaled; + } +} diff --git a/Plan/src/main/java/com/djrapitops/plan/ui/tables/SortableKillsTableCreator.java b/Plan/src/main/java/com/djrapitops/plan/ui/tables/SortableKillsTableCreator.java index f43db0594..b3f004c0a 100644 --- a/Plan/src/main/java/com/djrapitops/plan/ui/tables/SortableKillsTableCreator.java +++ b/Plan/src/main/java/com/djrapitops/plan/ui/tables/SortableKillsTableCreator.java @@ -33,7 +33,7 @@ public class SortableKillsTableCreator { OfflinePlayer victim = getOfflinePlayer(kill.getVictim()); String name = victim.getName(); html += Html.TABLELINE_3_CUSTOMKEY_1.parse( - date + "", FormatUtils.formatTimeStamp(date + ""), + date + "", FormatUtils.formatTimeStamp(date), Html.LINK.parse(HtmlUtils.getInspectUrl(name), name), kill.getWeapon() ); diff --git a/Plan/src/main/java/com/djrapitops/plan/ui/tables/SortablePlayersTableCreator.java b/Plan/src/main/java/com/djrapitops/plan/ui/tables/SortablePlayersTableCreator.java index 322f9f2d0..8763e4696 100644 --- a/Plan/src/main/java/com/djrapitops/plan/ui/tables/SortablePlayersTableCreator.java +++ b/Plan/src/main/java/com/djrapitops/plan/ui/tables/SortablePlayersTableCreator.java @@ -6,6 +6,7 @@ import main.java.com.djrapitops.plan.ui.Html; import main.java.com.djrapitops.plan.utilities.AnalysisUtils; import main.java.com.djrapitops.plan.utilities.FormatUtils; import main.java.com.djrapitops.plan.utilities.HtmlUtils; +import main.java.com.djrapitops.plan.utilities.MiscUtils; /** * @@ -20,17 +21,21 @@ public class SortablePlayersTableCreator { */ public static String createSortablePlayersTable(Collection data) { String html = ""; + long now = MiscUtils.getTime(); for (UserData uData : data) { try { - String bORaORi = uData.isBanned() ? Html.GRAPH_BANNED.parse() - : (AnalysisUtils.isActive(uData.getLastPlayed(), uData.getPlayTime(), uData.getLoginTimes()) - ? Html.GRAPH_ACTIVE.parse() : Html.GRAPH_INACTIVE.parse()); + String banOunknownOactiveOinactive = uData.isBanned() ? Html.GRAPH_BANNED.parse() + : uData.getLoginTimes() == 1 ? Html.GRAPH_UNKNOWN.parse() + : AnalysisUtils.isActive(now, uData.getLastPlayed(), uData.getPlayTime(), uData.getLoginTimes()) ? Html.GRAPH_ACTIVE.parse() + : Html.GRAPH_INACTIVE.parse(); - html += Html.TABLELINE_PLAYERS.parse("\"" " + Html.LINK.parse(HtmlUtils.getInspectUrl(uData.getName()), uData.getName()), bORaORi, - uData.getPlayTime() + "", FormatUtils.formatTimeAmount(uData.getPlayTime() + ""), + html += Html.TABLELINE_PLAYERS.parse( + Html.MINOTAR_SMALL_IMG.parse(uData.getName()) + Html.LINK.parse(HtmlUtils.getInspectUrl(uData.getName()), uData.getName()), + banOunknownOactiveOinactive, + uData.getPlayTime() + "", FormatUtils.formatTimeAmount(uData.getPlayTime()), uData.getLoginTimes() + "", - uData.getRegistered() + "", FormatUtils.formatTimeStamp(uData.getRegistered() + ""), - uData.getLastPlayed() + "", FormatUtils.formatTimeStamp(uData.getLastPlayed() + ""), + uData.getRegistered() + "", FormatUtils.formatTimeStamp(uData.getRegistered()), + uData.getLastPlayed() + "", FormatUtils.formatTimeStamp(uData.getLastPlayed()), uData.getDemData().getGeoLocation() ); } catch (NullPointerException e) { diff --git a/Plan/src/main/java/com/djrapitops/plan/ui/tables/SortableSessionTableCreator.java b/Plan/src/main/java/com/djrapitops/plan/ui/tables/SortableSessionTableCreator.java index 744920e92..8ba828001 100644 --- a/Plan/src/main/java/com/djrapitops/plan/ui/tables/SortableSessionTableCreator.java +++ b/Plan/src/main/java/com/djrapitops/plan/ui/tables/SortableSessionTableCreator.java @@ -37,9 +37,9 @@ public class SortableSessionTableCreator { continue; } html += Html.TABLELINE_3_CUSTOMKEY.parse( - start + "", FormatUtils.formatTimeStamp(start + ""), - end + "", FormatUtils.formatTimeStamp(end + ""), - length + "", FormatUtils.formatTimeAmount(length + "") + start + "", FormatUtils.formatTimeStamp(start), + end + "", FormatUtils.formatTimeStamp(end), + length + "", FormatUtils.formatTimeAmount(length) ); i++; } diff --git a/Plan/src/main/java/com/djrapitops/plan/utilities/Analysis.java b/Plan/src/main/java/com/djrapitops/plan/utilities/Analysis.java index 49d9df3bf..f130b4d6d 100644 --- a/Plan/src/main/java/com/djrapitops/plan/utilities/Analysis.java +++ b/Plan/src/main/java/com/djrapitops/plan/utilities/Analysis.java @@ -28,6 +28,10 @@ import main.java.com.djrapitops.plan.database.Database; import main.java.com.djrapitops.plan.ui.Html; import main.java.com.djrapitops.plan.ui.RecentPlayersButtonsCreator; import main.java.com.djrapitops.plan.ui.graphs.PlayerActivityGraphCreator; +import main.java.com.djrapitops.plan.ui.graphs.PunchCardGraphCreator; +import main.java.com.djrapitops.plan.ui.graphs.SessionLengthDistributionGraphCreator; +import main.java.com.djrapitops.plan.ui.tables.SortableCommandUseTableCreator; +import main.java.com.djrapitops.plan.ui.tables.SortablePlayersTableCreator; import org.bukkit.GameMode; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitTask; @@ -73,15 +77,6 @@ public class Analysis { }).runTaskAsynchronously(plugin); } - /** - * @param analysisCache - * @deprecated Does nothing anymore, use analyze(AnalysisCacheHandler, - * Database) - */ - @Deprecated - public void analyze(AnalysisCacheHandler analysisCache) { - } - private List fetchPlayersInDB(Database db) { try { log(Phrase.ANALYSIS_FETCH_PLAYERS + ""); @@ -106,52 +101,37 @@ public class Analysis { * @return Whether or not analysis was successful. */ public boolean analyze(AnalysisCacheHandler analysisCache, Database db) { - List rawData = new ArrayList<>(); - List added = new ArrayList<>(); - List uuids = fetchPlayersInDB(db); - if (uuids.isEmpty()) { - Log.info(Phrase.ANALYSIS_FAIL_NO_DATA + ""); - return false; - } - uuids.stream().forEach((uuid) -> { - inspectCache.cache(uuid); - }); log(Phrase.ANALYSIS_FETCH_DATA + ""); - while (rawData.size() != uuids.size()) { - uuids.stream() - .filter((uuid) -> (!added.contains(uuid))) - .forEach((uuid) -> { - if (inspectCache.isCached(uuid)) { - UserData userData = inspectCache.getFromCache(uuid); - if (userData != null) { - rawData.add(userData); - userData.access(); - added.add(uuid); - } - } - }); + try { + inspectCache.cacheAllUserData(db); + } catch (Exception ex) { + Log.toLog(this.getClass().getName(), ex); + Log.error(Phrase.ERROR_ANALYSIS_FETCH_FAIL + ""); } - if (added.isEmpty()) { + List rawData = inspectCache.getCachedUserData(); + if (rawData.isEmpty()) { Log.info(Phrase.ANALYSIS_FAIL_NO_DATA + ""); return false; } - return analyzeData(rawData, uuids, analysisCache); + return analyzeData(rawData, analysisCache); } /** * * @param rawData - * @param uuids * @param analysisCache * @return */ - public boolean analyzeData(List rawData, List uuids, AnalysisCacheHandler analysisCache) { + public boolean analyzeData(List rawData, AnalysisCacheHandler analysisCache) { + List uuids = rawData.stream().map(d -> d.getUuid()).collect(Collectors.toList()); // Create empty Dataset + long now = MiscUtils.getTime(); final RawAnalysisData sorted = new RawAnalysisData(); sorted.setCommandUse(plugin.getHandler().getCommandUse()); log(Phrase.ANALYSIS_BEGIN_ANALYSIS + ""); AnalysisData analysisData = new AnalysisData(); - analysisData.setSortablePlayersTable(AnalysisUtils.createSortablePlayersTable(rawData)); + String playersTable = SortablePlayersTableCreator.createSortablePlayersTable(rawData); + analysisData.setSortablePlayersTable(playersTable); sorted.fillGeolocations(); // Fill Dataset with userdata. rawData.stream().forEach((uData) -> { @@ -201,7 +181,7 @@ public class Analysis { sorted.addTotalBanned(1); } else if (uData.getLoginTimes() == 1) { sorted.addJoinleaver(1); - } else if (AnalysisUtils.isActive(uData.getLastPlayed(), playTime, uData.getLoginTimes())) { + } else if (AnalysisUtils.isActive(now, uData.getLastPlayed(), playTime, uData.getLoginTimes())) { sorted.addActive(1); sorted.getPlaytimes().put(html, playTime); } else { @@ -246,7 +226,7 @@ public class Analysis { long totalPlaytime = sorted.getTotalPlaytime(); analysisData.setTotalPlayTime(totalPlaytime); analysisData.setAveragePlayTime(totalPlaytime / rawData.size()); - analysisData.setSessionAverage(AnalysisUtils.average(AnalysisUtils.transformSessionDataToLengths(sorted.getSessiondata()))); + analysisData.setSessionAverage(MathUtils.averageLong(AnalysisUtils.transformSessionDataToLengths(sorted.getSessiondata()))); analysisData.setTotalLoginTimes(sorted.getTotalLoginTimes()); createActivityVisalization(uuids.size(), sorted.getTotalBanned(), sorted.getActive(), sorted.getInactive(), sorted.getJoinleaver(), analysisData); analysisData.setOps(sorted.getOps()); @@ -256,8 +236,11 @@ public class Analysis { analysisData.setTotaldeaths(sorted.getTotalDeaths()); analysisData.setTotalkills(sorted.getTotalKills()); analysisData.setTotalmobkills(sorted.getTotalMobKills()); - analysisData.setRefreshDate(new Date().getTime()); + analysisData.setRefreshDate(now); analysisData.setGenderData(sorted.getGenders()); + analysisData.setPunchCardData(PunchCardGraphCreator.generateDataArray(sorted.getSessiondata())); + analysisData.setSessionDistributionData(SessionLengthDistributionGraphCreator.generateDataArraySessions(sorted.getSessiondata())); + analysisData.setPlaytimeDistributionData(SessionLengthDistributionGraphCreator.generateDataArray(sorted.getPlaytimes().values())); analysisData.setAdditionalDataReplaceMap(analyzeAdditionalPluginData(uuids)); analysisCache.cache(analysisData); if (Settings.ANALYSIS_LOG_FINISHED.isTrue()) { @@ -269,7 +252,8 @@ public class Analysis { private void createCommandUseTable(final RawAnalysisData raw, AnalysisData data) { Map commandUse = raw.getCommandUse(); if (!commandUse.isEmpty()) { - data.setCommandUseTableHtml(AnalysisUtils.createTableOutOfMap(commandUse)); + String tableHtml = SortableCommandUseTableCreator.createSortedCommandUseTable(commandUse); + data.setCommandUseTableHtml(tableHtml); data.setTotalCommands(commandUse.size()); } else { data.setCommandUseTableHtml(Html.ERROR_TABLE_2.parse()); @@ -363,49 +347,49 @@ public class Analysis { } private Map analyzeAdditionalPluginData(List uuids) { - Map replaceMap = new HashMap<>(); - HookHandler hookHandler = Plan.getInstance().getHookHandler(); - List sources = hookHandler.getAdditionalDataSources(); - for (PluginData source : sources) { + final Map replaceMap = new HashMap<>(); + final HookHandler hookHandler = plugin.getHookHandler(); + final List sources = hookHandler.getAdditionalDataSources(); + final AnalysisType[] totalTypes = new AnalysisType[]{ + AnalysisType.INT_TOTAL, AnalysisType.LONG_TOTAL, AnalysisType.LONG_TIME_MS_TOTAL, AnalysisType.DOUBLE_TOTAL + }; + final AnalysisType[] avgTypes = new AnalysisType[]{ + AnalysisType.INT_AVG, AnalysisType.LONG_AVG, AnalysisType.LONG_TIME_MS_AVG, AnalysisType.LONG_EPOCH_MS_MINUS_NOW_AVG, AnalysisType.DOUBLE_AVG + }; + final AnalysisType bool = AnalysisType.BOOLEAN_PERCENTAGE; + final AnalysisType boolTot = AnalysisType.BOOLEAN_TOTAL; + sources.parallelStream().forEach(source -> { Log.debug("Analyzing source: " + source.getPlaceholder("").replace("%", "")); try { - List analysisTypes = source.getAnalysisTypes(); + final List analysisTypes = source.getAnalysisTypes(); if (analysisTypes.isEmpty()) { - continue; + return; } if (analysisTypes.contains(AnalysisType.HTML)) { replaceMap.put(source.getPlaceholder(AnalysisType.HTML.getPlaceholderModifier()), source.getHtmlReplaceValue(AnalysisType.HTML.getModifier(), uuids.get(0))); - continue; + return; } - AnalysisType[] totalTypes = new AnalysisType[]{ - AnalysisType.INT_TOTAL, AnalysisType.LONG_TOTAL, AnalysisType.LONG_TIME_MS_TOTAL, AnalysisType.DOUBLE_TOTAL - }; for (AnalysisType type : totalTypes) { if (analysisTypes.contains(type)) { replaceMap.put(source.getPlaceholder(type.getPlaceholderModifier()), AnalysisUtils.getTotal(type, source, uuids)); } } - AnalysisType[] avgTypes = new AnalysisType[]{ - AnalysisType.INT_AVG, AnalysisType.LONG_AVG, AnalysisType.LONG_TIME_MS_AVG, AnalysisType.LONG_EPOCH_MS_MINUS_NOW_AVG, AnalysisType.DOUBLE_AVG - }; for (AnalysisType type : avgTypes) { if (analysisTypes.contains(type)) { replaceMap.put(source.getPlaceholder(type.getPlaceholderModifier()), AnalysisUtils.getAverage(type, source, uuids)); } } - AnalysisType t = AnalysisType.BOOLEAN_PERCENTAGE; - if (analysisTypes.contains(t)) { - replaceMap.put(source.getPlaceholder(t.getPlaceholderModifier()), AnalysisUtils.getBooleanPercentage(t, source, uuids)); + if (analysisTypes.contains(bool)) { + replaceMap.put(source.getPlaceholder(bool.getPlaceholderModifier()), AnalysisUtils.getBooleanPercentage(bool, source, uuids)); } - t = AnalysisType.BOOLEAN_TOTAL; - if (analysisTypes.contains(t)) { - replaceMap.put(source.getPlaceholder(t.getPlaceholderModifier()), AnalysisUtils.getBooleanTotal(t, source, uuids)); + if (analysisTypes.contains(boolTot)) { + replaceMap.put(source.getPlaceholder(boolTot.getPlaceholderModifier()), AnalysisUtils.getBooleanTotal(boolTot, source, uuids)); } } catch (Throwable e) { Log.error("A PluginData-source caused an exception: " + source.getPlaceholder("").replace("%", "")); Log.toLog(this.getClass().getName(), e); } - } + }); return replaceMap; } } diff --git a/Plan/src/main/java/com/djrapitops/plan/utilities/AnalysisUtils.java b/Plan/src/main/java/com/djrapitops/plan/utilities/AnalysisUtils.java index f72550972..90d2a1847 100644 --- a/Plan/src/main/java/com/djrapitops/plan/utilities/AnalysisUtils.java +++ b/Plan/src/main/java/com/djrapitops/plan/utilities/AnalysisUtils.java @@ -2,21 +2,15 @@ package main.java.com.djrapitops.plan.utilities; import java.io.Serializable; import java.util.Collection; -import java.util.Date; import java.util.List; -import java.util.Map; -import java.util.OptionalDouble; import java.util.UUID; import java.util.stream.Collectors; import java.util.stream.Stream; import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.Settings; import main.java.com.djrapitops.plan.data.SessionData; -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.tables.SortableCommandUseTableCreator; -import main.java.com.djrapitops.plan.ui.tables.SortablePlayersTableCreator; /** * @@ -31,13 +25,18 @@ public class AnalysisUtils { * @param loginTimes * @return */ + @Deprecated public static boolean isActive(long lastPlayed, long playTime, int loginTimes) { + return isActive(MiscUtils.getTime(), lastPlayed, playTime, loginTimes); + } + + public static boolean isActive(long now, long lastPlayed, long playTime, int loginTimes) { int timeToActive = Settings.ANALYSIS_MINUTES_FOR_ACTIVE.getNumber(); if (timeToActive < 0) { timeToActive = 0; } long twoWeeks = 1209600000; - if (new Date().getTime() - lastPlayed < twoWeeks) { + if (now - lastPlayed < twoWeeks) { if (loginTimes > 3) { if (playTime > 60 * timeToActive) { return true; @@ -47,14 +46,6 @@ public class AnalysisUtils { return false; } - static String createTableOutOfMap(Map commandUse) { - return SortableCommandUseTableCreator.createSortedCommandUseTable(commandUse); - } - - static String createSortablePlayersTable(Collection data) { - return SortablePlayersTableCreator.createSortablePlayersTable(data); - } - /** * * @param registered @@ -89,24 +80,6 @@ public class AnalysisUtils { return list; } - /** - * - * @param list - * @return - */ - public static long average(Collection list) { - if (list.isEmpty()) { - return 0; - } - long total = 0; - for (Long long1 : list) { - total += long1; - } - return total / list.size(); - } - - // Refactor to MathUtils class - /** * * @param analysisType @@ -115,49 +88,40 @@ public class AnalysisUtils { * @return */ public static String getTotal(AnalysisType analysisType, PluginData source, List uuids) { - try { - if (null != analysisType) { - Number total; - switch (analysisType) { - case INT_TOTAL: - total = getCorrectValues(uuids, source) - .mapToInt(value -> (Integer) value) - .sum(); - break; - case LONG_TOTAL: - total = getCorrectValues(uuids, source) - .mapToLong(value -> (Long) value) - .sum(); - break; - case LONG_TIME_MS_TOTAL: - total = getCorrectValues(uuids, source) - .mapToLong(value -> (Long) value) - .sum(); - return source.parseContainer(analysisType.getModifier(), FormatUtils.formatTimeAmount(total + "")); - case DOUBLE_TOTAL: - total = getCorrectValues(uuids, source) - .mapToDouble(value -> (Double) value) - .sum(); - break; - default: - return source.parseContainer("ERROR ", "Wrong Analysistype specified: " + analysisType.name()); - } - return source.parseContainer(analysisType.getModifier(), total + ""); - } - } catch (Throwable e) { - Log.toLog("com.djrapitops.plan.utilities.AnalysisUtils", e); + if (analysisType == null) { + return source.parseContainer("Err ", "Null Analysistype. "); + } + try { + Number total; + switch (analysisType) { + case INT_TOTAL: + total = MathUtils.sumInt(getCorrectValues(uuids, source)); + break; + case LONG_TOTAL: + total = MathUtils.sumLong(getCorrectValues(uuids, source)); + break; + case LONG_TIME_MS_TOTAL: + total = MathUtils.sumLong(getCorrectValues(uuids, source)); + return source.parseContainer(analysisType.getModifier(), FormatUtils.formatTimeAmount((long) total)); + case DOUBLE_TOTAL: + total = MathUtils.sumDouble(getCorrectValues(uuids, source)); + break; + default: + return source.parseContainer("", "Wrong Analysistype specified: " + analysisType.name()); + } + return source.parseContainer(analysisType.getModifier(), total + ""); + } catch (Throwable e) { + return logPluginDataCausedError(source, e); } - return source.parseContainer("ERROR ", "Exception during total calculation."); } private static Stream getCorrectValues(List uuids, PluginData source) { return uuids.stream() .map(uuid -> source.getValue(uuid)) - .filter(value -> !value.equals(-1)); + .filter(value -> !value.equals(-1)) + .filter(value -> !value.equals(-1L)); } - // Refactor to MathUtils class - /** * * @param analysisType @@ -166,61 +130,38 @@ public class AnalysisUtils { * @return */ public static String getAverage(AnalysisType analysisType, PluginData source, List uuids) { - try { - if (null != analysisType) { - Number total; - switch (analysisType) { - case LONG_EPOCH_MS_MINUS_NOW_AVG: - final long now = new Date().getTime(); - List longValues = getCorrectValues(uuids, source) - .map(value -> ((long) value) - now) - .collect(Collectors.toList()); - return source.parseContainer(analysisType.getModifier(), FormatUtils.formatTimeAmount(average(longValues) + "")); - case INT_AVG: - OptionalDouble avg = getCorrectValues(uuids, source) - .map(value -> (Integer) value) - .mapToInt(i -> i) - .average(); - if (!avg.isPresent()) { - total = 0; - } else { - total = avg.getAsDouble(); - } - break; - case LONG_AVG: - List longVal = getCorrectValues(uuids, source) - .map(value -> (Long) value) - .collect(Collectors.toList()); - total = average(longVal); - break; - case LONG_TIME_MS_AVG: - List longVal2 = getCorrectValues(uuids, source) - .map(value -> (Long) value) - .collect(Collectors.toList()); - return source.parseContainer(analysisType.getModifier(), FormatUtils.formatTimeAmount(average(longVal2) + "")); - case DOUBLE_AVG: - OptionalDouble average = getCorrectValues(uuids, source) - .mapToDouble(value -> (Double) value) - .average(); - if (!average.isPresent()) { - total = 0; - } else { - total = average.getAsDouble(); - } - break; - default: - return source.parseContainer("", "Wrong Analysistype specified: " + analysisType.name()); - } - return source.parseContainer(analysisType.getModifier(), total + ""); - } - } catch (Throwable e) { - Log.error("A PluginData-source caused an exception: "+source.getPlaceholder("").replace("%", "")); - Log.toLog("com.djrapitops.plan.utilities.AnalysisUtils", e); + if (analysisType == null) { + return source.parseContainer("Err ", "Null Analysistype. "); + } + try { + double average; + switch (analysisType) { + case LONG_EPOCH_MS_MINUS_NOW_AVG: + final long now = MiscUtils.getTime(); + average = MathUtils.averageLong(getCorrectValues(uuids, source).map(value -> ((long) value) - now)); + return source.parseContainer(analysisType.getModifier(), FormatUtils.formatTimeAmount((long) average)); + case LONG_AVG: + long averageLong = MathUtils.averageLong(getCorrectValues(uuids, source).map(i -> (Long) i)); + return source.parseContainer(analysisType.getModifier(), averageLong + ""); + case LONG_TIME_MS_AVG: + average = MathUtils.averageLong(getCorrectValues(uuids, source).map(i -> (Long) i)); + return source.parseContainer(analysisType.getModifier(), FormatUtils.formatTimeAmount((long) average)); + case INT_AVG: + average = MathUtils.averageInt(getCorrectValues(uuids, source).map(i -> (Integer) i)); + break; + case DOUBLE_AVG: + average = MathUtils.averageDouble(getCorrectValues(uuids, source).map(i -> (Double) i)); + break; + default: + return source.parseContainer("Err ", "Wrong Analysistype specified: " + analysisType.name()); + } + return source.parseContainer(analysisType.getModifier(), FormatUtils.cutDecimals(average)); + } catch (Throwable e) { + return logPluginDataCausedError(source, e); } - return source.parseContainer("", "Exception during average calculation."); } - static String getBooleanPercentage(AnalysisType analysisType, PluginData source, List uuids) { + public static String getBooleanPercentage(AnalysisType analysisType, PluginData source, List uuids) { if (analysisType == AnalysisType.BOOLEAN_PERCENTAGE) { try { List tempList = getCorrectValues(uuids, source) @@ -229,15 +170,13 @@ public class AnalysisUtils { long count = tempList.stream().filter(value -> value).count(); return source.parseContainer(analysisType.getModifier(), ((double) (count / tempList.size()) * 100) + "%"); } catch (Throwable e) { - Log.error("A PluginData-source caused an exception: "+source.getPlaceholder("").replace("%", "")); - Log.toLog("com.djrapitops.plan.utilities.AnalysisUtils", e); - return source.parseContainer("", "Exception during calculation."); + return logPluginDataCausedError(source, e); } } - return source.parseContainer("", "Wrong Analysistype specified: " + analysisType.name()); + return source.parseContainer("Err ", "Wrong Analysistype specified: " + analysisType.name()); } - static String getBooleanTotal(AnalysisType analysisType, PluginData source, List uuids) { + public static String getBooleanTotal(AnalysisType analysisType, PluginData source, List uuids) { if (analysisType == AnalysisType.BOOLEAN_TOTAL) { try { List tempList = getCorrectValues(uuids, source) @@ -246,11 +185,16 @@ public class AnalysisUtils { long count = tempList.stream().filter(value -> value).count(); return source.parseContainer(analysisType.getModifier(), count + " / " + tempList.size()); } catch (Throwable e) { - Log.error("A PluginData-source caused an exception: "+source.getPlaceholder("").replace("%", "")); - Log.toLog("com.djrapitops.plan.utilities.AnalysisUtils", e); - return source.parseContainer("", "Exception during calculation."); + return logPluginDataCausedError(source, e); } } - return source.parseContainer("", "Wrong Analysistype specified: " + analysisType.name()); + return source.parseContainer("Err ", "Wrong Analysistype specified: " + analysisType.name()); + } + + private static String logPluginDataCausedError(PluginData source, Throwable e) { + Log.error("A PluginData-source caused an exception: " + source.getPlaceholder("").replace("%", "")); + Log.toLog("A PluginData-source caused an exception: " + source.getPlaceholder("").replace("%", "")); + Log.toLog("com.djrapitops.plan.utilities.AnalysisUtils", e); + return source.parseContainer("", "Exception during calculation."); } } diff --git a/Plan/src/main/java/com/djrapitops/plan/utilities/FormatUtils.java b/Plan/src/main/java/com/djrapitops/plan/utilities/FormatUtils.java index d6bce2e8e..7d8370e80 100644 --- a/Plan/src/main/java/com/djrapitops/plan/utilities/FormatUtils.java +++ b/Plan/src/main/java/com/djrapitops/plan/utilities/FormatUtils.java @@ -2,7 +2,6 @@ package main.java.com.djrapitops.plan.utilities; import java.text.DecimalFormat; import java.util.Date; -import main.java.com.djrapitops.plan.ui.Html; import org.bukkit.Location; /** @@ -11,58 +10,19 @@ import org.bukkit.Location; */ public class FormatUtils { - /** - * Formats a String of long in ms to readable format. - * - * @param string String of a Long in ms - * @return Readable format - * @throws NumberFormatException if String is not long. - */ - public static String formatTimeAmount(String string) throws NumberFormatException { - long ms = Long.parseLong(string); - return turnMsLongToString(ms); + public static String formatTimeAmount(long ms) { + return formatMilliseconds(ms); } - /** - * Formats the difference between the two dates into readable format. - * - * @param before - * @param now - * @return Readable format - * @throws NumberFormatException - */ - public static String formatTimeAmountSinceDate(Date before, Date now) throws NumberFormatException { - long ms = Math.abs((now.toInstant().getEpochSecond() * 1000) - (before.toInstant().getEpochSecond() * 1000)); - return turnMsLongToString(ms); + public static String formatTimeAmountDifference(long before, long after) { + return formatMilliseconds(Math.abs(after - before)); } - /** - * Creates a new Date with Epoch second and returns Date and Time String. - * - * @param string - * @return Readable TimeStamp - * @throws NumberFormatException String is not Long - */ - public static String formatTimeStamp(String string) throws NumberFormatException { - long ms = Long.parseLong(string); - Date sfd = new Date(ms); + public static String formatTimeStamp(long epochMs) { + Date sfd = new Date(epochMs); return ("" + sfd).substring(4, 19); } - /** - * Formats the difference between the two dates, where first is in String of - * Long format, into readable format. - * - * @param string Long in ms, date - * @param now - * @return - * @throws NumberFormatException - */ - public static String formatTimeAmountSinceString(String string, Date now) throws NumberFormatException { - long ms = Math.abs((now.toInstant().getEpochSecond() * 1000) - Long.parseLong(string)); - return turnMsLongToString(ms); - } - /** * Removes letters from a string leaving only numbers and dots. * @@ -72,7 +32,7 @@ public class FormatUtils { public static String removeLetters(String dataPoint) { return dataPoint.replaceAll("[^\\d.]", ""); } - + /** * * @param dataPoint @@ -80,15 +40,15 @@ public class FormatUtils { */ public static String removeNumbers(String dataPoint) { for (char c : removeLetters(dataPoint).toCharArray()) { - dataPoint = dataPoint.replace(c+"", ""); + dataPoint = dataPoint.replace(c + "", ""); } dataPoint = dataPoint.replace(" ", ""); return dataPoint; } // Formats long in milliseconds into d:h:m:s string - private static String turnMsLongToString(long ms) { - String returnValue = ""; + private static String formatMilliseconds(long ms) { + StringBuilder builder = new StringBuilder(); long x = ms / 1000; long seconds = x % 60; x /= 60; @@ -98,21 +58,22 @@ public class FormatUtils { x /= 24; long days = x; if (days != 0) { - returnValue += days + "d "; + builder.append(days).append("d "); } if (hours != 0) { - returnValue += hours + "h "; + builder.append(hours).append("h "); } if (minutes != 0) { - returnValue += minutes + "m "; + builder.append(minutes).append("m "); } if (seconds != 0) { - returnValue += seconds + "s"; + builder.append(seconds).append("s"); } - if (returnValue.isEmpty()) { - returnValue += "0s"; + String formattedTime = builder.toString(); + if (formattedTime.isEmpty()) { + return "0s"; } - return returnValue; + return formattedTime; } /** @@ -165,21 +126,6 @@ public class FormatUtils { return "x " + loc.getBlockX() + " z " + loc.getBlockZ() + " in " + loc.getWorld(); } - static String swapColorsToSpan(String string) { - Html[] replacer = new Html[]{Html.COLOR_0, Html.COLOR_1, Html.COLOR_2, Html.COLOR_3, - Html.COLOR_4, Html.COLOR_5, Html.COLOR_6, Html.COLOR_7, Html.COLOR_8, Html.COLOR_9, - Html.COLOR_a, Html.COLOR_b, Html.COLOR_c, Html.COLOR_d, Html.COLOR_e, Html.COLOR_f}; - - for (Html html : replacer) { - string = string.replaceAll("§" + html.name().charAt(6), html.parse()); - } - int spans = string.split(""); return html.toString(); } + + public static String swapColorsToSpan(String string) { + Html[] replacer = new Html[]{Html.COLOR_0, Html.COLOR_1, Html.COLOR_2, Html.COLOR_3, + Html.COLOR_4, Html.COLOR_5, Html.COLOR_6, Html.COLOR_7, Html.COLOR_8, Html.COLOR_9, + Html.COLOR_a, Html.COLOR_b, Html.COLOR_c, Html.COLOR_d, Html.COLOR_e, Html.COLOR_f}; + + for (Html html : replacer) { + string = string.replaceAll("§" + html.name().charAt(6), html.parse()); + } + int spans = string.split(" onTimeData, Plan plugin) { - DataCacheHandler handler = plugin.getHandler(); - for (UUID uuid : onTimeData.keySet()) { - OfflinePlayer player = getOfflinePlayer(uuid); - if (!plugin.getDB().wasSeenBefore(uuid)) { - - handler.newPlayer(player); - } - DBCallableProcessor importer = new DBCallableProcessor() { - @Override - public void process(UserData data) { - Long playTime = onTimeData.get(uuid); - if (playTime > data.getPlayTime()) { - data.setPlayTime(playTime); - data.setLastGamemode(GameMode.SURVIVAL); - data.setAllGMTimes(playTime, 0, 0, 0); - data.setLastGmSwapTime(playTime); - } - } - }; - handler.getUserDataForProcessing(importer, uuid); - } - handler.saveCachedUserData(); - return true; - } - /** * Get the saved UUIDs in a hashset * @@ -108,20 +67,9 @@ public class ManageUtils { public static boolean clearAndCopy(Database clearAndCopyToDB, Database copyFromDB, Collection fromDBsavedUUIDs) { try { clearAndCopyToDB.removeAllData(); - List allUserData = new ArrayList<>(); - for (UUID uuid : fromDBsavedUUIDs) { - copyFromDB.giveUserDataToProcessors(uuid, new DBCallableProcessor() { - @Override - public void process(UserData data) { - allUserData.add(data); - } - }); - } - while (fromDBsavedUUIDs.size() > allUserData.size()) { - - } + List allUserData = copyFromDB.getUserDataForUUIDS(copyFromDB.getSavedUUIDs()); clearAndCopyToDB.saveMultipleUserData(allUserData); - clearAndCopyToDB.saveCommandUse(copyFromDB.getCommandUse()); + clearAndCopyToDB.getCommandUseTable().saveCommandUse(copyFromDB.getCommandUseTable().getCommandUse()); } catch (SQLException | NullPointerException e) { Log.toLog("ManageUtils.move", e); return false; diff --git a/Plan/src/main/java/com/djrapitops/plan/utilities/MathUtils.java b/Plan/src/main/java/com/djrapitops/plan/utilities/MathUtils.java new file mode 100644 index 000000000..0f545ab9d --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/utilities/MathUtils.java @@ -0,0 +1,89 @@ +package main.java.com.djrapitops.plan.utilities; + +import java.io.Serializable; +import java.util.Collection; +import java.util.OptionalDouble; +import java.util.stream.Stream; + +/** + * + * @author Rsl1122 + */ +public class MathUtils { + + public static double averageInt(Stream values) { + OptionalDouble average = values.mapToInt(i -> i).average(); + if (average.isPresent()) { + return average.getAsDouble(); + } else { + return 0; + } + } + + public static long averageLong(Collection values) { + return averageLong(values.stream()); + } + + public static long averageLong(Stream values) { + OptionalDouble average = values.mapToLong(i -> i).average(); + if (average.isPresent()) { + return (long) average.getAsDouble(); + } else { + return 0L; + } + } + + public static double averageDouble(Stream values) { + OptionalDouble average = values.mapToDouble(i -> i).average(); + if (average.isPresent()) { + return average.getAsDouble(); + } else { + return 0; + } + } + + public static double average(int total, int size) { + return 1.0 * total / size; + } + + public static long countTrueBoolean(Stream values) { + return values.filter(i -> i).count(); + } + + public static int sumInt(Stream values) { + return values + .mapToInt(value -> (Integer) value) + .sum(); + } + + public static long sumLong(Stream values) { + return values + .mapToLong(value -> (Long) value) + .sum(); + } + + public static double sumDouble(Stream values) { + return values + .mapToDouble(value -> (Double) value) + .sum(); + } + + public static int getBiggest(Collection values) { + int biggest = 1; + for (Integer value : values) { + if (value > biggest) { + biggest = value; + } + } + return biggest; + } + public static long getBiggestLong(Collection values) { + long biggest = 1; + for (Long value : values) { + if (value > biggest) { + biggest = value; + } + } + return biggest; + } +} diff --git a/Plan/src/main/java/com/djrapitops/plan/utilities/MiscUtils.java b/Plan/src/main/java/com/djrapitops/plan/utilities/MiscUtils.java index 3da11cdec..9ac9d5e7b 100644 --- a/Plan/src/main/java/com/djrapitops/plan/utilities/MiscUtils.java +++ b/Plan/src/main/java/com/djrapitops/plan/utilities/MiscUtils.java @@ -4,10 +4,13 @@ import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; +import java.util.Date; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Scanner; import java.util.Set; +import java.util.stream.Collectors; import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.Permissions; import main.java.com.djrapitops.plan.Phrase; @@ -23,6 +26,10 @@ import org.bukkit.entity.Player; */ public class MiscUtils { + public static long getTime() { + return new Date().getTime(); + } + /** * Checks the version and returns response String. * @@ -80,7 +87,7 @@ public class MiscUtils { public static String getPlayerName(String[] args, CommandSender sender) { return getPlayerName(args, sender, Permissions.INSPECT_OTHER); } - + /** * Used by the inspect command. * diff --git a/Plan/src/main/java/com/djrapitops/plan/utilities/NewPlayerCreator.java b/Plan/src/main/java/com/djrapitops/plan/utilities/NewPlayerCreator.java index 7d21ff725..a117104de 100644 --- a/Plan/src/main/java/com/djrapitops/plan/utilities/NewPlayerCreator.java +++ b/Plan/src/main/java/com/djrapitops/plan/utilities/NewPlayerCreator.java @@ -1,6 +1,5 @@ package main.java.com.djrapitops.plan.utilities; -import java.util.Date; import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.data.DemographicsData; import main.java.com.djrapitops.plan.data.UserData; @@ -44,7 +43,7 @@ public class NewPlayerCreator { public static UserData createNewPlayer(OfflinePlayer player, GameMode gm) { UserData data = new UserData(player, new DemographicsData()); data.setLastGamemode(gm); - data.setLastPlayed(new Date().getTime()); + data.setLastPlayed(MiscUtils.getTime()); long zero = Long.parseLong("0"); data.setPlayTime(zero); data.setTimesKicked(0); diff --git a/Plan/src/main/java/com/djrapitops/plan/utilities/PlaceholderUtils.java b/Plan/src/main/java/com/djrapitops/plan/utilities/PlaceholderUtils.java index 640ed2423..a35be21c8 100644 --- a/Plan/src/main/java/com/djrapitops/plan/utilities/PlaceholderUtils.java +++ b/Plan/src/main/java/com/djrapitops/plan/utilities/PlaceholderUtils.java @@ -2,7 +2,6 @@ package main.java.com.djrapitops.plan.utilities; import java.io.FileNotFoundException; import java.util.Arrays; -import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.UUID; @@ -13,6 +12,8 @@ import main.java.com.djrapitops.plan.data.AnalysisData; import main.java.com.djrapitops.plan.data.UserData; import main.java.com.djrapitops.plan.ui.Html; import main.java.com.djrapitops.plan.ui.graphs.PlayerActivityGraphCreator; +import main.java.com.djrapitops.plan.ui.graphs.PunchCardGraphCreator; +import main.java.com.djrapitops.plan.ui.graphs.SessionLengthDistributionGraphCreator; import main.java.com.djrapitops.plan.ui.tables.SortableKillsTableCreator; import main.java.com.djrapitops.plan.ui.tables.SortableSessionTableCreator; import org.bukkit.GameMode; @@ -46,10 +47,10 @@ public class PlaceholderUtils { replaceMap.put("%commanduse%", HtmlUtils.removeXSS(data.getCommandUseListHtml())); replaceMap.put("%totalcommands%", data.getTotalCommands() + ""); replaceMap.put("%avgage%", (data.getAverageAge() != -1) ? "" + data.getAverageAge() : Phrase.DEM_UNKNOWN + ""); - replaceMap.put("%avgplaytime%", FormatUtils.formatTimeAmount("" + data.getAveragePlayTime())); - replaceMap.put("%totalplaytime%", FormatUtils.formatTimeAmount("" + data.getTotalPlayTime())); + replaceMap.put("%avgplaytime%", FormatUtils.formatTimeAmount(data.getAveragePlayTime())); + replaceMap.put("%totalplaytime%", FormatUtils.formatTimeAmount(data.getTotalPlayTime())); replaceMap.put("%ops%", "" + data.getOps()); - replaceMap.put("%refresh%", FormatUtils.formatTimeAmountSinceString("" + data.getRefreshDate(), new Date())); + replaceMap.put("%refresh%", FormatUtils.formatTimeAmountDifference(data.getRefreshDate(), MiscUtils.getTime())); replaceMap.put("%totallogins%", "" + data.getTotalLoginTimes()); replaceMap.put("%top20mostactive%", Html.ERROR_NOT_SET.parse()); replaceMap.put("%recentlogins%", data.getRecentPlayers()); @@ -105,10 +106,17 @@ public class PlaceholderUtils { + "\",\"#" + Settings.HCOLOR_GENP_U + "\""); replaceMap.put("%genderfcolor%", "#" + Settings.HCOLOR_GENP_F); replaceMap.put("%gendermcolor%", "#" + Settings.HCOLOR_GENP_M); - replaceMap.put("%sessionaverage%", FormatUtils.formatTimeAmount(data.getSessionAverage() + "")); + replaceMap.put("%sessionaverage%", FormatUtils.formatTimeAmount(data.getSessionAverage())); replaceMap.put("%geomapcountries%", data.getGeomapCountries()); replaceMap.put("%geomapz%", data.getGeomapZ()); replaceMap.put("%geomapcodes%", data.getGeomapCodes()); + replaceMap.put("%datapunchcard%", data.getPunchCardData()); + String[] distribution = data.getSessionDistributionData(); + replaceMap.put("%datasessiondistribution%", distribution[0]); + replaceMap.put("%labelssessiondistribution%", distribution[1]); + distribution = data.getPlaytimeDistributionData(); + replaceMap.put("%dataplaydistribution%", distribution[0]); + replaceMap.put("%labelsplaydistribution%", distribution[1]); String pluginsTabHtml = plugin.getHookHandler().getPluginsTabLayoutForAnalysis(); String replacedOnce = HtmlUtils.replacePlaceholders(pluginsTabHtml, data.getAdditionalDataReplaceMap()); replaceMap.put("%plugins%", HtmlUtils.replacePlaceholders(replacedOnce, data.getAdditionalDataReplaceMap())); @@ -116,7 +124,7 @@ public class PlaceholderUtils { String[] defaultCols = new String[]{"348e0f", "267F00", "5cb239", "89c471", "5da341"}; for (int i = 0; i < colors.length; i++) { if (!defaultCols[i].equals(colors[i])) { - replaceMap.put("#"+defaultCols[i], "#"+colors[i]); + replaceMap.put("#" + defaultCols[i], "#" + colors[i]); } } return replaceMap; @@ -134,10 +142,11 @@ public class PlaceholderUtils { boolean showIPandUUID = Settings.SECURITY_IP_UUID.isTrue(); UUID uuid = data.getUuid(); replaceMap.put("%uuid%", (showIPandUUID ? "" + uuid : Html.HIDDEN.parse())); - replaceMap.put("%lastseen%", FormatUtils.formatTimeStamp("" + data.getLastPlayed())); + replaceMap.put("%lastseen%", FormatUtils.formatTimeStamp(data.getLastPlayed())); replaceMap.put("%logintimes%", "" + data.getLoginTimes()); replaceMap.put("%geoloc%", data.getDemData().getGeoLocation()); - boolean isActive = AnalysisUtils.isActive(data.getLastPlayed(), data.getPlayTime(), data.getLoginTimes()); + long now = MiscUtils.getTime(); + boolean isActive = AnalysisUtils.isActive(now, data.getLastPlayed(), data.getPlayTime(), data.getLoginTimes()); replaceMap.put("%active%", isActive ? Html.ACTIVE.parse() : Html.INACTIVE.parse()); int age = data.getDemData().getAge(); replaceMap.put("%age%", (age != -1) ? "" + age : Phrase.DEM_UNKNOWN + ""); @@ -160,21 +169,21 @@ public class PlaceholderUtils { gmThree }; long total = gmData[0] + gmData[1] + gmData[2] + gmData[3]; - replaceMap.put("%gm0%", FormatUtils.formatTimeAmount("" + gmData[0])); - replaceMap.put("%gm1%", FormatUtils.formatTimeAmount("" + gmData[1])); - replaceMap.put("%gm2%", FormatUtils.formatTimeAmount("" + gmData[2])); - replaceMap.put("%gm3%", FormatUtils.formatTimeAmount("" + gmData[3])); + replaceMap.put("%gm0%", FormatUtils.formatTimeAmount(gmData[0])); + replaceMap.put("%gm1%", FormatUtils.formatTimeAmount(gmData[1])); + replaceMap.put("%gm2%", FormatUtils.formatTimeAmount(gmData[2])); + replaceMap.put("%gm3%", FormatUtils.formatTimeAmount(gmData[3])); replaceMap.put("%gmdata%", Arrays.toString(gmData)); replaceMap.put("%gmlabels%", "[\"Survival\", \"Creative\", \"Adventure\", \"Spectator\"]"); replaceMap.put("%gmcolors%", "\"#" + Settings.HCOLOR_GMP_0 + "\",\"#" + Settings.HCOLOR_GMP_1 + "\",\"#" + Settings.HCOLOR_GMP_2 + "\",\"#" + Settings.HCOLOR_GMP_3 + "\""); - replaceMap.put("%gmtotal%", FormatUtils.formatTimeAmount("" + total)); + replaceMap.put("%gmtotal%", FormatUtils.formatTimeAmount(total)); replaceMap.put("%ips%", (showIPandUUID ? data.getIps().toString() : Html.HIDDEN.parse())); - replaceMap.put("%nicknames%", HtmlUtils.removeXSS(FormatUtils.swapColorsToSpan(data.getNicknames().toString()))); + replaceMap.put("%nicknames%", HtmlUtils.removeXSS(HtmlUtils.swapColorsToSpan(data.getNicknames().toString()))); replaceMap.put("%name%", data.getName()); - replaceMap.put("%registered%", FormatUtils.formatTimeStamp("" + data.getRegistered())); + replaceMap.put("%registered%", FormatUtils.formatTimeStamp(data.getRegistered())); replaceMap.put("%timeskicked%", "" + data.getTimesKicked()); - replaceMap.put("%playtime%", FormatUtils.formatTimeAmount("" + data.getPlayTime())); + replaceMap.put("%playtime%", FormatUtils.formatTimeAmount(data.getPlayTime())); replaceMap.put("%banned%", data.isBanned() ? Html.BANNED.parse() : ""); replaceMap.put("%op%", data.isOp() ? Html.OPERATOR.parse() : ""); replaceMap.put("%isonline%", (data.isOnline()) ? Html.ONLINE.parse() : Html.OFFLINE.parse()); @@ -183,7 +192,7 @@ public class PlaceholderUtils { replaceMap.put("%playerkills%", data.getPlayerKills().size() + ""); replaceMap.put("%mobkills%", data.getMobKills() + ""); replaceMap.put("%sessionstable%", SortableSessionTableCreator.createSortedSessionDataTable10(data.getSessions())); - replaceMap.put("%sessionaverage%", FormatUtils.formatTimeAmount(AnalysisUtils.average(AnalysisUtils.transformSessionDataToLengths(data.getSessions())) + "")); + replaceMap.put("%sessionaverage%", FormatUtils.formatTimeAmount(MathUtils.averageLong(AnalysisUtils.transformSessionDataToLengths(data.getSessions())))); replaceMap.put("%killstable%", SortableKillsTableCreator.createSortedSessionDataTable10(data.getPlayerKills())); Plan plugin = Plan.getInstance(); replaceMap.put("%version%", plugin.getDescription().getVersion()); @@ -197,7 +206,11 @@ public class PlaceholderUtils { replaceMap.put("%gm1col%", Settings.HCOLOR_GMP_1 + ""); replaceMap.put("%gm2col%", Settings.HCOLOR_GMP_2 + ""); replaceMap.put("%gm3col%", Settings.HCOLOR_GMP_3 + ""); - replaceMap.put("%inaccuratedatawarning%", (new Date().getTime() - data.getRegistered() < 180000) ? Html.WARN_INACCURATE.parse() : ""); + replaceMap.put("%datapunchcard%", PunchCardGraphCreator.generateDataArray(data.getSessions())); + String[] distribution = SessionLengthDistributionGraphCreator.generateDataArraySessions(data.getSessions()); + replaceMap.put("%datasessiondistribution%", distribution[0]); + replaceMap.put("%labelssessiondistribution%", distribution[1]); + replaceMap.put("%inaccuratedatawarning%", (now - data.getRegistered() < 180000) ? Html.WARN_INACCURATE.parse() : ""); String pluginsTabHtml = plugin.getHookHandler().getPluginsTabLayoutForInspect(); Map additionalReplaceRules = plugin.getHookHandler().getAdditionalInspectReplaceRules(uuid); String replacedOnce = HtmlUtils.replacePlaceholders(pluginsTabHtml, additionalReplaceRules); diff --git a/Plan/src/main/resources/plugin.yml b/Plan/src/main/resources/plugin.yml index 14255c916..fc049e7a0 100644 --- a/Plan/src/main/resources/plugin.yml +++ b/Plan/src/main/resources/plugin.yml @@ -1,7 +1,7 @@ name: Plan author: Rsl1122 main: main.java.com.djrapitops.plan.Plan -version: 3.1.0 +version: 3.2.0 softdepend: - OnTime diff --git a/Plan/src/test/java/main/java/com/djrapitops/plan/PermissionsTest.java b/Plan/src/test/java/main/java/com/djrapitops/plan/PermissionsTest.java new file mode 100644 index 000000000..6e4eba1a1 --- /dev/null +++ b/Plan/src/test/java/main/java/com/djrapitops/plan/PermissionsTest.java @@ -0,0 +1,34 @@ +/* + * 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 test.java.main.java.com.djrapitops.plan; + +import main.java.com.djrapitops.plan.Permissions; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import static org.junit.Assert.*; +import test.java.utils.MockUtils; + +/** + * + * @author Risto + */ +public class PermissionsTest { + + public PermissionsTest() { + } + + @Test + public void testUserHasThisPermission() { + assertTrue(Permissions.INSPECT_OTHER.userHasThisPermission(MockUtils.mockPlayer())); + } + + @Test + public void testGetPermission() { + assertEquals("plan.inspect.other", Permissions.INSPECT_OTHER.getPermission()); + } + +} diff --git a/Plan/src/test/java/main/java/com/djrapitops/plan/PhraseTest.java b/Plan/src/test/java/main/java/com/djrapitops/plan/PhraseTest.java index 16732f91c..4d5461426 100644 --- a/Plan/src/test/java/main/java/com/djrapitops/plan/PhraseTest.java +++ b/Plan/src/test/java/main/java/com/djrapitops/plan/PhraseTest.java @@ -1,12 +1,6 @@ -/* - * 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 test.java.main.java.com.djrapitops.plan; import main.java.com.djrapitops.plan.Phrase; -import main.java.com.djrapitops.plan.Plan; import org.bukkit.ChatColor; import org.bukkit.plugin.java.JavaPlugin; import static org.junit.Assert.*; @@ -24,15 +18,13 @@ import test.java.utils.TestInit; @RunWith(PowerMockRunner.class) @PrepareForTest(JavaPlugin.class) public class PhraseTest { - - private Plan plan; - + /** * */ public PhraseTest() { } - + /** * */ @@ -40,17 +32,16 @@ public class PhraseTest { public void setUp() { TestInit t = new TestInit(); assertTrue("Not set up", t.setUp()); - plan = t.getPlanMock(); } - + /** * */ @Test - public void testToString() { + public void testToString() { Phrase instance = Phrase.REPLACE0; String expResult = "REPLACE0"; - instance.setText(expResult); + instance.setText(expResult); String result = instance.toString(); assertEquals(expResult, result); } diff --git a/Plan/src/test/java/main/java/com/djrapitops/plan/SettingsTest.java b/Plan/src/test/java/main/java/com/djrapitops/plan/SettingsTest.java index 132031a3f..d978e9268 100644 --- a/Plan/src/test/java/main/java/com/djrapitops/plan/SettingsTest.java +++ b/Plan/src/test/java/main/java/com/djrapitops/plan/SettingsTest.java @@ -5,6 +5,8 @@ */ package test.java.main.java.com.djrapitops.plan; +import java.util.ArrayList; +import java.util.List; import main.java.com.djrapitops.plan.Settings; import org.bukkit.plugin.java.JavaPlugin; import static org.junit.Assert.*; @@ -51,7 +53,7 @@ public class SettingsTest { */ @Test public void testToString() { - assertEquals("sqlite",Settings.DB_TYPE.toString()); + assertEquals("sqlite", Settings.DB_TYPE.toString()); } /** @@ -59,9 +61,17 @@ public class SettingsTest { */ @Test public void testGetNumber() { - assertEquals(8804,Settings.WEBSERVER_PORT.getNumber()); + assertEquals(8804, Settings.WEBSERVER_PORT.getNumber()); } + @Test + public void testGetStringList() { + List exp = new ArrayList<>(); + exp.add("ExampleTown"); + List result = Settings.HIDE_TOWNS.getStringList(); + assertEquals(exp, result); + } + /** * */ diff --git a/Plan/src/test/java/main/java/com/djrapitops/plan/api/GenderTest.java b/Plan/src/test/java/main/java/com/djrapitops/plan/api/GenderTest.java index 64b1a0de1..92f383cfd 100644 --- a/Plan/src/test/java/main/java/com/djrapitops/plan/api/GenderTest.java +++ b/Plan/src/test/java/main/java/com/djrapitops/plan/api/GenderTest.java @@ -1,8 +1,3 @@ -/* - * 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 test.java.main.java.com.djrapitops.plan.api; import main.java.com.djrapitops.plan.api.Gender; diff --git a/Plan/src/test/java/main/java/com/djrapitops/plan/data/additional/AnalysisTypeTest.java b/Plan/src/test/java/main/java/com/djrapitops/plan/data/additional/AnalysisTypeTest.java new file mode 100644 index 000000000..f9c458901 --- /dev/null +++ b/Plan/src/test/java/main/java/com/djrapitops/plan/data/additional/AnalysisTypeTest.java @@ -0,0 +1,31 @@ +/* + * 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 test.java.main.java.com.djrapitops.plan.data.additional; + +import main.java.com.djrapitops.plan.data.additional.AnalysisType; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + * @author Risto + */ +public class AnalysisTypeTest { + + public AnalysisTypeTest() { + } + + @Test + public void testGetModifier() { + assertEquals("Average ", AnalysisType.INT_AVG.getModifier()); + } + + @Test + public void testGetPlaceholderModifier() { + assertEquals("totalInt_", AnalysisType.INT_TOTAL.getPlaceholderModifier()); + } + +} diff --git a/Plan/src/test/java/main/java/com/djrapitops/plan/data/cache/DataCacheHandlerTest.java b/Plan/src/test/java/main/java/com/djrapitops/plan/data/cache/DataCacheHandlerTest.java index 0795b6b8c..4898eb390 100644 --- a/Plan/src/test/java/main/java/com/djrapitops/plan/data/cache/DataCacheHandlerTest.java +++ b/Plan/src/test/java/main/java/com/djrapitops/plan/data/cache/DataCacheHandlerTest.java @@ -7,9 +7,9 @@ package test.java.main.java.com.djrapitops.plan.data.cache; import java.sql.SQLException; import java.util.Collection; -import java.util.Date; import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.UUID; import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.data.DemographicsData; @@ -18,6 +18,7 @@ import main.java.com.djrapitops.plan.data.cache.DBCallableProcessor; import main.java.com.djrapitops.plan.data.cache.DataCacheHandler; import main.java.com.djrapitops.plan.database.Database; import main.java.com.djrapitops.plan.database.databases.SQLiteDB; +import main.java.com.djrapitops.plan.utilities.MiscUtils; import org.bukkit.OfflinePlayer; import org.bukkit.plugin.java.JavaPlugin; import org.junit.After; @@ -64,7 +65,7 @@ public class DataCacheHandlerTest { plan = t.getPlanMock(); calledSaveCommandUse = false; calledSaveUserData = false; - db = new SQLiteDB(plan, "debug" + new Date().getTime()) { + db = new SQLiteDB(plan, "debug" + MiscUtils.getTime()) { @Override public void startConnectionPingTask(Plan plugin) { @@ -93,17 +94,17 @@ public class DataCacheHandlerTest { } @Override - public void saveCommandUse(HashMap c) { + public void saveCommandUse(Map c) { calledSaveCommandUse = true; } @Override - public void saveUserData(UUID uuid, UserData data) throws SQLException { + public void saveUserData(UserData data) throws SQLException { calledSaveUserData = true; } @Override - public void saveMultipleUserData(List data) throws SQLException { + public void saveMultipleUserData(Collection data) throws SQLException { calledSaveMultiple = true; } }; @@ -133,7 +134,7 @@ public class DataCacheHandlerTest { public void testGetUserDataForProcessingCache() throws SQLException, InterruptedException { // db.init(); UserData data = new UserData(MockUtils.mockPlayer(), new DemographicsData()); - db.saveUserData(data.getUuid(), data); + db.saveUserData(data); handler.getUserDataForProcessing(new DBCallableProcessor() { @Override public void process(UserData d) { @@ -154,7 +155,7 @@ public class DataCacheHandlerTest { @Test public void testGetUserDataForProcessingDontCache() throws SQLException, InterruptedException { UserData data = new UserData(MockUtils.mockPlayer(), new DemographicsData()); - db.saveUserData(data.getUuid(), data); + db.saveUserData(data); handler.getUserDataForProcessing(new DBCallableProcessor() { @Override public void process(UserData d) { diff --git a/Plan/src/test/java/main/java/com/djrapitops/plan/data/cache/queue/DataCacheClearQueueTest.java b/Plan/src/test/java/main/java/com/djrapitops/plan/data/cache/queue/DataCacheClearQueueTest.java index 1b27523d2..e207f1170 100644 --- a/Plan/src/test/java/main/java/com/djrapitops/plan/data/cache/queue/DataCacheClearQueueTest.java +++ b/Plan/src/test/java/main/java/com/djrapitops/plan/data/cache/queue/DataCacheClearQueueTest.java @@ -11,6 +11,7 @@ import org.bukkit.plugin.java.JavaPlugin; import org.junit.After; import static org.junit.Assert.assertTrue; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.core.classloader.annotations.PrepareForTest; @@ -68,6 +69,7 @@ public class DataCacheClearQueueTest { /** * */ + @Ignore @Test public void testScheduleForClear_UUID() { } @@ -75,6 +77,7 @@ public class DataCacheClearQueueTest { /** * */ + @Ignore @Test public void testScheduleForClear_Collection() { } @@ -82,6 +85,7 @@ public class DataCacheClearQueueTest { /** * */ + @Ignore @Test public void testStop() { } diff --git a/Plan/src/test/java/main/java/com/djrapitops/plan/data/cache/queue/DataCacheGetQueueTest.java b/Plan/src/test/java/main/java/com/djrapitops/plan/data/cache/queue/DataCacheGetQueueTest.java index 5518f0e2d..b23589c94 100644 --- a/Plan/src/test/java/main/java/com/djrapitops/plan/data/cache/queue/DataCacheGetQueueTest.java +++ b/Plan/src/test/java/main/java/com/djrapitops/plan/data/cache/queue/DataCacheGetQueueTest.java @@ -10,7 +10,6 @@ import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files; import java.sql.SQLException; -import java.util.Date; import java.util.UUID; import java.util.stream.Collectors; import main.java.com.djrapitops.plan.Plan; @@ -20,6 +19,7 @@ import main.java.com.djrapitops.plan.data.cache.DBCallableProcessor; import main.java.com.djrapitops.plan.data.cache.queue.DataCacheGetQueue; import main.java.com.djrapitops.plan.database.Database; import main.java.com.djrapitops.plan.database.databases.SQLiteDB; +import main.java.com.djrapitops.plan.utilities.MiscUtils; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.plugin.java.JavaPlugin; @@ -61,7 +61,7 @@ public class DataCacheGetQueueTest { TestInit t = new TestInit(); assertTrue("Not set up", t.setUp()); plan = t.getPlanMock(); - db = new SQLiteDB(plan, "debug" + new Date().getTime()) { + db = new SQLiteDB(plan, "debug" + MiscUtils.getTime()) { @Override public void startConnectionPingTask(Plan plugin) { diff --git a/Plan/src/test/java/main/java/com/djrapitops/plan/data/cache/queue/DataCacheProcessQueueTest.java b/Plan/src/test/java/main/java/com/djrapitops/plan/data/cache/queue/DataCacheProcessQueueTest.java index 8f72f0f49..04a4b5ff6 100644 --- a/Plan/src/test/java/main/java/com/djrapitops/plan/data/cache/queue/DataCacheProcessQueueTest.java +++ b/Plan/src/test/java/main/java/com/djrapitops/plan/data/cache/queue/DataCacheProcessQueueTest.java @@ -21,6 +21,7 @@ import org.bukkit.plugin.java.JavaPlugin; import org.junit.After; import static org.junit.Assert.*; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.core.classloader.annotations.PrepareForTest; @@ -104,7 +105,7 @@ public class DataCacheProcessQueueTest { }); Thread.sleep(1000); assertTrue(q.stop().isEmpty()); - + } /** @@ -135,6 +136,7 @@ public class DataCacheProcessQueueTest { * * @throws InterruptedException */ + @Ignore("Inconsistant") @Test public void testContainsUUID() throws InterruptedException { DataCacheProcessQueue q = new DataCacheProcessQueue(handler); diff --git a/Plan/src/test/java/main/java/com/djrapitops/plan/data/cache/queue/DataCacheSaveQueueTest.java b/Plan/src/test/java/main/java/com/djrapitops/plan/data/cache/queue/DataCacheSaveQueueTest.java index 41d51e63b..11f564c0f 100644 --- a/Plan/src/test/java/main/java/com/djrapitops/plan/data/cache/queue/DataCacheSaveQueueTest.java +++ b/Plan/src/test/java/main/java/com/djrapitops/plan/data/cache/queue/DataCacheSaveQueueTest.java @@ -6,12 +6,12 @@ package test.java.main.java.com.djrapitops.plan.data.cache.queue; import java.sql.SQLException; -import java.util.Date; import java.util.UUID; import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.data.UserData; import main.java.com.djrapitops.plan.database.Database; import main.java.com.djrapitops.plan.database.databases.SQLiteDB; +import main.java.com.djrapitops.plan.utilities.MiscUtils; import org.bukkit.plugin.java.JavaPlugin; import org.junit.After; import static org.junit.Assert.*; @@ -53,7 +53,7 @@ public class DataCacheSaveQueueTest { plan = t.getPlanMock(); calledSaveUserData = false; calledSaveUserData2 = false; - db = new SQLiteDB(plan, "debug" + new Date().getTime()) { + db = new SQLiteDB(plan, "debug" + MiscUtils.getTime()) { @Override public void startConnectionPingTask(Plan plugin) { diff --git a/Plan/src/test/java/main/java/com/djrapitops/plan/data/handling/KillHandlingTest.java b/Plan/src/test/java/main/java/com/djrapitops/plan/data/handling/KillHandlingTest.java index 26c27c3e0..026964211 100644 --- a/Plan/src/test/java/main/java/com/djrapitops/plan/data/handling/KillHandlingTest.java +++ b/Plan/src/test/java/main/java/com/djrapitops/plan/data/handling/KillHandlingTest.java @@ -7,7 +7,6 @@ package test.java.main.java.com.djrapitops.plan.data.handling; import java.io.IOException; import java.sql.SQLException; -import java.util.Date; import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.data.DemographicsData; import main.java.com.djrapitops.plan.data.KillData; @@ -15,6 +14,7 @@ import main.java.com.djrapitops.plan.data.UserData; import main.java.com.djrapitops.plan.data.handling.KillHandling; import main.java.com.djrapitops.plan.database.Database; import main.java.com.djrapitops.plan.database.databases.SQLiteDB; +import main.java.com.djrapitops.plan.utilities.MiscUtils; import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import org.junit.After; @@ -55,7 +55,7 @@ public class KillHandlingTest { TestInit t = new TestInit(); assertTrue("Not set up", t.setUp()); plan = t.getPlanMock(); - db = new SQLiteDB(plan, "debug" + new Date().getTime()) { + db = new SQLiteDB(plan, "debug" + MiscUtils.getTime()) { @Override public void startConnectionPingTask(Plan plugin) { diff --git a/Plan/src/test/java/main/java/com/djrapitops/plan/data/handling/info/KillInfoTest.java b/Plan/src/test/java/main/java/com/djrapitops/plan/data/handling/info/KillInfoTest.java index d52829aa2..759edf968 100644 --- a/Plan/src/test/java/main/java/com/djrapitops/plan/data/handling/info/KillInfoTest.java +++ b/Plan/src/test/java/main/java/com/djrapitops/plan/data/handling/info/KillInfoTest.java @@ -6,7 +6,6 @@ package test.java.main.java.com.djrapitops.plan.data.handling.info; import java.sql.SQLException; -import java.util.Date; import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.data.DemographicsData; import main.java.com.djrapitops.plan.data.KillData; @@ -14,6 +13,7 @@ import main.java.com.djrapitops.plan.data.UserData; import main.java.com.djrapitops.plan.data.handling.info.KillInfo; import main.java.com.djrapitops.plan.database.Database; import main.java.com.djrapitops.plan.database.databases.SQLiteDB; +import main.java.com.djrapitops.plan.utilities.MiscUtils; import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import org.junit.After; @@ -51,7 +51,7 @@ public class KillInfoTest { TestInit t = new TestInit(); assertTrue("Not set up", t.setUp()); Plan plan = t.getPlanMock(); - db = new SQLiteDB(plan, "debug" + new Date().getTime()) { + db = new SQLiteDB(plan, "debug" + MiscUtils.getTime()) { @Override public void startConnectionPingTask(Plan plugin) { diff --git a/Plan/src/test/java/main/java/com/djrapitops/plan/database/DatabaseTest.java b/Plan/src/test/java/main/java/com/djrapitops/plan/database/DatabaseTest.java index 205c4fb78..3f721c5a7 100644 --- a/Plan/src/test/java/main/java/com/djrapitops/plan/database/DatabaseTest.java +++ b/Plan/src/test/java/main/java/com/djrapitops/plan/database/DatabaseTest.java @@ -7,24 +7,30 @@ package test.java.main.java.com.djrapitops.plan.database; import java.io.File; import java.io.IOException; +import java.net.InetAddress; +import java.net.UnknownHostException; import java.nio.charset.Charset; import java.nio.file.Files; import java.sql.SQLException; import java.util.ArrayList; -import java.util.Date; +import java.util.Arrays; import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.stream.Collectors; import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.data.DemographicsData; +import main.java.com.djrapitops.plan.data.KillData; +import main.java.com.djrapitops.plan.data.SessionData; import main.java.com.djrapitops.plan.data.UserData; import main.java.com.djrapitops.plan.data.cache.DBCallableProcessor; import main.java.com.djrapitops.plan.database.Database; import main.java.com.djrapitops.plan.database.databases.MySQLDB; import main.java.com.djrapitops.plan.database.databases.SQLiteDB; import main.java.com.djrapitops.plan.utilities.ManageUtils; +import main.java.com.djrapitops.plan.utilities.MiscUtils; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.plugin.java.JavaPlugin; @@ -71,12 +77,12 @@ public class DatabaseTest { TestInit t = new TestInit(); assertTrue("Not set up", t.setUp()); plan = t.getPlanMock(); - db = new SQLiteDB(plan, "debug" + new Date().getTime()) { + db = new SQLiteDB(plan, "debug" + MiscUtils.getTime()) { @Override public void startConnectionPingTask(Plan plugin) { } - }; + }; File f = new File(plan.getDataFolder(), "Errors.txt"); rows = 0; if (f.exists()) { @@ -183,7 +189,7 @@ public class DatabaseTest { public void testRemoveAll() throws SQLException { db.init(); UserData data = new UserData(MockUtils.mockPlayer(), new DemographicsData()); - db.saveUserData(data.getUuid(), data); + db.saveUserData(data); HashMap c = new HashMap<>(); c.put("/plan", 1); c.put("/tp", 4); @@ -192,7 +198,7 @@ public class DatabaseTest { c.put("/roiergbnougbierubieugbeigubeigubgierbgeugeg", 3); db.saveCommandUse(c); assertTrue(db.removeAllData()); - assertTrue("Contains the user", db.getUserId(data.getUuid().toString()) == -1); + assertTrue("Contains the user", db.getUserDataForUUIDS(Arrays.asList(new UUID[]{MockUtils.getPlayerUUID(), MockUtils.getPlayer2UUID()})).isEmpty()); assertTrue("Contains commandUse", db.getCommandUse().isEmpty()); } @@ -210,11 +216,12 @@ public class DatabaseTest { c.put("/help", 21); c.put("/roiergbnougbierubieugbeigubeigubgierbgeugeg", 3); db.saveCommandUse(c); - assertTrue("Doesn't contain /plan", db.getCommandUse().containsKey("/plan")); - assertTrue("Doesn't contain /tp", db.getCommandUse().containsKey("/tp")); - assertTrue("Doesn't contain /pla", db.getCommandUse().containsKey("/pla")); - assertTrue("Doesn't contain /help", db.getCommandUse().containsKey("/help")); - assertTrue("Contains too long cmd", !db.getCommandUse().containsKey("/roiergbnougbierubieugbeigubeigubgierbgeugeg")); + Map commandUse = db.getCommandUse(); + assertTrue("Doesn't contain /plan", commandUse.containsKey("/plan")); + assertTrue("Doesn't contain /tp", commandUse.containsKey("/tp")); + assertTrue("Doesn't contain /pla", commandUse.containsKey("/pla")); + assertTrue("Doesn't contain /help", commandUse.containsKey("/help")); + assertTrue("Contains too long cmd", !commandUse.containsKey("/roiergbnougbierubieugbeigubeigubgierbgeugeg")); } /** @@ -225,9 +232,9 @@ public class DatabaseTest { public void testSaveUserData() throws SQLException { db.init(); UserData data = new UserData(MockUtils.mockPlayer(), new DemographicsData()); - db.saveUserData(data.getUuid(), data); + db.saveUserData(data); data.addNickname("TestUpdateForSave"); - db.saveUserData(data.getUuid(), data); + db.saveUserData(data); DBCallableProcessor process = new DBCallableProcessor() { @Override public void process(UserData d) { @@ -246,30 +253,48 @@ public class DatabaseTest { db.init(); UserData data = new UserData(MockUtils.mockPlayer(), new DemographicsData()); UserData data2 = new UserData(MockUtils.mockPlayer2(), new DemographicsData()); - db.saveUserData(data2.getUuid(), data2); + db.saveUserData(data2); data.addNickname("s); DROP TABLE plan_users;--"); - db.saveUserData(data.getUuid(), data); + db.saveUserData(data); assertTrue("Removed Users table.", db.getUserId(data2.getUuid().toString()) != -1); } /** * * @throws SQLException + * @throws java.net.UnknownHostException */ @Test - public void testSaveMultipleUserData() throws SQLException { + public void testSaveMultipleUserData() throws SQLException, UnknownHostException { db.init(); UserData data = new UserData(MockUtils.mockPlayer(), new DemographicsData()); - db.saveUserData(data.getUuid(), data); + data.addIpAddress(InetAddress.getByName("185.64.113.61")); + data.addSession(new SessionData(1286349L, 2342978L)); + data.addNickname("TestNick"); + data.addPlayerKill(new KillData(MockUtils.getPlayer2UUID(), 2, "DiamondSword", 75843759L)); + System.out.println(data.toString()); + db.saveUserData(data); + data.getPlayerKills().clear(); + System.out.println(data.toString()); data.addNickname("TestUpdateForSave"); UserData data2 = new UserData(MockUtils.mockPlayer2(), new DemographicsData()); + data2.addNickname("Alright"); + data.addNickname("TestNick2"); + data2.addIpAddress(InetAddress.getByName("185.64.113.60")); + data2.addSession(new SessionData(2348743L, 4839673L)); + data2.addPlayerKill(new KillData(MockUtils.getPlayerUUID(), 1, "DiamondSword", 753759L)); List list = new ArrayList<>(); list.add(data); list.add(data2); db.saveMultipleUserData(list); + data.addPlayerKill(new KillData(MockUtils.getPlayer2UUID(), 2, "DiamondSword", 75843759L)); + data.setLocation(null); + data2.setLocation(null); DBCallableProcessor process = new DBCallableProcessor() { @Override public void process(UserData d) { + System.out.println("\n" + data.toString()); + System.out.println(d.toString()); assertTrue("Not Equals", data.equals(d)); } }; @@ -277,6 +302,8 @@ public class DatabaseTest { DBCallableProcessor process2 = new DBCallableProcessor() { @Override public void process(UserData d) { + System.out.println("\n" + data2.toString()); + System.out.println(d.toString()); assertTrue("Not Equals", data2.equals(d)); } }; @@ -291,7 +318,7 @@ public class DatabaseTest { public void testRemove() throws SQLException { db.init(); UserData data = new UserData(MockUtils.mockPlayer(), new DemographicsData()); - db.saveUserData(data.getUuid(), data); + db.saveUserData(data); assertTrue(db.removeAccount(data.getUuid().toString())); assertTrue("Contains the user", !db.wasSeenBefore(data.getUuid())); } @@ -326,6 +353,7 @@ public class DatabaseTest { * * @throws SQLException */ + // Big test because @Test public void testRestore() throws SQLException { db.init(); @@ -335,6 +363,12 @@ public class DatabaseTest { list.add(data); list.add(data2); db.saveMultipleUserData(list); + HashMap c = new HashMap<>(); + c.put("/plan", 1); + c.put("/tp", 4); + c.put("/pla", 7); + c.put("/help", 21); + db.saveCommandUse(c); backup = new SQLiteDB(plan, "debug-backup") { @Override public void startConnectionPingTask(Plan plugin) { @@ -347,5 +381,10 @@ public class DatabaseTest { Set savedUUIDs = db.getSavedUUIDs(); assertTrue("Didn't contain 1", savedUUIDs.contains(data.getUuid())); assertTrue("Didn't contain 2", savedUUIDs.contains(data2.getUuid())); + Map commandUse = db.getCommandUse(); + assertTrue("Doesn't contain /plan", commandUse.containsKey("/plan")); + assertTrue("Doesn't contain /tp", commandUse.containsKey("/tp")); + assertTrue("Doesn't contain /pla", commandUse.containsKey("/pla")); + assertTrue("Doesn't contain /help", commandUse.containsKey("/help")); } } diff --git a/Plan/src/test/java/main/java/com/djrapitops/plan/utilities/AnalysisUtilsTest.java b/Plan/src/test/java/main/java/com/djrapitops/plan/utilities/AnalysisUtilsTest.java index b5bef7383..42f77a88e 100644 --- a/Plan/src/test/java/main/java/com/djrapitops/plan/utilities/AnalysisUtilsTest.java +++ b/Plan/src/test/java/main/java/com/djrapitops/plan/utilities/AnalysisUtilsTest.java @@ -7,10 +7,10 @@ package test.java.main.java.com.djrapitops.plan.utilities; import java.util.ArrayList; import java.util.Collection; -import java.util.Date; import java.util.List; import main.java.com.djrapitops.plan.data.SessionData; import main.java.com.djrapitops.plan.utilities.AnalysisUtils; +import main.java.com.djrapitops.plan.utilities.MiscUtils; import org.bukkit.plugin.java.JavaPlugin; import static org.junit.Assert.*; import org.junit.Before; @@ -48,7 +48,7 @@ public class AnalysisUtilsTest { */ @Test public void testIsActive() { - long lastPlayed = new Date().getTime(); + long lastPlayed = MiscUtils.getTime(); long playTime = 12638934876L; int loginTimes = 4; boolean expResult = true; @@ -61,7 +61,7 @@ public class AnalysisUtilsTest { */ @Test public void testIsNotActive2() { - long lastPlayed = new Date().getTime(); + long lastPlayed = MiscUtils.getTime(); long playTime = 0L; int loginTimes = 4; boolean expResult = false; @@ -74,7 +74,7 @@ public class AnalysisUtilsTest { */ @Test public void testIsNotActive3() { - long lastPlayed = new Date().getTime(); + long lastPlayed = MiscUtils.getTime(); long playTime = 12638934876L; int loginTimes = 0; boolean expResult = false; @@ -137,33 +137,5 @@ public class AnalysisUtilsTest { expResult.add(20L); List result = AnalysisUtils.transformSessionDataToLengths(data); assertEquals(expResult, result); - } - - /** - * - */ - @Test - public void testAverage() { - Collection o = new ArrayList<>(); - o.add(0L); - o.add(1L); - o.add(2L); - o.add(3L); - o.add(4L); - long expResult = 2L; - long result = AnalysisUtils.average(o); - assertEquals(expResult, result); - } - - /** - * - */ - @Test - public void testAverageEmpty() { - Collection list = new ArrayList<>(); - long expResult = 0L; - long result = AnalysisUtils.average(list); - assertEquals(expResult, result); - } - + } } diff --git a/Plan/src/test/java/main/java/com/djrapitops/plan/utilities/FormatUtilsTest.java b/Plan/src/test/java/main/java/com/djrapitops/plan/utilities/FormatUtilsTest.java index 0d860865e..3116978b4 100644 --- a/Plan/src/test/java/main/java/com/djrapitops/plan/utilities/FormatUtilsTest.java +++ b/Plan/src/test/java/main/java/com/djrapitops/plan/utilities/FormatUtilsTest.java @@ -30,9 +30,9 @@ public class FormatUtilsTest { */ @Test public void testFormatTimeAmount() { - String string = "" + 1000L; + long second = 1000L; String expResult = "1s"; - String result = FormatUtils.formatTimeAmount(string); + String result = FormatUtils.formatTimeAmount(second); assertEquals(expResult, result); } @@ -44,7 +44,7 @@ public class FormatUtilsTest { Date before = new Date(300000L); Date now = new Date(310000L); String expResult = "10s"; - String result = FormatUtils.formatTimeAmountSinceDate(before, now); + String result = FormatUtils.formatTimeAmountDifference(before.getTime(), now.getTime()); assertEquals(expResult, result); } @@ -53,21 +53,9 @@ public class FormatUtilsTest { */ @Test public void testFormatTimeStamp() { - String string = "0"; + long epochZero = 0L; String expResult = "Jan 01 02:00:00"; - String result = FormatUtils.formatTimeStamp(string); - assertEquals(expResult, result); - } - - /** - * - */ - @Test - public void testFormatTimeAmountSinceString() { - String string = "" + new Date(310000L).toInstant().getEpochSecond() * 1000L; - Date now = new Date(300000L); - String expResult = "10s"; - String result = FormatUtils.formatTimeAmountSinceString(string, now); + String result = FormatUtils.formatTimeStamp(epochZero); assertEquals(expResult, result); } diff --git a/Plan/src/test/java/main/java/com/djrapitops/plan/utilities/MathUtilsTest.java b/Plan/src/test/java/main/java/com/djrapitops/plan/utilities/MathUtilsTest.java new file mode 100644 index 000000000..a84c8edf7 --- /dev/null +++ b/Plan/src/test/java/main/java/com/djrapitops/plan/utilities/MathUtilsTest.java @@ -0,0 +1,127 @@ +/* + * 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 test.java.main.java.com.djrapitops.plan.utilities; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import main.java.com.djrapitops.plan.utilities.MathUtils; +import static org.junit.Assert.assertTrue; +import org.junit.Test; + +/** + * + * @author Risto + */ +public class MathUtilsTest { + + public MathUtilsTest() { + } + + @Test + public void testAverageInt() { + List l = new ArrayList<>(); + double exp = 10; + l.add(0); + l.add(20); + l.add(5); + l.add(15); + double result = MathUtils.averageInt(l.stream()); + assertTrue(exp == result); + } + + @Test + public void testAverageIntEmpty() { + List l = new ArrayList<>(); + double exp = 0; + double result = MathUtils.averageInt(l.stream()); + assertTrue(result + "/" + exp, exp == result); + } + + @Test + public void testAverageLong_Collection() { + List l = new ArrayList<>(); + double exp = 10; + l.add(0L); + l.add(20L); + l.add(5L); + l.add(15L); + double result = MathUtils.averageLong(l); + assertTrue(result + "/" + exp, exp == result); + } + + @Test + public void testAverageDouble() { + List l = new ArrayList<>(); + double exp = 10; + l.add(0.0); + l.add(20.5); + l.add(4.5); + l.add(15.0); + double result = MathUtils.averageDouble(l.stream()); + assertTrue(result + "/" + exp, exp == result); + + } + + @Test + public void testAverage() { + double exp = 10; + double result = MathUtils.average(40, 4); + assertTrue(result + "/" + exp, exp == result); + } + + @Test + public void testCountTrueBoolean() { + List l = new ArrayList<>(); + int exp = new Random().nextInt(1000); + for (int i = 0; i < exp; i++) { + l.add(true); + } + for (int i = exp; i < 1000; i++) { + l.add(false); + } + long result = MathUtils.countTrueBoolean(l.stream()); + assertTrue(result + "/" + exp, exp == result); + } + + @Test + public void testSumInt() { + List l = new ArrayList<>(); + double exp = 40; + l.add(0); + l.add(20); + l.add(5); + l.add(15); + double result = MathUtils.sumInt(l.stream()); + assertTrue(result + "/" + exp, exp == result); + } + + @Test + public void testSumLong() { + List l = new ArrayList<>(); + long exp = 40; + l.add(0L); + l.add(20L); + l.add(5L); + l.add(15L); + long result = MathUtils.sumLong(l.stream()); + assertTrue(result + "/" + exp, exp == result); + } + + @Test + public void testSumDouble() { + List l = new ArrayList<>(); + double exp = 100.4531541; + l.add(0.0); + l.add(50.4); + l.add(45.0); + l.add(5.0531541); + double result = MathUtils.sumDouble(l.stream()); + assertTrue(result + "/" + exp, exp == result); + } + +} diff --git a/Plan/src/test/java/main/java/com/djrapitops/plan/utilities/NewPlayerCreatorTest.java b/Plan/src/test/java/main/java/com/djrapitops/plan/utilities/NewPlayerCreatorTest.java index bb334e9dd..27efc1468 100644 --- a/Plan/src/test/java/main/java/com/djrapitops/plan/utilities/NewPlayerCreatorTest.java +++ b/Plan/src/test/java/main/java/com/djrapitops/plan/utilities/NewPlayerCreatorTest.java @@ -5,9 +5,9 @@ */ package test.java.main.java.com.djrapitops.plan.utilities; -import java.util.Date; import main.java.com.djrapitops.plan.data.DemographicsData; import main.java.com.djrapitops.plan.data.UserData; +import main.java.com.djrapitops.plan.utilities.MiscUtils; import main.java.com.djrapitops.plan.utilities.NewPlayerCreator; import org.bukkit.GameMode; import org.bukkit.OfflinePlayer; @@ -62,7 +62,7 @@ public class NewPlayerCreatorTest { UserData result = NewPlayerCreator.createNewPlayer(p); UserData exp = new UserData(p, new DemographicsData()); exp.setLastGamemode(GameMode.SURVIVAL); - exp.setLastPlayed(new Date().getTime()); + exp.setLastPlayed(MiscUtils.getTime()); long zero = Long.parseLong("0"); exp.setPlayTime(zero); exp.setTimesKicked(0); @@ -82,7 +82,7 @@ public class NewPlayerCreatorTest { UserData result = NewPlayerCreator.createNewPlayer(p); UserData exp = new UserData(p, new DemographicsData()); exp.setLastGamemode(GameMode.SPECTATOR); - exp.setLastPlayed(new Date().getTime()); + exp.setLastPlayed(MiscUtils.getTime()); long zero = Long.parseLong("0"); exp.setPlayTime(zero); exp.setTimesKicked(0); @@ -102,7 +102,7 @@ public class NewPlayerCreatorTest { UserData result = NewPlayerCreator.createNewPlayer(p, GameMode.CREATIVE); UserData exp = new UserData(p, new DemographicsData()); exp.setLastGamemode(GameMode.CREATIVE); - exp.setLastPlayed(new Date().getTime()); + exp.setLastPlayed(MiscUtils.getTime()); long zero = Long.parseLong("0"); exp.setPlayTime(zero); exp.setTimesKicked(0); diff --git a/Plan/src/test/java/utils/TestInit.java b/Plan/src/test/java/utils/TestInit.java index 0acddd07a..41e21bde3 100644 --- a/Plan/src/test/java/utils/TestInit.java +++ b/Plan/src/test/java/utils/TestInit.java @@ -10,6 +10,7 @@ import java.io.FileInputStream; import java.nio.file.Files; import java.util.logging.Logger; import main.java.com.djrapitops.plan.Plan; +import main.java.com.djrapitops.plan.Settings; import org.bukkit.Server; import org.bukkit.configuration.file.YamlConfiguration; import org.powermock.api.mockito.PowerMockito; @@ -63,7 +64,8 @@ public class TestInit { when(planMock.getServer()).thenReturn(mockServer); when(planMock.getLogger()).thenReturn(Logger.getGlobal()); Plan.setInstance(planMock); -// Mockito.doReturn("0.0.0.0").when(planMock).getServer().getIp(); +// Mockito.doReturn("0.0.0.0").when(planMock).getServer().getIp(); + Settings.DEBUG.setValue(true); return true; } catch (Exception ex) { System.out.println(ex); diff --git a/documentation/CommandsAndPermissions.md b/documentation/CommandsAndPermissions.md index ff3655233..482077127 100644 --- a/documentation/CommandsAndPermissions.md +++ b/documentation/CommandsAndPermissions.md @@ -10,7 +10,7 @@ This page is an in depth documentation of all permissions & commands. Command | Permission | Default | Description --- | ---- | ------ | --------------------------------- -/plan | plan.? | OP | Base command, Shows help. Alias for /plan inspect [player] when used like /plan [player] +/plan | plan.? | true | Base command, Shows help. Alias for /plan inspect [player] when used like /plan [player] /plan inspect | plan.inspect | true | Gives the link to player page of the player who issued the command. /plan inspect [player] | plan.inspect.other | OP | Gives link to player page of the given playername, CaSe-SenSiTiVe. /plan qinspect | plan.qinspect | OP | Displays information about the issuing player in the chatbox.