From 5fdae6878e98698aef62224f62a4e1a1d1aca66b Mon Sep 17 00:00:00 2001 From: Rsl1122 Date: Fri, 25 Aug 2017 12:46:38 +0300 Subject: [PATCH] Analysis Fetch Phase --- .../plan/command/commands/AnalyzeCommand.java | 63 ++++++++---- .../plan/data/analysis/ActivityPart.java | 4 + .../plan/data/analysis/GeolocationPart.java | 33 +++++++ .../plan/data/analysis/JoinInfoPart.java | 45 ++++++--- .../plan/data/analysis/KillPart.java | 30 ++---- .../plan/data/analysis/PlayerCountPart.java | 5 + .../plan/data/analysis/PlaytimePart.java | 22 +++++ .../plan/data/analysis/WorldPart.java | 19 ++-- .../plan/database/tables/IPsTable.java | 37 ++++++- .../plan/database/tables/SessionsTable.java | 69 +++++++++++++ .../plan/database/tables/WorldTimesTable.java | 48 +++++++++ .../plan/systems/cache/SessionCache.java | 1 - .../plan/systems/info/InformationManager.java | 19 +++- .../plan/utilities/analysis/Analysis.java | 97 ++++++++++--------- .../html/graphs/WorldPieCreator.java | 44 +++++---- 15 files changed, 405 insertions(+), 131 deletions(-) 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 5ce3486e9..b8ba94d0b 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,5 +1,6 @@ package main.java.com.djrapitops.plan.command.commands; +import com.djrapitops.plugin.api.TimeAmount; import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.CommandUtils; import com.djrapitops.plugin.command.ISender; @@ -11,9 +12,16 @@ import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.command.ConditionUtils; import main.java.com.djrapitops.plan.locale.Locale; import main.java.com.djrapitops.plan.locale.Msg; +import main.java.com.djrapitops.plan.systems.info.InformationManager; import main.java.com.djrapitops.plan.utilities.Check; +import main.java.com.djrapitops.plan.utilities.MiscUtils; +import main.java.com.djrapitops.plan.utilities.html.HtmlUtils; import org.bukkit.ChatColor; +import java.util.Collection; +import java.util.Collections; +import java.util.Optional; + /** * This subcommand is used to run the analysis and access the /server link. * @@ -23,6 +31,7 @@ import org.bukkit.ChatColor; public class AnalyzeCommand extends SubCommand { private final Plan plugin; + private final InformationManager infoManager; /** * Subcommand Constructor. @@ -35,6 +44,7 @@ public class AnalyzeCommand extends SubCommand { Permissions.ANALYZE.getPermission(), Locale.get(Msg.CMD_USG_ANALYZE).parse()); this.plugin = plugin; + infoManager = plugin.getInfoManager(); } @Override @@ -48,11 +58,14 @@ public class AnalyzeCommand extends SubCommand { return true; } - // TODO Check if analysis is enabled. -// if (!Check.isTrue(analysisCache.isAnalysisEnabled(), Locale.get(Msg.CMD_INFO_ANALYSIS_TEMP_DISABLE).toString(), sender) -// && !analysisCache.isCached()) { -// return true; -// } + Optional analysisRefreshDate = infoManager.getAnalysisRefreshDate(); + boolean forcedRefresh = args.length >= 1 && "-r".equals(args[0]); + boolean refresh = !analysisRefreshDate.isPresent() + || analysisRefreshDate.get() < MiscUtils.getTime() - TimeAmount.MINUTE.ms() + || forcedRefresh; + if (refresh) { + updateCache(sender, refresh); + } sender.sendMessage(Locale.get(Msg.CMD_INFO_FETCH_DATA).toString()); if (plugin.getWebServer().isAuthRequired() && CommandUtils.isPlayer(sender)) { @@ -72,21 +85,37 @@ public class AnalyzeCommand extends SubCommand { } }).runTaskAsynchronously(); } - updateCache(sender); return true; } - private void updateCache(ISender sender) { + private void updateCache(ISender sender, boolean refresh) { // TODO -// if (!analysisCache.isCached() || MiscUtils.getTime() - analysisCache.getData().getRefreshDate() > TimeAmount.MINUTE.ms()) { -// int bootAnID = plugin.getBootAnalysisTaskID(); -// if (bootAnID != -1) { -// plugin.getServer().getScheduler().cancelTask(bootAnID); -// } -// analysisCache.addNotification(sender); -// analysisCache.updateCache(); -// } else { -// analysisCache.sendAnalysisMessage(sender); -// } + if (refresh) { + int bootAnID = plugin.getBootAnalysisTaskID(); + if (bootAnID != -1) { + plugin.getServer().getScheduler().cancelTask(bootAnID); + } + infoManager.addAnalysisNotification(sender); + infoManager.refreshAnalysis(); + } else { + sendAnalysisMessage(Collections.singletonList(sender)); + } + } + + public static void sendAnalysisMessage(Collection senders) { + for (ISender sender : senders) { + sender.sendMessage(Locale.get(Msg.CMD_HEADER_ANALYZE).toString()); + // Link + String url = HtmlUtils.getServerAnalysisUrlWithProtocol(); + String message = Locale.get(Msg.CMD_INFO_LINK).toString(); + boolean console = !CommandUtils.isPlayer(sender); + if (console) { + sender.sendMessage(message + url); + } else { + sender.sendMessage(message); + sender.sendLink(" ", Locale.get(Msg.CMD_INFO_CLICK_ME).toString(), url); + } + sender.sendMessage(Locale.get(Msg.CMD_CONSTANT_FOOTER).toString()); + } } } diff --git a/Plan/src/main/java/com/djrapitops/plan/data/analysis/ActivityPart.java b/Plan/src/main/java/com/djrapitops/plan/data/analysis/ActivityPart.java index 10bae816e..edfcbdfb4 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/analysis/ActivityPart.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/analysis/ActivityPart.java @@ -107,6 +107,10 @@ public class ActivityPart extends RawData { addValue("banned", counts[3]); } + public void addBans(Collection uuids) { + bans.addAll(uuids); + } + public void addBan(UUID uuid) { Verify.nullCheck(uuid); bans.add(uuid); diff --git a/Plan/src/main/java/com/djrapitops/plan/data/analysis/GeolocationPart.java b/Plan/src/main/java/com/djrapitops/plan/data/analysis/GeolocationPart.java index f3b1f3c62..f73003c18 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/analysis/GeolocationPart.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/analysis/GeolocationPart.java @@ -3,7 +3,11 @@ package main.java.com.djrapitops.plan.data.analysis; import main.java.com.djrapitops.plan.utilities.html.graphs.WorldMapCreator; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.UUID; +import java.util.function.Function; +import java.util.stream.Collectors; /** * Part responsible for all Geolocation related analysis. @@ -18,12 +22,14 @@ import java.util.Map; */ public class GeolocationPart extends RawData { + private final Map mostCommonGeolocations; private final Map geoCodes; private final Map geoCodeCounts; public GeolocationPart() { geoCodes = new HashMap<>(); geoCodeCounts = new HashMap<>(); + mostCommonGeolocations = new HashMap<>(); String[] countries = new String[]{"Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra", "Angola", "Anguilla", "Antigua and Barbuda", "Argentina", "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan", "Bahamas, The", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia", "Bosnia and Herzegovina", "Botswana", "Brazil", "British Virgin Islands", "Brunei", "Bulgaria", "Burkina Faso", "Burma", "Burundi", "Cabo Verde", "Cambodia", "Cameroon", "Canada", "Cayman Islands", "Central African Republic", "Chad", "Chile", "China", "Colombia", "Comoros", "Congo, Democratic Republic of the", "Congo, Republic of the", "Cook Islands", "Costa Rica", "Cote d'Ivoire", "Croatia", "Cuba", "Curacao", "Cyprus", "Czech Republic", "Denmark", "Djibouti", "Dominica", "Dominican Republic", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Ethiopia", "Falkland Islands (Islas Malvinas)", "Faroe Islands", "Fiji", "Finland", "France", "French Polynesia", "Gabon", "Gambia, The", "Georgia", "Germany", "Ghana", "Gibraltar", "Greece", "Greenland", "Grenada", "Guam", "Guatemala", "Guernsey", "Guinea-Bissau", "Guinea", "Guyana", "Haiti", "Honduras", "Hong Kong", "Hungary", "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Isle of Man", "Israel", "Italy", "Jamaica", "Japan", "Jersey", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Korea, North", "Korea, South", "Kosovo", "Kuwait", "Kyrgyzstan", "Laos", "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg", "Macau", "Macedonia", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", "Mauritania", "Mauritius", "Mexico", "Micronesia, Federated States of", "Moldova", "Monaco", "Mongolia", "Montenegro", "Morocco", "Mozambique", "Namibia", "Nepal", "Netherlands", "New Caledonia", "New Zealand", "Nicaragua", "Nigeria", "Niger", "Niue", "Northern Mariana Islands", "Norway", "Oman", "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines", "Poland", "Portugal", "Puerto Rico", "Qatar", "Romania", "Russia", "Rwanda", "Saint Kitts and Nevis", "Saint Lucia", "Saint Martin", "Saint Pierre and Miquelon", "Saint Vincent and the Grenadines", "Samoa", "San Marino", "Sao Tome and Principe", "Saudi Arabia", "Senegal", "Serbia", "Seychelles", "Sierra Leone", "Singapore", "Sint Maarten", "Slovakia", "Slovenia", "Solomon Islands", "Somalia", "South Africa", "South Sudan", "Spain", "Sri Lanka", "Sudan", "Suriname", "Swaziland", "Sweden", "Switzerland", "Syria", "Taiwan", "Tajikistan", "Tanzania", "Thailand", "Timor-Leste", "Togo", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey", "Turkmenistan", "Tuvalu", "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom", "United States", "Uruguay", "Uzbekistan", "Vanuatu", "Venezuela", "Vietnam", "Virgin Islands", "West Bank", "Yemen", "Zambia", "Zimbabwe"}; String[] codes = new String[]{"AFG", "ALB", "DZA", "ASM", "AND", "AGO", "AIA", "ATG", "ARG", "ARM", "ABW", "AUS", "AUT", "AZE", "BHM", "BHR", "BGD", "BRB", "BLR", "BEL", "BLZ", "BEN", "BMU", "BTN", "BOL", "BIH", "BWA", "BRA", "VGB", "BRN", "BGR", "BFA", "MMR", "BDI", "CPV", "KHM", "CMR", "CAN", "CYM", "CAF", "TCD", "CHL", "CHN", "COL", "COM", "COD", "COG", "COK", "CRI", "CIV", "HRV", "CUB", "CUW", "CYP", "CZE", "DNK", "DJI", "DMA", "DOM", "ECU", "EGY", "SLV", "GNQ", "ERI", "EST", "ETH", "FLK", "FRO", "FJI", "FIN", "FRA", "PYF", "GAB", "GMB", "GEO", "DEU", "GHA", "GIB", "GRC", "GRL", "GRD", "GUM", "GTM", "GGY", "GNB", "GIN", "GUY", "HTI", "HND", "HKG", "HUN", "ISL", "IND", "IDN", "IRN", "IRQ", "IRL", "IMN", "ISR", "ITA", "JAM", "JPN", "JEY", "JOR", "KAZ", "KEN", "KIR", "KOR", "PRK", "KSV", "KWT", "KGZ", "LAO", "LVA", "LBN", "LSO", "LBR", "LBY", "LIE", "LTU", "LUX", "MAC", "MKD", "MDG", "MWI", "MYS", "MDV", "MLI", "MLT", "MHL", "MRT", "MUS", "MEX", "FSM", "MDA", "MCO", "MNG", "MNE", "MAR", "MOZ", "NAM", "NPL", "NLD", "NCL", "NZL", "NIC", "NGA", "NER", "NIU", "MNP", "NOR", "OMN", "PAK", "PLW", "PAN", "PNG", "PRY", "PER", "PHL", "POL", "PRT", "PRI", "QAT", "ROU", "RUS", "RWA", "KNA", "LCA", "MAF", "SPM", "VCT", "WSM", "SMR", "STP", "SAU", "SEN", "SRB", "SYC", "SLE", "SGP", "SXM", "SVK", "SVN", "SLB", "SOM", "ZAF", "SSD", "ESP", "LKA", "SDN", "SUR", "SWZ", "SWE", "CHE", "SYR", "TWN", "TJK", "TZA", "THA", "TLS", "TGO", "TON", "TTO", "TUN", "TUR", "TKM", "TUV", "UGA", "UKR", "ARE", "GBR", "USA", "URY", "UZB", "VUT", "VEN", "VNM", "VGB", "WBG", "YEM", "ZMB", "ZWE"}; @@ -47,4 +53,31 @@ public class GeolocationPart extends RawData { geoCodeCounts.computeIfPresent(countryCode, (computedCountry, amount) -> amount + 1); } } + + public void addGeoLocations(Map> geolocations) { + for (Map.Entry> entry : geolocations.entrySet()) { + String mostCommon = getMostCommon(entry.getValue()); + mostCommonGeolocations.put(entry.getKey(), mostCommon); + addGeolocation(mostCommon); + } + } + + private String getMostCommon(List geoLocs) { + Map occurrences = + geoLocs.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + String mostCommon = "Not Known"; + long count = -1; + for (Map.Entry entry : occurrences.entrySet()) { + Long value = entry.getValue(); + if (value > count) { + mostCommon = entry.getKey(); + count = value; + } + } + return mostCommon; + } + + public Map getMostCommonGeoLocations() { + return mostCommonGeolocations; + } } diff --git a/Plan/src/main/java/com/djrapitops/plan/data/analysis/JoinInfoPart.java b/Plan/src/main/java/com/djrapitops/plan/data/analysis/JoinInfoPart.java index 133ccf483..93f19fe4b 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/analysis/JoinInfoPart.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/analysis/JoinInfoPart.java @@ -31,18 +31,21 @@ import java.util.stream.Collectors; * ${playersNewAverageWeek} - (Number) * ${playersNewAverageMonth} - (Number) * //TODO ${tableBodySessions}, ${sessionCount}, ${lastPeakTime}, ${playersLastPeak}, ${bestPeakTime}, ${playersBestPeak} + * * @author Rsl1122 * @since 3.5.2 */ public class JoinInfoPart extends RawData { + private final Map activeSessions; private final Map> sessions; - private final List registered; + private final Map registered; private long loginTimes; public JoinInfoPart() { + activeSessions = new HashMap<>(); sessions = new HashMap<>(); - registered = new ArrayList<>(); + registered = new HashMap<>(); loginTimes = 0; } @@ -77,18 +80,19 @@ public class JoinInfoPart extends RawData { private void newPlayers() { long now = MiscUtils.getTime(); - long newDay = AnalysisUtils.getNewPlayers(registered, TimeAmount.DAY.ms(), now); - long newWeek = AnalysisUtils.getNewPlayers(registered, TimeAmount.WEEK.ms(), now); - long newMonth = AnalysisUtils.getNewPlayers(registered, TimeAmount.MONTH.ms(), now); + List registeredList = getRegisteredList(); + long newDay = AnalysisUtils.getNewPlayers(registeredList, TimeAmount.DAY.ms(), now); + long newWeek = AnalysisUtils.getNewPlayers(registeredList, TimeAmount.WEEK.ms(), now); + long newMonth = AnalysisUtils.getNewPlayers(registeredList, TimeAmount.MONTH.ms(), now); addValue("playersNewDay", newDay); addValue("playersNewWeek", newWeek); addValue("playersNewMonth", newMonth); - long newPerDay = AnalysisUtils.getNewUsersPerDay(registered, -1); - long newPerDayDay = AnalysisUtils.getNewUsersPerDay(registered, TimeAmount.DAY.ms()); - long newPerDayWeek = AnalysisUtils.getNewUsersPerDay(registered, TimeAmount.WEEK.ms()); - long newPerDayMonth = AnalysisUtils.getNewUsersPerDay(registered, TimeAmount.MONTH.ms()); + long newPerDay = AnalysisUtils.getNewUsersPerDay(registeredList, -1); + long newPerDayDay = AnalysisUtils.getNewUsersPerDay(registeredList, TimeAmount.DAY.ms()); + long newPerDayWeek = AnalysisUtils.getNewUsersPerDay(registeredList, TimeAmount.WEEK.ms()); + long newPerDayMonth = AnalysisUtils.getNewUsersPerDay(registeredList, TimeAmount.MONTH.ms()); addValue("playersNewAverage", newPerDay); addValue("playersNewAverageDay", newPerDayDay); @@ -116,17 +120,34 @@ public class JoinInfoPart extends RawData { return MiscUtils.flatMap(sessions.values()); } - public void addRegistered(long registerDate) { - registered.add(registerDate); + public void addRegistered(UUID uuid, long registerDate) { + registered.put(uuid, registerDate); } - public List getRegistered() { + public void addRegistered(Map registerDates) { + registered.putAll(registerDates); + } + + public Map getRegistered() { return registered; } + public List getRegisteredList() { + return new ArrayList<>(registered.values()); + } + + public void addSessions(Map> sessions) { + Verify.nullCheck(sessions); + this.sessions.putAll(sessions); + } + public void addSessions(UUID uuid, List sessions) { Verify.nullCheck(uuid); Verify.nullCheck(sessions); this.sessions.put(uuid, sessions.stream().distinct().collect(Collectors.toList())); } + + public void addActiveSessions(Map activeSessions) { + this.activeSessions.putAll(activeSessions); + } } diff --git a/Plan/src/main/java/com/djrapitops/plan/data/analysis/KillPart.java b/Plan/src/main/java/com/djrapitops/plan/data/analysis/KillPart.java index 01fddf6a4..b554da22a 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/analysis/KillPart.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/analysis/KillPart.java @@ -1,14 +1,5 @@ package main.java.com.djrapitops.plan.data.analysis; -import com.djrapitops.plugin.utilities.Verify; -import main.java.com.djrapitops.plan.data.PlayerKill; -import main.java.com.djrapitops.plan.utilities.MiscUtils; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - /** * Part responsible for all Death related analysis. *

@@ -24,12 +15,12 @@ import java.util.UUID; */ public class KillPart extends RawData { - private final Map> playerKills; + private long playerKills; private long mobKills; private long deaths; public KillPart() { - playerKills = new HashMap<>(); + playerKills = 0; mobKills = 0; deaths = 0; } @@ -38,20 +29,17 @@ public class KillPart extends RawData { public void analyse() { addValue("deathCount", deaths); addValue("mobKillCount", mobKills); - int playerKillAmount = getAllPlayerKills().size(); - addValue("killCount", playerKillAmount); + addValue("killCount", playerKills); } /** * Adds kills to the dataset. * - * @param uuid Player whose kills are being added - * @param kills all kills of a player + * @param amount amount of kills * @throws IllegalArgumentException if kills is null */ - public void addKills(UUID uuid, List kills) { - Verify.nullCheck(kills); - playerKills.put(uuid, kills); + public void addKills(long amount) { + playerKills += amount; } public void addMobKills(long amount) { @@ -62,14 +50,10 @@ public class KillPart extends RawData { deaths += amount; } - public Map> getPlayerKills() { + public long getPlayerKills() { return playerKills; } - public List getAllPlayerKills() { - return MiscUtils.flatMap(playerKills.values()); - } - public long getMobKills() { return mobKills; } diff --git a/Plan/src/main/java/com/djrapitops/plan/data/analysis/PlayerCountPart.java b/Plan/src/main/java/com/djrapitops/plan/data/analysis/PlayerCountPart.java index 7eadb6743..9b4b16b99 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/analysis/PlayerCountPart.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/analysis/PlayerCountPart.java @@ -44,6 +44,11 @@ public class PlayerCountPart extends RawData { this.uuids.addAll(uuids); } + public void addOPs(Collection uuids) { + Verify.nullCheck(uuids); + this.ops.addAll(uuids); + } + public void addOP(UUID uuid) { Verify.nullCheck(uuid); ops.add(uuid); diff --git a/Plan/src/main/java/com/djrapitops/plan/data/analysis/PlaytimePart.java b/Plan/src/main/java/com/djrapitops/plan/data/analysis/PlaytimePart.java index e1e13f962..bdd6e20e9 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/analysis/PlaytimePart.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/analysis/PlaytimePart.java @@ -16,6 +16,9 @@ import main.java.com.djrapitops.plan.utilities.FormatUtils; public class PlaytimePart extends RawData { private long totalPlaytime; + private long playtime30d; + private long playtime7d; + private long playtime24h; public PlaytimePart() { totalPlaytime = 0; @@ -24,9 +27,28 @@ public class PlaytimePart extends RawData { @Override public void analyse() { addValue("playtimeTotal", FormatUtils.formatTimeAmount(totalPlaytime)); + addValue("playtimeMonth", FormatUtils.formatTimeAmount(playtime30d)); + addValue("playtimeWeek", FormatUtils.formatTimeAmount(playtime7d)); + addValue("playtimeDay", FormatUtils.formatTimeAmount(playtime24h)); } public void addToPlaytime(long amount) { totalPlaytime += amount; } + + public void setTotalPlaytime(long totalPlaytime) { + this.totalPlaytime = totalPlaytime; + } + + public void setPlaytime30d(long playtime30d) { + this.playtime30d = playtime30d; + } + + public void setPlaytime7d(long playtime7d) { + this.playtime7d = playtime7d; + } + + public void setPlaytime24h(long playtime24h) { + this.playtime24h = playtime24h; + } } diff --git a/Plan/src/main/java/com/djrapitops/plan/data/analysis/WorldPart.java b/Plan/src/main/java/com/djrapitops/plan/data/analysis/WorldPart.java index dd880b3a8..d7c27abbb 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/analysis/WorldPart.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/analysis/WorldPart.java @@ -1,9 +1,10 @@ package main.java.com.djrapitops.plan.data.analysis; +import main.java.com.djrapitops.plan.data.time.WorldTimes; +import main.java.com.djrapitops.plan.utilities.FormatUtils; import main.java.com.djrapitops.plan.utilities.html.graphs.WorldPieCreator; import java.util.HashMap; -import java.util.Map; /** * Part responsible for all World Playtime related analysis. @@ -21,21 +22,23 @@ import java.util.Map; */ public class WorldPart extends RawData { - private final Map worldTimes; + private WorldTimes worldTimes; public WorldPart() { - worldTimes = new HashMap<>(); + worldTimes = new WorldTimes(new HashMap<>()); } @Override protected void analyse() { -// TODO WorldTimes t = new WorldTimes(worldTimes); -// addValue("worldTotal", FormatUtils.formatTimeAmount(t.getTotal())); + addValue("worldTotal", FormatUtils.formatTimeAmount(worldTimes.getTotal())); addValue("worldSeries", WorldPieCreator.createSeriesData(worldTimes)); } - public void addToWorld(String worldName, long playTime) { - Long value = worldTimes.getOrDefault(worldName, 0L); - worldTimes.put(worldName, value + playTime); + public void setWorldTimes(WorldTimes worldTimes) { + this.worldTimes = worldTimes; + } + + public WorldTimes getWorldTimes() { + return worldTimes; } } 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 9563b6b32..fb33de998 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 @@ -8,10 +8,7 @@ import main.java.com.djrapitops.plan.database.sql.TableSqlParser; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.UUID; +import java.util.*; /** * @author Rsl1122 @@ -67,6 +64,7 @@ public class IPsTable extends UserIDTable { statement = prepareStatement(Select.from(tableName, column) .where(columnUserID + "=" + usersTable.statementSelectID) .toString()); + statement.setFetchSize(50); statement.setString(1, uuid.toString()); set = statement.executeQuery(); while (set.next()) { @@ -128,4 +126,35 @@ public class IPsTable extends UserIDTable { close(set, statement); } } + + public Map> getAllGeolocations() throws SQLException { + PreparedStatement statement = null; + ResultSet set = null; + try { + Map> geoLocations = new HashMap<>(); + + String usersIDColumn = usersTable + "." + usersTable.getColumnID(); + String usersUUIDColumn = usersTable + "." + usersTable.getColumnUUID() + " as uuid"; + + statement = prepareStatement("SELECT " + + columnGeolocation + ", " + + usersUUIDColumn + + " FROM " + tableName + + " JOIN " + usersTable + " on " + usersIDColumn + "=" + columnUserID + ); + statement.setFetchSize(5000); + set = statement.executeQuery(); + while (set.next()) { + UUID uuid = UUID.fromString(set.getString("uuid")); + + List userGeoLocs = geoLocations.getOrDefault(uuid, new ArrayList<>()); + userGeoLocs.add(set.getString(columnGeolocation)); + geoLocations.put(uuid, userGeoLocs); + } + return geoLocations; + } finally { + endTransaction(statement); + close(set, 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 20c27c568..047851432 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 @@ -313,6 +313,16 @@ public class SessionsTable extends UserIDTable { } } + /** + * Used to get the Total Playtime of THIS Server. + * + * @return Milliseconds played on the server. 0 if server not found. + * @throws SQLException + */ + public long getPlaytimeOfServer() throws SQLException { + return getPlaytimeOfServer(Plan.getServerUUID()); + } + /** * Used to get the Total Playtime of a Server. * @@ -324,6 +334,17 @@ public class SessionsTable extends UserIDTable { return getPlaytimeOfServer(serverUUID, 0L); } + /** + * Used to get Playtime after a date of THIS Server. + * + * @param afterDate Epoch ms (Playtime after this date is calculated) + * @return Milliseconds played after given epoch ms on the server. 0 if server not found. + * @throws SQLException + */ + public long getPlaytimeOfServer(long afterDate) throws SQLException { + return getPlaytimeOfServer(Plan.getServerUUID(), afterDate); + } + /** * Used to get Playtime after a date of a Server. * @@ -425,4 +446,52 @@ public class SessionsTable extends UserIDTable { public String getColumnID() { return columnID; } + + public Map> getSessionInfoOfServer() throws SQLException { + return getSessionInfoOfServer(Plan.getServerUUID()); + } + + public Map> getSessionInfoOfServer(UUID serverUUID) throws SQLException { + Optional id = serverTable.getServerID(serverUUID); + if (!id.isPresent()) { + return new HashMap<>(); + } + int serverID = id.get(); + Map> sessionsByUser = new HashMap<>(); + PreparedStatement statement = null; + ResultSet set = null; + try { + String usersIDColumn = usersTable + "." + usersTable.getColumnID(); + String usersUUIDColumn = usersTable + "." + usersTable.getColumnUUID() + " as uuid"; + + statement = prepareStatement("SELECT " + + columnSessionStart + ", " + + columnSessionEnd + ", " + + columnDeaths + ", " + + columnMobKills + ", " + + usersUUIDColumn + + " FROM " + tableName + + " JOIN " + usersTable + " on " + usersIDColumn + "=" + columnUserID + + " WHERE " + columnServerID + "=" + serverTable.statementSelectServerID + ); + statement.setFetchSize(5000); + statement.setString(1, serverUUID.toString()); + set = statement.executeQuery(); + while (set.next()) { + UUID uuid = UUID.fromString(set.getString("uuid")); + long start = set.getLong(columnSessionStart); + long end = set.getLong(columnSessionEnd); + + int deaths = set.getInt(columnDeaths); + int mobKills = set.getInt(columnMobKills); + List sessions = sessionsByUser.getOrDefault(uuid, new ArrayList<>()); + sessions.add(new Session(serverID, start, end, deaths, mobKills)); + sessionsByUser.put(uuid, sessions); + } + return sessionsByUser; + } finally { + endTransaction(statement); + close(set, statement); + } + } } diff --git a/Plan/src/main/java/com/djrapitops/plan/database/tables/WorldTimesTable.java b/Plan/src/main/java/com/djrapitops/plan/database/tables/WorldTimesTable.java index fb79a221b..5102a9632 100644 --- a/Plan/src/main/java/com/djrapitops/plan/database/tables/WorldTimesTable.java +++ b/Plan/src/main/java/com/djrapitops/plan/database/tables/WorldTimesTable.java @@ -1,6 +1,7 @@ package main.java.com.djrapitops.plan.database.tables; import com.djrapitops.plugin.utilities.Verify; +import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.data.Session; import main.java.com.djrapitops.plan.data.time.GMTimes; import main.java.com.djrapitops.plan.data.time.WorldTimes; @@ -154,4 +155,51 @@ public class WorldTimesTable extends UserIDTable { close(set, statement); } } + + public WorldTimes getWorldTimesOfServer() throws SQLException { + return getWorldTimesOfServer(Plan.getServerUUID()); + } + + public WorldTimes getWorldTimesOfServer(UUID serverUUID) throws SQLException { + PreparedStatement statement = null; + ResultSet set = null; + try { + String worldIDColumn = worldTable + "." + worldTable.getColumnID(); + String worldNameColumn = worldTable + "." + worldTable.getColumnWorldName() + " as world_name"; + String sessionIDColumn = sessionsTable + "." + sessionsTable.getColumnID(); + String sessionServerIDColumn = sessionsTable + ".server_id"; + statement = prepareStatement("SELECT " + + "SUM(" + columnSurvival + ") as survival, " + + "SUM(" + columnCreative + ") as creative, " + + "SUM(" + columnAdventure + ") as adventure, " + + "SUM(" + columnSpectator + ") as spectator, " + + worldNameColumn + + " FROM " + tableName + + " JOIN " + worldTable + " on " + worldIDColumn + "=" + columnWorldId + + " JOIN " + sessionsTable + " on " + sessionIDColumn + "=" + columnSessionID + + " WHERE " + sessionServerIDColumn + "=" + db.getServerTable().statementSelectServerID + ); + statement.setString(1, serverUUID.toString()); + set = statement.executeQuery(); + String[] gms = GMTimes.getGMKeyArray(); + + WorldTimes worldTimes = new WorldTimes(new HashMap<>()); + while (set.next()) { + String worldName = set.getString("world_name"); + + Map gmMap = new HashMap<>(); + gmMap.put(gms[0], set.getLong("survival")); + gmMap.put(gms[1], set.getLong("creative")); + gmMap.put(gms[2], set.getLong("adventure")); + gmMap.put(gms[3], set.getLong("spectator")); + GMTimes gmTimes = new GMTimes(gmMap); + + worldTimes.setGMTimesForWorld(worldName, gmTimes); + } + return worldTimes; + } finally { + endTransaction(statement); + close(set, statement); + } + } } diff --git a/Plan/src/main/java/com/djrapitops/plan/systems/cache/SessionCache.java b/Plan/src/main/java/com/djrapitops/plan/systems/cache/SessionCache.java index 27ca8b801..ecdcb2842 100644 --- a/Plan/src/main/java/com/djrapitops/plan/systems/cache/SessionCache.java +++ b/Plan/src/main/java/com/djrapitops/plan/systems/cache/SessionCache.java @@ -66,7 +66,6 @@ public class SessionCache { * * @return key:value UUID:Session */ - @Deprecated public Map getActiveSessions() { return activeSessions; } diff --git a/Plan/src/main/java/com/djrapitops/plan/systems/info/InformationManager.java b/Plan/src/main/java/com/djrapitops/plan/systems/info/InformationManager.java index d8761edab..22b872fbc 100644 --- a/Plan/src/main/java/com/djrapitops/plan/systems/info/InformationManager.java +++ b/Plan/src/main/java/com/djrapitops/plan/systems/info/InformationManager.java @@ -4,15 +4,20 @@ */ package main.java.com.djrapitops.plan.systems.info; +import com.djrapitops.plugin.command.ISender; import main.java.com.djrapitops.plan.Plan; +import main.java.com.djrapitops.plan.command.commands.AnalyzeCommand; import main.java.com.djrapitops.plan.data.AnalysisData; import main.java.com.djrapitops.plan.database.Database; import main.java.com.djrapitops.plan.systems.cache.DataCache; import main.java.com.djrapitops.plan.systems.cache.SessionCache; import main.java.com.djrapitops.plan.systems.info.parsing.UrlParser; import main.java.com.djrapitops.plan.utilities.MiscUtils; +import main.java.com.djrapitops.plan.utilities.analysis.Analysis; +import java.util.HashSet; import java.util.Optional; +import java.util.Set; import java.util.UUID; /** @@ -30,7 +35,10 @@ public class InformationManager { private boolean usingBungeeWebServer; private String webServerAddress; + private final Set analysisNotification; + private final Analysis analysis; private AnalysisData analysisData; + private String analysisPluginsTab; private Long refreshDate; public InformationManager(Plan plugin) { @@ -41,6 +49,8 @@ public class InformationManager { .ifPresent(address -> webServerAddress = address); dataCache = new DataCache(plugin); + analysis = new Analysis(plugin); + analysisNotification = new HashSet<>(); if (webServerAddress != null) { attemptBungeeConnection(); @@ -65,7 +75,7 @@ public class InformationManager { } public void refreshAnalysis() { - plugin.addToProcessQueue(); // TODO Analysis, PluginData + analysis.runAnalysis(this); } public DataCache getDataCache() { @@ -99,6 +109,13 @@ public class InformationManager { public void cacheAnalysisdata(AnalysisData analysisData) { this.analysisData = analysisData; refreshDate = MiscUtils.getTime(); + // TODO Web Caching + AnalyzeCommand.sendAnalysisMessage(analysisNotification); + analysisNotification.clear(); + } + + public void addAnalysisNotification(ISender sender) { + analysisNotification.add(sender); } public AnalysisData getAnalysisData() { diff --git a/Plan/src/main/java/com/djrapitops/plan/utilities/analysis/Analysis.java b/Plan/src/main/java/com/djrapitops/plan/utilities/analysis/Analysis.java index cffdad65d..298a68d65 100644 --- a/Plan/src/main/java/com/djrapitops/plan/utilities/analysis/Analysis.java +++ b/Plan/src/main/java/com/djrapitops/plan/utilities/analysis/Analysis.java @@ -1,15 +1,19 @@ package main.java.com.djrapitops.plan.utilities.analysis; +import com.djrapitops.plugin.api.TimeAmount; import com.djrapitops.plugin.task.AbsRunnable; import com.djrapitops.plugin.utilities.Verify; import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.data.AnalysisData; +import main.java.com.djrapitops.plan.data.Session; import main.java.com.djrapitops.plan.data.TPS; +import main.java.com.djrapitops.plan.data.UserInfo; import main.java.com.djrapitops.plan.data.additional.AnalysisType; import main.java.com.djrapitops.plan.data.additional.HookHandler; import main.java.com.djrapitops.plan.data.additional.PluginData; import main.java.com.djrapitops.plan.data.analysis.*; +import main.java.com.djrapitops.plan.data.time.WorldTimes; import main.java.com.djrapitops.plan.database.Database; import main.java.com.djrapitops.plan.locale.Locale; import main.java.com.djrapitops.plan.locale.Msg; @@ -24,6 +28,7 @@ import main.java.com.djrapitops.plan.utilities.MiscUtils; import main.java.com.djrapitops.plan.utilities.html.HtmlUtils; import java.io.Serializable; +import java.sql.SQLException; import java.util.*; import java.util.stream.Collectors; @@ -91,7 +96,7 @@ public class Analysis { Log.toLog(this.getClass().getName(), ex); } - return analyzeData(tpsData, infoManager); + return analyzeData(tpsData, infoManager, db); } /** @@ -99,7 +104,7 @@ public class Analysis { * @param infoManager InformationManager of the plugin. * @return */ - public boolean analyzeData(List tpsData, InformationManager infoManager) { + public boolean analyzeData(List tpsData, InformationManager infoManager, Database db) { try { // rawData.sort(new UserDataLastPlayedComparator()); // List uuids = rawData.stream().map(UserInfo::getUuid).collect(Collectors.toList()); @@ -130,7 +135,7 @@ public class Analysis { // String playersTable = PlayersTableCreator.createSortablePlayersTable(rawData); // analysisData.setPlayersTable(playersTable); - fillDataset(analysisData); + fillDataset(analysisData, db); // Analyze analysisData.analyseData(); Benchmark.stop("Analysis", "Analysis Phase"); @@ -235,60 +240,64 @@ public class Analysis { taskId = id; } - private void fillDataset(AnalysisData analysisData) { + private void fillDataset(AnalysisData analysisData, Database db) { ActivityPart activity = analysisData.getActivityPart(); GeolocationPart geolocPart = analysisData.getGeolocationPart(); JoinInfoPart joinInfo = analysisData.getJoinInfoPart(); - KillPart killPart = analysisData.getKillPart(); PlayerCountPart playerCount = analysisData.getPlayerCountPart(); PlaytimePart playtime = analysisData.getPlaytimePart(); WorldPart worldPart = analysisData.getWorldPart(); long now = MiscUtils.getTime(); - Benchmark.start("Fill Dataset"); - List banSources = plugin.getHookHandler().getAdditionalDataSources() - .stream().filter(PluginData::isBanData).collect(Collectors.toList()); -// rawData.forEach(uData -> { -// TODO Map worldTimes = uData.getWorldTimes().getTimes(); + Benchmark.start("Fetch Phase"); + try { + List userInfo = db.getUserInfoTable().getAllUserInfo(); + playerCount.addPlayers(userInfo.stream().map(UserInfo::getUuid).collect(Collectors.toSet())); - // TODO playtime.addToPlaytime(playTime); -// joinInfo.addToLoginTimes(uData.getLoginTimes()); -// joinInfo.addRegistered(uData.getRegistered()); + Map registered = userInfo.stream().collect(Collectors.toMap(UserInfo::getUuid, UserInfo::getRegistered)); + joinInfo.addRegistered(registered); + activity.addBans(userInfo.stream().filter(UserInfo::isBanned).map(UserInfo::getUuid).collect(Collectors.toSet())); - //TODO geolocPart.addGeolocation(uData.getGeolocation()); + playerCount.addOPs(userInfo.stream().filter(UserInfo::isOpped).map(UserInfo::getUuid).collect(Collectors.toSet())); -// final UUID uuid = uData.getUuid(); -// if (uData.isOp()) { -// playerCount.addOP(uuid); -// } + Map activeSessions = plugin.getDataCache().getActiveSessions(); + Map> sessions = db.getSessionsTable().getSessionInfoOfServer(); + joinInfo.addActiveSessions(activeSessions); + joinInfo.addSessions(sessions); -// boolean banned = uData.isBanned(); -// if (!banned) { -// banned = banSources.stream() -// .anyMatch(banData -> { -// Serializable value = banData.getValue(uuid); -// if (value instanceof Boolean) { -// return (Boolean) value; -// } -// return false; -// }); -// } -// -// if (banned) { -// activity.addBan(uuid); -// } else if (uData.getLoginTimes() == 1) { -// activity.addJoinedOnce(uuid); -// TODO } else if (AnalysisUtils.isActive(now, uData.getLastPlayed(), playTime, uData.getSessionCount())) { -// activity.addActive(uuid); -// } else { -// activity.addInActive(uuid); -// } - //TODO List playerKills = uData.getPlayerKills(); + Map> geolocations = db.getIpsTable().getAllGeolocations(); + geolocPart.addGeoLocations(geolocations); -// List sessions = uData.getSessions(); -// joinInfo.addSessions(uuid, sessions); -// }); - Benchmark.stop("Analysis", "Fill Dataset"); + WorldTimes worldTimes = db.getWorldTimesTable().getWorldTimesOfServer(); + worldPart.setWorldTimes(worldTimes); + + playtime.setTotalPlaytime(db.getSessionsTable().getPlaytimeOfServer()); + playtime.setPlaytime30d(db.getSessionsTable().getPlaytimeOfServer(now - TimeAmount.MONTH.ms())); + playtime.setPlaytime7d(db.getSessionsTable().getPlaytimeOfServer(now - TimeAmount.WEEK.ms())); + playtime.setPlaytime24h(db.getSessionsTable().getPlaytimeOfServer(now - TimeAmount.DAY.ms())); + + List banSources = plugin.getHookHandler().getAdditionalDataSources() + .stream().filter(PluginData::isBanData).collect(Collectors.toList()); + + for (UUID uuid : playerCount.getUuids()) { + boolean banned = banSources.stream().anyMatch(pluginData -> { + try { + Serializable value = pluginData.getValue(uuid); + return value instanceof Boolean + && (boolean) value; + } catch (Exception | NoClassDefFoundError | NoSuchMethodError | NoSuchFieldError e) { + Log.toLog(pluginData.getSourcePlugin() + pluginData.getPlaceholder("") + " (Cause) ", e); + return false; + } + }); + if (banned) { + activity.addBan(uuid); + } + } + } catch (SQLException e) { + Log.toLog(this.getClass().getName(), e); + } + Benchmark.stop("Analysis", "Fetch Phase"); } } diff --git a/Plan/src/main/java/com/djrapitops/plan/utilities/html/graphs/WorldPieCreator.java b/Plan/src/main/java/com/djrapitops/plan/utilities/html/graphs/WorldPieCreator.java index 2aef8209e..be507280d 100644 --- a/Plan/src/main/java/com/djrapitops/plan/utilities/html/graphs/WorldPieCreator.java +++ b/Plan/src/main/java/com/djrapitops/plan/utilities/html/graphs/WorldPieCreator.java @@ -1,6 +1,6 @@ package main.java.com.djrapitops.plan.utilities.html.graphs; -import java.util.Map; +import main.java.com.djrapitops.plan.data.time.WorldTimes; public class WorldPieCreator { @@ -8,25 +8,27 @@ public class WorldPieCreator { throw new IllegalStateException("Utility Class"); } - public static String createSeriesData(Map worldTimes) { - StringBuilder arrayBuilder = new StringBuilder("["); - int i = 0; - int size = worldTimes.size(); - for (Map.Entry world : worldTimes.entrySet()) { - arrayBuilder.append("{name:'").append(world.getKey()) - .append("',y:").append(world.getValue()); - - if (i == 1) { - arrayBuilder.append(", sliced: true, selected: true"); - } - - arrayBuilder.append("}"); - if (i < size - 1) { - arrayBuilder.append(","); - } - i++; - } - arrayBuilder.append("]"); - return arrayBuilder.toString(); + public static String createSeriesData(WorldTimes worldTimes) { + // TODO Rewrite WorldPie +// StringBuilder arrayBuilder = new StringBuilder("["); +// int i = 0; +// int size = worldTimes.size(); +// for (Map.Entry world : worldTimes.entrySet()) { +// arrayBuilder.append("{name:'").append(world.getKey()) +// .append("',y:").append(world.getValue()); +// +// if (i == 1) { +// arrayBuilder.append(", sliced: true, selected: true"); +// } +// +// arrayBuilder.append("}"); +// if (i < size - 1) { +// arrayBuilder.append(","); +// } +// i++; +// } +// arrayBuilder.append("]"); +// return arrayBuilder.toString(); + return "[]"; } }