From 96240195efb241aa2f3aeba34660f3b71348f309 Mon Sep 17 00:00:00 2001 From: Rsl1122 Date: Thu, 26 Jan 2017 11:32:42 +0200 Subject: [PATCH] Bugfix, Database optimization, Locations, Partial 2.2.0 features [2.2.0-DEV] - Bugfix for #2 (Catch for NoSuchFieldError, null checks) - Database now uses Batch processing with Commanduse, IPs, Nicknames & Locations. Also used when saving whole cache. - Uncommented Location gathering and swapped the location saving to use batch processing. TODO: Worlds table - Added placeholders for top lists & recent players to analysis & planlite.html TODO: - Worlds Table - Links to players - New HashMaps in Analysis for recent players - InspectCache clear multiper - InspectCache clear task check. (Time value for each task) --- .gitignore | 4 +- Plan Lite/nbproject/build-impl.xml | 21 +- Plan Lite/nbproject/genfiles.properties | 4 +- Plan/pom.xml | 6 + .../main/java/com/djrapitops/plan/Phrase.java | 1 + .../main/java/com/djrapitops/plan/Plan.java | 51 +- .../com/djrapitops/plan/data/UserData.java | 32 +- .../plan/data/cache/DataCacheHandler.java | 21 +- .../djrapitops/plan/database/Database.java | 6 + .../plan/database/databases/SQLDB.java | 527 ++++++++---------- .../ui/graphs/GMTimesPieChartCreator.java | 21 +- .../plan/ui/graphs/HeatMapCreator.java | 52 ++ .../djrapitops/plan/utilities/Analysis.java | 16 +- .../plan/utilities/AnalysisUtils.java | 11 +- Plan/src/main/resources/analysis.html | 3 + Plan/src/main/resources/planlite.html | 4 + 16 files changed, 409 insertions(+), 371 deletions(-) create mode 100644 Plan/src/main/java/com/djrapitops/plan/ui/graphs/HeatMapCreator.java diff --git a/.gitignore b/.gitignore index e937d9cd0..26a128446 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,6 @@ /Plan Advanced/build/ /Plan Advanced/dist/ /Plan Advanced/nbproject/private/ -/Plan/target/ \ No newline at end of file +/Plan/target/ +/Plan/nbproject/ +/Debugger/nbproject/private/ \ No newline at end of file diff --git a/Plan Lite/nbproject/build-impl.xml b/Plan Lite/nbproject/build-impl.xml index b36c85e41..e0aa68d67 100644 --- a/Plan Lite/nbproject/build-impl.xml +++ b/Plan Lite/nbproject/build-impl.xml @@ -46,8 +46,8 @@ is divided into following sections: - - + + @@ -76,7 +76,7 @@ is divided into following sections: - + @@ -156,6 +156,7 @@ is divided into following sections: + @@ -840,7 +841,7 @@ is divided into following sections: - + @@ -852,7 +853,7 @@ is divided into following sections: - + @@ -975,15 +976,15 @@ is divided into following sections: - + - + - + @@ -991,7 +992,7 @@ is divided into following sections: - + @@ -1186,7 +1187,7 @@ is divided into following sections: Must select one file in the IDE or set run.class - + Must select one file in the IDE or set applet.url diff --git a/Plan Lite/nbproject/genfiles.properties b/Plan Lite/nbproject/genfiles.properties index d97a5b35c..60bf2d379 100644 --- a/Plan Lite/nbproject/genfiles.properties +++ b/Plan Lite/nbproject/genfiles.properties @@ -4,5 +4,5 @@ build.xml.stylesheet.CRC32=8064a381@1.79.1.48 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. nbproject/build-impl.xml.data.CRC32=f0bf6c4b -nbproject/build-impl.xml.script.CRC32=b8db7136 -nbproject/build-impl.xml.stylesheet.CRC32=05530350@1.79.1.48 +nbproject/build-impl.xml.script.CRC32=ca4555e3 +nbproject/build-impl.xml.stylesheet.CRC32=830a3534@1.80.1.48 diff --git a/Plan/pom.xml b/Plan/pom.xml index 47bc69b61..4e2801b47 100644 --- a/Plan/pom.xml +++ b/Plan/pom.xml @@ -24,6 +24,12 @@ 1.3 compile + + com.javaheatmap + jheatchart + 0.6 + compile + clean package install diff --git a/Plan/src/main/java/com/djrapitops/plan/Phrase.java b/Plan/src/main/java/com/djrapitops/plan/Phrase.java index 8348bd233..01a4d77f9 100644 --- a/Plan/src/main/java/com/djrapitops/plan/Phrase.java +++ b/Plan/src/main/java/com/djrapitops/plan/Phrase.java @@ -8,6 +8,7 @@ import static org.bukkit.plugin.java.JavaPlugin.getPlugin; * @author Rsl1122 */ public enum Phrase { + CONFIG_HEADER("Plan Config | More info at https://www.spigotmc.org/wiki/plan-configuration/"), DATABASE_TYPE_DOES_NOT_EXIST("That database type doesn't exist."), DATABASE_FAILURE_DISABLE("Database initialization has failed, disabling Plan."), PLANLITE_REG_HOOK("Registered additional hook, passed on to PlanLite: "), diff --git a/Plan/src/main/java/com/djrapitops/plan/Plan.java b/Plan/src/main/java/com/djrapitops/plan/Plan.java index 6ffd551c0..5dd652e63 100644 --- a/Plan/src/main/java/com/djrapitops/plan/Plan.java +++ b/Plan/src/main/java/com/djrapitops/plan/Plan.java @@ -17,19 +17,19 @@ import java.util.HashSet; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import org.bukkit.Bukkit; -import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.plugin.PluginManager; import org.bukkit.scheduler.BukkitRunnable; /* TODO 2.1.0 Placeholder API Immutable InspectCache ? -Recent players -Optimize db with batch processing (commanduse, ips, nicks) +Recent players 25% + Optimize db with batch processing (commanduse, ips, nicks) Manage command Database cleaning -PlanLite Top 20 richest -PlanLite Top 20 most votes -Top 20 most active +PlanLite Top 20 richest 25% +PlanLite Top 20 most votes 25% +Top 20 most active 25% Clear setting multiper (InspectCache) Clear check for existing clear task. (InspectCache) */ @@ -63,31 +63,20 @@ public class Plan extends JavaPlugin { databases.add(new MySQLDB(this)); databases.add(new SQLiteDB(this)); -// for (Database database : databases) { -// String name = database.getConfigName(); -// -// ConfigurationSection section = getConfig().getConfigurationSection(name); -// -// if (section == null) { -// section = getConfig().createSection(name); -// } -// -// database.getConfigDefaults(section); -// -// if (section.getKeys(false).isEmpty()) { -// getConfig().set(name, null); -// } -// } - getConfig().options().copyDefaults(true); - getConfig().options().header("Plan Config | More info at https://www.spigotmc.org/wiki/plan-configuration/"); + getConfig().options().header(Phrase.CONFIG_HEADER + ""); saveConfig(); log("Database init.."); - initDatabase(); - log("Database initiated."); + if (initDatabase()) { + log("Database initiated."); + } else { + logError(Phrase.DATABASE_FAILURE_DISABLE.toString()); + getServer().getPluginManager().disablePlugin(this); + return; + } hookPlanLite(); this.handler = new DataCacheHandler(this); @@ -183,12 +172,12 @@ public class Plan extends JavaPlugin { } private void registerListeners() { - getServer().getPluginManager().registerEvents(new PlanChatListener(this), this); - getServer().getPluginManager().registerEvents(new PlanPlayerListener(this), this); - getServer().getPluginManager().registerEvents(new PlanGamemodeChangeListener(this), this); - getServer().getPluginManager().registerEvents(new PlanCommandPreprocessListener(this), this); - // Locations Removed from Build 2.0.0 for performance reasons. - // getServer().getPluginManager().registerEvents(new PlanPlayerMoveListener(this), this); + final PluginManager pluginManager = getServer().getPluginManager(); + pluginManager.registerEvents(new PlanChatListener(this), this); + pluginManager.registerEvents(new PlanPlayerListener(this), this); + pluginManager.registerEvents(new PlanGamemodeChangeListener(this), this); + pluginManager.registerEvents(new PlanCommandPreprocessListener(this), this); + pluginManager.registerEvents(new PlanPlayerMoveListener(this), this); } private boolean initDatabase() { diff --git a/Plan/src/main/java/com/djrapitops/plan/data/UserData.java b/Plan/src/main/java/com/djrapitops/plan/data/UserData.java index ec910b38c..301b7f0cc 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/UserData.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/UserData.java @@ -36,10 +36,10 @@ public class UserData { private boolean isOp; private boolean isBanned; private DemographicsData demData; - + private boolean planLiteFound; private PlanLitePlayerData planLiteData; - + private String name; private boolean isOnline; @@ -60,7 +60,10 @@ public class UserData { gmTimes.put(GameMode.SURVIVAL, zero); gmTimes.put(GameMode.CREATIVE, zero); gmTimes.put(GameMode.ADVENTURE, zero); - gmTimes.put(GameMode.SPECTATOR, zero); + try { + gmTimes.put(GameMode.SPECTATOR, zero); + } catch (NoSuchFieldError e) { + } lastGamemode = player.getGameMode(); this.demData = demData; isBanned = player.isBanned(); @@ -84,7 +87,10 @@ public class UserData { gmTimes.put(GameMode.SURVIVAL, zero); gmTimes.put(GameMode.CREATIVE, zero); gmTimes.put(GameMode.ADVENTURE, zero); - gmTimes.put(GameMode.SPECTATOR, zero); + try { + gmTimes.put(GameMode.SPECTATOR, zero); + } catch (NoSuchFieldError e) { + } this.demData = demData; isBanned = player.isBanned(); name = player.getName(); @@ -102,18 +108,15 @@ public class UserData { } public void addLocation(Location loc) { -// locations.add(loc); + locations.add(loc); location = loc; } - @Deprecated public void addLocations(Collection addLocs) { - /* locations.addAll(addLocs); if (!locations.isEmpty()) { location = locations.get(locations.size() - 1); } - */ } public void addNickname(String nick) { @@ -135,7 +138,10 @@ public class UserData { gmTimes.put(GameMode.SURVIVAL, survivalTime); gmTimes.put(GameMode.CREATIVE, creativeTime); gmTimes.put(GameMode.ADVENTURE, adventureTime); - gmTimes.put(GameMode.SPECTATOR, spectatorTime); + try { + gmTimes.put(GameMode.SPECTATOR, spectatorTime); + } catch (NoSuchFieldError e) { + } } public void updateBanned(Player p) { @@ -151,7 +157,6 @@ public class UserData { } // Getters ------------------------------------------------------------- - public boolean isPlanLiteFound() { return planLiteFound; } @@ -167,17 +172,15 @@ public class UserData { public void setPlanLiteData(PlanLitePlayerData planLiteData) { this.planLiteData = planLiteData; } - + public UUID getUuid() { return uuid; } - @Deprecated public Location getLocation() { return location; } - @Deprecated public List getLocations() { return locations; } @@ -314,6 +317,5 @@ public class UserData { public boolean isOnline() { return isOnline; } - - + } 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 32f8b6a61..0853b3819 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,8 +4,10 @@ import com.djrapitops.plan.Plan; import com.djrapitops.plan.database.Database; import com.djrapitops.plan.data.*; import com.djrapitops.plan.data.handlers.*; +import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.UUID; import org.bukkit.Bukkit; @@ -147,9 +149,9 @@ public class DataCacheHandler { * Saves all data in the cache to Database with AsyncTasks */ public void saveCachedUserData() { - dataCache.keySet().stream().forEach((uuid) -> { - saveCachedData(uuid); - }); + List data = new ArrayList<>(); + data.addAll(dataCache.values()); + db.saveMultipleUserData(data); timesSaved++; } @@ -157,11 +159,14 @@ public class DataCacheHandler { * Saves all data in the cache to Database and closes the database down. */ public void saveCacheOnDisable() { - dataCache.keySet().stream().forEach((uuid) -> { - if (dataCache.get(uuid) != null) { - db.saveUserData(uuid, dataCache.get(uuid)); - } - }); +// dataCache.keySet().stream().forEach((uuid) -> { +// if (dataCache.get(uuid) != null) { +// db.saveUserData(uuid, dataCache.get(uuid)); +// } +// }); + List data = new ArrayList<>(); + data.addAll(dataCache.values()); + db.saveMultipleUserData(data); db.saveServerData(serverData); db.close(); } 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 d99ca25da..4033ae7f4 100644 --- a/Plan/src/main/java/com/djrapitops/plan/database/Database.java +++ b/Plan/src/main/java/com/djrapitops/plan/database/Database.java @@ -49,6 +49,12 @@ public abstract class Database { */ public abstract void saveUserData(UUID uuid, UserData data); + /** + * Saves multiple UserData to the Database using batch processing. + * @param data List of Data + */ + public abstract void saveMultipleUserData(List data); + /** * Check if the player is found in the database. * 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 b929dd86a..c526a7ddf 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 @@ -155,10 +155,10 @@ public abstract class SQLDB extends Database { return false; } - ResultSet set = connection.prepareStatement(supportsModification ? ("SHOW TABLES LIKE '" + userName + "'") : "SELECT name FROM sqlite_master WHERE type='table' AND name='" + userName + "'").executeQuery(); +// ResultSet set = connection.prepareStatement(supportsModification ? ("SHOW TABLES LIKE '" + userName + "'") : "SELECT name FROM sqlite_master WHERE type='table' AND name='" + userName + "'").executeQuery(); // boolean newDatabase = set.next(); - set.close(); +// set.close(); query("CREATE TABLE IF NOT EXISTS " + userName + " (" + userColumnID + " integer PRIMARY KEY, " @@ -173,7 +173,7 @@ public abstract class SQLDB extends Database { + userColumnLastPlayed + " bigint NOT NULL" + ")" ); - /* Locations Removed from Build 2.0.0 for performance reasons. + query("CREATE TABLE IF NOT EXISTS " + locationName + " (" + locationColumnID + " integer PRIMARY KEY, " + locationColumnUserID + " integer NOT NULL, " @@ -183,7 +183,7 @@ public abstract class SQLDB extends Database { + "FOREIGN KEY(" + locationColumnUserID + ") REFERENCES " + userName + "(" + userColumnID + ")" + ")" ); - */ + query("CREATE TABLE IF NOT EXISTS " + gamemodetimesName + " (" + gamemodetimesColumnUserID + " integer NOT NULL, " + gamemodetimesColumnSurvivalTime + " bigint NOT NULL, " @@ -308,109 +308,6 @@ public abstract class SQLDB extends Database { return userId; } - @Override - public UserData getUserData(UUID uuid) { - checkConnection(); - // Check if user is in the database - if (!wasSeenBefore(uuid)) { - return null; - } - List worldList = Bukkit.getServer().getWorlds(); - World defaultWorld = worldList.get(0); - HashMap worlds = new HashMap<>(); - for (World w : worldList) { - worlds.put(w.getName(), w); - } - // Get the data - UserData data = new UserData(getOfflinePlayer(uuid), new DemographicsData(), this); - try { - PreparedStatement statement = connection.prepareStatement("SELECT * FROM " + userName + " WHERE UPPER(" + userColumnUUID + ") LIKE UPPER(?)"); - statement.setString(1, uuid.toString()); - ResultSet set = statement.executeQuery(); - - while (set.next()) { - data.getDemData().setAge(set.getInt(userColumnDemAge)); - data.getDemData().setGender(Gender.parse(set.getString(userColumnDemGender))); - data.getDemData().setGeoLocation(set.getString(userColumnDemGeoLocation)); - data.setLastGamemode(GameMode.valueOf(set.getString(userColumnLastGM))); - data.setLastGmSwapTime(set.getLong(userColumnLastGMSwapTime)); - data.setPlayTime(set.getLong(userColumnPlayTime)); - data.setLoginTimes(set.getInt(userColumnLoginTimes)); - data.setLastPlayed(set.getLong(userColumnLastPlayed)); - } - set.close(); - statement.close(); - String userId = "" + getUserId(uuid.toString()); - - /* Locations Removed from Build 2.0.0 for performance reasons. - statement = connection.prepareStatement("SELECT * FROM " + locationName + " WHERE UPPER(" + locationColumnUserID + ") LIKE UPPER(?)"); - statement.setString(1, userId); - set = statement.executeQuery(); - - List locations = new ArrayList<>(); - while (set.next()) { - locations.add(new Location(worlds.get(set.getString(locationColumnWorld)), set.getInt(locationColumnCoordinatesX), 0, set.getInt(locationColumnCoordinatesZ))); - } - set.close(); - statement.close(); - data.addLocations(locations); - - if (locations.isEmpty()) { - data.setLocation(new Location(defaultWorld, 0, 0, 0)); - } else { - data.setLocation(locations.get(locations.size() - 1)); - } - */ - data.setLocation(new Location(defaultWorld, 0, 0, 0)); - - statement = connection.prepareStatement("SELECT * FROM " + nicknamesName + " WHERE UPPER(" + nicknamesColumnUserID + ") LIKE UPPER(?)"); - statement.setString(1, userId); - set = statement.executeQuery(); - - List nicknames = new ArrayList<>(); - while (set.next()) { - nicknames.add(set.getString(nicknamesColumnNick)); - } - set.close(); - statement.close(); - data.addNicknames(nicknames); - - statement = connection.prepareStatement("SELECT * FROM " + ipsName + " WHERE UPPER(" + ipsColumnUserID + ") LIKE UPPER(?)"); - statement.setString(1, userId); - set = statement.executeQuery(); - - List ips = new ArrayList<>(); - while (set.next()) { - try { - ips.add(InetAddress.getByName(set.getString(ipsColumnIP))); - } catch (SQLException | UnknownHostException e) { - } - } - set.close(); - statement.close(); - data.addIpAddresses(ips); - - statement = connection.prepareStatement("SELECT * FROM " + gamemodetimesName + " WHERE UPPER(" + gamemodetimesColumnUserID + ") LIKE UPPER(?)"); - statement.setString(1, userId); - set = statement.executeQuery(); - - HashMap times = new HashMap<>(); - while (set.next()) { - times.put(GameMode.SURVIVAL, set.getLong(gamemodetimesColumnSurvivalTime)); - times.put(GameMode.CREATIVE, set.getLong(gamemodetimesColumnCreativeTime)); - times.put(GameMode.ADVENTURE, set.getLong(gamemodetimesColumnAdventureTime)); - times.put(GameMode.SPECTATOR, set.getLong(gamemodetimesColumnSpectatorTime)); - } - set.close(); - statement.close(); - data.setGmTimes(times); - } catch (SQLException e) { - data = null; - e.printStackTrace(); - } - return data; - } - @Override public HashMap getServerDataHashMap() { HashMap commandUse = getCommandUse(); @@ -487,17 +384,21 @@ public abstract class SQLDB extends Database { "DELETE FROM " + commanduseName); statement.execute(); statement.close(); - for (String key : data.keySet()) { - statement = connection.prepareStatement("INSERT INTO " + commanduseName + " (" - + commanduseColumnCommand + ", " - + commanduseColumnTimesUsed - + ") VALUES (?, ?)"); + connection.setAutoCommit(false); + statement = connection.prepareStatement("INSERT INTO " + commanduseName + " (" + + commanduseColumnCommand + ", " + + commanduseColumnTimesUsed + + ") VALUES (?, ?)"); + for (String key : data.keySet()) { statement.setString(1, key); statement.setInt(2, data.get(key)); - statement.execute(); - statement.close(); + statement.addBatch(); } + statement.executeBatch(); + connection.commit(); + statement.close(); + connection.setAutoCommit(true); } catch (SQLException e) { e.printStackTrace(); @@ -536,12 +437,12 @@ public abstract class SQLDB extends Database { statement.setString(1, uuid); statement.execute(); statement.close(); - /* Locations Removed from Build 2.0.0 for performance reasons. + statement = connection.prepareStatement("DELETE FROM " + locationName + " WHERE UPPER(" + locationColumnUserID + ") LIKE UPPER(?)"); statement.setString(1, "" + userId); statement.execute(); statement.close(); - */ + statement = connection.prepareStatement("DELETE FROM " + nicknamesName + " WHERE UPPER(" + nicknamesColumnUserID + ") LIKE UPPER(?)"); statement.setString(1, "" + userId); statement.execute(); @@ -559,6 +460,171 @@ public abstract class SQLDB extends Database { } } + @Override + public UserData getUserData(UUID uuid) { + checkConnection(); + // Check if user is in the database + if (!wasSeenBefore(uuid)) { + plugin.logError(uuid + " was not found from the database!"); + return null; + } + List worldList = Bukkit.getServer().getWorlds(); + World defaultWorld = worldList.get(0); + HashMap worlds = new HashMap<>(); + for (World w : worldList) { + worlds.put(w.getName(), w); + } + // Get the data + UserData data = new UserData(getOfflinePlayer(uuid), new DemographicsData(), this); + try { + PreparedStatement statement = connection.prepareStatement("SELECT * FROM " + userName + " WHERE UPPER(" + userColumnUUID + ") LIKE UPPER(?)"); + statement.setString(1, uuid.toString()); + ResultSet set = statement.executeQuery(); + + while (set.next()) { + data.getDemData().setAge(set.getInt(userColumnDemAge)); + data.getDemData().setGender(Gender.parse(set.getString(userColumnDemGender))); + data.getDemData().setGeoLocation(set.getString(userColumnDemGeoLocation)); + data.setLastGamemode(GameMode.valueOf(set.getString(userColumnLastGM))); + data.setLastGmSwapTime(set.getLong(userColumnLastGMSwapTime)); + data.setPlayTime(set.getLong(userColumnPlayTime)); + data.setLoginTimes(set.getInt(userColumnLoginTimes)); + data.setLastPlayed(set.getLong(userColumnLastPlayed)); + } + set.close(); + statement.close(); + String userId = "" + getUserId(uuid.toString()); + + statement = connection.prepareStatement("SELECT * FROM " + locationName + " WHERE UPPER(" + locationColumnUserID + ") LIKE UPPER(?)"); + statement.setString(1, userId); + set = statement.executeQuery(); + + List locations = new ArrayList<>(); + while (set.next()) { + locations.add(new Location(worlds.get(set.getString(locationColumnWorld)), set.getInt(locationColumnCoordinatesX), 0, set.getInt(locationColumnCoordinatesZ))); + } + set.close(); + statement.close(); + data.addLocations(locations); + + if (locations.isEmpty()) { + data.setLocation(new Location(defaultWorld, 0, 0, 0)); + } else { + data.setLocation(locations.get(locations.size() - 1)); + } + + data.setLocation(new Location(defaultWorld, 0, 0, 0)); + + statement = connection.prepareStatement("SELECT * FROM " + nicknamesName + " WHERE UPPER(" + nicknamesColumnUserID + ") LIKE UPPER(?)"); + statement.setString(1, userId); + set = statement.executeQuery(); + + List nicknames = new ArrayList<>(); + while (set.next()) { + nicknames.add(set.getString(nicknamesColumnNick)); + } + set.close(); + statement.close(); + data.addNicknames(nicknames); + + statement = connection.prepareStatement("SELECT * FROM " + ipsName + " WHERE UPPER(" + ipsColumnUserID + ") LIKE UPPER(?)"); + statement.setString(1, userId); + set = statement.executeQuery(); + + List ips = new ArrayList<>(); + while (set.next()) { + try { + ips.add(InetAddress.getByName(set.getString(ipsColumnIP))); + } catch (SQLException | UnknownHostException e) { + } + } + set.close(); + statement.close(); + data.addIpAddresses(ips); + + statement = connection.prepareStatement("SELECT * FROM " + gamemodetimesName + " WHERE UPPER(" + gamemodetimesColumnUserID + ") LIKE UPPER(?)"); + statement.setString(1, userId); + set = statement.executeQuery(); + + HashMap times = new HashMap<>(); + while (set.next()) { + times.put(GameMode.SURVIVAL, set.getLong(gamemodetimesColumnSurvivalTime)); + times.put(GameMode.CREATIVE, set.getLong(gamemodetimesColumnCreativeTime)); + times.put(GameMode.ADVENTURE, set.getLong(gamemodetimesColumnAdventureTime)); + try { + times.put(GameMode.SPECTATOR, set.getLong(gamemodetimesColumnSpectatorTime)); + } catch (NoSuchFieldError e) { + } + } + set.close(); + statement.close(); + data.setGmTimes(times); + } catch (SQLException e) { + data = null; + e.printStackTrace(); + } + return data; + } + + @Override + public void saveMultipleUserData(List data) { + List saveLast = new ArrayList<>(); + String uSQL = "UPDATE " + userName + " SET " + + userColumnDemAge + "=?, " + + userColumnDemGender + "=?, " + + userColumnDemGeoLocation + "=?, " + + userColumnLastGM + "=?, " + + userColumnLastGMSwapTime + "=?, " + + userColumnPlayTime + "=?, " + + userColumnLoginTimes + "=?, " + + userColumnLastPlayed + "=? " + + "WHERE UPPER(" + userColumnUUID + ") LIKE UPPER(?)"; + try { + connection.setAutoCommit(false); + PreparedStatement uStatement = connection.prepareStatement(uSQL); + for (UserData uData : data) { + int userId = getUserId(uData.getUuid().toString()); + if (userId == -1) { + saveLast.add(uData); + continue; + } + + uStatement.setInt(1, uData.getDemData().getAge()); + uStatement.setString(2, uData.getDemData().getGender().toString().toLowerCase()); + uStatement.setString(3, uData.getDemData().getGeoLocation()); + GameMode gm = uData.getLastGamemode(); + if (gm != null) { + uStatement.setString(4, uData.getLastGamemode().name()); + } else { + uStatement.setString(4, GameMode.SURVIVAL.name()); + } + uStatement.setLong(5, uData.getLastGmSwapTime()); + uStatement.setLong(6, uData.getPlayTime()); + uStatement.setInt(7, uData.getLoginTimes()); + uStatement.setLong(8, uData.getLastPlayed()); + uStatement.setString(9, uData.getUuid().toString()); + uStatement.addBatch(); + } + uStatement.executeBatch(); + connection.commit(); + uStatement.close(); + connection.setAutoCommit(true); + data.removeAll(saveLast); + for (UserData uData : data) { + int userId = getUserId(uData.getUuid().toString()); + saveLocationList(userId, uData.getLocations()); + saveNickList(userId, uData.getNicknames()); + saveIPList(userId, uData.getIps()); + saveGMTimes(userId, uData.getGmTimes()); + } + for (UserData userData : saveLast) { + saveUserData(userData.getUuid(), userData); + } + } catch (SQLException | NullPointerException e) { + e.printStackTrace(); + } + } + @Override public void saveUserData(UUID uuid, UserData data) { checkConnection(); @@ -627,7 +693,7 @@ public abstract class SQLDB extends Database { statement.close(); userId = getUserId(uuid.toString()); } - // saveLocationList(userId, data.getLocations()); + saveLocationList(userId, data.getLocations()); saveNickList(userId, data.getNicknames()); saveIPList(userId, data.getIps()); saveGMTimes(userId, data.getGmTimes()); @@ -638,37 +704,34 @@ public abstract class SQLDB extends Database { data.setAccessing(false); } - @Deprecated // Locations Removed from Build 2.0.0 for performance reasons. public void saveLocationList(int userId, List locations) { - /* try { - PreparedStatement statement = connection.prepareStatement( + PreparedStatement deleteStatement = connection.prepareStatement( "DELETE FROM " + locationName + " WHERE UPPER(" + locationColumnUserID + ") LIKE UPPER(?)"); - statement.setString(1, "" + userId); - statement.execute(); - statement.close(); - + deleteStatement.setString(1, "" + userId); + deleteStatement.execute(); + deleteStatement.close(); + connection.setAutoCommit(false); + PreparedStatement saveStatement = connection.prepareStatement("INSERT INTO " + locationName + " (" + + locationColumnUserID + ", " + + locationColumnCoordinatesX + ", " + + locationColumnCoordinatesZ + ", " + + locationColumnWorld + + ") VALUES (?, ?, ?, ?)"); for (Location location : locations) { - PreparedStatement saveStatement = connection.prepareStatement("INSERT INTO " + locationName + " (" - + locationColumnUserID + ", " - + locationColumnCoordinatesX + ", " - + locationColumnCoordinatesZ + ", " - + locationColumnWorld - + ") VALUES (?, ?, ?, ?)"); - saveStatement.setInt(1, userId); saveStatement.setInt(2, (int) location.getBlockX()); saveStatement.setInt(3, (int) location.getBlockZ()); saveStatement.setString(4, location.getWorld().getName()); - - saveStatement.execute(); - saveStatement.close(); + saveStatement.addBatch(); } - + saveStatement.executeBatch(); + connection.commit(); + saveStatement.close(); + connection.setAutoCommit(true); } catch (SQLException e) { e.printStackTrace(); } - */ } public void saveNickList(int userId, HashSet names) { @@ -678,17 +741,20 @@ public abstract class SQLDB extends Database { statement.setString(1, "" + userId); statement.execute(); + connection.setAutoCommit(false); + statement = connection.prepareStatement("INSERT INTO " + nicknamesName + " (" + + nicknamesColumnUserID + ", " + + nicknamesColumnNick + + ") VALUES (?, ?)"); for (String name : names) { - statement = connection.prepareStatement("INSERT INTO " + nicknamesName + " (" - + nicknamesColumnUserID + ", " - + nicknamesColumnNick - + ") VALUES (?, ?)"); - statement.setInt(1, userId); statement.setString(2, name); - statement.execute(); - statement.close(); + statement.addBatch(); } + statement.executeBatch(); + connection.commit(); + statement.close(); + connection.setAutoCommit(true); } catch (SQLException e) { e.printStackTrace(); @@ -703,17 +769,20 @@ public abstract class SQLDB extends Database { statement.execute(); statement.close(); + connection.setAutoCommit(false); + statement = connection.prepareStatement("INSERT INTO " + ipsName + " (" + + ipsColumnUserID + ", " + + ipsColumnIP + + ") VALUES (?, ?)"); for (InetAddress ip : ips) { - statement = connection.prepareStatement("INSERT INTO " + ipsName + " (" - + ipsColumnUserID + ", " - + ipsColumnIP - + ") VALUES (?, ?)"); - statement.setInt(1, userId); statement.setString(2, ip.getHostAddress()); - statement.execute(); - statement.close(); + statement.addBatch(); } + statement.executeBatch(); + connection.commit(); + statement.close(); + connection.setAutoCommit(true); } catch (SQLException e) { e.printStackTrace(); @@ -740,7 +809,16 @@ public abstract class SQLDB extends Database { statement.setLong(2, gamemodeTimes.get(GameMode.SURVIVAL)); statement.setLong(3, gamemodeTimes.get(GameMode.CREATIVE)); statement.setLong(4, gamemodeTimes.get(GameMode.ADVENTURE)); - statement.setLong(5, gamemodeTimes.get(GameMode.SPECTATOR)); + try { + Long gm = gamemodeTimes.get(GameMode.SPECTATOR); + if (gm != null) { + statement.setLong(5, gm); + } else { + statement.setLong(5, 0); + } + } catch (NoSuchFieldError e) { + statement.setLong(5, 0); + } statement.execute(); statement.close(); @@ -901,151 +979,4 @@ public abstract class SQLDB extends Database { return connection; } - public String getUserName() { - return userName; - } - - public String getLocationName() { - return locationName; - } - - public String getServerdataName() { - return serverdataName; - } - - public String getCommanduseName() { - return commanduseName; - } - - public String getGamemodetimesName() { - return gamemodetimesName; - } - - public String getNicknamesName() { - return nicknamesName; - } - - public String getIpsName() { - return ipsName; - } - - public String getUserColumnUUID() { - return userColumnUUID; - } - - public String getUserColumnID() { - return userColumnID; - } - - public String getUserColumnPlayTime() { - return userColumnPlayTime; - } - - public String getUserColumnDemGeoLocation() { - return userColumnDemGeoLocation; - } - - public String getUserColumnDemAge() { - return userColumnDemAge; - } - - public String getUserColumnDemGender() { - return userColumnDemGender; - } - - public String getUserColumnLastGM() { - return userColumnLastGM; - } - - public String getUserColumnLastGMSwapTime() { - return userColumnLastGMSwapTime; - } - - public String getUserColumnLoginTimes() { - return userColumnLoginTimes; - } - - public String getUserColumnLastPlayed() { - return userColumnLastPlayed; - } - - public String getLocationColumnUserID() { - return locationColumnUserID; - } - - public String getLocationColumnID() { - return locationColumnID; - } - - public String getLocationColumnCoordinatesX() { - return locationColumnCoordinatesX; - } - - public String getLocationColumnCoordinatesZ() { - return locationColumnCoordinatesZ; - } - - public String getLocationColumnWorld() { - return locationColumnWorld; - } - - public String getServerdataColumnDate() { - return serverdataColumnDate; - } - - public String getServerdataColumnPlayersOnline() { - return serverdataColumnPlayersOnline; - } - - public String getServerdataColumnNewPlayers() { - return serverdataColumnNewPlayers; - } - - public String getCommanduseColumnCommand() { - return commanduseColumnCommand; - } - - public String getCommanduseColumnTimesUsed() { - return commanduseColumnTimesUsed; - } - - public String getGamemodetimesColumnUserID() { - return gamemodetimesColumnUserID; - } - - public String getGamemodetimesColumnSurvivalTime() { - return gamemodetimesColumnSurvivalTime; - } - - public String getGamemodetimesColumnCreativeTime() { - return gamemodetimesColumnCreativeTime; - } - - public String getGamemodetimesColumnAdventureTime() { - return gamemodetimesColumnAdventureTime; - } - - public String getGamemodetimesColumnSpectatorTime() { - return gamemodetimesColumnSpectatorTime; - } - - public String getNicknamesColumnUserID() { - return nicknamesColumnUserID; - } - - public String getNicknamesColumnNick() { - return nicknamesColumnNick; - } - - public String getIpsColumnUserID() { - return ipsColumnUserID; - } - - public String getIpsColumnIP() { - return ipsColumnIP; - } - - public String getVersionName() { - return versionName; - } } diff --git a/Plan/src/main/java/com/djrapitops/plan/ui/graphs/GMTimesPieChartCreator.java b/Plan/src/main/java/com/djrapitops/plan/ui/graphs/GMTimesPieChartCreator.java index 211437a81..be5c8dc71 100644 --- a/Plan/src/main/java/com/djrapitops/plan/ui/graphs/GMTimesPieChartCreator.java +++ b/Plan/src/main/java/com/djrapitops/plan/ui/graphs/GMTimesPieChartCreator.java @@ -24,8 +24,17 @@ public class GMTimesPieChartCreator { * @return Url of charts4j image link. */ public static String createChart(HashMap gmTimes) { + Long gm3; + try { + gm3 = gmTimes.get(GameMode.SPECTATOR); + if (gm3 == null) { + gm3 = (long) 0; + } + } catch (NoSuchFieldError e) { + gm3 = (long) 0; + } long total = gmTimes.get(GameMode.SURVIVAL) + gmTimes.get(GameMode.CREATIVE) - + gmTimes.get(GameMode.ADVENTURE) + gmTimes.get(GameMode.SPECTATOR); + + gmTimes.get(GameMode.ADVENTURE) + gm3; return createChart(gmTimes, total); } @@ -42,7 +51,15 @@ public class GMTimesPieChartCreator { long gmZero = gmTimes.get(GameMode.SURVIVAL); long gmOne = gmTimes.get(GameMode.CREATIVE); long gmTwo = gmTimes.get(GameMode.ADVENTURE); - long gmThree = gmTimes.get(GameMode.SPECTATOR); + Long gmThree; + try { + gmThree = gmTimes.get(GameMode.SPECTATOR); + if (gmThree == null) { + gmThree = (long) 0; + } + } catch (NoSuchFieldError e) { + gmThree = (long) 0; + } int zero = (int) ((gmZero * 1.0 / total) * 100); int one = (int) ((gmOne * 1.0 / total) * 100); int two = (int) ((gmTwo * 1.0 / total) * 100); diff --git a/Plan/src/main/java/com/djrapitops/plan/ui/graphs/HeatMapCreator.java b/Plan/src/main/java/com/djrapitops/plan/ui/graphs/HeatMapCreator.java new file mode 100644 index 000000000..97a54e0bd --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/ui/graphs/HeatMapCreator.java @@ -0,0 +1,52 @@ + +package main.java.com.djrapitops.plan.ui.graphs; + +import com.djrapitops.plan.Plan; +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.bukkit.Location; +import org.tc33.jheatchart.HeatChart; +import static org.bukkit.plugin.java.JavaPlugin.getPlugin; + +/** + * + * @author Rsl1122 + */ +public class HeatMapCreator { + + public static String createLocationHeatmap(List locations) { + double[][] data = new double[1000][1000]; + for (int i = 0; i < 1000; i++) { + for (int j = 0; j < 1000; j++) { + data[i][j] = 0; + } + } + for (Location loc : locations) { + int x = loc.getBlockX()+500; + int z = loc.getBlockZ()+500; + if (x < 0 || x > 1000) { + continue; + } + if (z < 0 || z > 1000) { + continue; + } + data[x][z] = data[x][z] + 1; + } + HeatChart map = new HeatChart(data); + + map.setTitle("Location heatmap."); + map.setXAxisLabel("X"); + map.setYAxisLabel("Z"); + try { + String folder = getPlugin(Plan.class).getDataFolder().getAbsolutePath()+File.separator+"Heatmaps"; + map.saveToFile(new File(folder + File.separator+"java-heat-chart.png")); + } catch (IOException ex) { + Logger.getLogger(HeatMapCreator.class.getName()).log(Level.SEVERE, null, ex); + } + return ""; + } + +} 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 fdcf79239..1f1d9be61 100644 --- a/Plan/src/main/java/com/djrapitops/plan/utilities/Analysis.java +++ b/Plan/src/main/java/com/djrapitops/plan/utilities/Analysis.java @@ -14,6 +14,7 @@ import java.util.List; import java.util.UUID; import main.java.com.djrapitops.plan.data.PlanLiteAnalyzedData; import main.java.com.djrapitops.plan.data.PlanLitePlayerData; +import main.java.com.djrapitops.plan.ui.graphs.HeatMapCreator; import org.bukkit.GameMode; import org.bukkit.OfflinePlayer; import org.bukkit.scheduler.BukkitRunnable; @@ -113,7 +114,7 @@ public class Analysis { int ops = 0; List ages = new ArrayList<>(); - + boolean planLiteEnabled; PlanLiteHook planLiteHook = plugin.getPlanLiteHook(); if (planLiteHook != null) { @@ -149,7 +150,13 @@ public class Analysis { gmZero += gmTimes.get(GameMode.SURVIVAL); gmOne += gmTimes.get(GameMode.CREATIVE); gmTwo += gmTimes.get(GameMode.ADVENTURE); - gmThree += gmTimes.get(GameMode.SPECTATOR); + try { + Long gm = gmTimes.get(GameMode.SPECTATOR); + if (gm != null) { + gmThree += gm; + } + } catch (NoSuchFieldError e) { + } totalPlaytime += uData.getPlayTime(); totalLoginTimes += uData.getLoginTimes(); int age = uData.getDemData().getAge(); @@ -213,7 +220,10 @@ public class Analysis { totalGmTimes.put(GameMode.SURVIVAL, gmZero); totalGmTimes.put(GameMode.CREATIVE, gmOne); totalGmTimes.put(GameMode.ADVENTURE, gmTwo); - totalGmTimes.put(GameMode.SPECTATOR, gmThree); + try { + totalGmTimes.put(GameMode.SPECTATOR, gmThree); + } catch (NoSuchFieldError e) { + } String serverGMChartHtml = AnalysisUtils.createGMPieChart(totalGmTimes, gmTotal); data.setGmTimesChartImgHtml(serverGMChartHtml); data.setGm0Perc((gmZero * 1.0 / gmTotal)); 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 09850a2a2..33927565a 100644 --- a/Plan/src/main/java/com/djrapitops/plan/utilities/AnalysisUtils.java +++ b/Plan/src/main/java/com/djrapitops/plan/utilities/AnalysisUtils.java @@ -73,7 +73,16 @@ public class AnalysisUtils { long gmZero = gmTimes.get(GameMode.SURVIVAL); long gmOne = gmTimes.get(GameMode.CREATIVE); long gmTwo = gmTimes.get(GameMode.ADVENTURE); - long gmThree = gmTimes.get(GameMode.SPECTATOR); + long gmThree; + try { + Long gm3 = gmTimes.get(GameMode.SPECTATOR); + if (gm3 == null) { + gm3 = (long) 0; + } + gmThree = gm3; + } catch (NoSuchFieldError e) { + gmThree = 0; + } long total = gmZero + gmOne + gmTwo + gmThree; replaceMap.put("%gm0%", FormatUtils.formatTimeAmount("" + gmZero)); replaceMap.put("%gm1%", FormatUtils.formatTimeAmount("" + gmOne)); diff --git a/Plan/src/main/resources/analysis.html b/Plan/src/main/resources/analysis.html index b0f23e640..36bb69599 100644 --- a/Plan/src/main/resources/analysis.html +++ b/Plan/src/main/resources/analysis.html @@ -28,6 +28,9 @@ %playerchartweek%

Player Activity - Last 30 days

%playerchartmonth% +

Recent logins: %recentlogins%

+

Top 20 Most Active

+ %top20mostactive%