[2.8.4-DEV] Moved things around, Improvements, Bugfixes

- Fixed new bugs found while creating tests with PlanDebug #47
- Moved manage things around to remove copy-paste code. New ManageUtils
class
- Made analyze more flexible, now allows analysis of any abstract
Database class' data.
- Moved RecentPlayerButtons creation to new class
This commit is contained in:
Rsl1122 2017-03-12 21:41:19 +02:00
parent ce6b961e99
commit 989dc17a4f
12 changed files with 478 additions and 385 deletions

View File

@ -14,6 +14,7 @@ import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.cache.DBCallableProcessor;
import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.database.databases.SQLiteDB;
import main.java.com.djrapitops.plan.utilities.ManageUtils;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.scheduler.BukkitRunnable;
@ -77,31 +78,10 @@ public class ManageBackupCommand extends SubCommand {
(new BukkitRunnable() {
@Override
public void run() {
try {
Date now = new Date();
SQLiteDB backupDB = new SQLiteDB(plugin,
args[0] + "-backup-" + now.toString().substring(4, 10).replaceAll(" ", "-").replaceAll(":", "-"));
sender.sendMessage(Phrase.MANAGE_PROCESS_START.parse());
backupDB.removeAllData();
Set<UUID> uuids = copyFromDB.getSavedUUIDs();
List<UserData> allUserData = new ArrayList<>();
for (UUID uuid : uuids) {
copyFromDB.giveUserDataToProcessors(uuid, new DBCallableProcessor() {
@Override
public void process(UserData data) {
allUserData.add(data);
}
});
}
while (uuids.size() > allUserData.size()) {
}
backupDB.saveMultipleUserData(allUserData);
backupDB.saveCommandUse(copyFromDB.getCommandUse());
sender.sendMessage(Phrase.MANAGE_COPY_SUCCESS.toString());
} catch (SQLException e) {
plugin.toLog(this.getClass().getName(), e);
if (ManageUtils.backup(args[0], copyFromDB)) {
sender.sendMessage(Phrase.MANAGE_COPY_SUCCESS.toString());
} else {
sender.sendMessage(Phrase.MANAGE_PROCESS_FAIL.toString());
}
this.cancel();

View File

@ -15,6 +15,7 @@ import main.java.com.djrapitops.plan.data.cache.DBCallableProcessor;
import main.java.com.djrapitops.plan.data.cache.DataCacheHandler;
import main.java.com.djrapitops.plan.data.importing.Importer;
import main.java.com.djrapitops.plan.data.importing.OnTimeImporter;
import main.java.com.djrapitops.plan.utilities.ManageUtils;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.OfflinePlayer;
@ -23,6 +24,7 @@ import org.bukkit.command.CommandSender;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask;
import static org.bukkit.Bukkit.getOfflinePlayer;
import static org.bukkit.Bukkit.getOfflinePlayer;
/**
*
@ -90,40 +92,17 @@ public class ManageImportCommand extends SubCommand {
}
HashMap<UUID, Long> numbericData = importPlugins.get(importFromPlugin).grabNumericData(uuids);
DataCacheHandler handler = plugin.getHandler();
if (importFromPlugin.equals("ontime")) {
importOnTime(numbericData, handler, sender);
}
return true;
}
private void importOnTime(HashMap<UUID, Long> onTimeData, DataCacheHandler handler, CommandSender sender) {
BukkitTask asyncOnTimeImportTask = (new BukkitRunnable() {
BukkitTask asyncImportTask = (new BukkitRunnable() {
@Override
public void run() {
for (UUID uuid : onTimeData.keySet()) {
OfflinePlayer player = getOfflinePlayer(uuid);
if (handler.getActivityHandler().isFirstTimeJoin(uuid)) {
handler.newPlayer(player);
if (importFromPlugin.equals("ontime")) {
if (ManageUtils.importOnTime(numbericData, handler)) {
sender.sendMessage(Phrase.MANAGE_SUCCESS + "");
}
DBCallableProcessor importer = new DBCallableProcessor() {
@Override
public void process(UserData data) {
Long playTime = onTimeData.get(uuid);
if (playTime > data.getPlayTime()) {
data.setPlayTime(playTime);
data.setLastGamemode(GameMode.SURVIVAL);
data.setAllGMTimes(playTime, 0, 0, 0);
data.setLastGmSwapTime(playTime);
}
}
};
handler.getUserDataForProcessing(importer, uuid);
}
handler.saveCachedUserData();
sender.sendMessage(Phrase.MANAGE_SUCCESS + "");
}
this.cancel();
}
}).runTaskAsynchronously(plugin);
return true;
}
}

View File

@ -3,6 +3,7 @@ package main.java.com.djrapitops.plan.command.commands.manage;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.UUID;
@ -13,6 +14,7 @@ import main.java.com.djrapitops.plan.command.SubCommand;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.cache.DBCallableProcessor;
import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.utilities.ManageUtils;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.scheduler.BukkitRunnable;
@ -96,53 +98,29 @@ public class ManageMoveCommand extends SubCommand {
plugin.logError(toDB + " was null!");
return true;
}
final Set<UUID> uuids;
try {
uuids = fromDatabase.getSavedUUIDs();
} catch (SQLException e) {
plugin.toLog(this.getClass().getName(), e);
sender.sendMessage(Phrase.MANAGE_PROCESS_FAIL + "");
return true;
}
if (uuids.isEmpty()) {
sender.sendMessage(Phrase.MANAGE_ERROR_NO_PLAYERS + " (" + fromDB + ")");
return true;
}
final Database moveFromDB = fromDatabase;
final Database moveToDB = toDatabase;
(new BukkitRunnable() {
@Override
public void run() {
try {
sender.sendMessage(Phrase.MANAGE_PROCESS_START.parse());
moveToDB.removeAllData();
List<UserData> allUserData = new ArrayList<>();
for (UUID uuid : uuids) {
moveFromDB.giveUserDataToProcessors(uuid, new DBCallableProcessor() {
@Override
public void process(UserData data) {
allUserData.add(data);
}
});
}
while (uuids.size() > allUserData.size()) {
}
moveToDB.saveMultipleUserData(allUserData);
moveToDB.saveCommandUse(moveFromDB.getCommandUse());
final Collection<UUID> uuids = ManageUtils.getUUIDS(moveFromDB);
if (uuids.isEmpty()) {
sender.sendMessage(Phrase.MANAGE_ERROR_NO_PLAYERS + " (" + fromDB + ")");
this.cancel();
return;
}
sender.sendMessage(Phrase.MANAGE_PROCESS_START.parse());
if (ManageUtils.clearAndCopy(moveToDB, moveFromDB, uuids)) {
sender.sendMessage(Phrase.MANAGE_MOVE_SUCCESS + "");
if (!toDB.equals(plugin.getDB().getConfigName())) {
sender.sendMessage(Phrase.MANAGE_DB_CONFIG_REMINDER + "");
}
} catch (SQLException | NullPointerException e) {
plugin.toLog(this.getClass().getName(), e);
} else {
sender.sendMessage(Phrase.MANAGE_PROCESS_FAIL + "");
}
this.cancel();
}
}).runTaskAsynchronously(plugin);
return true;

View File

@ -1,20 +1,16 @@
package main.java.com.djrapitops.plan.command.commands.manage;
import java.io.File;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.Collection;
import java.util.UUID;
import main.java.com.djrapitops.plan.Phrase;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.command.CommandType;
import main.java.com.djrapitops.plan.command.SubCommand;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.cache.DBCallableProcessor;
import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.database.databases.SQLiteDB;
import main.java.com.djrapitops.plan.utilities.ManageUtils;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.scheduler.BukkitRunnable;
@ -83,45 +79,34 @@ public class ManageRestoreCommand extends SubCommand {
BukkitTask asyncRestoreTask = (new BukkitRunnable() {
@Override
public void run() {
try {
String backupDBName = args[0];
String backupDBName = args[0];
File backupDBFile = new File(plugin.getDataFolder(), backupDBName + (backupDBName.contains(".db") ? "" : ".db"));
if (!backupDBFile.exists()) {
sender.sendMessage(Phrase.MANAGE_ERROR_BACKUP_FILE_NOT_FOUND + " " + args[0]);
this.cancel();
return;
}
if (backupDBName.contains(".db")) {
backupDBName = backupDBName.replace(".db", "");
}
SQLiteDB backupDB = new SQLiteDB(plugin, backupDBName);
if (!backupDB.init()) {
sender.sendMessage(Phrase.MANAGE_DATABASE_FAILURE + "");
this.cancel();
return;
}
sender.sendMessage(Phrase.MANAGE_PROCESS_START.parse());
copyToDB.removeAllData();
Set<UUID> uuids = backupDB.getSavedUUIDs();
List<UserData> allUserData = new ArrayList<>();
for (UUID uuid : uuids) {
backupDB.giveUserDataToProcessors(uuid, new DBCallableProcessor() {
@Override
public void process(UserData data) {
allUserData.add(data);
}
});
}
while (uuids.size() > allUserData.size()) {
}
copyToDB.saveMultipleUserData(allUserData);
copyToDB.saveCommandUse(backupDB.getCommandUse());
File backupDBFile = new File(plugin.getDataFolder(), backupDBName + (backupDBName.contains(".db") ? "" : ".db"));
if (!backupDBFile.exists()) {
sender.sendMessage(Phrase.MANAGE_ERROR_BACKUP_FILE_NOT_FOUND + " " + args[0]);
this.cancel();
return;
}
if (backupDBName.contains(".db")) {
backupDBName = backupDBName.replace(".db", "");
}
SQLiteDB backupDB = new SQLiteDB(plugin, backupDBName);
if (!backupDB.init()) {
sender.sendMessage(Phrase.MANAGE_DATABASE_FAILURE + "");
this.cancel();
return;
}
sender.sendMessage(Phrase.MANAGE_PROCESS_START.parse());
final Collection<UUID> uuids = ManageUtils.getUUIDS(backupDB);
if (uuids.isEmpty()) {
sender.sendMessage(Phrase.MANAGE_ERROR_NO_PLAYERS + " (" + backupDBName + ")");
this.cancel();
return;
}
if (ManageUtils.clearAndCopy(copyToDB, backupDB, uuids)) {
sender.sendMessage(Phrase.MANAGE_COPY_SUCCESS.toString());
} catch (SQLException | NullPointerException e) {
plugin.toLog(this.getClass().getName(), e);
sender.sendMessage(Phrase.MANAGE_PROCESS_FAIL + "");
} else {
sender.sendMessage(Phrase.MANAGE_PROCESS_FAIL.toString());
}
this.cancel();
}

View File

@ -52,17 +52,12 @@ public class UserData {
private SessionData currentSession;
private List<SessionData> sessions;
/**
*
* @param player
* @param demData
*/
public UserData(Player player, DemographicsData demData) {
public UserData(UUID uuid, long reg, Location loc, boolean op, GameMode lastGM, DemographicsData demData, String name, boolean online) {
accessing = 0;
uuid = player.getUniqueId();
registered = player.getFirstPlayed();
location = player.getLocation();
isOp = player.isOp();
this.uuid = uuid;
registered = reg;
location = loc;
isOp = op;
locations = new ArrayList<>();
nicknames = new HashSet<>();
ips = new HashSet<>();
@ -75,17 +70,10 @@ public class UserData {
gmTimes.put(GameMode.SPECTATOR, zero);
} catch (NoSuchFieldError e) {
}
lastGamemode = player.getGameMode();
lastGamemode = lastGM;
this.demData = demData;
try {
isBanned = player.isBanned();
} catch (Exception e) {
Plan plugin = getPlugin(Plan.class);
plugin.logError("Error getting ban date from Bukkit files. " + uuid.toString());
plugin.toLog(this.getClass().getName(), e);
}
name = player.getName();
isOnline = player.isOnline();
this.name = name;
isOnline = online;
sessions = new ArrayList<>();
lastNick = "";
playerKills = new ArrayList<>();
@ -96,36 +84,33 @@ public class UserData {
* @param player
* @param demData
*/
public UserData(OfflinePlayer player, DemographicsData demData) {
accessing = 0;
uuid = player.getUniqueId();
registered = player.getFirstPlayed();
isOp = player.isOp();
locations = new ArrayList<>();
nicknames = new HashSet<>();
ips = new HashSet<>();
gmTimes = new HashMap<>();
long zero = 0;
gmTimes.put(GameMode.SURVIVAL, zero);
gmTimes.put(GameMode.CREATIVE, zero);
gmTimes.put(GameMode.ADVENTURE, zero);
try {
gmTimes.put(GameMode.SPECTATOR, zero);
} catch (NoSuchFieldError e) {
}
this.demData = demData;
public UserData(Player player, DemographicsData demData) {
this(player.getUniqueId(), player.getFirstPlayed(), player.getLocation(), player.isOp(), player.getGameMode(), demData, player.getName(), player.isOnline());
try {
isBanned = player.isBanned();
} catch (Exception e) {
Plan plugin = getPlugin(Plan.class);
plugin.logError("Error getting ban date from Bukkit files. " + uuid.toString());
plugin.toLog(this.getClass().getName(), e);
isBanned = false;
}
}
/**
*
* @param player
* @param demData
*/
public UserData(OfflinePlayer player, DemographicsData demData) {
this(player.getUniqueId(), player.getFirstPlayed(), null, player.isOp(), GameMode.SURVIVAL, demData, player.getName(), player.isOnline());
try {
isBanned = player.isBanned();
} catch (Exception e) {
Plan plugin = getPlugin(Plan.class);
plugin.logError("Error getting ban date from Bukkit files. " + uuid.toString());
plugin.toLog(this.getClass().getName(), e);
isBanned = false;
}
name = player.getName();
isOnline = player.isOnline();
sessions = new ArrayList<>();
lastNick = "";
playerKills = new ArrayList<>();
}
/**

View File

@ -31,7 +31,7 @@ public class AnalysisCacheHandler {
*/
public void updateCache() {
cache = null;
analysis.analyze(this);
analysis.runAnalysis(this);
}
/**

View File

@ -18,6 +18,7 @@ import main.java.com.djrapitops.plan.api.Gender;
import main.java.com.djrapitops.plan.data.*;
import main.java.com.djrapitops.plan.data.cache.DBCallableProcessor;
import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.utilities.UUIDFetcher;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.World;
@ -192,8 +193,7 @@ public abstract class SQLDB extends Database {
/**
*
* @return
* @throws SQLException
* @return @throws SQLException
*/
public boolean checkConnection() throws SQLException {
if (connection == null || connection.isClosed()) {
@ -352,8 +352,7 @@ public abstract class SQLDB extends Database {
/**
*
* @return
* @throws SQLException
* @return @throws SQLException
*/
@Override
public int getVersion() throws SQLException {
@ -439,8 +438,7 @@ public abstract class SQLDB extends Database {
/**
*
* @return
* @throws SQLException
* @return @throws SQLException
*/
@Override
public Set<UUID> getSavedUUIDs() throws SQLException {
@ -500,8 +498,7 @@ public abstract class SQLDB extends Database {
/**
*
* @return
* @throws SQLException
* @return @throws SQLException
*/
@Override
public HashMap<String, Integer> getCommandUse() throws SQLException {
@ -782,11 +779,18 @@ public abstract class SQLDB extends Database {
continue;
}
UUID uuid = uData.getUuid();
if (uuid == null) {
try {
uData.setUuid(UUIDFetcher.getUUIDOf(uData.getName()));
} catch (Exception ex) {
continue;
}
}
uuid = uData.getUuid();
if (uuid == null) {
continue;
}
uData.access();
int userId = getUserId(uuid.toString());
if (userId == -1) {
saveLast.add(uData);
@ -832,6 +836,17 @@ public abstract class SQLDB extends Database {
if (uData == null) {
continue;
}
UUID uuid = uData.getUuid();
if (uuid == null) {
try {
uData.setUuid(UUIDFetcher.getUUIDOf(uData.getName()));
if (uData.getUuid() == null) {
continue;
}
} catch (Exception ex) {
continue;
}
}
uData.access();
try {
int userId = getUserId(uData.getUuid().toString());
@ -970,7 +985,7 @@ public abstract class SQLDB extends Database {
return;
}
List<Location> newLocations = new ArrayList<>();
newLocations.addAll(locations);
newLocations.addAll(locations);
PreparedStatement saveStatement = connection.prepareStatement("INSERT INTO " + locationName + " ("
+ locationColumnUserID + ", "
+ locationColumnCoordinatesX + ", "

View File

@ -0,0 +1,40 @@
package main.java.com.djrapitops.plan.ui;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import main.java.com.djrapitops.plan.utilities.comparators.MapComparator;
/**
*
* @author Rsl1122
*/
public class RecentPlayersButtonsCreator {
/**
* Creates recent players buttons inside a p-tag.
*
* @param map Map of Playername, Logintime in ms
* @param limit How many playes will be shown
* @return html p-tag list of recent logins.
*/
public static String createRecentLoginsButtons(HashMap<String, Long> map, int limit) {
List<String[]> sorted = MapComparator.sortByValueLong(map);
String html = "<p>";
if (sorted.isEmpty()) {
html = Html.ERROR_LIST.parse();
return html;
}
Collections.reverse(sorted);
int i = 1;
for (String[] values : sorted) {
if (i >= limit) {
break;
}
html += values[1] + " ";
i++;
}
html += "</p>";
return html;
}
}

View File

@ -33,6 +33,9 @@ public class SortableSessionTableCreator {
long start = session.getSessionStart();
long end = session.getSessionEnd();
long length = end - start;
if (length < 0) {
continue;
}
html += Html.TABLELINE_3_CUSTOMKEY.parse(
start+"", FormatUtils.formatTimeStamp(start+""),
end+"", FormatUtils.formatTimeStamp(end+""),

View File

@ -16,7 +16,9 @@ import main.java.com.djrapitops.plan.data.SessionData;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.cache.AnalysisCacheHandler;
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;
import main.java.com.djrapitops.plan.ui.RecentPlayersButtonsCreator;
import main.java.com.djrapitops.plan.ui.graphs.PlayerActivityGraphCreator;
import org.bukkit.GameMode;
import org.bukkit.scheduler.BukkitRunnable;
@ -39,7 +41,7 @@ public class Analysis {
*/
public Analysis(Plan plugin) {
this.plugin = plugin;
this.inspectCache = plugin.getInspectCache();
this.inspectCache = plugin.getInspectCache();
}
/**
@ -51,197 +53,31 @@ public class Analysis {
*
* @param analysisCache Cache that the data is saved to.
*/
public void analyze(AnalysisCacheHandler analysisCache) {
List<UserData> rawData = new ArrayList<>();
List<UUID> added = new ArrayList<>();
public void runAnalysis(AnalysisCacheHandler analysisCache) {
log(Phrase.ANALYSIS_START + "");
List<UUID> uuids = fetchPlayersInDB();
if (uuids.isEmpty()) {
plugin.log(Phrase.ANALYSIS_FAIL_NO_DATA + "");
return;
}
// Async task for Analysis
BukkitTask asyncAnalysisTask = (new BukkitRunnable() {
@Override
public void run() {
uuids.stream().forEach((uuid) -> {
inspectCache.cache(uuid, 15);
});
log(Phrase.ANALYSIS_FETCH_DATA + "");
while (rawData.size() != uuids.size()) {
uuids.stream()
.filter((uuid) -> (!added.contains(uuid)))
.forEach((uuid) -> {
if (inspectCache.isCached(uuid)) {
UserData userData = inspectCache.getFromCache(uuid);
if (userData != null) {
rawData.add(userData);
userData.access();
added.add(uuid);
}
}
});
}
// Create empty Dataset
final RawAnalysisData sorted = new RawAnalysisData();
sorted.setCommandUse(plugin.getHandler().getCommandUse());
log(Phrase.ANALYSIS_BEGIN_ANALYSIS + "");
AnalysisData analysisData = new AnalysisData();
analysisData.setSortablePlayersTable(AnalysisUtils.createSortablePlayersTable(rawData));
// Fill Dataset with userdata.
rawData.parallelStream().forEach((uData) -> {
try {
HashMap<GameMode, Long> gmTimes = uData.getGmTimes();
sorted.addToGmZero(gmTimes.get(GameMode.SURVIVAL));
sorted.addToGmOne(gmTimes.get(GameMode.CREATIVE));
sorted.addToGmTwo(gmTimes.get(GameMode.ADVENTURE));
try {
Long gm = gmTimes.get(GameMode.SPECTATOR);
if (gm != null) {
sorted.addGmThree(gm);
}
} catch (NoSuchFieldError e) {
}
long playTime = uData.getPlayTime();
sorted.addTotalPlaytime(playTime);
String playerName = uData.getName();
String url = HtmlUtils.getInspectUrl(playerName);
String html = Html.BUTTON.parse(url, playerName);
sorted.getLatestLogins().put(html, uData.getLastPlayed());
sorted.addTotalLoginTimes(uData.getLoginTimes());
int age = uData.getDemData().getAge();
if (age != -1) {
sorted.getAges().add(age);
}
if (uData.isOp()) {
sorted.addOps(1);
}
if (uData.isBanned()) {
sorted.addTotalBanned(1);
} else if (uData.getLoginTimes() == 1) {
sorted.addJoinleaver(1);
} else if (AnalysisUtils.isActive(uData.getLastPlayed(), playTime, uData.getLoginTimes())) {
sorted.addActive(1);
sorted.getPlaytimes().put(html, playTime);
} else {
sorted.addInactive(1);
}
sorted.addTotalKills(uData.getPlayerKills().size());
sorted.addTotalMobKills(uData.getMobKills());
sorted.addTotalDeaths(uData.getDeaths());
sorted.getSessiondata().addAll(uData.getSessions());
sorted.getRegistered().add(uData.getRegistered());
uData.stopAccessing();
} catch (NullPointerException e) {
plugin.logError(Phrase.DATA_CORRUPTION_WARN.parse(uData.getUuid() + ""));
plugin.toLog(this.getClass().getName(), e);
}
});
// Analyze & Save RawAnalysisData to AnalysisData
createPlayerActivityGraphs(analysisData, sorted.getSessiondata(), sorted.getRegistered());
analysisData.setRecentPlayers(AnalysisUtils.createListStringOutOfHashMapLong(sorted.getLatestLogins(), 20));
long totalPlaytime = sorted.getTotalPlaytime();
analysisData.setTotalPlayTime(totalPlaytime);
analysisData.setAveragePlayTime(totalPlaytime / rawData.size());
analysisData.setSessionAverage(AnalysisUtils.average(AnalysisUtils.transformSessionDataToLengths(sorted.getSessiondata())));
analysisData.setTotalLoginTimes(sorted.getTotalLoginTimes());
createActivityVisalization(sorted.getTotalBanned(), sorted.getActive(), sorted.getInactive(), sorted.getJoinleaver(), analysisData);
analysisData.setOps(sorted.getOps());
analyzeAverageAge(sorted.getAges(), analysisData);
createGamemodeUsageVisualization(sorted.getGmZero(), sorted.getGmOne(), sorted.getGmTwo(), sorted.getGmThree(), analysisData);
createCommandUseTable(sorted, analysisData);
analysisData.setTotaldeaths(sorted.getTotalDeaths());
analysisData.setTotalkills(sorted.getTotalKills());
analysisData.setTotalmobkills(sorted.getTotalMobKills());
analysisData.setRefreshDate(new Date().getTime());
analysisCache.cache(analysisData);
plugin.log(Phrase.ANALYSIS_COMPLETE + "");
analyze(analysisCache, plugin.getDB());
this.cancel();
}
private void createCommandUseTable(final RawAnalysisData raw, AnalysisData data) {
HashMap<String, Integer> commandUse = raw.getCommandUse();
if (!commandUse.isEmpty()) {
data.setCommandUseTableHtml(AnalysisUtils.createTableOutOfHashMap(commandUse));
data.setTotalCommands(commandUse.size());
} else {
data.setCommandUseTableHtml(Html.ERROR_TABLE_2.parse());
data.setTotalCommands(0);
}
}
private void createActivityVisalization(int totalBanned, int active, int inactive, int joinleaver, AnalysisData data) {
data.setActive(active);
data.setInactive(inactive);
data.setBanned(totalBanned);
data.setJoinleaver(joinleaver);
data.setTotal(uuids.size());
}
private void analyzeAverageAge(List<Integer> ages, AnalysisData data) {
int totalAge = 0;
for (int age : ages) {
totalAge += age;
}
double averageAge;
if (!ages.isEmpty()) {
averageAge = totalAge * 1.0 / ages.size();
} else {
averageAge = -1;
}
data.setAverageAge(averageAge);
}
private void createGamemodeUsageVisualization(long gmZero, long gmOne, long gmTwo, long gmThree, AnalysisData data) {
long gmTotal = gmZero + gmOne + gmTwo + gmThree;
HashMap<GameMode, Long> totalGmTimes = new HashMap<>();
totalGmTimes.put(GameMode.SURVIVAL, gmZero);
totalGmTimes.put(GameMode.CREATIVE, gmOne);
totalGmTimes.put(GameMode.ADVENTURE, gmTwo);
try {
totalGmTimes.put(GameMode.SPECTATOR, gmThree);
} catch (NoSuchFieldError e) {
}
data.setGm0Perc((gmZero * 1.0 / gmTotal));
data.setGm1Perc((gmOne * 1.0 / gmTotal));
data.setGm2Perc((gmTwo * 1.0 / gmTotal));
data.setGm3Perc((gmThree * 1.0 / gmTotal));
}
private void createPlayerActivityGraphs(AnalysisData data, List<SessionData> sData, List<Long> registered) {
long now = new Date().toInstant().getEpochSecond() * (long) 1000;
long scaleDay = 86400 * 1000;
long scaleWeek = 604800 * 1000;
long scaleMonth = (long) 2592000 * (long) 1000;
data.setNewPlayersDay(AnalysisUtils.getNewPlayers(registered, scaleDay, now));
data.setNewPlayersWeek(AnalysisUtils.getNewPlayers(registered, scaleWeek, now));
data.setNewPlayersMonth(AnalysisUtils.getNewPlayers(registered, scaleMonth, now));
String[] dayArray = PlayerActivityGraphCreator.generateDataArray(sData, scaleDay);
String[] weekArray = PlayerActivityGraphCreator.generateDataArray(sData, scaleWeek);
String[] monthArray = PlayerActivityGraphCreator.generateDataArray(sData, scaleMonth);
data.setPlayersDataArray(new String[]{dayArray[0], dayArray[1], weekArray[0], weekArray[1], monthArray[0], monthArray[1]});
}
}).runTaskAsynchronously(plugin);
}
private List<UUID> fetchPlayersInDB() {
/**
* @param analysisCache
* @deprecated Does nothing anymore, use analyze(AnalysisCacheHandler,
* Database)
*/
@Deprecated
public void analyze(AnalysisCacheHandler analysisCache) {
}
private List<UUID> fetchPlayersInDB(Database db) {
try {
// final List<UUID> uuids = new ArrayList<>();
log(Phrase.ANALYSIS_FETCH_PLAYERS + "");
Set<UUID> savedUUIDs = plugin.getDB().getSavedUUIDs();
log(Phrase.ANALYSIS_FETCH_PLAYERS + "");
Set<UUID> savedUUIDs = db.getSavedUUIDs();
List<UUID> uuids = savedUUIDs.parallelStream()
.filter(uuid -> uuid != null)
.filter((uuid) -> (getOfflinePlayer(uuid).hasPlayedBefore()))
@ -253,6 +89,188 @@ public class Analysis {
return new ArrayList<>();
}
/**
* Caches analyzed data of db to the provided cache analysisCache.
*
* @param analysisCache Cache that will contain AnalysisData result of this method.
* @param db Database which data will be analyzed.
* @return Whether or not analysis was successful.
*/
public boolean analyze(AnalysisCacheHandler analysisCache, Database db) {
List<UserData> rawData = new ArrayList<>();
List<UUID> added = new ArrayList<>();
List<UUID> uuids = fetchPlayersInDB(db);
if (uuids.isEmpty()) {
plugin.log(Phrase.ANALYSIS_FAIL_NO_DATA + "");
return false;
}
uuids.stream().forEach((uuid) -> {
inspectCache.cache(uuid, 15);
});
log(Phrase.ANALYSIS_FETCH_DATA + "");
while (rawData.size() != uuids.size()) {
uuids.stream()
.filter((uuid) -> (!added.contains(uuid)))
.forEach((uuid) -> {
if (inspectCache.isCached(uuid)) {
UserData userData = inspectCache.getFromCache(uuid);
if (userData != null) {
rawData.add(userData);
userData.access();
added.add(uuid);
}
}
});
}
if (added.isEmpty()) {
plugin.log(Phrase.ANALYSIS_FAIL_NO_DATA + "");
return false;
}
// Create empty Dataset
final RawAnalysisData sorted = new RawAnalysisData();
sorted.setCommandUse(plugin.getHandler().getCommandUse());
log(Phrase.ANALYSIS_BEGIN_ANALYSIS + "");
AnalysisData analysisData = new AnalysisData();
analysisData.setSortablePlayersTable(AnalysisUtils.createSortablePlayersTable(rawData));
// Fill Dataset with userdata.
rawData.parallelStream().forEach((uData) -> {
try {
HashMap<GameMode, Long> gmTimes = uData.getGmTimes();
sorted.addToGmZero(gmTimes.get(GameMode.SURVIVAL));
sorted.addToGmOne(gmTimes.get(GameMode.CREATIVE));
sorted.addToGmTwo(gmTimes.get(GameMode.ADVENTURE));
try {
Long gm = gmTimes.get(GameMode.SPECTATOR);
if (gm != null) {
sorted.addGmThree(gm);
}
} catch (NoSuchFieldError e) {
}
long playTime = uData.getPlayTime();
sorted.addTotalPlaytime(playTime);
String playerName = uData.getName();
String url = HtmlUtils.getInspectUrl(playerName);
String html = Html.BUTTON.parse(url, playerName);
sorted.getLatestLogins().put(html, uData.getLastPlayed());
sorted.addTotalLoginTimes(uData.getLoginTimes());
int age = uData.getDemData().getAge();
if (age != -1) {
sorted.getAges().add(age);
}
if (uData.isOp()) {
sorted.addOps(1);
}
if (uData.isBanned()) {
sorted.addTotalBanned(1);
} else if (uData.getLoginTimes() == 1) {
sorted.addJoinleaver(1);
} else if (AnalysisUtils.isActive(uData.getLastPlayed(), playTime, uData.getLoginTimes())) {
sorted.addActive(1);
sorted.getPlaytimes().put(html, playTime);
} else {
sorted.addInactive(1);
}
sorted.addTotalKills(uData.getPlayerKills().size());
sorted.addTotalMobKills(uData.getMobKills());
sorted.addTotalDeaths(uData.getDeaths());
sorted.getSessiondata().addAll(uData.getSessions());
sorted.getRegistered().add(uData.getRegistered());
uData.stopAccessing();
} catch (NullPointerException e) {
plugin.logError(Phrase.DATA_CORRUPTION_WARN.parse(uData.getUuid() + ""));
plugin.toLog(this.getClass().getName(), e);
}
});
// Analyze & Save RawAnalysisData to AnalysisData
createPlayerActivityGraphs(analysisData, sorted.getSessiondata(), sorted.getRegistered());
analysisData.setRecentPlayers(RecentPlayersButtonsCreator.createRecentLoginsButtons(sorted.getLatestLogins(), 20));
long totalPlaytime = sorted.getTotalPlaytime();
analysisData.setTotalPlayTime(totalPlaytime);
analysisData.setAveragePlayTime(totalPlaytime / rawData.size());
analysisData.setSessionAverage(AnalysisUtils.average(AnalysisUtils.transformSessionDataToLengths(sorted.getSessiondata())));
analysisData.setTotalLoginTimes(sorted.getTotalLoginTimes());
createActivityVisalization(uuids.size(), sorted.getTotalBanned(), sorted.getActive(), sorted.getInactive(), sorted.getJoinleaver(), analysisData);
analysisData.setOps(sorted.getOps());
analyzeAverageAge(sorted.getAges(), analysisData);
createGamemodeUsageVisualization(sorted.getGmZero(), sorted.getGmOne(), sorted.getGmTwo(), sorted.getGmThree(), analysisData);
createCommandUseTable(sorted, analysisData);
analysisData.setTotaldeaths(sorted.getTotalDeaths());
analysisData.setTotalkills(sorted.getTotalKills());
analysisData.setTotalmobkills(sorted.getTotalMobKills());
analysisData.setRefreshDate(new Date().getTime());
analysisCache.cache(analysisData);
plugin.log(Phrase.ANALYSIS_COMPLETE + "");
return true;
}
private void createCommandUseTable(final RawAnalysisData raw, AnalysisData data) {
HashMap<String, Integer> commandUse = raw.getCommandUse();
if (!commandUse.isEmpty()) {
data.setCommandUseTableHtml(AnalysisUtils.createTableOutOfHashMap(commandUse));
data.setTotalCommands(commandUse.size());
} else {
data.setCommandUseTableHtml(Html.ERROR_TABLE_2.parse());
data.setTotalCommands(0);
}
}
private void createActivityVisalization(int total, int totalBanned, int active, int inactive, int joinleaver, AnalysisData data) {
data.setActive(active);
data.setInactive(inactive);
data.setBanned(totalBanned);
data.setJoinleaver(joinleaver);
data.setTotal(total);
}
private void analyzeAverageAge(List<Integer> ages, AnalysisData data) {
int totalAge = 0;
for (int age : ages) {
totalAge += age;
}
double averageAge;
if (!ages.isEmpty()) {
averageAge = totalAge * 1.0 / ages.size();
} else {
averageAge = -1;
}
data.setAverageAge(averageAge);
}
private void createGamemodeUsageVisualization(long gmZero, long gmOne, long gmTwo, long gmThree, AnalysisData data) {
long gmTotal = gmZero + gmOne + gmTwo + gmThree;
HashMap<GameMode, Long> totalGmTimes = new HashMap<>();
totalGmTimes.put(GameMode.SURVIVAL, gmZero);
totalGmTimes.put(GameMode.CREATIVE, gmOne);
totalGmTimes.put(GameMode.ADVENTURE, gmTwo);
try {
totalGmTimes.put(GameMode.SPECTATOR, gmThree);
} catch (NoSuchFieldError e) {
}
data.setGm0Perc((gmZero * 1.0 / gmTotal));
data.setGm1Perc((gmOne * 1.0 / gmTotal));
data.setGm2Perc((gmTwo * 1.0 / gmTotal));
data.setGm3Perc((gmThree * 1.0 / gmTotal));
}
private void createPlayerActivityGraphs(AnalysisData data, List<SessionData> sData, List<Long> registered) {
long now = new Date().toInstant().getEpochSecond() * (long) 1000;
long scaleDay = 86400 * 1000;
long scaleWeek = 604800 * 1000;
long scaleMonth = (long) 2592000 * (long) 1000;
data.setNewPlayersDay(AnalysisUtils.getNewPlayers(registered, scaleDay, now));
data.setNewPlayersWeek(AnalysisUtils.getNewPlayers(registered, scaleWeek, now));
data.setNewPlayersMonth(AnalysisUtils.getNewPlayers(registered, scaleMonth, now));
String[] dayArray = PlayerActivityGraphCreator.generateDataArray(sData, scaleDay);
String[] weekArray = PlayerActivityGraphCreator.generateDataArray(sData, scaleWeek);
String[] monthArray = PlayerActivityGraphCreator.generateDataArray(sData, scaleMonth);
data.setPlayersDataArray(new String[]{dayArray[0], dayArray[1], weekArray[0], weekArray[1], monthArray[0], monthArray[1]});
}
private void log(String msg) {
if (Settings.ANALYSIS_LOG_TO_CONSOLE.isTrue()) {
plugin.log(msg);

View File

@ -51,26 +51,6 @@ public class AnalysisUtils {
return SortablePlayersTableCreator.createSortablePlayersTable(data);
}
static String createListStringOutOfHashMapLong(HashMap<String, Long> map, int limit) {
List<String[]> sorted = MapComparator.sortByValueLong(map);
String html = "<p>";
if (sorted.isEmpty()) {
html = Html.ERROR_LIST.parse();
return html;
}
Collections.reverse(sorted);
int i = 1;
for (String[] values : sorted) {
if (i >= limit) {
break;
}
html += values[1] + " ";
i++;
}
html += "</p>";
return html;
}
public static int getNewPlayers(List<Long> registered, long scale, long now) {
int newPlayers = 0;
if (!registered.isEmpty()) {

View File

@ -0,0 +1,130 @@
package main.java.com.djrapitops.plan.utilities;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import main.java.com.djrapitops.plan.Plan;
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.database.Database;
import main.java.com.djrapitops.plan.database.databases.SQLiteDB;
import org.bukkit.GameMode;
import org.bukkit.OfflinePlayer;
import static org.bukkit.plugin.java.JavaPlugin.getPlugin;
import static org.bukkit.Bukkit.getOfflinePlayer;
/**
*
* @author Rsl1122
*/
public class ManageUtils {
/**
* Creates a new backup sqlite file with the data of copyFromDB.
*
* @param dbName Name of database (mysql/sqlite)
* @param copyFromDB Database you want to backup.
* @return success?
*/
public static boolean backup(String dbName, Database copyFromDB) {
Plan plugin = getPlugin(Plan.class);
Date now = new Date();
SQLiteDB backupDB = new SQLiteDB(plugin,
dbName + "-backup-" + now.toString().substring(4, 10).replaceAll(" ", "-").replaceAll(":", "-"));
final Collection<UUID> uuids = ManageUtils.getUUIDS(copyFromDB);
if (uuids.isEmpty()) {
return false;
}
return clearAndCopy(backupDB, copyFromDB, uuids);
}
/**
* Import OnTime plugin data to the provided DataCacheHandler, and save
* cache.
*
* @param onTimeData PlayTime data of Ontime
* @param handler Cache the data will be cached to.
* @return success?
*/
public static boolean importOnTime(HashMap<UUID, Long> onTimeData, DataCacheHandler handler) {
for (UUID uuid : onTimeData.keySet()) {
OfflinePlayer player = getOfflinePlayer(uuid);
if (handler.getActivityHandler().isFirstTimeJoin(uuid)) {
handler.newPlayer(player);
}
DBCallableProcessor importer = new DBCallableProcessor() {
@Override
public void process(UserData data) {
Long playTime = onTimeData.get(uuid);
if (playTime > data.getPlayTime()) {
data.setPlayTime(playTime);
data.setLastGamemode(GameMode.SURVIVAL);
data.setAllGMTimes(playTime, 0, 0, 0);
data.setLastGmSwapTime(playTime);
}
}
};
handler.getUserDataForProcessing(importer, uuid);
}
handler.saveCachedUserData();
return true;
}
/**
* Get the saved UUIDs in a hashset
*
* @param db Database to get UUIDs from
* @return uuids hashset as a Collection.
*/
public static Collection<UUID> getUUIDS(Database db) {
Plan plugin = getPlugin(Plan.class);
final Set<UUID> uuids = new HashSet<>();
try {
uuids.addAll(db.getSavedUUIDs());
} catch (SQLException e) {
plugin.toLog("ManageUtils.getUUIDS", e);
}
return uuids;
}
/**
* Clears a database and copies data from other database to that database.
*
* @param clearAndCopyToDB Database that will be cleared data will be copied
* to.
* @param copyFromDB Database where data will be copied from
* @param fromDBsavedUUIDs UUID collection of saved uuids in the copyFromDB
* @return success?
*/
public static boolean clearAndCopy(Database clearAndCopyToDB, Database copyFromDB, Collection<UUID> fromDBsavedUUIDs) {
Plan plugin = getPlugin(Plan.class);
try {
clearAndCopyToDB.removeAllData();
List<UserData> allUserData = new ArrayList<>();
for (UUID uuid : fromDBsavedUUIDs) {
copyFromDB.giveUserDataToProcessors(uuid, new DBCallableProcessor() {
@Override
public void process(UserData data) {
allUserData.add(data);
}
});
}
while (fromDBsavedUUIDs.size() > allUserData.size()) {
}
clearAndCopyToDB.saveMultipleUserData(allUserData);
clearAndCopyToDB.saveCommandUse(copyFromDB.getCommandUse());
} catch (SQLException | NullPointerException e) {
plugin.toLog("ManageUtils.move", e);
return false;
}
return true;
}
}