mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2025-01-21 23:51:29 +01:00
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:
parent
8c4d3e0f4d
commit
f9df236c59
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
|
@ -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>";
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user