Added Refresh setting for analysis, More Html Enum, Fixes

Fixes:
- Boot analysis no longer run if /plan analyze is used before boot
analysis
- Config now responds properly (with exception of colors) [Settings
Enum]
This commit is contained in:
Rsl1122 2017-02-02 13:04:35 +02:00
parent a19fcbd4e0
commit 3ab8f89852
7 changed files with 201 additions and 119 deletions

View File

@ -5,11 +5,10 @@ import com.djrapitops.plan.api.API;
import com.djrapitops.plan.data.cache.AnalysisCacheHandler;
import com.djrapitops.plan.utilities.MiscUtils;
import com.djrapitops.plan.database.Database;
import com.djrapitops.plan.database.databases.MySQLDB;
import com.djrapitops.plan.database.databases.SQLiteDB;
import com.djrapitops.plan.data.cache.DataCacheHandler;
import com.djrapitops.plan.data.cache.InspectCacheHandler;
import com.djrapitops.plan.database.databases.*;
import com.djrapitops.plan.data.cache.*;
import com.djrapitops.plan.data.listeners.*;
import java.util.Date;
import main.java.com.djrapitops.plan.ui.webserver.WebSocketServer;
import org.bukkit.plugin.java.JavaPlugin;
@ -18,8 +17,10 @@ import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import main.java.com.djrapitops.plan.Settings;
import org.bukkit.Bukkit;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.plugin.PluginManager;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask;
/* TODO 2.2.0
Placeholder API
@ -27,7 +28,6 @@ Database cleaning
Location Analysis to view meaningful locations on Dynmap (Investigate dynmap api)
Integrate PlanLite features to Plan and discontinue PlanLite
Seperate serverdata and userdata saving
Make Analysis.java readable
Database Cleaning of useless data
Fix any bugs that come up
- New Players not reset if server not restarted
@ -47,10 +47,15 @@ public class Plan extends JavaPlugin {
private HashSet<Database> databases;
private WebSocketServer uiServer;
private int bootAnalysisTaskID;
/**
* OnEnable method.
*
* Initiates the plugin with database, webserver, commands & listeners.
* Creates the config file. Checks for new version. Initializes Database.
* Hooks PlanLite. Initializes DataCaches. Registers Listeners. Registers
* Command /plan and initializes API. Enables Webserver & analysis tasks if
* enabled in config. Warns about possible mistakes made in config.
*/
@Override
public void onEnable() {
@ -61,13 +66,12 @@ public class Plan extends JavaPlugin {
databases.add(new SQLiteDB(this));
getConfig().options().copyDefaults(true);
getConfig().options().header(Phrase.CONFIG_HEADER + "");
saveConfig();
log(MiscUtils.checkVersion());
log(Phrase.DB_INIT+"");
log(Phrase.DB_INIT + "");
if (initDatabase()) {
log(Phrase.DB_ESTABLISHED.parse(db.getConfigName()));
} else {
@ -86,30 +90,29 @@ public class Plan extends JavaPlugin {
this.api = new API(this);
handler.handleReload();
ConsoleCommandSender consoleSender = getServer().getConsoleSender();
bootAnalysisTaskID = -1;
if (Settings.WEBSERVER_ENABLED.isTrue()) {
uiServer = new WebSocketServer(this);
uiServer.initServer();
if (Settings.ANALYSIS_REFRESH_ON_ENABLE.isTrue()) {
log(Phrase.ANALYSIS_BOOT_NOTIFY + "");
(new BukkitRunnable() {
@Override
public void run() {
log(Phrase.ANALYSIS_BOOT + "");
analysisCache.updateCache();
this.cancel();
}
}).runTaskLater(this, 30 * 20);
startBootRefreshTask();
}
int analysisRefreshMinutes = Settings.ANALYSIS_AUTO_REFRESH.getNumber();
if (analysisRefreshMinutes != -1) {
startAnalysisRefreshTask(analysisRefreshMinutes);
}
} else if (!(Settings.SHOW_ALTERNATIVE_IP.isTrue())
|| (Settings.USE_ALTERNATIVE_UI.isTrue()
&& planLiteHook.isEnabled())) {
Bukkit.getServer().getConsoleSender().sendMessage(Phrase.PREFIX + "" + Phrase.ERROR_NO_DATA_VIEW);
consoleSender.sendMessage(Phrase.PREFIX + "" + Phrase.ERROR_NO_DATA_VIEW);
}
if (!Settings.SHOW_ALTERNATIVE_IP.isTrue() && getServer().getIp().isEmpty()) {
log(Phrase.NOTIFY_EMPTY_IP+"");
consoleSender.sendMessage(Phrase.NOTIFY_EMPTY_IP + "");
}
log(Phrase.ENABLED+"");
log(Phrase.ENABLED + "");
}
/**
@ -126,7 +129,7 @@ public class Plan extends JavaPlugin {
/**
* Disables the plugin.
*
* Stops the webserver, cancels all tasks and saves cache to the database. *
* Stops the webserver, cancels all tasks and saves cache to the database.
*/
@Override
public void onDisable() {
@ -135,7 +138,7 @@ public class Plan extends JavaPlugin {
}
Bukkit.getScheduler().cancelTasks(this);
if (handler != null) {
log(Phrase.SAVE_CACHE+"");
log(Phrase.SAVE_CACHE + "");
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.execute(() -> {
handler.saveCacheOnDisable();
@ -143,7 +146,7 @@ public class Plan extends JavaPlugin {
scheduler.shutdown();
}
log(Phrase.DISABLED+"");
log(Phrase.DISABLED + "");
}
/**
@ -182,8 +185,14 @@ public class Plan extends JavaPlugin {
}
}
/**
* Initializes the database according to settings in the config.
*
* If database connection can not be established plugin is disabled.
* @return true if init was successful, false if not.
*/
public boolean initDatabase() {
String type = Settings.DB_TYPE+"";
String type = Settings.DB_TYPE + "";
db = null;
@ -211,6 +220,32 @@ public class Plan extends JavaPlugin {
return true;
}
private void startAnalysisRefreshTask(int analysisRefreshMinutes) throws IllegalStateException, IllegalArgumentException {
(new BukkitRunnable() {
@Override
public void run() {
if (!analysisCache.isCached()) {
analysisCache.updateCache();
} else if (new Date().getTime() - analysisCache.getData().getRefreshDate() > 60000) {
analysisCache.updateCache();
}
}
}).runTaskTimerAsynchronously(this, analysisRefreshMinutes * 60 * 20, analysisRefreshMinutes * 60 * 20);
}
private void startBootRefreshTask() throws IllegalStateException, IllegalArgumentException {
log(Phrase.ANALYSIS_BOOT_NOTIFY + "");
BukkitTask analysis = (new BukkitRunnable() {
@Override
public void run() {
log(Phrase.ANALYSIS_BOOT + "");
analysisCache.updateCache();
this.cancel();
}
}).runTaskLater(this, 30 * 20);
bootAnalysisTaskID = analysis.getTaskId();
}
/**
* @return Currnet instance of the AnalysisCacheHandler
*/
@ -253,7 +288,17 @@ public class Plan extends JavaPlugin {
return uiServer;
}
/**
* @return Set containing SqLite & MySQL classes.
*/
public HashSet<Database> getDatabases() {
return databases;
}
/**
* @return
*/
public int getBootAnalysisTaskID() {
return bootAnalysisTaskID;
}
}

View File

@ -8,59 +8,53 @@ import static org.bukkit.plugin.java.JavaPlugin.getPlugin;
* @author Rsl1122
*/
public enum Settings {
WEBSERVER_ENABLED(getPlugin(Plan.class).getConfig().getBoolean("Settings.WebServer.Enabled")),
WEBSERVER_PORT(getPlugin(Plan.class).getConfig().getInt("Settings.WebServer.Port")),
ANALYSIS_REFRESH_ON_ENABLE(getPlugin(Plan.class).getConfig().getBoolean("Settings.Cache.AnalysisCache.RefreshAnalysisCacheOnEnable")),
ANALYSIS_LOG_TO_CONSOLE(getPlugin(Plan.class).getConfig().getBoolean("Settings.Analysis.LogProgressOnConsole")),
ANALYSIS_MINUTES_FOR_ACTIVE(getPlugin(Plan.class).getConfig().getInt("Settings.Analysis.MinutesPlayedUntilConsidiredActive")),
SHOW_ALTERNATIVE_IP(getPlugin(Plan.class).getConfig().getBoolean("Settings.WebServer.ShowAlternativeServerIP")),
ALTERNATIVE_IP(getPlugin(Plan.class).getConfig().getString("Settings.WebServer.AlternativeIP")),
USE_ALTERNATIVE_UI(getPlugin(Plan.class).getConfig().getBoolean("Settings.PlanLite.UseAsAlternativeUI")),
PLANLITE_ENABLED(getPlugin(Plan.class).getConfig().getBoolean("Settings.PlanLite.Enabled")),
GATHERLOCATIONS(getPlugin(Plan.class).getConfig().getBoolean("Settings.Data.GatherLocations")),
DB_TYPE(getPlugin(Plan.class).getConfig().getString("database.type")),
SAVE_CACHE_MIN(getPlugin(Plan.class).getConfig().getInt("Settings.Cache.DataCache.SaveEveryXMinutes")),
SAVE_SERVER_MIN(getPlugin(Plan.class).getConfig().getInt("Settings.Cache.DataCache.SaveServerDataEveryXMinutes")),
CLEAR_INSPECT_CACHE(getPlugin(Plan.class).getConfig().getInt("Settings.Cache.InspectCache.ClearFromInspectCacheAfterXMinutes")),
CLEAR_CACHE_X_SAVES(getPlugin(Plan.class).getConfig().getInt("Settings.Cache.DataCache.ClearCacheEveryXSaves")),
DEM_TRIGGERS(getPlugin(Plan.class).getConfig().getString("Customization.DemographicsTriggers.Trigger")),
DEM_FEMALE(getPlugin(Plan.class).getConfig().getString("Customization.DemographicsTriggers.Female")),
DEM_MALE(getPlugin(Plan.class).getConfig().getString("Customization.DemographicsTriggers.Male")),
DEM_IGNORE(getPlugin(Plan.class).getConfig().getString("Customization.DemographicsTriggers.IgnoreWhen")),
;
// Boolean
WEBSERVER_ENABLED("Settings.WebServer.Enabled"),
ANALYSIS_REFRESH_ON_ENABLE("Settings.Cache.AnalysisCache.RefreshAnalysisCacheOnEnable"),
ANALYSIS_LOG_TO_CONSOLE("Settings.Analysis.LogProgressOnConsole"),
SHOW_ALTERNATIVE_IP("Settings.WebServer.ShowAlternativeServerIP"),
USE_ALTERNATIVE_UI("Settings.PlanLite.UseAsAlternativeUI"),
PLANLITE_ENABLED("Settings.PlanLite.Enabled"),
GATHERLOCATIONS("Settings.Data.GatherLocations"),
// Integer
ANALYSIS_MINUTES_FOR_ACTIVE("Settings.Analysis.MinutesPlayedUntilConsidiredActive"),
SAVE_CACHE_MIN("Settings.Cache.DataCache.SaveEveryXMinutes"),
SAVE_SERVER_MIN("Settings.Cache.DataCache.SaveServerDataEveryXMinutes"),
CLEAR_INSPECT_CACHE("Settings.Cache.InspectCache.ClearFromInspectCacheAfterXMinutes"),
CLEAR_CACHE_X_SAVES("Settings.Cache.DataCache.ClearCacheEveryXSaves"),
WEBSERVER_PORT("Settings.WebServer.Port"),
ANALYSIS_AUTO_REFRESH("Settings.Cache.AnalysisCache.RefreshEveryXMinutes"),
// String
ALTERNATIVE_IP("Settings.WebServer.AlternativeIP"),
DB_TYPE("database.type"),
DEM_TRIGGERS("Customization.DemographicsTriggers.Trigger"),
DEM_FEMALE("Customization.DemographicsTriggers.Female"),
DEM_MALE("Customization.DemographicsTriggers.Male"),
DEM_IGNORE("Customization.DemographicsTriggers.IgnoreWhen"),;
private String text;
private boolean bool;
private int number;
private String configPath;
private Settings(String text) {
this.text = text;
this.bool = false;
this.number = -1;
private Settings(String path) {
this.configPath = path;
}
private Settings(boolean bool) {
this.bool = bool;
this.text = "";
this.number = -1;
}
private Settings(int number) {
this.bool = false;
this.text = "";
this.number = number;
/**
* @return Boolean value of the config setting
*/
public boolean isTrue() {
return getPlugin(Plan.class).getConfig().getBoolean(configPath);
}
@Override
public String toString() {
return text;
}
public boolean isTrue() {
return this.bool;
return getPlugin(Plan.class).getConfig().getString(configPath);
}
/**
* @return Integer value of the config setting
*/
public int getNumber() {
return number;
return getPlugin(Plan.class).getConfig().getInt(configPath);
}
}

View File

@ -59,6 +59,10 @@ public class AnalyzeCommand extends SubCommand {
}
sender.sendMessage(Phrase.GRABBING_DATA_MESSAGE+"");
if (!analysisCache.isCached()) {
int bootAnID = plugin.getBootAnalysisTaskID();
if (bootAnID != -1) {
plugin.getServer().getScheduler().cancelTask(bootAnID);
}
analysisCache.updateCache();
} else if (new Date().getTime() - analysisCache.getData().getRefreshDate() > 60000) {
analysisCache.updateCache();

View File

@ -43,7 +43,14 @@ public enum Html {
FRIENDS("<p>Friends with "+REPLACE0+"</p>"),
FACTION("<p>Faction: " + REPLACE0 + "</p>"),
BALANCE("<p>Balance: " + REPLACE0 + "</p>"),
VOTES("<p>Player has voted " + REPLACE0 + " times.</p>")
VOTES("<p>Player has voted " + REPLACE0 + " times.</p>"),
BANNED("| "+SPAN.parse(COLOR_4.parse()+"Banned")),
OPERATOR(", Operator (Op)"),
ONLINE("| "+SPAN.parse(COLOR_2.parse()+"Online")),
OFFLINE("| "+SPAN.parse(COLOR_4.parse()+"Online")),
ACTIVE("| Player is Active"),
INACTIVE("| Player is inactive"),
ERROR_LIST("Error Creating List</p>"),
;
private final String html;

View File

@ -65,21 +65,17 @@ public class Analysis {
plugin.log(Phrase.ANALYSIS_FAIL_NO_PLAYERS + "");
return;
}
final List<UUID> uuids = new ArrayList<>();
log(Phrase.ANALYSIS_FETCH_PLAYERS + "");
for (OfflinePlayer p : offlinePlayers) {
UUID uuid = p.getUniqueId();
if (plugin.getDB().wasSeenBefore(uuid)) {
uuids.add(uuid);
}
}
List<UUID> uuids = fetchPlayersInDB(offlinePlayers);
if (uuids.isEmpty()) {
plugin.log(Phrase.ANALYSIS_FAIL_NO_DATA + "");
return;
}
// Settings for urls
final boolean useAlternativeIP = Settings.SHOW_ALTERNATIVE_IP.isTrue();
final int port = Settings.WEBSERVER_PORT.getNumber();
final String alternativeIP = Settings.ALTERNATIVE_IP.toString().replaceAll("%port%", "" + port);
// Async task for Analysis
(new BukkitRunnable() {
@Override
public void run() {
@ -121,14 +117,7 @@ public class Analysis {
int ops = 0;
List<Integer> ages = new ArrayList<>();
boolean planLiteEnabled;
PlanLiteHook planLiteHook = plugin.getPlanLiteHook();
if (planLiteHook != null) {
planLiteEnabled = planLiteHook.isEnabled();
} else {
planLiteEnabled = false;
}
boolean planLiteEnabled = isPlanLiteEnabled();
PlanLiteAnalyzedData plData = new PlanLiteAnalyzedData();
HashMap<String, Integer> townMap = new HashMap<>();
HashMap<String, Integer> factionMap = new HashMap<>();
@ -196,6 +185,39 @@ public class Analysis {
// Save Dataset to AnalysisData
data.setTop20ActivePlayers(AnalysisUtils.createActivePlayersTable(playtimes, 20));
data.setRecentPlayers(AnalysisUtils.createListStringOutOfHashMapLong(latestLogins, 20));
addPlanLiteToData(planLiteEnabled, plData, factionMap, townMap, totalVotes, totalMoney, data);
data.setTotalPlayTime(totalPlaytime);
data.setAveragePlayTime(totalPlaytime / rawData.size());
data.setTotalLoginTimes(totalLoginTimes);
createActivityVisalization(totalBanned, active, inactive, joinleaver, data);
data.setOps(ops);
analyzeAverageAge(ages, data);
createGamemodeUsageVisualization(gmZero, gmOne, gmTwo, gmThree, data);
createCommandUseTable(data);
data.setRefreshDate(new Date().getTime());
analysisCache.cache(data);
plugin.log(Phrase.ANALYSIS_COMPLETE + "");
this.cancel();
}
private boolean isPlanLiteEnabled() {
boolean planLiteEnabled;
PlanLiteHook planLiteHook = plugin.getPlanLiteHook();
if (planLiteHook != null) {
planLiteEnabled = planLiteHook.isEnabled();
} else {
planLiteEnabled = false;
}
return planLiteEnabled;
}
private void addPlanLiteToData(boolean planLiteEnabled, PlanLiteAnalyzedData plData, HashMap<String, Integer> factionMap, HashMap<String, Integer> townMap, int totalVotes, int totalMoney, AnalysisData data) {
if (planLiteEnabled) {
plData.setFactionMap(factionMap);
plData.setTownMap(townMap);
@ -206,21 +228,19 @@ public class Analysis {
} else {
data.setPlanLiteEnabled(false);
}
}
data.setTotalLoginTimes(totalLoginTimes);
private void createActivityVisalization(int totalBanned, int active, int inactive, int joinleaver, AnalysisData data) {
String activityPieChartHtml = AnalysisUtils.createActivityPieChart(totalBanned, active, inactive, joinleaver);
data.setActivityChartImgHtml(activityPieChartHtml);
data.setActive(active);
data.setInactive(inactive);
data.setBanned(totalBanned);
data.setJoinleaver(joinleaver);
data.setTotal(offlinePlayers.length);
data.setOps(ops);
}
data.setTotalPlayTime(totalPlaytime);
data.setAveragePlayTime(totalPlaytime / rawData.size());
private void analyzeAverageAge(List<Integer> ages, AnalysisData data) {
int totalAge = 0;
for (int age : ages) {
totalAge += age;
@ -232,7 +252,24 @@ public class Analysis {
averageAge = -1;
}
data.setAverageAge(averageAge);
}
private void createCommandUseTable(AnalysisData data) {
if (rawServerData.keySet().size() > 0) {
ServerData sData = null;
for (long sDataKey : rawServerData.keySet()) {
sData = rawServerData.get(sDataKey);
break;
}
if (sData != null) {
data.setTop50CommandsListHtml(AnalysisUtils.createTableOutOfHashMap(sData.getCommandUsage()));
}
} else {
data.setTop50CommandsListHtml(Html.ERROR_TABLE.parse());
}
}
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);
@ -248,24 +285,6 @@ public class Analysis {
data.setGm1Perc((gmOne * 1.0 / gmTotal));
data.setGm2Perc((gmTwo * 1.0 / gmTotal));
data.setGm3Perc((gmThree * 1.0 / gmTotal));
if (rawServerData.keySet().size() > 0) {
ServerData sData = null;
for (long sDataKey : rawServerData.keySet()) {
sData = rawServerData.get(sDataKey);
break;
}
if (sData != null) {
data.setTop50CommandsListHtml(AnalysisUtils.createTableOutOfHashMap(sData.getCommandUsage()));
}
} else {
data.setTop50CommandsListHtml(Html.ERROR_TABLE.parse());
}
data.setRefreshDate(new Date().getTime());
analysisCache.cache(data);
plugin.log(Phrase.ANALYSIS_COMPLETE + "");
this.cancel();
}
private void createPlayerActivityGraphs(AnalysisData data) {
@ -282,6 +301,18 @@ public class Analysis {
}).runTaskAsynchronously(plugin);
}
private List<UUID> fetchPlayersInDB(OfflinePlayer[] offlinePlayers) {
final List<UUID> uuids = new ArrayList<>();
log(Phrase.ANALYSIS_FETCH_PLAYERS + "");
for (OfflinePlayer p : offlinePlayers) {
UUID uuid = p.getUniqueId();
if (plugin.getDB().wasSeenBefore(uuid)) {
uuids.add(uuid);
}
}
return uuids;
}
private void log(String msg) {
if (Settings.ANALYSIS_LOG_TO_CONSOLE.isTrue()) {
plugin.log(msg);

View File

@ -67,7 +67,7 @@ public class AnalysisUtils {
replaceMap.put("%bed%", FormatUtils.formatLocation(data.getBedLocation()));
replaceMap.put("%geoloc%", data.getDemData().getGeoLocation());
replaceMap.put("%active%", AnalysisUtils.isActive(data.getLastPlayed(), data.getPlayTime(), data.getLoginTimes())
? "| Player is Active" : "| Player is inactive");
? Html.ACTIVE.parse() : Html.INACTIVE.parse());
int age = data.getDemData().getAge();
replaceMap.put("%age%", (age != -1) ? "" + age : Phrase.DEM_UNKNOWN + "");
replaceMap.put("%gender%", "" + data.getDemData().getGender().name().toLowerCase());
@ -87,7 +87,6 @@ public class AnalysisUtils {
} catch (NoSuchFieldError e) {
gmThree = 0;
}
Plan plugin = getPlugin(Plan.class);
long total = gmZero + gmOne + gmTwo + gmThree;
replaceMap.put("%gm0%", FormatUtils.formatTimeAmount("" + gmZero));
replaceMap.put("%gm1%", FormatUtils.formatTimeAmount("" + gmOne));
@ -100,9 +99,10 @@ public class AnalysisUtils {
replaceMap.put("%registered%", FormatUtils.formatTimeStamp("" + data.getRegistered()));
replaceMap.put("%timeskicked%", "" + data.getTimesKicked());
replaceMap.put("%playtime%", FormatUtils.formatTimeAmount("" + data.getPlayTime()));
replaceMap.put("%banned%", data.isBanned() ? "Banned" : "Not Banned");
replaceMap.put("%op%", data.isOp() ? ", Operator (Op)" : "");
replaceMap.put("%isonline%", (data.isOnline()) ? "| Online" : "| Offline");
replaceMap.put("%banned%", data.isBanned() ? Html.BANNED.parse() : "");
replaceMap.put("%op%", data.isOp() ? Html.OPERATOR.parse() : "");
replaceMap.put("%isonline%", (data.isOnline()) ? Html.ONLINE.parse() : Html.OFFLINE.parse());
Plan plugin = getPlugin(Plan.class);
replaceMap.put("%version%", plugin.getDescription().getVersion());
PlanLiteHook hook = plugin.getPlanLiteHook();
if (hook != null) {
@ -235,7 +235,7 @@ public class AnalysisUtils {
List<String[]> sorted = MapComparator.sortByValueLong(map);
String html = "<p>";
if (sorted.isEmpty()) {
html = "Error Creating List</p>";
html = Html.ERROR_LIST.parse();
return html;
}
Collections.reverse(sorted);

View File

@ -2,16 +2,17 @@ Settings:
Data:
GatherLocations: true
Analysis:
LogProgressOnConsole: true
LogProgressOnConsole: false
MinutesPlayedUntilConsidiredActive: 10
Cache:
AnalysisCache:
RefreshAnalysisCacheOnEnable: true
RefreshEveryXMinutes: -1
InspectCache:
ClearFromInspectCacheAfterXMinutes: 5
DataCache:
SaveEveryXMinutes: 5
SaveServerDataEveryXMinutes: 5
SaveEveryXMinutes: 2
SaveServerDataEveryXMinutes: 1
ClearCacheEveryXSaves: 5
WebServer:
Enabled: true