diff --git a/Plan/src/main/java/com/djrapitops/plan/Phrase.java b/Plan/src/main/java/com/djrapitops/plan/Phrase.java index ed9646c69..7aa65f915 100644 --- a/Plan/src/main/java/com/djrapitops/plan/Phrase.java +++ b/Plan/src/main/java/com/djrapitops/plan/Phrase.java @@ -73,8 +73,8 @@ public enum Phrase { ANALYSIS_FETCH_DATA(ANALYSIS + "Fetching Data.."), ANALYSIS_FAIL_NO_PLAYERS(ANALYSIS + "Analysis failed, no known players."), ANALYSIS_FAIL_NO_DATA(ANALYSIS + "Analysis failed, no data in the database."), - ANALYSIS_BEGIN_ANALYSIS(ANALYSIS + "Data Fetched, beginning Analysis of data.."), - ANALYSIS_COMPLETE(ANALYSIS + "Analysis Complete."), + ANALYSIS_BEGIN_ANALYSIS(ANALYSIS + "Data Fetched (REPLACE0 users, took REPLACE1ms), beginning Analysis of data.."), + ANALYSIS_COMPLETE(ANALYSIS + "Analysis Complete. (took REPLACE0ms) REPLACE1"), DATA_CORRUPTION_WARN("Some data might be corrupted: " + REPLACE0), // ERROR_CONSOLE_PLAYER("This point of code should not be accessable on console. Inform author: " + REPLACE0 + " Console: REPLACE1"), @@ -113,6 +113,10 @@ public enum Phrase { CMD_MANAGE_HELP_HEADER(CMD_FOOTER + "" + COLOR_MAIN.color() + " Player Analytics - Managment Help"), CMD_MANAGE_STATUS_HEADER(CMD_FOOTER + "" + COLOR_MAIN.color() + " Player Analytics - Database status"), CMD_MANAGE_STATUS_ACTIVE_DB(CMD_BALL + "" + COLOR_MAIN.color() + " Active Database: " + COLOR_SEC.color() + "REPLACE0"), + CMD_MANAGE_STATUS_QUEUE_SAVE(CMD_BALL + "" + COLOR_MAIN.color() + " Save Queue Size: " + COLOR_SEC.color() + "REPLACE0/"+Settings.PROCESS_SAVE_LIMIT.getNumber()), + CMD_MANAGE_STATUS_QUEUE_GET(CMD_BALL + "" + COLOR_MAIN.color() + " Get Queue Size: " + COLOR_SEC.color() + "REPLACE0/"+Settings.PROCESS_GET_LIMIT.getNumber()), + CMD_MANAGE_STATUS_QUEUE_CLEAR(CMD_BALL + "" + COLOR_MAIN.color() + " Clear Queue Size: " + COLOR_SEC.color() + "REPLACE0/"+Settings.PROCESS_CLEAR_LIMIT.getNumber()), + CMD_MANAGE_STATUS_QUEUE_PROCESS(CMD_BALL + "" + COLOR_MAIN.color() + " Process Queue Size: " + COLOR_SEC.color() + "REPLACE0/20000"), CMD_CLICK_ME("Click Me"), CMD_LINK(COLOR_SEC.color() + " " + BALL + COLOR_MAIN.color() + " Link: " + COLOR_TER.color()), CMD_PASS_PLANLITE("UNUSED"), diff --git a/Plan/src/main/java/com/djrapitops/plan/Plan.java b/Plan/src/main/java/com/djrapitops/plan/Plan.java index 440480da3..eae10e623 100644 --- a/Plan/src/main/java/com/djrapitops/plan/Plan.java +++ b/Plan/src/main/java/com/djrapitops/plan/Plan.java @@ -62,6 +62,7 @@ public class Plan extends JavaPlugin { private HashSet databases; private WebSocketServer uiServer; private HookHandler hookHandler; + private ServerVariableHolder variable; private int bootAnalysisTaskID; @@ -80,7 +81,9 @@ public class Plan extends JavaPlugin { getDataFolder().mkdirs(); initLocale(); - + + variable = new ServerVariableHolder(this); + databases = new HashSet<>(); databases.add(new MySQLDB(this)); databases.add(new SQLiteDB(this)); @@ -130,6 +133,7 @@ public class Plan extends JavaPlugin { } hookHandler = new HookHandler(); + Log.debug("Verboose debug messages are enabled."); Log.info(Phrase.ENABLED + ""); } @@ -385,6 +389,10 @@ public class Plan extends JavaPlugin { Log.info("Using locale: " + usingLocale); } + public ServerVariableHolder getVariable() { + return variable; + } + /** * Used to get the current instance of Plan. * diff --git a/Plan/src/main/java/com/djrapitops/plan/ServerVariableHolder.java b/Plan/src/main/java/com/djrapitops/plan/ServerVariableHolder.java new file mode 100644 index 000000000..0a3193a63 --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/ServerVariableHolder.java @@ -0,0 +1,20 @@ +package main.java.com.djrapitops.plan; + +/** + * + * @author Rsl1122 + */ +public class ServerVariableHolder { + + private int maxPlayers; + + public ServerVariableHolder(Plan plugin) { + maxPlayers = plugin.getServer().getMaxPlayers(); + } + + public int getMaxPlayers() { + return maxPlayers; + } + + +} diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageStatusCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageStatusCommand.java index b256b59b0..1e304be3f 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageStatusCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageStatusCommand.java @@ -5,7 +5,6 @@ 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 org.bukkit.ChatColor; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; @@ -31,13 +30,17 @@ public class ManageStatusCommand extends SubCommand { @Override public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) { - ChatColor hColor = Phrase.COLOR_TER.color(); + String[] messages = new String[]{ + Phrase.CMD_MANAGE_STATUS_HEADER + "", + Phrase.CMD_MANAGE_STATUS_ACTIVE_DB.parse(plugin.getDB().getConfigName()), + Phrase.CMD_MANAGE_STATUS_QUEUE_PROCESS.parse("" + plugin.getHandler().getProcessTask().size()), + Phrase.CMD_MANAGE_STATUS_QUEUE_SAVE.parse("" + plugin.getHandler().getSaveTask().size()), + Phrase.CMD_MANAGE_STATUS_QUEUE_GET.parse("" + plugin.getHandler().getGetTask().size()), + Phrase.CMD_MANAGE_STATUS_QUEUE_CLEAR.parse("" + plugin.getHandler().getClearTask().size()), + Phrase.CMD_FOOTER + "" + }; - sender.sendMessage(Phrase.CMD_MANAGE_STATUS_HEADER + ""); - - sender.sendMessage(Phrase.CMD_MANAGE_STATUS_ACTIVE_DB.parse(plugin.getDB().getConfigName())); - - sender.sendMessage(hColor + Phrase.ARROWS_RIGHT.toString()); + sender.sendMessage(messages); return true; } } diff --git a/Plan/src/main/java/com/djrapitops/plan/data/SessionData.java b/Plan/src/main/java/com/djrapitops/plan/data/SessionData.java index c0d46d68d..d80aef7b1 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/SessionData.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/SessionData.java @@ -32,6 +32,10 @@ public class SessionData { this.sessionEnd = sessionEnd; } + public SessionData(SessionData s) { + this.sessionStart = s.getSessionStart(); + this.sessionEnd = s.getSessionEnd(); + } /** * Ends the session with given end point. * diff --git a/Plan/src/main/java/com/djrapitops/plan/data/additional/advancedachievements/AdvancedAchievementsAchievements.java b/Plan/src/main/java/com/djrapitops/plan/data/additional/advancedachievements/AdvancedAchievementsAchievements.java index f0c1d0b11..9a4cc413d 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/additional/advancedachievements/AdvancedAchievementsAchievements.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/additional/advancedachievements/AdvancedAchievementsAchievements.java @@ -42,22 +42,24 @@ public class AdvancedAchievementsAchievements extends PluginData { @Override public String getHtmlReplaceValue(String modifierPrefix, UUID uuid) { - if (MiscUtils.getTime()- lastRefresh > 60000) { + if (MiscUtils.getTime() - lastRefresh > 60000) { totalAchievements = aaAPI.getPlayersTotalAchievements(); } - if (totalAchievements.containsKey(uuid)) { - return parseContainer(modifierPrefix,totalAchievements.get(uuid) + ""); + Integer total = totalAchievements.get(uuid); + if (total != null) { + return parseContainer(modifierPrefix, total + ""); } - return parseContainer(modifierPrefix, 0+""); + return parseContainer(modifierPrefix, 0 + ""); } @Override public Serializable getValue(UUID uuid) { - if (MiscUtils.getTime()- lastRefresh > 60000) { + if (MiscUtils.getTime() - lastRefresh > 60000) { totalAchievements = aaAPI.getPlayersTotalAchievements(); } - if (totalAchievements.containsKey(uuid)) { - return totalAchievements.get(uuid); + Integer total = totalAchievements.get(uuid); + if (total != null) { + return total; } 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 c03a9c849..53d593741 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 @@ -64,7 +64,6 @@ public class DataCacheHandler extends LocationCache { // Variables private int timesSaved; - private int maxPlayers; /** * Class Constructor. @@ -83,7 +82,6 @@ public class DataCacheHandler extends LocationCache { startQueues(); timesSaved = 0; - maxPlayers = plugin.getServer().getMaxPlayers(); commandUse = new HashMap<>(); if (!getCommandUseFromDb()) { @@ -253,7 +251,7 @@ public class DataCacheHandler extends LocationCache { saveTask.stop(); getTask.stop(); clearTask.stop(); - List toProcess = processTask.stop(); + List toProcess = processTask.stopAndReturnLeftovers(); Benchmark.start("ProcessOnlineHandlingInfo"); Log.debug("ToProcess size: " + toProcess.size() + " DataCache size: " + dataCache.keySet().size()); Collection onlinePlayers = Bukkit.getOnlinePlayers(); @@ -337,7 +335,7 @@ public class DataCacheHandler extends LocationCache { */ public void saveCommandUse() { try { - db.saveCommandUse(commandUse); + db.saveCommandUse(new HashMap<>(commandUse)); } catch (SQLException | NullPointerException e) { Log.toLog(this.getClass().getName(), e); } @@ -347,15 +345,23 @@ public class DataCacheHandler extends LocationCache { * Refreshes the calculations for all online players with ReloadInfo. */ public void saveHandlerDataToCache() { - Bukkit.getServer().getOnlinePlayers().parallelStream().forEach((p) -> { - saveHandlerDataToCache(p); + Bukkit.getServer().getOnlinePlayers().stream().forEach((p) -> { + saveHandlerDataToCache(p, false); }); } - private void saveHandlerDataToCache(Player player) { + private void saveHandlerDataToCache(Player player, boolean pool) { long time = MiscUtils.getTime(); UUID uuid = player.getUniqueId(); - addToPool(new ReloadInfo(uuid, time, player.getAddress().getAddress(), player.isBanned(), player.getDisplayName(), player.getGameMode())); + ReloadInfo info = new ReloadInfo(uuid, time, player.getAddress().getAddress(), player.isBanned(), player.getDisplayName(), player.getGameMode()); + if (!pool) { + UserData data = dataCache.get(uuid); + if (data != null) { + info.process(data); + return; + } + } + addToPool(info); } /** @@ -474,22 +480,13 @@ public class DataCacheHandler extends LocationCache { newPlayer(player); } startSession(uuid); - saveHandlerDataToCache(player); + saveHandlerDataToCache(player, true); } this.cancel(); } }).runTaskAsynchronously(plugin); } - /** - * Used by Analysis for Player activity graphs. - * - * @return Maximum number of players defined in server.properties. - */ - public int getMaxPlayers() { - return maxPlayers; - } - /** * Used to handle a command's execution. * @@ -501,4 +498,20 @@ public class DataCacheHandler extends LocationCache { } commandUse.put(command, commandUse.get(command) + 1); } + + public DataCacheSaveQueue getSaveTask() { + return saveTask; + } + + public DataCacheClearQueue getClearTask() { + return clearTask; + } + + public DataCacheProcessQueue getProcessTask() { + return processTask; + } + + public DataCacheGetQueue getGetTask() { + return getTask; + } } 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 b8a34b66f..7b293c13e 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,5 +1,6 @@ package main.java.com.djrapitops.plan.data.cache; +import java.io.IOException; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; @@ -13,6 +14,7 @@ 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.utilities.MiscUtils; +import main.java.com.djrapitops.plan.utilities.analysis.ExportUtility; /** * This class stores UserData objects used for displaying the Html pages. @@ -53,6 +55,11 @@ public class InspectCacheHandler { public void process(UserData data) { cache.put(uuid, new UserData(data)); cacheTimes.put(uuid, MiscUtils.getTime()); + try { + ExportUtility.writeInspectHtml(data, ExportUtility.getPlayersFolder(ExportUtility.getFolder())); + } catch (IOException ex) { + Log.toLog(this.getClass().getName(), ex); + } } }; handler.getUserDataForProcessing(cacher, uuid, false); @@ -81,7 +88,7 @@ public class InspectCacheHandler { long time = MiscUtils.getTime(); for (UserData uData : userDataForUUIDS) { UUID uuid = uData.getUuid(); - cache.put(uuid, uData); + cache.put(uuid, new UserData(uData)); cacheTimes.put(uuid, time); } } diff --git a/Plan/src/main/java/com/djrapitops/plan/data/cache/queue/Consumer.java b/Plan/src/main/java/com/djrapitops/plan/data/cache/queue/Consumer.java new file mode 100644 index 000000000..17048e9cf --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/data/cache/queue/Consumer.java @@ -0,0 +1,43 @@ +package main.java.com.djrapitops.plan.data.cache.queue; + +import java.util.concurrent.BlockingQueue; + +/** + * Abstract class representing a queue consumer. + * + * @author Rsl1122 + * @param + */ +public abstract class Consumer implements Runnable { + + boolean run; + final BlockingQueue queue; + + /** + * Constructor, defines queue. + * + * @param queue Queue to consume from. + */ + public Consumer(BlockingQueue queue) { + this.queue = queue; + run = true; + } + + @Override + public void run() { + try { + while (run) { + consume(queue.take()); + } + } catch (InterruptedException ex) { + } + } + + void stop() { + run = false; + } + + abstract void clearVariables(); + + abstract void consume(T toConsume); +} diff --git a/Plan/src/main/java/com/djrapitops/plan/data/cache/queue/DataCacheClearQueue.java b/Plan/src/main/java/com/djrapitops/plan/data/cache/queue/DataCacheClearQueue.java index feda61ab3..0cc2683a0 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/cache/queue/DataCacheClearQueue.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/cache/queue/DataCacheClearQueue.java @@ -15,10 +15,7 @@ import main.java.com.djrapitops.plan.data.cache.DataCacheHandler; * @author Rsl1122 * @since 3.0.0 */ -public class DataCacheClearQueue { - - private BlockingQueue q; - private ClearSetup s; +public class DataCacheClearQueue extends Queue{ /** * Class constructor, starts the new Thread for clearing. @@ -26,9 +23,9 @@ public class DataCacheClearQueue { * @param handler current instance of DataCachehandler. */ public DataCacheClearQueue(DataCacheHandler handler) { - q = new ArrayBlockingQueue(Settings.PROCESS_CLEAR_LIMIT.getNumber()); - s = new ClearSetup(); - s.go(q, handler); + super(new ArrayBlockingQueue(Settings.PROCESS_CLEAR_LIMIT.getNumber())); + setup = new ClearSetup(queue, handler); + setup.go(); } /** @@ -38,7 +35,7 @@ public class DataCacheClearQueue { */ public void scheduleForClear(UUID uuid) { Log.debug(uuid + ": Scheduling for clear"); - q.add(uuid); + queue.add(uuid); } /** @@ -52,46 +49,23 @@ public class DataCacheClearQueue { } Log.debug("Scheduling for clear: " + uuids); try { - q.addAll(uuids); + queue.addAll(uuids); } catch (IllegalStateException e) { Log.error(Phrase.ERROR_TOO_SMALL_QUEUE.parse("Clear Queue", Settings.PROCESS_CLEAR_LIMIT.getNumber() + "")); } } - - /** - * Stops all activity and clears the queue. - */ - public void stop() { - if (s != null) { - s.stop(); - } - s = null; - q.clear(); - } } -class ClearConsumer implements Runnable { +class ClearConsumer extends Consumer implements Runnable { - private final BlockingQueue queue; private DataCacheHandler handler; - private boolean run; ClearConsumer(BlockingQueue q, DataCacheHandler handler) { - queue = q; + super(q); this.handler = handler; - run = true; } @Override - public void run() { - try { - while (run) { - consume(queue.take()); - } - } catch (InterruptedException ex) { - } - } - void consume(UUID uuid) { if (handler == null) { return; @@ -108,24 +82,16 @@ class ClearConsumer implements Runnable { } } - void stop() { - run = false; + @Override + void clearVariables() { if (handler != null) { handler = null; } } } -class ClearSetup { - - private ClearConsumer one; - - void go(BlockingQueue q, DataCacheHandler handler) { - one = new ClearConsumer(q, handler); - new Thread(one).start(); - } - - void stop() { - one.stop(); +class ClearSetup extends Setup { + public ClearSetup(BlockingQueue q, DataCacheHandler handler) { + super(new ClearConsumer(q, handler)); } } diff --git a/Plan/src/main/java/com/djrapitops/plan/data/cache/queue/DataCacheGetQueue.java b/Plan/src/main/java/com/djrapitops/plan/data/cache/queue/DataCacheGetQueue.java index a173de89f..3af466867 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/cache/queue/DataCacheGetQueue.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/cache/queue/DataCacheGetQueue.java @@ -5,6 +5,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.UUID; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; @@ -21,10 +22,7 @@ import main.java.com.djrapitops.plan.database.Database; * @author Rsl1122 * @since 3.0.0 */ -public class DataCacheGetQueue { - - private BlockingQueue>> q; - private GetSetup s; +public class DataCacheGetQueue extends Queue>> { /** * Class constructor, starts the new Thread for fetching. @@ -32,9 +30,9 @@ public class DataCacheGetQueue { * @param plugin current instance of Plan */ public DataCacheGetQueue(Plan plugin) { - q = new ArrayBlockingQueue(Settings.PROCESS_GET_LIMIT.getNumber()); - s = new GetSetup(); - s.go(q, plugin.getDB()); + super(new ArrayBlockingQueue(Settings.PROCESS_GET_LIMIT.getNumber())); + setup = new GetSetup(queue, plugin.getDB()); + setup.go(); } /** @@ -47,52 +45,29 @@ public class DataCacheGetQueue { public void scheduleForGet(UUID uuid, DBCallableProcessor... processors) { Log.debug(uuid + ": Scheduling for get"); try { - HashMap> map = new HashMap<>(); + Map> map = new HashMap<>(); if (map.get(uuid) == null) { map.put(uuid, new ArrayList<>()); } map.get(uuid).addAll(Arrays.asList(processors)); - q.add(map); + queue.add(map); } catch (IllegalStateException e) { Log.error(Phrase.ERROR_TOO_SMALL_QUEUE.parse("Get Queue", Settings.PROCESS_GET_LIMIT.getNumber() + "")); } } - - /** - * Stops the activities and clears the queue. - */ - public void stop() { - if (s != null) { - s.stop(); - } - s = null; - q.clear(); - } } -class GetConsumer implements Runnable { +class GetConsumer extends Consumer>> { - private final BlockingQueue>> queue; private Database db; - private boolean run; GetConsumer(BlockingQueue q, Database db) { - queue = q; + super(q); this.db = db; - run = true; } @Override - public void run() { - try { - while (run) { - consume(queue.take()); - } - } catch (InterruptedException ex) { - } - } - - void consume(HashMap> processors) { + void consume(Map> processors) { if (db == null) { return; } @@ -116,28 +91,17 @@ class GetConsumer implements Runnable { } } - void stop() { - run = false; + @Override + void clearVariables() { if (db != null) { db = null; } } } -class GetSetup { +class GetSetup extends Setup>> { - private GetConsumer one; - private GetConsumer two; - - void go(BlockingQueue>> q, Database db) { - one = new GetConsumer(q, db); - two = new GetConsumer(q, db); - new Thread(one).start(); - new Thread(two).start(); - } - - void stop() { - one.stop(); - two.stop(); + GetSetup(BlockingQueue>> q, Database db) { + super(new GetConsumer(q, db), new GetConsumer(q, db)); } } diff --git a/Plan/src/main/java/com/djrapitops/plan/data/cache/queue/DataCacheProcessQueue.java b/Plan/src/main/java/com/djrapitops/plan/data/cache/queue/DataCacheProcessQueue.java index b84352a1e..d86d433ec 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/cache/queue/DataCacheProcessQueue.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/cache/queue/DataCacheProcessQueue.java @@ -20,10 +20,7 @@ import main.java.com.djrapitops.plan.data.handling.info.HandlingInfo; * @author Rsl1122 * @since 3.0.0 */ -public class DataCacheProcessQueue { - - private BlockingQueue queue; - private ProcessSetup setup; +public class DataCacheProcessQueue extends Queue { /** * Class constructor, starts the new Thread for processing. @@ -31,9 +28,9 @@ public class DataCacheProcessQueue { * @param handler current instance of DataCachehandler. */ public DataCacheProcessQueue(DataCacheHandler handler) { - queue = new ArrayBlockingQueue(20000); - setup = new ProcessSetup(); - setup.go(queue, handler); + super(new ArrayBlockingQueue(20000)); + setup = new ProcessSetup(queue, handler); + setup.go(); } /** @@ -72,48 +69,18 @@ public class DataCacheProcessQueue { public boolean containsUUID(UUID uuid) { return new ArrayList<>(queue).stream().map(d -> d.getUuid()).collect(Collectors.toList()).contains(uuid); } - - /** - * Stops all activites and clears the queue. - * - * @return unprocessed HandlingInfo objects. - */ - public List stop() { - try { - if (setup != null) { - setup.stop(); - return new ArrayList<>(queue); - } - return new ArrayList<>(); - } finally { - setup = null; - queue.clear(); - } - } } -class ProcessConsumer implements Runnable { +class ProcessConsumer extends Consumer { - private final BlockingQueue queue; private DataCacheHandler handler; - private boolean run; ProcessConsumer(BlockingQueue q, DataCacheHandler h) { + super(q); handler = h; - queue = q; - run = true; } @Override - public void run() { - try { - while (run) { - consume(queue.take()); - } - } catch (InterruptedException ex) { - } - } - void consume(HandlingInfo info) { if (handler == null) { return; @@ -130,28 +97,16 @@ class ProcessConsumer implements Runnable { handler.getUserDataForProcessing(p, info.getUuid()); } - void stop() { - run = false; + @Override + void clearVariables() { if (handler != null) { handler = null; } } } -class ProcessSetup { - - private ProcessConsumer one; - private ProcessConsumer two; - - void go(BlockingQueue q, DataCacheHandler h) { - one = new ProcessConsumer(q, h); - two = new ProcessConsumer(q, h); - new Thread(one).start(); - new Thread(two).start(); - } - - void stop() { - one.stop(); - two.stop(); +class ProcessSetup extends Setup { + ProcessSetup(BlockingQueue q, DataCacheHandler h) { + super(new ProcessConsumer(q, h), new ProcessConsumer(q, h)); } } 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 a8793bf12..505b08295 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 @@ -20,10 +20,7 @@ import main.java.com.djrapitops.plan.database.Database; * @author Rsl1122 * @since 3.0.0 */ -public class DataCacheSaveQueue { - - private BlockingQueue q; - private SaveSetup s; +public class DataCacheSaveQueue extends Queue{ /** * Class constructor, starts the new Thread for saving. @@ -33,9 +30,9 @@ public class DataCacheSaveQueue { * UserData.clearAfterSave() is true */ public DataCacheSaveQueue(Plan plugin, DataCacheClearQueue clear) { - q = new ArrayBlockingQueue(Settings.PROCESS_SAVE_LIMIT.getNumber()); - s = new SaveSetup(); - s.go(q, clear, plugin.getDB()); + super(new ArrayBlockingQueue(Settings.PROCESS_SAVE_LIMIT.getNumber())); + setup = new SaveSetup(queue, clear, plugin.getDB()); + setup.go(); } /** @@ -46,7 +43,7 @@ public class DataCacheSaveQueue { public void scheduleForSave(UserData data) { Log.debug(data.getUuid() + ": Scheduling for save"); try { - q.add(data); + queue.add(data); } catch (IllegalStateException e) { Log.error(Phrase.ERROR_TOO_SMALL_QUEUE.parse("Save Queue", Settings.PROCESS_SAVE_LIMIT.getNumber() + "")); } @@ -60,7 +57,7 @@ public class DataCacheSaveQueue { public void scheduleForSave(Collection data) { Log.debug("Scheduling for save: " + data.stream().map(u -> u.getUuid()).collect(Collectors.toList())); try { - q.addAll(data); + queue.addAll(data); } catch (IllegalStateException e) { Log.error(Phrase.ERROR_TOO_SMALL_QUEUE.parse("Save Queue", Settings.PROCESS_SAVE_LIMIT.getNumber() + "")); } @@ -74,7 +71,7 @@ public class DataCacheSaveQueue { public void scheduleNewPlayer(UserData data) { Log.debug(data.getUuid() + ": Scheduling new Player"); try { - q.add(data); + queue.add(data); } catch (IllegalStateException e) { Log.error(Phrase.ERROR_TOO_SMALL_QUEUE.parse("Save Queue", Settings.PROCESS_SAVE_LIMIT.getNumber() + "")); } @@ -87,45 +84,23 @@ public class DataCacheSaveQueue { * @return true/false */ public boolean containsUUID(UUID uuid) { - return new ArrayList<>(q).stream().map(d -> d.getUuid()).collect(Collectors.toList()).contains(uuid); - } - - /** - * Stops all activites and clears the queue. - */ - public void stop() { - if (s != null) { - s.stop(); - } - s = null; - q.clear(); + return new ArrayList<>(queue).stream().map(d -> d.getUuid()).collect(Collectors.toList()).contains(uuid); } } -class SaveConsumer implements Runnable { +class SaveConsumer extends Consumer { - private final BlockingQueue queue; private Database db; private DataCacheClearQueue clear; - private boolean run; SaveConsumer(BlockingQueue q, DataCacheClearQueue clear, Database db) { - queue = q; + super(q); this.db = db; this.clear = clear; run = true; } @Override - public void run() { - try { - while (run) { - consume(queue.take()); - } - } catch (InterruptedException ex) { - } - } - void consume(UserData data) { if (db == null) { return; @@ -147,8 +122,8 @@ class SaveConsumer implements Runnable { } } - void stop() { - run = false; + @Override + void clearVariables() { if (db != null) { db = null; } @@ -158,20 +133,8 @@ class SaveConsumer implements Runnable { } } -class SaveSetup { - - private SaveConsumer one; - private SaveConsumer two; - - void go(BlockingQueue q, DataCacheClearQueue clear, Database db) { - one = new SaveConsumer(q, clear, db); - two = new SaveConsumer(q, clear, db); - new Thread(one).start(); - new Thread(two).start(); - } - - void stop() { - one.stop(); - two.stop(); +class SaveSetup extends Setup{ + SaveSetup(BlockingQueue q, DataCacheClearQueue clear, Database db) { + super(new SaveConsumer(q, clear, db), new SaveConsumer(q, clear, db)); } } diff --git a/Plan/src/main/java/com/djrapitops/plan/data/cache/queue/Queue.java b/Plan/src/main/java/com/djrapitops/plan/data/cache/queue/Queue.java new file mode 100644 index 000000000..caf919e88 --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/data/cache/queue/Queue.java @@ -0,0 +1,72 @@ +package main.java.com.djrapitops.plan.data.cache.queue; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.BlockingQueue; + +/** + * Abstract implementation of a Queue. + * + * @author Rsl1122 + * @param Object this queue consumes + */ +public abstract class Queue { + + final BlockingQueue queue; + Setup setup; + + /** + * Consturctor, defines queue. + * + * @param queue BlockingQueue to use for this queue. + */ + public Queue(BlockingQueue queue) { + this.queue = queue; + } + + /** + * Add a object to the queue, default implementation. + * + * @param object Object to add. + */ + public void add(T object) { + queue.add(object); + } + + /** + * Used to stop the queue processing & get the unprocessed objects. + * + * @return List of unprocessed objects. + */ + public List stopAndReturnLeftovers() { + try { + if (setup != null) { + setup.stop(); + return new ArrayList<>(queue); + } + return new ArrayList<>(); + } finally { + stop(); + } + } + + /** + * Stops all activity and clears the queue. + */ + public void stop() { + if (setup != null) { + setup.stop(); + } + setup = null; + queue.clear(); + } + + /** + * Get how many objects are in the queue. + * + * @return size of the queue. + */ + public int size() { + return queue.size(); + } +} diff --git a/Plan/src/main/java/com/djrapitops/plan/data/cache/queue/Setup.java b/Plan/src/main/java/com/djrapitops/plan/data/cache/queue/Setup.java new file mode 100644 index 000000000..5421da2e3 --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/data/cache/queue/Setup.java @@ -0,0 +1,33 @@ +package main.java.com.djrapitops.plan.data.cache.queue; + +/** + * Abstract representation of a queue setup. + * + * @author Rsl1122 + * @param Object this queue consumes. + */ +public abstract class Setup { + + private Consumer[] consumers; + + /** + * Constructor, defines consumers. + * + * @param consumers Consumers for the new threads. + */ + public Setup(Consumer... consumers) { + this.consumers = consumers; + } + + void go() { + for (Consumer consumer : consumers) { + new Thread(consumer).start(); + } + } + + void stop() { + for (Consumer consumer : consumers) { + consumer.stop(); + } + } +} 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 9694ba467..88fdd1734 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 @@ -11,6 +11,7 @@ import java.util.Map; import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; +import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.Settings; import main.java.com.djrapitops.plan.data.SessionData; import main.java.com.djrapitops.plan.utilities.Benchmark; @@ -27,10 +28,9 @@ public class PlayerActivityGraphCreator { * * @param sessionData * @param scale - * @param maxPlayers * @return */ - public static String[] generateDataArray(List sessionData, long scale, int maxPlayers) { + public static String[] generateDataArray(List sessionData, long scale) { Benchmark.start("Generate Player Activity Graph " + sessionData.size() + " " + scale + " |"); long now = new Date().toInstant().getEpochSecond() * (long) 1000; long nowMinusScale = now - scale; @@ -75,17 +75,12 @@ public class PlayerActivityGraphCreator { for (int i = 0; i < playersOnline.size(); i++) { long value = playersOnline.get(i); if (value - average > 3 * standardDiviation) { - playersOnline.set(i, (long) maxPlayers + 10); + playersOnline.set(i, (long) Plan.getInstance().getVariable().getMaxPlayers() + 10); } } } } Benchmark.stop("Player Activity Graph Amount Calculation"); - playersOnline.add(0L); - playersOnline.add(0L); - playersOnline.add(0L); - playersOnline.add(0L); - playersOnline.add((long) maxPlayers); Benchmark.stop("Generate Player Activity Graph " + sessionData.size() + " " + scale + " |"); return new String[]{playersOnline.toString(), labels.toString()}; } @@ -142,7 +137,7 @@ public class PlayerActivityGraphCreator { public static List> filterAndTransformSessions(List sessionData, long nowMinusScale) { List values = sessionData.parallelStream() .filter(session -> (session != null)) - .filter(session -> session.isValid()) + .filter(session -> session.isValid() || session.getSessionEnd() == -1) .filter((session) -> (session.getSessionStart() >= nowMinusScale || session.getSessionEnd() >= nowMinusScale)) .map(session -> new Long[]{session.getSessionStart(), session.getSessionEnd()}) .collect(Collectors.toList()); @@ -150,7 +145,10 @@ public class PlayerActivityGraphCreator { List sessionEnds = new ArrayList<>(); for (Long[] startAndEnd : values) { sessionStarts.add(getSecond(startAndEnd[0])); - sessionEnds.add(getSecond(startAndEnd[1])); + Long end = startAndEnd[1]; + if (end != -1) { + sessionEnds.add(getSecond(end)); + } } List> r = new ArrayList<>(); r.add(sessionStarts); 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 index 501f3dbcd..dccdf5973 100644 --- a/Plan/src/main/java/com/djrapitops/plan/ui/graphs/PunchCardGraphCreator.java +++ b/Plan/src/main/java/com/djrapitops/plan/ui/graphs/PunchCardGraphCreator.java @@ -40,10 +40,6 @@ public class PunchCardGraphCreator { 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]; @@ -160,7 +156,7 @@ public class PunchCardGraphCreator { scaled[i][j] = value; } } - Log.debug("Biggest value: " + big); + Log.debug("Punchcard Biggest value: " + big); 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 index 83aee3e0c..7e716b354 100644 --- a/Plan/src/main/java/com/djrapitops/plan/ui/graphs/SessionLengthDistributionGraphCreator.java +++ b/Plan/src/main/java/com/djrapitops/plan/ui/graphs/SessionLengthDistributionGraphCreator.java @@ -39,9 +39,9 @@ public class SessionLengthDistributionGraphCreator { */ public static String[] generateDataArray(Collection lengths) { Map values = getValues(lengths); - Map scaled = scale(values); - StringBuilder arrayBuilder = buildString(scaled); - StringBuilder labelBuilder = buildLabels(scaled); +// Map scaled = scale(values); + StringBuilder arrayBuilder = buildString(values); + StringBuilder labelBuilder = buildLabels(values); return new String[]{arrayBuilder.toString(), labelBuilder.toString()}; } 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 7d40a8aee..198a71868 100644 --- a/Plan/src/main/java/com/djrapitops/plan/utilities/PlaceholderUtils.java +++ b/Plan/src/main/java/com/djrapitops/plan/utilities/PlaceholderUtils.java @@ -130,6 +130,7 @@ public class PlaceholderUtils { replaceMap.put("#" + defaultCols[i], "#" + colors[i]); } } + replaceMap.put("%graphmaxplayers%", plugin.getVariable().getMaxPlayers()+""); replaceMap.put("%refreshlong%", data.getRefreshDate()+""); replaceMap.put("%servername%", Settings.SERVER_NAME.toString()); Benchmark.stop("Replace Placeholders Anaysis"); @@ -205,7 +206,8 @@ public class PlaceholderUtils { Plan plugin = Plan.getInstance(); replaceMap.put("%version%", plugin.getDescription().getVersion()); replaceMap.put("%planlite%", ""); - String[] playersDataArray = PlayerActivityGraphCreator.generateDataArray(data.getSessions(), (long) 604800 * 1000, 2); + String[] playersDataArray = PlayerActivityGraphCreator.generateDataArray(data.getSessions(), (long) 604800 * 1000); + replaceMap.put("%graphmaxplayers%", 2+""); replaceMap.put("%dataweek%", playersDataArray[0]); replaceMap.put("%labelsweek%", playersDataArray[1]); replaceMap.put("%playersgraphcolor%", Settings.HCOLOR_ACT_ONL + ""); 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 4a979b923..58d2ee5ed 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 @@ -20,6 +20,7 @@ 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.cache.AnalysisCacheHandler; +import main.java.com.djrapitops.plan.data.cache.DataCacheHandler; import main.java.com.djrapitops.plan.data.cache.InspectCacheHandler; import main.java.com.djrapitops.plan.database.Database; import main.java.com.djrapitops.plan.ui.Html; @@ -99,7 +100,7 @@ public class Analysis { Log.info(Phrase.ANALYSIS_FAIL_NO_DATA + ""); return false; } - Benchmark.stop("Analysis Fetch Phase"); + ; return analyzeData(rawData, analysisCache); } @@ -115,11 +116,21 @@ public class Analysis { List uuids = rawData.stream().map(d -> d.getUuid()).collect(Collectors.toList()); Benchmark.stop("Analysis UUID transform"); Benchmark.start("Analysis Create Empty dataset"); - Map commandUse = plugin.getHandler().getCommandUse(); + DataCacheHandler handler = plugin.getHandler(); + Map activeSessions = handler.getActiveSessions(); long now = MiscUtils.getTime(); + rawData.stream().forEach((data) -> { + SessionData session = activeSessions.get(data.getUuid()); + List sessions = data.getSessions(); + if (session != null && !sessions.contains(session)) { + sessions.add(session); + } + }); + Map commandUse = handler.getCommandUse(); + AnalysisData analysisData = new AnalysisData(); Benchmark.stop("Analysis Create Empty dataset"); - log(Phrase.ANALYSIS_BEGIN_ANALYSIS + ""); + log(Phrase.ANALYSIS_BEGIN_ANALYSIS.parse(rawData.size() + "", Benchmark.stop("Analysis Fetch Phase") + "")); String playersTable = SortablePlayersTableCreator.createSortablePlayersTable(rawData); analysisData.setSortablePlayersTable(playersTable); @@ -150,14 +161,13 @@ public class Analysis { analysisData.setAdditionalDataReplaceMap(analyzeAdditionalPluginData(uuids)); analysisCache.cache(analysisData); - Benchmark.stop("Analysis"); + long time = Benchmark.stop("Analysis"); if (Settings.ANALYSIS_LOG_FINISHED.isTrue()) { - Log.info(Phrase.ANALYSIS_COMPLETE + ""); - } -// LocationAnalysis.performAnalysis(analysisData, plugin.getDB()); - if (Settings.ANALYSIS_EXPORT.isTrue()) { - ExportUtility.export(plugin, analysisData, rawData); + Log.info(Phrase.ANALYSIS_COMPLETE.parse(time + "", HtmlUtils.getServerAnalysisUrl())); } +// LocationAnalysis.performAnalysis(analysisData, plugin.getDB()); + ExportUtility.export(plugin, analysisData, rawData); + return true; } @@ -291,7 +301,6 @@ public class Analysis { long scaleDay = 86400 * 1000; long scaleWeek = 604800 * 1000; long scaleMonth = (long) 2592000 * (long) 1000; - int maxPlayers = plugin.getHandler().getMaxPlayers(); data.setNewPlayersDay(AnalysisUtils.getNewPlayers(registered, scaleDay, now)); data.setNewPlayersWeek(AnalysisUtils.getNewPlayers(registered, scaleWeek, now)); @@ -303,22 +312,22 @@ public class Analysis { data.setAvgUniqJoinsWeek(AnalysisUtils.getUniqueJoinsPerDay(sortedSData, scaleWeek)); data.setAvgUniqJoinsMonth(AnalysisUtils.getUniqueJoinsPerDay(sortedSData, scaleMonth)); Benchmark.stop("Analysis Unique/day"); - + Benchmark.start("Analysis Unique"); data.setUniqueJoinsDay(AnalysisUtils.getUniqueJoins(sortedSData, scaleDay)); data.setUniqueJoinsWeek(AnalysisUtils.getUniqueJoins(sortedSData, scaleWeek)); data.setUniqueJoinsMonth(AnalysisUtils.getUniqueJoins(sortedSData, scaleMonth)); Benchmark.stop("Analysis Unique"); - + List sessions = sData.stream() .filter(session -> (session != null)) .filter(session -> session.isValid()) .filter((session) -> (session.getSessionStart() >= now - scaleMonth || session.getSessionEnd() >= now - scaleMonth)) .collect(Collectors.toList()); - String[] dayArray = PlayerActivityGraphCreator.generateDataArray(sessions, scaleDay, maxPlayers); - String[] weekArray = PlayerActivityGraphCreator.generateDataArray(sessions, scaleWeek, maxPlayers); - String[] monthArray = PlayerActivityGraphCreator.generateDataArray(sessions, scaleMonth, maxPlayers); + String[] dayArray = PlayerActivityGraphCreator.generateDataArray(sessions, scaleDay); + String[] weekArray = PlayerActivityGraphCreator.generateDataArray(sessions, scaleWeek); + String[] monthArray = PlayerActivityGraphCreator.generateDataArray(sessions, scaleMonth); data.setPlayersDataArray(new String[]{dayArray[0], dayArray[1], weekArray[0], weekArray[1], monthArray[0], monthArray[1]}); } diff --git a/Plan/src/main/java/com/djrapitops/plan/utilities/analysis/ExportUtility.java b/Plan/src/main/java/com/djrapitops/plan/utilities/analysis/ExportUtility.java index b5f6d9c84..408b4de54 100644 --- a/Plan/src/main/java/com/djrapitops/plan/utilities/analysis/ExportUtility.java +++ b/Plan/src/main/java/com/djrapitops/plan/utilities/analysis/ExportUtility.java @@ -27,7 +27,7 @@ import main.java.com.djrapitops.plan.utilities.PlaceholderUtils; */ public class ExportUtility { - private static File getFolder() throws IOException { + public static File getFolder() throws IOException { String path = Settings.ANALYSIS_EXPORT_PATH.toString(); if (path.contains(":")) { File folder = new File(path); @@ -46,12 +46,14 @@ public class ExportUtility { } public static void export(Plan plugin, AnalysisData analysisData, List rawData) { + if (!Settings.ANALYSIS_EXPORT.isTrue()) { + return; + } Benchmark.start("Exporting Html pages"); try { File folder = getFolder(); writeAnalysisHtml(analysisData, folder); - File playersFolder = new File(folder, "player"); - playersFolder.mkdirs(); + File playersFolder = getPlayersFolder(folder); for (UserData userData : rawData) { writeInspectHtml(userData, playersFolder); } @@ -62,7 +64,16 @@ public class ExportUtility { } } - private static void writeInspectHtml(UserData userData, File playersFolder) throws FileNotFoundException, IOException { + public static File getPlayersFolder(File folder) { + File playersFolder = new File(folder, "player"); + playersFolder.mkdirs(); + return playersFolder; + } + + public static void writeInspectHtml(UserData userData, File playersFolder) throws FileNotFoundException, IOException { + if (!Settings.ANALYSIS_EXPORT.isTrue()) { + return; + } String inspectHtml = HtmlUtils.replacePlaceholders(HtmlUtils.getHtmlStringFromResource("player.html"), PlaceholderUtils.getInspectReplaceRules(userData)); File playerFolder = new File(playersFolder, userData.getName()); @@ -74,7 +85,10 @@ public class ExportUtility { Files.write(inspectHtmlFile.toPath(), Arrays.asList(inspectHtml)); } - private static void writeAnalysisHtml(AnalysisData analysisData, File folder) throws FileNotFoundException, IOException { + public static void writeAnalysisHtml(AnalysisData analysisData, File folder) throws FileNotFoundException, IOException { + if (!Settings.ANALYSIS_EXPORT.isTrue()) { + return; + } String analysisHtml = HtmlUtils.replacePlaceholders(HtmlUtils.getHtmlStringFromResource("analysis.html"), PlaceholderUtils.getAnalysisReplaceRules(analysisData)) .replace(HtmlUtils.getInspectUrl(""), "./player/"); diff --git a/Plan/src/main/resources/analysis.html b/Plan/src/main/resources/analysis.html index df40df06d..d2510367f 100644 --- a/Plan/src/main/resources/analysis.html +++ b/Plan/src/main/resources/analysis.html @@ -630,6 +630,7 @@ header p { +

If the graph contains more sessions than login times, likely cause is use of /reload (Restarts sessions).