Added Player Activity Graphs , updated htmls with padding

- Added Player Activity graph
- Top 50 Commands now looks proper

Fixed bugs:
- Activity now determined properly (two weeks seconds multiplied by
1000)

Known Bugs:
- GMTimes on analysis page still shows 0 but graph works
- Page has to be refreshed multiple times to view (Faulty response)
- (Player activity graph data might not be properly saved)

Not implemented:
- PlanLite features
This commit is contained in:
Rsl1122 2017-01-13 18:01:22 +02:00
parent 8c4d3e0f4d
commit f9df236c59
7 changed files with 180 additions and 52 deletions

View File

@ -12,7 +12,9 @@ public class AnalysisData {
private long totalPlayTime;
private double averageAge;
private String gmTimesChartImgHtml;
private String playersChartImgHtml;
private String playersChartImgHtmlMonth;
private String playersChartImgHtmlWeek;
private String playersChartImgHtmlDay;
private String activityChartImgHtml;
private String top50CommandsListHtml;
@ -35,6 +37,30 @@ public class AnalysisData {
// Getters and setters v---------------------------------v
public String getPlayersChartImgHtmlMonth() {
return playersChartImgHtmlMonth;
}
public void setPlayersChartImgHtmlMonth(String playersChartImgHtmlMonth) {
this.playersChartImgHtmlMonth = playersChartImgHtmlMonth;
}
public String getPlayersChartImgHtmlWeek() {
return playersChartImgHtmlWeek;
}
public void setPlayersChartImgHtmlWeek(String playersChartImgHtmlWeek) {
this.playersChartImgHtmlWeek = playersChartImgHtmlWeek;
}
public String getPlayersChartImgHtmlDay() {
return playersChartImgHtmlDay;
}
public void setPlayersChartImgHtmlDay(String playersChartImgHtmlDay) {
this.playersChartImgHtmlDay = playersChartImgHtmlDay;
}
public String getTop50CommandsListHtml() {
return top50CommandsListHtml;
}
@ -141,9 +167,6 @@ public class AnalysisData {
return gmTimesChartImgHtml;
}
public String getPlayersChartImgHtml() {
return playersChartImgHtml;
}
public String getActivityChartImgHtml() {
return activityChartImgHtml;
@ -173,9 +196,6 @@ public class AnalysisData {
this.gmTimesChartImgHtml = gmTimesChartImgHtml;
}
public void setPlayersChartImgHtml(String playersChartImgHtml) {
this.playersChartImgHtml = playersChartImgHtml;
}
public void setActivityChartImgHtml(String activityChartImgHtml) {
this.activityChartImgHtml = activityChartImgHtml;

View File

@ -34,6 +34,7 @@ public class DataCacheHandler {
private final NewPlayerCreator newPlayerCreator;
private int timesSaved;
private int maxPlayers;
/**
* Class Constructor.
@ -59,6 +60,7 @@ public class DataCacheHandler {
newPlayerCreator = new NewPlayerCreator(plugin, this);
timesSaved = 0;
maxPlayers = plugin.getServer().getMaxPlayers();
int minutes = plugin.getConfig().getInt("Settings.Cache.DataCache.SaveEveryXMinutes");
if (minutes <= 0) {
@ -337,4 +339,8 @@ public class DataCacheHandler {
saveCachedData(uuid);
}
}
public int getMaxPlayers() {
return maxPlayers;
}
}

View File

@ -0,0 +1,84 @@
package main.java.com.djrapitops.plan.ui.graphs;
import com.djrapitops.plan.Plan;
import com.djrapitops.plan.data.ServerData;
import com.djrapitops.plan.utilities.FormatUtils;
import com.googlecode.charts4j.AxisLabels;
import com.googlecode.charts4j.AxisLabelsFactory;
import com.googlecode.charts4j.Color;
import com.googlecode.charts4j.Data;
import com.googlecode.charts4j.GCharts;
import com.googlecode.charts4j.LineChart;
import com.googlecode.charts4j.Plots;
import com.googlecode.charts4j.XYLine;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import static org.bukkit.plugin.java.JavaPlugin.getPlugin;
/**
*
* @author Rsl1122
*/
public class PlayerActivityGraphCreator {
public static String createChart(HashMap<Long, ServerData> rawServerData, long scale) {
List<Double> xListDate = new ArrayList<>();
List<Double> pYList = new ArrayList<>();
List<Double> nYList = new ArrayList<>();
List<String> xDateAxisLabels = new ArrayList<>();
List<Double> xDateAxisLabelsLocations = new ArrayList<>();
Plan plugin = getPlugin(Plan.class);
int maxPlayers = plugin.getHandler().getMaxPlayers();
long now = new Date().getTime();
long nowMinusScale = now - scale;
int i = 0;
for (long keyDate : rawServerData.keySet()) {
if (keyDate < nowMinusScale) {
continue;
}
Double scaledDateValue = ((keyDate - nowMinusScale) * 1.0 / scale) * 100;
ServerData serverData = rawServerData.get(keyDate);
Double scaledPlayerValue = (serverData.getPlayersOnline() * 1.0 / maxPlayers) * 100;
Double scaledNewPValue = (serverData.getNewPlayers() * 1.0 / maxPlayers) * 100;
xListDate.add(scaledDateValue);
pYList.add(scaledPlayerValue);
nYList.add(scaledNewPValue);
}
// Date labels
for (long j = 0; j <= 8; j++) {
long scaleAddition = j * (scale / 8);
xDateAxisLabels.add(FormatUtils.formatTimeStamp("" + (nowMinusScale + scaleAddition)));
xDateAxisLabelsLocations.add((scaleAddition * 1.0 / scale) * 100);
}
// Player labels
List<String> yAxisLabels = new ArrayList<>();
for (int k = 0; k <= maxPlayers; k++) {
if (k % 5 == 0) {
yAxisLabels.add("" + k);
}
}
AxisLabels xAxisLabels = AxisLabelsFactory.newAxisLabels(xDateAxisLabels, xDateAxisLabelsLocations);
Data xData = Data.newData(xListDate);
Data pYData = Data.newData(pYList);
Data nYData = Data.newData(nYList);
XYLine playerLine = Plots.newXYLine(xData, pYData, Color.BLUE, "Online Players");
XYLine newPlayerLine = Plots.newXYLine(xData, nYData, Color.GREEN, "New Players");
LineChart chart = GCharts.newLineChart(playerLine, newPlayerLine);
chart.addXAxisLabels(xAxisLabels);
chart.addTopAxisLabels(AxisLabelsFactory.newAxisLabels("Players", 1));
chart.addYAxisLabels(AxisLabelsFactory.newAxisLabels(yAxisLabels));
chart.addRightAxisLabels(AxisLabelsFactory.newAxisLabels("Date", 4));
chart.setSize(1000, 250);
return chart.toURLString();
}
}

View File

@ -74,8 +74,15 @@ public class Analysis {
rawServerData = plugin.getDB().getServerDataHashMap();
plugin.log("Analysis | Data Fetched, beginning Analysis of data..");
AnalysisData data = new AnalysisData();
String playerActivityHtml = AnalysisUtils.createPlayerActivityGraph(rawServerData, new Date().getTime());
data.setPlayersChartImgHtml(playerActivityHtml);
long scale = 2592000 * Long.valueOf("1000");
String playerActivityHtmlMonth = AnalysisUtils.createPlayerActivityGraph(rawServerData, scale);
data.setPlayersChartImgHtmlMonth(playerActivityHtmlMonth);
scale = 604800 * 1000;
String playerActivityHtmlWeek = AnalysisUtils.createPlayerActivityGraph(rawServerData, scale);
data.setPlayersChartImgHtmlWeek(playerActivityHtmlWeek);
scale = 86400 * 1000;
String playerActivityHtmlDay = AnalysisUtils.createPlayerActivityGraph(rawServerData, scale);
data.setPlayersChartImgHtmlDay(playerActivityHtmlDay);
long gmZero = 0;
long gmOne = 0;
long gmTwo = 0;

View File

@ -9,6 +9,7 @@ import java.util.Date;
import java.util.HashMap;
import java.util.List;
import main.java.com.djrapitops.plan.ui.graphs.ActivityPieChartCreator;
import main.java.com.djrapitops.plan.ui.graphs.PlayerActivityGraphCreator;
import main.java.com.djrapitops.plan.utilities.comparators.MapComparator;
import org.bukkit.GameMode;
import static org.bukkit.plugin.java.JavaPlugin.getPlugin;
@ -23,6 +24,7 @@ public class AnalysisUtils {
String url = GMTimesPieChartCreator.createChart(gmTimes);
return "<img src=\"" + url + "\">";
}
public static String createGMPieChart(HashMap<GameMode, Long> gmTimes, long total) {
String url = GMTimesPieChartCreator.createChart(gmTimes, total);
return "<img src=\"" + url + "\">";
@ -31,9 +33,12 @@ public class AnalysisUtils {
public static HashMap<String, String> getInspectReplaceRules(UserData data) {
HashMap<String, String> replaceMap = new HashMap<>();
replaceMap.put("%uuid%", "" + data.getUuid());
replaceMap.put("%lastseen%", FormatUtils.formatTimeStamp("" + data.getLastPlayed()));
replaceMap.put("%logintimes%", "" + data.getLoginTimes());
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");
int age = data.getDemData().getAge();
replaceMap.put("%age%", (age != -1) ? "" + age : "Not known");
replaceMap.put("%gender%", "" + data.getDemData().getGender().name().toLowerCase());
@ -60,37 +65,40 @@ public class AnalysisUtils {
return replaceMap;
}
static String createPlayerActivityGraph(HashMap<Long, ServerData> rawServerData, long time) {
return "<img src=\"" + "\">";
static String createPlayerActivityGraph(HashMap<Long, ServerData> rawServerData, long scale) {
String url = PlayerActivityGraphCreator.createChart(rawServerData, scale);
return "<img src=\"" + url + "\">";
}
public static HashMap<String, String> getAnalysisReplaceRules(AnalysisData data) {
HashMap<String, String> replaceMap = new HashMap<>();
replaceMap.put("%activitypiechart%", data.getActivityChartImgHtml());
replaceMap.put("%gmpiechart%", data.getGmTimesChartImgHtml());
replaceMap.put("%gm0%", (int) data.getGm0Perc()*100+"%");
replaceMap.put("%gm1%", (int) data.getGm1Perc()*100+"%");
replaceMap.put("%gm2%", (int) data.getGm2Perc()*100+"%");
replaceMap.put("%gm3%", (int) data.getGm3Perc()*100+"%");
replaceMap.put("%gm0%", (int) data.getGm0Perc() * 100 + "%");
replaceMap.put("%gm1%", (int) data.getGm1Perc() * 100 + "%");
replaceMap.put("%gm2%", (int) data.getGm2Perc() * 100 + "%");
replaceMap.put("%gm3%", (int) data.getGm3Perc() * 100 + "%");
replaceMap.put("%active%", "" + data.getActive());
replaceMap.put("%banned%", "" + data.getBanned());
replaceMap.put("%inactive%", "" + data.getInactive());
replaceMap.put("%activitytotal%", "" + data.getTotal());
replaceMap.put("%playerchart%", data.getPlayersChartImgHtml());
replaceMap.put("%playerchartmonth%", data.getPlayersChartImgHtmlMonth());
replaceMap.put("%playerchartweek%", data.getPlayersChartImgHtmlWeek());
replaceMap.put("%playerchartday%", data.getPlayersChartImgHtmlDay());
replaceMap.put("%top50commands%", data.getTop50CommandsListHtml());
replaceMap.put("%avgage%", ""+data.getAverageAge());
replaceMap.put("%avgplaytime%", FormatUtils.formatTimeAmount(""+data.getAveragePlayTime()));
replaceMap.put("%totalplaytime%", FormatUtils.formatTimeAmount(""+data.getTotalPlayTime()));
replaceMap.put("%ops%", ""+data.getOps());
replaceMap.put("%refresh%", FormatUtils.formatTimeAmountSinceString(""+data.getRefreshDate(), new Date()));
replaceMap.put("%totallogins%", ""+data.getTotalLoginTimes());
replaceMap.put("%avgage%", "" + data.getAverageAge());
replaceMap.put("%avgplaytime%", FormatUtils.formatTimeAmount("" + data.getAveragePlayTime()));
replaceMap.put("%totalplaytime%", FormatUtils.formatTimeAmount("" + data.getTotalPlayTime()));
replaceMap.put("%ops%", "" + data.getOps());
replaceMap.put("%refresh%", FormatUtils.formatTimeAmountSinceString("" + data.getRefreshDate(), new Date()));
replaceMap.put("%totallogins%", "" + data.getTotalLoginTimes());
return replaceMap;
}
static boolean isActive(long lastPlayed, long playTime, int loginTimes) {
Plan plugin = getPlugin(Plan.class);
int timeToActive = plugin.getConfig().getInt("Settings.Analysis.MinutesPlayedUntilConsidiredActive");
long twoWeeks = 1209600;
long twoWeeks = 1209600000;
if (new Date().getTime() - lastPlayed < twoWeeks) {
if (loginTimes > 3) {
if (playTime > 60 * timeToActive) {
@ -105,10 +113,10 @@ public class AnalysisUtils {
String url = ActivityPieChartCreator.createChart(totalBanned, active, inactive);
return "<img src=\"" + url + "\">";
}
static String createCommandUseListHtml(HashMap<String, Integer> commandUse) {
List<String[]> sorted = MapComparator.sortByValue(commandUse);
String html ="<table>";
String html = "<table style=\"border-collapse: collapse;table-layout: fixed; border-style: solid; border-width: 1px; width: 100%;\">";
if (sorted.isEmpty()) {
html = "<p>Error Calcuclating Command usages</p>";
return html;
@ -118,7 +126,7 @@ public class AnalysisUtils {
if (i >= 50) {
break;
}
html += "<tr style=\"text-align: center;\"><td><b>"+values[1]+"</b></td>\r\n<td>"+values[0]+"</td></tr>";
html += "<tr style=\"text-align: center;border-style: solid; border-width: 1px;height: 28px;\"><td><b>" + values[1] + "</b></td>\r\n<td>" + values[0] + "</td></tr>";
i++;
}
html += "</table>";

View File

@ -14,49 +14,49 @@
</head>
<body>
<div style="line-height: 55%; font-family: Verdana, Geneva, sans-serif;">
<div style="line-height: 55%; font-family: Verdana, Geneva, sans-serif;padding: 2px 4px 2px 3px;">
<h1 style="text-decoration: underline;">Plan | Server Analysis</h1>
<h4>Analysis refreshed %refresh% ago</h4>
<table>
<tr>
<td style="margin-left: 3px; margin-right: auto;
border-style: groove; border-width: 3px; border-radius: 12px;
border-style: groove; border-width: 3px; border-radius: 12px; padding: 2px 4px 2px 3px;
box-shadow: 5px 5px 4px 0px #888888;">
%playerchart%
<h4>Player Activity - Last 24h</h4>
%playerchartday%
<h4>Player Activity - Last 7 days</h4>
%playerchartweek%
<h4>Player Activity - Last 30 days</h4>
%playerchartmonth%
</td>
<td style="margin-left: 3px; margin-right: auto;
border-style: groove; border-width: 3px; border-radius: 12px;
box-shadow: 5px 5px 4px 0px #888888;text-align: center;">
%activitypiechart%
<p>Active %active% | Inactive %inactive% | Banned %banned% | Total Players: %activitytotal%</p>
</td>
</tr>
<tr>
<td style="margin-left: 3px; margin-right: auto;
border-style: groove; border-width: 3px; border-radius: 12px;
box-shadow: 5px 5px 4px 0px #888888;">
border-style: groove; border-width: 3px; border-radius: 12px; padding: 2px 4px 2px 3px;
box-shadow: 5px 5px 4px 0px #888888;text-align: left;vertical-align: top;">
<h4>Information</h4>
<p>%activitytotal% players have played on this server.</p>
<p>A Total of %totalplaytime% has been played with the average of %avgplaytime%</p>
<p>Players have joined %totallogins% times.</p>
<p>The average age of known players is %avgage%.</p>
</td>
<td style="margin-left: 3px; margin-right: auto;
border-style: groove; border-width: 3px; border-radius: 12px;
box-shadow: 5px 5px 4px 0px #888888;text-align: center;">
<br/><h4>Playerbase composition</h4>
%activitypiechart%
<p>Active %active% | Inactive %inactive% | Banned %banned% | Total Players: %activitytotal%</p>
<br/><h4>Gamemode Usage</h4>
%gmpiechart%
<p>Survival: %gm0% | Creative: %gm1% | Adventure: %gm2% | Spectator: %gm3%</p>
<br/><h4>Top 50 Most used commands</h4>
%top50commands%
</td>
</tr>
<tr>
<td style="margin-left: 3px; margin-right: auto;
border-style: groove; border-width: 3px; border-radius: 12px;
box-shadow: 5px 5px 4px 0px #888888;text-align: center;">
%top50commands%
border-style: groove; border-width: 3px; border-radius: 12px; padding: 2px 4px 2px 3px;
box-shadow: 5px 5px 4px 0px #888888;text-align: center;">
<p>Empty wrapper</p>
</td>
<td style="margin-left: 3px; margin-right: auto;
border-style: groove; border-width: 3px; border-radius: 12px;
border-style: groove; border-width: 3px; border-radius: 12px; padding: 2px 4px 2px 3px;
box-shadow: 5px 5px 4px 0px #888888;text-align: center;">
%top50commands%
<p>Empty wrapper</p>
</td>
</tr>
</table>

View File

@ -14,15 +14,17 @@
</head>
<body>
<div style="line-height: 55%; font-family: Verdana, Geneva, sans-serif;">
<div style="line-height: 55%; font-family: Verdana, Geneva, sans-serif;padding: 2px 4px 2px 3px;">
<h1 style="text-decoration: underline;">Plan | Inspect Player %name%</h1>
<h4>UUID: %uuid%</h4>
<h4>Registered: %registered% - %banned%%op%</h4>
<h4>Registered: %registered% %banned%%op%</h4>
<table>
<tr>
<td style="margin-left: 3px; margin-right: auto;
border-style: groove; border-width: 3px; border-radius: 12px;
border-style: groove; border-width: 3px; border-radius: 12px; padding: 2px 4px 2px 3px;
box-shadow: 5px 5px 4px 0px #888888;">
<h4>Information</h4>
<p>Last seen: %lastseen% - %active%</p>
<p>Nicknames: %nicknames% | Has connected from ips: %ips%</p>
<p>Geolocation: %geoloc%</p>
<p>Playtime: %playtime%</p>
@ -30,8 +32,9 @@
<p>Age: %age% | Gender: %gender%</p>
</td>
<td style="margin-left: 3px; margin-right: auto;
border-style: groove; border-width: 3px; border-radius: 12px;
border-style: groove; border-width: 3px; border-radius: 12px; padding: 2px 4px 2px 3px;
box-shadow: 5px 5px 4px 0px #888888;">
<h4>Gamemode Usage</h4>
%gmpiechart%
<p>Survival: %gm0% | Creative: %gm1% | Adventure: %gm2% | Spectator: %gm3% | Total: %gmtotal%</p>
</td>