Geolocation Cache implemented, it uses the Google Guava Cache.

More info can be found in the JavaDoc of GeolocationCacheHandler.

Misc:
Removes unnecessary variables which aren't accessed
Adds some debug messages
Fix some typos
Change some variable names to fulfill the java conventions
Making the code somewhat more viewable
Correct the amount of requests that can be sent per hour
Removes one == null call because the variable is never null
This commit is contained in:
Fuzzlemann 2017-07-24 18:40:48 +02:00
parent 4c317221f4
commit 5a92ef99fd
34 changed files with 258 additions and 202 deletions

View File

@ -5,7 +5,7 @@ import java.util.Collection;
/**
* This class manages the messages going to the Console Logger.
*
* Methods of Abtract Plugin Framework log utility are used.
* Methods of Abstract Plugin Framework log utility are used.
*
* @author Rsl1122
* @since 3.0.0
@ -22,7 +22,7 @@ public class Log {
}
/**
* Sends a message to the console with the chatcolors.
* Sends a message to the console with the ChatColors.
*
* @param message Message to send.
*/

View File

@ -25,26 +25,17 @@ import com.djrapitops.plugin.settings.ColorScheme;
import com.djrapitops.plugin.task.AbsRunnable;
import com.djrapitops.plugin.task.ITask;
import com.djrapitops.plugin.utilities.Verify;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URL;
import java.util.HashSet;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import main.java.com.djrapitops.plan.api.API;
import main.java.com.djrapitops.plan.command.PlanCommand;
import main.java.com.djrapitops.plan.command.commands.RegisterCommandFilter;
import main.java.com.djrapitops.plan.data.additional.HookHandler;
import main.java.com.djrapitops.plan.data.cache.*;
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.data.listeners.*;
import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.database.databases.*;
import main.java.com.djrapitops.plan.database.databases.MySQLDB;
import main.java.com.djrapitops.plan.database.databases.SQLiteDB;
import main.java.com.djrapitops.plan.ui.html.Html;
import main.java.com.djrapitops.plan.ui.webserver.WebSocketServer;
import main.java.com.djrapitops.plan.utilities.Benchmark;
@ -52,6 +43,12 @@ import main.java.com.djrapitops.plan.utilities.Check;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
import org.bukkit.Bukkit;
import java.io.*;
import java.net.URL;
import java.util.HashSet;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
/**
* Main class for Bukkit that manages the plugin.
*
@ -335,7 +332,7 @@ public class Plan extends BukkitPlugin<Plan> {
URL localeURL = new URL("https://raw.githubusercontent.com/Rsl1122/Plan-PlayerAnalytics/master/Plan/localization/locale_" + locale + ".txt");
InputStream inputStream = localeURL.openStream();
OutputStream outputStream = new FileOutputStream(localeFile);
int read = 0;
int read;
byte[] bytes = new byte[1024];
while ((read = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);

View File

@ -26,12 +26,12 @@ import java.util.stream.Collectors;
/**
* This class contains the API methods.
*
* Methods can be called from Asyncronous task and are thread safe unless
* Methods can be called from Asynchronous task and are thread safe unless
* otherwise stated.
*
* Use Plan.getPlanAPI() to get the API.
*
* More information about API methods can be found on Github.
* More information about API methods can be found on GitHub.
*
* @author Rsl1122
* @since 2.0.0
@ -136,7 +136,7 @@ public class API {
/**
* Used to save the cached data to the database.
*
* Should be only called from an Asyncronous thread.
* Should be only called from an Asynchronous thread.
*/
public void saveCachedData() {
plugin.getHandler().saveCachedUserData();
@ -155,7 +155,7 @@ public class API {
/**
* Cache the UserData to InspectCache.
*
* Uses cache if data is cached or database if not. Call from an Asyncronous
* Uses cache if data is cached or database if not. Call from an Asynchronous
* thread.
*
* @param uuid UUID of the player.
@ -194,7 +194,7 @@ public class API {
* Run's the analysis with the current data in the cache and fetches rest
* from the database.
*
* Starts a new Asyncronous task to run the analysis.
* Starts a new Asynchronous task to run the analysis.
*/
public void updateAnalysisCache() {
plugin.getAnalysisCache().updateCache();

View File

@ -89,17 +89,17 @@ public class AnalyzeCommand extends SubCommand {
private void runMessageSenderTask(ISender sender) {
plugin.getRunnableFactory().createNew("AnalysisMessageSenderTask", new AbsRunnable() {
private int timesrun = 0;
private int timesRun = 0;
@Override
public void run() {
timesrun++;
timesRun++;
if (analysisCache.isCached() && (!analysisCache.isAnalysisBeingRun() || !analysisCache.isAnalysisEnabled())) {
sendAnalysisMessage(sender);
this.cancel();
return;
}
if (timesrun > 10) {
if (timesRun > 10) {
Log.debug("Command Timeout Message, Analysis.");
sender.sendMessage(Phrase.COMMAND_TIMEOUT.parse("Analysis"));
this.cancel();

View File

@ -66,18 +66,18 @@ public class QuickAnalyzeCommand extends SubCommand {
private void runMessageSenderTask(ISender sender) {
plugin.getRunnableFactory().createNew(new AbsRunnable("QanalysisMessageSenderTask") {
private int timesrun = 0;
private int timesRun = 0;
@Override
public void run() {
timesrun++;
timesRun++;
if (analysisCache.isCached() && (!analysisCache.isAnalysisBeingRun() || !analysisCache.isAnalysisEnabled())) {
sender.sendMessage(Phrase.CMD_ANALYZE_HEADER + "");
sender.sendMessage(TextUI.getAnalysisMessages());
sender.sendMessage(Phrase.CMD_FOOTER + "");
this.cancel();
}
if (timesrun > 10) {
if (timesRun > 10) {
Log.debug("Command Timeout Message, QuickAnalyze.");
sender.sendMessage(Phrase.COMMAND_TIMEOUT.parse("Analysis"));
this.cancel();

View File

@ -22,7 +22,7 @@ public class KillData {
* @param victim UUID of the victim.
* @param victimID ID of the victim, get from the database.
* @param weapon Weapon used.
* @param date Epoch millisecond at which the kill occurrred.
* @param date Epoch millisecond at which the kill occurred.
*/
public KillData(UUID victim, int victimID, String weapon, long date) {
this.victim = victim;
@ -84,7 +84,9 @@ public class KillData {
return false;
}
final KillData other = (KillData) obj;
return this.date == other.date && Objects.equals(this.weapon, other.weapon) && Objects.equals(this.victim, other.victim);
return this.date == other.date
&& Objects.equals(this.weapon, other.weapon)
&& Objects.equals(this.victim, other.victim);
}
@Override

View File

@ -57,7 +57,7 @@ public class UserData {
* All Collections are left empty: locations, nicknames, ips, sessions,
* playerKills. Because nicknames is empty, lastNick is an empty string.
*
* gmTimes Hashmap will contain 4 '0L' values: SURVIVAL, CREATIVE,
* gmTimes HashMap will contain 4 '0L' values: SURVIVAL, CREATIVE,
* ADVENTURE, SPECTATOR
*
* @param uuid UUID of the player
@ -99,7 +99,7 @@ public class UserData {
* All Collections are left empty: locations, nicknames, ips, sessions,
* playerKills. Because nicknames is empty, lastNick is an empty string.
*
* gmTimes Hashmap will contain 4 '0L' values: SURVIVAL, CREATIVE,
* gmTimes HashMap will contain 4 '0L' values: SURVIVAL, CREATIVE,
* ADVENTURE, SPECTATOR
*
* @param player IPlayer object.
@ -128,7 +128,7 @@ public class UserData {
* All Collections are left empty: locations, nicknames, ips, sessions,
* playerKills. Because nicknames is empty, lastNick is an empty string.
*
* gmTimes Hashmap will contain 4 '0L' values: SURVIVAL, CREATIVE,
* gmTimes HashMap will contain 4 '0L' values: SURVIVAL, CREATIVE,
* ADVENTURE, SPECTATOR
*
* lastGM will be set as SURVIVAL
@ -778,7 +778,7 @@ public class UserData {
}
/**
* Check wether or not the object should be cleared from cache after it has
* Check whether or not the object should be cleared from cache after it has
* been saved.
*
* @return true/false
@ -788,7 +788,7 @@ public class UserData {
}
/**
* Set wether or not the object should be cleared from cache after it has
* Set whether or not the object should be cleared from cache after it has
* been saved.
*
* @param clearAfterSave true/false

View File

@ -7,7 +7,7 @@ package main.java.com.djrapitops.plan.data.additional;
* The enum determines what should be done to the return value of
* PluginData.getValue() method when the analysis is run.
*
* Refer to the documentation on github for additional information.
* Refer to the documentation on GitHub for additional information.
*
* @author Rsl1122
* @since 3.1.0

View File

@ -1,17 +1,13 @@
package main.java.com.djrapitops.plan.data.additional;
import com.djrapitops.pluginbridge.plan.Bridge;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.utilities.HtmlUtils;
import java.util.*;
import java.util.stream.Collectors;
/**
* Class responsible for hooking to other plugins and managing the %plugins%
* placeholder on Analysis and Inspect pages.
@ -46,7 +42,7 @@ public class HookHandler {
* The plugin data will appear on Analysis and/or Inspect pages depending on
* how the extending object is set up.
*
* Refer to documentation on github for more information.
* Refer to documentation on GitHub for more information.
*
* @param dataSource an object extending the PluginData class.
*/
@ -76,7 +72,7 @@ public class HookHandler {
/**
* Used to get the Layout with PluginData placeholders to replace %plugins%
* placeholder on analysis.hmtl.
* placeholder on analysis.html.
*
* @return html, getPluginsTabLayout-method
* @see HtmlUtils
@ -89,7 +85,7 @@ public class HookHandler {
/**
* Used to get the Layout with PluginData placeholders to replace %plugins%
* placeholder on player.hmtl.
* placeholder on player.html.
*
* @return html, getPluginsTabLayout-method
* @see HtmlUtils

View File

@ -31,7 +31,7 @@ public abstract class PluginData {
/**
* Name of the plugin the data is coming from.
*
* All datasources with the same sourcePlugin will be placed in the same
* All sources of data with the same sourcePlugin will be placed in the same
* "box" in the "Plugins" tab.
*
* A box has a max height of 600px, and higher than that will add a
@ -277,7 +277,7 @@ public abstract class PluginData {
/**
* If a PluginData object has same placeholder, sourcePlugin and
* analysisTypes, it is considired equal.
* analysisTypes, it is considered equal.
*
* @param obj Another Object.
* @return Is current object equal to given object.

View File

@ -29,12 +29,12 @@ import java.util.*;
* This Class contains the Cache.
*
* This class is the main processing class that initialises Save, Clear, Process
* and Get queue and Starts the asyncronous save task.
* and Get queue and Starts the asynchronous save task.
*
* It is used to store command use, locations, active sessions and UserData
* objects in memory.
*
* It's methods can be used to access all the data it stores and to clear them.
* Its methods can be used to access all the data it stores and to clear them.
*
* @author Rsl1122
* @since 2.0.0
@ -63,7 +63,7 @@ public class DataCacheHandler extends SessionCache {
* Class Constructor.
*
* Gets the Database from the plugin. Starts the queues. Registers
* Asyncronous Periodic Save Task
* Asynchronous Periodic Save Task
*
* @param plugin Current instance of Plan
*/
@ -112,7 +112,7 @@ public class DataCacheHandler extends SessionCache {
}
/**
* Used to start the Asyncronous Save Task.
* Used to start the Asynchronous Save Task.
*
* @throws IllegalArgumentException BukkitRunnable was given wrong
* parameters.
@ -335,7 +335,7 @@ public class DataCacheHandler extends SessionCache {
/**
* Saves the cached CommandUse.
*
* Should be only called from an Asyncronous Thread.
* Should be only called from an Asynchronous Thread.
*/
public void saveCommandUse() {
try {
@ -364,10 +364,10 @@ public class DataCacheHandler extends SessionCache {
}
List<List<TPS>> copy = new ArrayList<>(unsavedTPSHistory);
for (List<TPS> history : copy) {
final long lastdate = history.get(history.size() - 1).getDate();
final long lastDate = history.get(history.size() - 1).getDate();
final double averageTPS = MathUtils.averageDouble(history.stream().map(TPS::getTps));
final int averagePlayersOnline = (int) MathUtils.averageInt(history.stream().map(TPS::getPlayers));
averages.add(new TPS(lastdate, averageTPS, averagePlayersOnline));
averages.add(new TPS(lastDate, averageTPS, averagePlayersOnline));
}
unsavedTPSHistory.removeAll(copy);
return averages;
@ -426,7 +426,7 @@ public class DataCacheHandler extends SessionCache {
*
* @param uuid Player's UUID.
*/
public void scheludeForClear(UUID uuid) {
public void scheduldeForClear(UUID uuid) {
clearTask.scheduleForClear(uuid);
}

View File

@ -0,0 +1,93 @@
package main.java.com.djrapitops.plan.data.cache;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Phrase;
import main.java.com.djrapitops.plan.utilities.Benchmark;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Map;
/**
* This class contains the geolocation cache.
* <p>
* It caches all IPs with their matching country.
* <p>
* This cache uses the Google Guava {@link Cache} and has a capacity of 10.000 entries.
*
* @author Fuzzlemann
*/
public class GeolocationCacheHandler {
private static final Cache<String, String> geolocationCache = CacheBuilder.newBuilder()
.maximumSize(10000)
.build();
/**
* Retrieves the country in full length (e.g. United States) from the IP Address.
* <p>
* This method uses the {@code geolocationCache}, every first access is getting cached and then retrieved later.
*
* @param ipAddress The IP Address from which the country is retrieved
* @return The name of the country in full length.
* <p>
* An exception from that rule is when the country is unknown or the retrieval of the country failed in any way,
* if that happens, the phrase for unknown country set in the config will be returned.
* @see #getUncachedCountry(String)
*/
public static String getCountry(String ipAddress) {
Log.debug("Started country retrieval from IP Address " + ipAddress);
Map<String, String> geolocationMap = geolocationCache.asMap();
String country = geolocationMap.get(ipAddress);
Log.debug("Got country from " + ipAddress + " out of cache: " + country + " (if null, country wasn't cached)");
if (country != null) {
return country;
} else {
country = getUncachedCountry(ipAddress);
geolocationCache.put(ipAddress, country);
Log.debug("Got uncached country from IP Address " + ipAddress + ": " + country);
return country;
}
}
/**
* Retrieves the country in full length (e.g. United States) from the IP Address.
* <p>
* This method uses the free service of freegeoip.net. The maximum amount of requests is 15.000 per hour.
*
* @param ipAddress The IP Address from which the country is retrieved
* @return The name of the country in full length.
* <p>
* An exception from that rule is when the country is unknown or the retrieval of the country failed in any way,
* if that happens, the phrase for unknown country set in the config will be returned.
* @see <a href="http://freegeoip.net">http://freegeoip.net</a>
* @see #getCountry(String)
*/
private static String getUncachedCountry(String ipAddress) {
try {
Benchmark.start("getUncachedCountry");
URL url = new URL("http://freegeoip.net/csv/" + ipAddress);
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
String resultLine = in.readLine();
in.close();
String[] results = resultLine.split(",");
String result = results[2];
String country = result.isEmpty() ? Phrase.DEM_UNKNOWN.toString() : result;
Benchmark.stop("getUncachedCountry");
return country;
} catch (Exception exc) {
return Phrase.DEM_UNKNOWN.toString();
}
}
}

View File

@ -1,18 +1,19 @@
package main.java.com.djrapitops.plan.data.cache.queue;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Phrase;
import main.java.com.djrapitops.plan.Settings;
import main.java.com.djrapitops.plan.data.cache.DataCacheHandler;
import java.util.Collection;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.stream.Collectors;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Phrase;
import main.java.com.djrapitops.plan.Settings;
import main.java.com.djrapitops.plan.data.cache.DataCacheHandler;
/**
* This Class strats the Clear Queue Thread, that clears data from DataCache.
* This Class contains the Clear Queue Thread, which is clearing data from the DataCache.
*
* @author Rsl1122
* @since 3.0.0
@ -22,7 +23,7 @@ public class DataCacheClearQueue extends Queue<UUID> {
/**
* Class constructor, starts the new Thread for clearing.
*
* @param handler current instance of DataCachehandler.
* @param handler current instance of DataCacheHandler.
*/
public DataCacheClearQueue(DataCacheHandler handler) {
super(new ArrayBlockingQueue(Settings.PROCESS_CLEAR_LIMIT.getNumber()));

View File

@ -1,14 +1,5 @@
package main.java.com.djrapitops.plan.data.cache.queue;
import java.sql.SQLException;
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;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Phrase;
import main.java.com.djrapitops.plan.Plan;
@ -16,6 +7,11 @@ import main.java.com.djrapitops.plan.Settings;
import main.java.com.djrapitops.plan.data.cache.DBCallableProcessor;
import main.java.com.djrapitops.plan.database.Database;
import java.sql.SQLException;
import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
/**
* This Class is starts the Get Queue Thread, that fetches data from DataCache.
*
@ -36,7 +32,7 @@ public class DataCacheGetQueue extends Queue<Map<UUID, List<DBCallableProcessor>
}
/**
* Schedules UserData objects to be get for the given proecssors.
* Schedules UserData objects to be get for the given processors.
*
* @param uuid UUID of the player whose UserData object is fetched.
* @param processors Processors which process-method will be called after

View File

@ -1,15 +1,16 @@
package main.java.com.djrapitops.plan.data.cache.queue;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.cache.DBCallableProcessor;
import main.java.com.djrapitops.plan.data.cache.DataCacheHandler;
import main.java.com.djrapitops.plan.data.handling.info.HandlingInfo;
import java.util.ArrayList;
import java.util.Collection;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.cache.DBCallableProcessor;
import main.java.com.djrapitops.plan.data.cache.DataCacheHandler;
import main.java.com.djrapitops.plan.data.handling.info.HandlingInfo;
/**
* This Class is starts the Process Queue Thread, that processes HandlingInfo
@ -23,7 +24,7 @@ public class DataCacheProcessQueue extends Queue<HandlingInfo> {
/**
* Class constructor, starts the new Thread for processing.
*
* @param handler current instance of DataCachehandler.
* @param handler current instance of DataCacheHandler.
*/
public DataCacheProcessQueue(DataCacheHandler handler) {
super(new ArrayBlockingQueue(20000));

View File

@ -1,12 +1,5 @@
package main.java.com.djrapitops.plan.data.cache.queue;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.stream.Collectors;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Phrase;
import main.java.com.djrapitops.plan.Plan;
@ -15,8 +8,16 @@ import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.cache.DataCacheHandler;
import main.java.com.djrapitops.plan.database.Database;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.stream.Collectors;
/**
* This Class is starts the Save Queue Thread, that saves data to the Databse.
* This Class is starts the Save Queue Thread, that saves data to the Database.
*
* @author Rsl1122
* @since 3.0.0

View File

@ -16,7 +16,7 @@ public abstract class Queue<T> {
Setup<T> setup;
/**
* Consturctor, defines queue.
* Constructor, defines queue.
*
* @param queue BlockingQueue to use for this queue.
*/

View File

@ -1,9 +1,10 @@
package main.java.com.djrapitops.plan.data.handling;
import com.djrapitops.plugin.utilities.player.Gamemode;
import java.util.Map;
import main.java.com.djrapitops.plan.data.UserData;
import java.util.Map;
/**
* Class containing static methods for processing information contained in a
* GamemodeChangeEvent.
@ -33,10 +34,7 @@ public class GamemodeHandling {
}
lastGamemode = data.getLastGamemode();
Map<String, Long> times = data.getGmTimes();
Long currentGMTime = times.get(lastGamemode);
if (currentGMTime == null) {
currentGMTime = 0L;
}
long currentGMTime = times.getOrDefault(lastGamemode, 0L);
data.setPlayTime(data.getPlayTime() + (time - data.getLastPlayed()));
data.setLastPlayed(time);
long lastSwap = data.getLastGmSwapTime();

View File

@ -1,12 +1,9 @@
package main.java.com.djrapitops.plan.data.handling;
import main.java.com.djrapitops.plan.Phrase;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.cache.GeolocationCacheHandler;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.URL;
/**
* Class containing static methods for processing information contained in a
@ -40,29 +37,15 @@ public class LoginHandling {
/**
* Updates the geolocation of the player.
*
* Uses free service of freegeoip.net. 10000 requests can be sent per hour.
* Uses free service of freegeoip.net. 15000 requests can be sent per hour.
*
* @param ip InetAddress used for location.
* @param data UserData of the player.
* @see GeolocationCacheHandler
*/
public static void updateGeolocation(InetAddress ip, UserData data) {
try {
StringBuilder result = new StringBuilder();
URL url = new URL("http://freegeoip.net/csv/" + ip.getHostAddress());
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
String geoLocation = GeolocationCacheHandler.getCountry(ip.getHostAddress());
String resultline;
while ((resultline = in.readLine()) != null) {
result.append(resultline).append(",");
}
in.close();
String[] results = result.toString().split(",");
if (!results[2].isEmpty()) {
data.setGeolocation(results[2]);
}
} catch (Exception e) {
data.setGeolocation(Phrase.DEM_UNKNOWN + "");
}
data.setGeolocation(geoLocation);
}
}

View File

@ -1,10 +1,8 @@
package main.java.com.djrapitops.plan.data.listeners;
import com.djrapitops.plugin.task.AbsRunnable;
import com.djrapitops.plugin.task.ITask;
import com.djrapitops.plugin.utilities.player.Gamemode;
import com.djrapitops.plugin.utilities.player.bukkit.BukkitPlayer;
import java.util.UUID;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.UserData;
@ -22,6 +20,8 @@ import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerKickEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import java.util.UUID;
/**
* Event Listener for PlayerJoin, PlayerQuit and PlayerKickEvents.
*
@ -59,7 +59,7 @@ public class PlanPlayerListener implements Listener {
UUID uuid = player.getUniqueId();
handler.startSession(uuid);
Log.debug(uuid + ": PlayerJoinEvent");
ITask asyncNewPlayerCheckTask = plugin.getRunnableFactory().createNew(new AbsRunnable("NewPlayerCheckTask") {
plugin.getRunnableFactory().createNew(new AbsRunnable("NewPlayerCheckTask") {
@Override
public void run() {
LoginInfo loginInfo = new LoginInfo(uuid, MiscUtils.getTime(), player.getAddress().getAddress(), player.isBanned(), player.getDisplayName(), Gamemode.wrap(player.getGameMode()), 1);
@ -112,8 +112,10 @@ public class PlanPlayerListener implements Listener {
Player player = event.getPlayer();
UUID uuid = player.getUniqueId();
handler.endSession(uuid);
Log.debug(uuid + ": PlayerKickEvent");
handler.addToPool(new LogoutInfo(uuid, MiscUtils.getTime(), player.isBanned(), Gamemode.wrap(player.getGameMode()), handler.getSession(uuid)));
handler.addToPool(new KickInfo(uuid));
handler.saveCachedData(uuid);
Log.debug(uuid + ": PlayerKickEvent_END");
}
}

View File

@ -2,14 +2,15 @@ package main.java.com.djrapitops.plan.data.listeners;
import com.djrapitops.plugin.api.TimeAmount;
import com.djrapitops.plugin.task.AbsRunnable;
import java.util.ArrayList;
import java.util.List;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.TPS;
import main.java.com.djrapitops.plan.data.cache.DataCacheHandler;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
import java.util.ArrayList;
import java.util.List;
/**
* Class responsible for calculating TPS every second.
*
@ -32,15 +33,15 @@ public class TPSCountTimer extends AbsRunnable {
@Override
public void run() {
long nanotime = System.nanoTime();
long nanoTime = System.nanoTime();
long now = MiscUtils.getTime();
long diff = nanotime - lastCheckNano;
lastCheckNano = nanotime;
if (diff > nanotime) { // First run's diff = nanotime + 1, no calc possible.
long diff = nanoTime - lastCheckNano;
lastCheckNano = nanoTime;
if (diff > nanoTime) { // First run's diff = nanoTime + 1, no calc possible.
Log.debug("First run of TPSCountTimer Task.");
return;
}
diff -= TimeAmount.MILLISECOND.ns() * 40L; // 40ms Removed because the run appears to take 40-50ms, scewing the tps.
diff -= TimeAmount.MILLISECOND.ns() * 40L; // 40ms removed because the run appears to take 40-50ms, screwing the tps.
TPS tps = calculateTPS(diff, now);
history.add(tps);
if (history.size() >= 60) {

View File

@ -1,26 +1,17 @@
package main.java.com.djrapitops.plan.database;
import java.sql.SQLException;
import java.util.*;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.cache.DBCallableProcessor;
import main.java.com.djrapitops.plan.database.tables.CommandUseTable;
import main.java.com.djrapitops.plan.database.tables.GMTimesTable;
import main.java.com.djrapitops.plan.database.tables.IPsTable;
import main.java.com.djrapitops.plan.database.tables.KillsTable;
import main.java.com.djrapitops.plan.database.tables.LocationsTable;
import main.java.com.djrapitops.plan.database.tables.NicknamesTable;
import main.java.com.djrapitops.plan.database.tables.SecurityTable;
import main.java.com.djrapitops.plan.database.tables.SessionsTable;
import main.java.com.djrapitops.plan.database.tables.TPSTable;
import main.java.com.djrapitops.plan.database.tables.UsersTable;
import main.java.com.djrapitops.plan.database.tables.VersionTable;
import main.java.com.djrapitops.plan.database.tables.*;
import java.sql.SQLException;
import java.util.*;
/**
* Abstract class representing a Database.
*
* All methods should be only called from an asyncronous thread, unless stated
* All methods should be only called from an asynchronous thread, unless stated
* otherwise.
*
* @author Rsl1122

View File

@ -1,16 +1,13 @@
package main.java.com.djrapitops.plan.database.tables;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.database.databases.SQLDB;
import main.java.com.djrapitops.plan.utilities.Benchmark;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.database.databases.SQLDB;
import main.java.com.djrapitops.plan.utilities.Benchmark;
import java.util.*;
/**
*
@ -151,7 +148,7 @@ public class GMTimesTable extends Table {
}
PreparedStatement statement = null;
String[] gms = getGMKeyArray();
int update = 0;
int update;
try {
statement = prepareStatement(
"UPDATE " + tableName + " SET "

View File

@ -246,9 +246,6 @@ public class UsersTable extends Table {
set = statement.executeQuery();
while (set.next()) {
UUID uuid = UUID.fromString(set.getString(columnUUID));
if (uuid == null) {
continue;
}
uuids.add(uuid);
}
return uuids;

View File

@ -1,8 +1,9 @@
package main.java.com.djrapitops.plan.ui.html;
import java.util.List;
import main.java.com.djrapitops.plan.utilities.HtmlUtils;
import java.util.List;
/**
*
* @author Rsl1122
@ -12,8 +13,8 @@ public class RecentPlayersButtonsCreator {
/**
* Creates recent players buttons inside a p-tag.
*
* @param names Playernames sorted by last playtime.
* @param limit How many playes will be shown
* @param names The name of players sorted by last playtime.
* @param limit How many players will be shown
* @return html p-tag list of recent logins.
*/
public static String createRecentLoginsButtons(List<String> names, int limit) {

View File

@ -79,11 +79,11 @@ public class PlayerActivityGraphCreator {
}
if (Settings.ANALYSIS_REMOVE_OUTLIERS.isTrue()) {
long average = MathUtils.averageLong(playersOnline.stream());
double standardDiviation = getStandardDiviation(playersOnline, average);
if (standardDiviation > 3.5) {
double standardDeviation = getStandardDeviation(playersOnline, average);
if (standardDeviation > 3.5) {
for (int i = 0; i < playersOnline.size(); i++) {
long value = playersOnline.get(i);
if (value - average > 3 * standardDiviation) {
if (value - average > 3 * standardDeviation) {
playersOnline.set(i, (long) Plan.getInstance().getVariable().getMaxPlayers() + 10);
}
}
@ -92,7 +92,7 @@ public class PlayerActivityGraphCreator {
return new String[]{playersOnline.toString(), labels.toString()};
}
private static double getStandardDiviation(List<Long> players, long avg) {
private static double getStandardDeviation(List<Long> players, long avg) {
List<Double> valueMinusAvg = players.stream()
.map(p -> Math.pow(Math.abs(p - avg), 2))
.collect(Collectors.toList());

View File

@ -67,13 +67,13 @@ public class PunchCardGraphCreator {
}
if (Settings.ANALYSIS_REMOVE_OUTLIERS.isTrue()) {
int avg = findAverage(dataArray);
double standardDiviation = getStandardDiviation(dataArray, avg);
Log.debug("Diviation: " + standardDiviation);
if (standardDiviation > 3.5) {
double standardDeviation = getStandardDeviation(dataArray, avg);
Log.debug("Deviation: " + standardDeviation);
if (standardDeviation > 3.5) {
for (int i = 0; i < 7; i++) {
for (int j = 0; j < 24; j++) {
int value = dataArray[i][j];
if (value - avg > 3 * standardDiviation) {
if (value - avg > 3 * standardDeviation) {
dataArray[i][j] = avg;
}
}
@ -83,7 +83,7 @@ public class PunchCardGraphCreator {
return dataArray;
}
private static double getStandardDiviation(int[][] array, int avg) {
private static double getStandardDeviation(int[][] array, int avg) {
int[][] valueMinusAvg = new int[7][24];
for (int i = 0; i < 7; i++) {
for (int j = 0; j < 24; j++) {

View File

@ -127,7 +127,7 @@ public class Request implements Closeable {
/**
* Closes the Request.
*
* Closes the inputstream.
* Closes the InputStream.
*
* @throws IOException if the stream can not be closed.
*/

View File

@ -2,6 +2,20 @@ package main.java.com.djrapitops.plan.ui.webserver;
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.Phrase;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.Settings;
import main.java.com.djrapitops.plan.data.WebUser;
import main.java.com.djrapitops.plan.database.tables.SecurityTable;
import main.java.com.djrapitops.plan.ui.html.DataRequestHandler;
import main.java.com.djrapitops.plan.ui.webserver.response.*;
import main.java.com.djrapitops.plan.utilities.Benchmark;
import main.java.com.djrapitops.plan.utilities.HtmlUtils;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
import main.java.com.djrapitops.plan.utilities.PassEncryptUtil;
import main.java.com.djrapitops.plan.utilities.uuid.UUIDUtility;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@ -12,26 +26,6 @@ import java.sql.SQLException;
import java.util.Base64;
import java.util.UUID;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Phrase;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.Settings;
import main.java.com.djrapitops.plan.data.WebUser;
import main.java.com.djrapitops.plan.database.tables.SecurityTable;
import main.java.com.djrapitops.plan.ui.html.DataRequestHandler;
import main.java.com.djrapitops.plan.ui.webserver.response.AnalysisPageResponse;
import main.java.com.djrapitops.plan.ui.webserver.response.InspectPageResponse;
import main.java.com.djrapitops.plan.ui.webserver.response.InternalErrorResponse;
import main.java.com.djrapitops.plan.ui.webserver.response.NotFoundResponse;
import main.java.com.djrapitops.plan.ui.webserver.response.PlayersPageResponse;
import main.java.com.djrapitops.plan.ui.webserver.response.RedirectResponse;
import main.java.com.djrapitops.plan.ui.webserver.response.Response;
import main.java.com.djrapitops.plan.utilities.Benchmark;
import main.java.com.djrapitops.plan.utilities.HtmlUtils;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
import main.java.com.djrapitops.plan.utilities.PassEncryptUtil;
import main.java.com.djrapitops.plan.utilities.uuid.UUIDUtility;
/**
*
* @author Rsl1122
@ -63,7 +57,7 @@ public class WebSocketServer {
}
/**
* Starts up the Webserver in a Asyncronous thread.
* Starts up the Webserver in a Asynchronous thread.
*/
public void initServer() {
//Server is already enabled stop code

View File

@ -1,13 +1,14 @@
package main.java.com.djrapitops.plan.ui.webserver.response;
import java.io.OutputStream;
import java.util.List;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.ui.html.Html;
import main.java.com.djrapitops.plan.utilities.HtmlUtils;
import main.java.com.djrapitops.plan.utilities.comparators.UserDataNameComparator;
import java.io.OutputStream;
import java.util.List;
/**
*
* @author Rsl1122
@ -21,7 +22,7 @@ public class PlayersPageResponse extends Response {
super.setContent(buildContent(plugin.getInspectCache().getCachedUserData()));
}
public static final String buildContent(List<UserData> cached) {
public static String buildContent(List<UserData> cached) {
StringBuilder html = new StringBuilder();
int size = cached.size();
html.append("<h1>Cached Players</h1><p>")

View File

@ -18,14 +18,14 @@ public abstract class Response {
/**
* Class Constructor.
*
* @param output Website outputstream to write the response to.
* @param output Website OutputStream to write the response to.
*/
public Response(OutputStream output) {
this.output = output;
}
/**
* Wrties the HTML to the Outputstream according to the requested page.
* Writes the HTML to the OutputStream according to the requested page.
*
* @throws IOException
*/

View File

@ -45,10 +45,10 @@ public class Analysis {
}
/**
* Analyzes the data of all offlineplayers on the server.
* Analyzes the data of all offline players on the server.
*
* First retrieves all Offlineplayers and checks those that are in the
* database. Then Runs a new Analysis Task Asyncronously. Saves AnalysisData
* First retrieves all offline players and checks those that are in the
* database. Then Runs a new Analysis Task Asynchronously. Saves AnalysisData
* to the provided Cache. Saves all UserData to InspectCache for 15 minutes.
*
* @param analysisCache Cache that the data is saved to.

View File

@ -2,8 +2,6 @@ package test.java.utils;
import com.djrapitops.plugin.utilities.player.Fetch;
import com.djrapitops.plugin.utilities.player.IPlayer;
import java.net.InetAddress;
import java.util.UUID;
import main.java.com.djrapitops.plan.data.KillData;
import main.java.com.djrapitops.plan.data.SessionData;
import main.java.com.djrapitops.plan.data.UserData;
@ -15,6 +13,10 @@ import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import java.net.InetAddress;
import java.util.UUID;
import static org.powermock.api.mockito.PowerMockito.when;
/**
@ -37,7 +39,7 @@ public class MockUtils {
return NewPlayerCreator.createNewPlayer(mockIPlayer());
}
public static UserData mockUserWithmoreData() throws Exception {
public static UserData mockUserWithMoreData() throws Exception {
UserData mock = mockUser();
mock.addIpAddress(InetAddress.getByName("247.183.163.155"));
mock.addNickname("MoreNicks");

View File

@ -5,11 +5,6 @@ import com.djrapitops.plugin.utilities.BenchUtil;
import com.djrapitops.plugin.utilities.log.BukkitLog;
import com.djrapitops.plugin.utilities.player.Fetch;
import com.djrapitops.plugin.utilities.status.ProcessStatus;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.util.logging.Logger;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.ServerVariableHolder;
import main.java.com.djrapitops.plan.Settings;
@ -18,6 +13,13 @@ import org.bukkit.Server;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.powermock.api.mockito.PowerMockito;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.util.logging.Logger;
import static org.junit.Assert.assertTrue;
import static org.powermock.api.mockito.PowerMockito.when;
@ -50,7 +52,7 @@ public class TestInit {
YamlConfiguration config = mockConfig();
when(planMock.getConfig()).thenReturn(config);
File testFolder = getEmptyTestfolder();
File testFolder = getEmptyTestFolder();
when(planMock.getDataFolder()).thenReturn(testFolder);
// Html Files
@ -91,7 +93,7 @@ public class TestInit {
return mockServer;
}
private File getEmptyTestfolder() throws IOException {
private File getEmptyTestFolder() throws IOException {
File testFolder = new File("temporaryTestFolder");
if (testFolder.exists()) {
for (File f : testFolder.listFiles()) {