Removed Charts4j, added Chart.js

Removed Charts4j from the plugin, and moved to Chart.js javascript graph
rendering library - this almost halved the jar size, and analysis might
have gotten a tiny performance boost (Graph rendering delegated to
browsers).
- The new graphs are more accurate, and you can hover over the graphs to
view more in-depth detail about the data.
- This update allows possible multiple lines in one graph in future
updates.
Updated Phrase & Html to include every message that was not yet
available. Updated locale files will be uploaded to github As soon as
possible.
Before they are uploaded using the config locale setting will
malfunction.
This commit is contained in:
Rsl1122 2017-02-24 21:23:39 +02:00
parent de1a4570b1
commit dc05286f19
14 changed files with 329 additions and 404 deletions

View File

@ -56,12 +56,6 @@
<scope>provided</scope>
</dependency>
<!-- -->
<dependency>
<groupId>com.googlecode.charts4j</groupId>
<artifactId>charts4j</artifactId>
<version>1.3</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<defaultGoal>clean package install</defaultGoal>

View File

@ -44,16 +44,6 @@ public enum Phrase {
COLOR_MAIN(ChatColor.getByChar(getPlugin(Plan.class).getConfig().getString("Customization.Colors.Commands.Main").charAt(1))),
COLOR_SEC(ChatColor.getByChar(getPlugin(Plan.class).getConfig().getString("Customization.Colors.Commands.Secondary").charAt(1))),
COLOR_TER(ChatColor.getByChar(getPlugin(Plan.class).getConfig().getString("Customization.Colors.Commands.Highlight").charAt(1))),
HCOLOR_ACT_ONL(getPlugin(Plan.class).getConfig().getString("Customization.Colors.HTML.ActivityGraph.OnlinePlayers")),
HCOLOR_ACT_NEW(getPlugin(Plan.class).getConfig().getString("Customization.Colors.HTML.ActivityGraph.NewPlayers")),
HCOLOR_GMP_0(getPlugin(Plan.class).getConfig().getString("Customization.Colors.HTML.GamemodePie.Survival")),
HCOLOR_GMP_1(getPlugin(Plan.class).getConfig().getString("Customization.Colors.HTML.GamemodePie.Creative")),
HCOLOR_GMP_2(getPlugin(Plan.class).getConfig().getString("Customization.Colors.HTML.GamemodePie.Adventure")),
HCOLOR_GMP_3(getPlugin(Plan.class).getConfig().getString("Customization.Colors.HTML.GamemodePie.Spectator")),
HCOLOR_ACTP_ACT(getPlugin(Plan.class).getConfig().getString("Customization.Colors.HTML.ActivityPie.Active")),
HCOLOR_ACTP_BAN(getPlugin(Plan.class).getConfig().getString("Customization.Colors.HTML.ActivityPie.Banned")),
HCOLOR_ACTP_INA(getPlugin(Plan.class).getConfig().getString("Customization.Colors.HTML.ActivityPie.Inactive")),
HCOLOR_ACTP_JON(getPlugin(Plan.class).getConfig().getString("Customization.Colors.HTML.ActivityPie.JoinedOnce")),
//
ARROWS_RIGHT("»"),
BALL(""),

View File

@ -30,7 +30,18 @@ public enum Settings {
DEM_MALE("Customization.DemographicsTriggers.Male"),
DEM_IGNORE("Customization.DemographicsTriggers.IgnoreWhen"),
LOCALE("Settings.Locale"),
SECURITY_CODE("Settings.WebServer.Security.AddressSecurityCode");
SECURITY_CODE("Settings.WebServer.Security.AddressSecurityCode"),
//
HCOLOR_ACT_ONL("Customization.Colors.HTML.ActivityGraph.OnlinePlayers"),
HCOLOR_ACT_ONL_FILL("Customization.Colors.HTML.ActivityGraph.OnlinePlayersFill"),
HCOLOR_ACTP_ACT("Customization.Colors.HTML.ActivityPie.Active"),
HCOLOR_ACTP_BAN("Customization.Colors.HTML.ActivityPie.Banned"),
HCOLOR_ACTP_INA("Customization.Colors.HTML.ActivityPie.Inactive"),
HCOLOR_ACTP_JON("Customization.Colors.HTML.ActivityPie.JoinedOnce"),
HCOLOR_GMP_0("Customization.Colors.HTML.GamemodePie.Survival"),
HCOLOR_GMP_1("Customization.Colors.HTML.GamemodePie.Creative"),
HCOLOR_GMP_2("Customization.Colors.HTML.GamemodePie.Adventure"),
HCOLOR_GMP_3("Customization.Colors.HTML.GamemodePie.Spectator");
private final String configPath;

View File

@ -13,15 +13,11 @@ public class AnalysisData {
private long averagePlayTime;
private long totalPlayTime;
private double averageAge;
private String gmTimesChartImgHtml;
private String playersChartImgHtmlMonth;
private String playersChartImgHtmlWeek;
private String playersChartImgHtmlDay;
private String activityChartImgHtml;
private String top50CommandsListHtml;
private String top20ActivePlayers;
private String recentPlayers;
private String sortablePlayersTable;
private String[] playersDataArray;
private int newPlayersMonth;
private int newPlayersWeek;
@ -53,14 +49,10 @@ public class AnalysisData {
*/
public AnalysisData() {
sortablePlayersTable = Html.ERROR_NOT_SET+"";
gmTimesChartImgHtml = Html.ERROR_NOT_SET+"";
playersChartImgHtmlMonth = Html.ERROR_NOT_SET+"";
playersChartImgHtmlWeek = Html.ERROR_NOT_SET+"";
playersChartImgHtmlDay = Html.ERROR_NOT_SET+"";
activityChartImgHtml = Html.ERROR_NOT_SET+"";
top50CommandsListHtml = Html.ERROR_NOT_SET+"";
top20ActivePlayers = Html.ERROR_NOT_SET+"";
recentPlayers = Html.ERROR_NOT_SET+"";
playersDataArray = new String[]{"[0]","[\"No data\"]","[0]","[\"No data\"]","[0]","[\"No data\"]"};
}
// Getters and setters v---------------------------------v
@ -85,49 +77,7 @@ public class AnalysisData {
public void setJoinleaver(int joinleaver) {
this.joinleaver = joinleaver;
}
/**
* @return HTML String of the Month Activity graph
*/
public String getPlayersChartImgHtmlMonth() {
return playersChartImgHtmlMonth;
}
/**
* @param playersChartImgHtmlMonth HTML String of the Month Activity graph
*/
public void setPlayersChartImgHtmlMonth(String playersChartImgHtmlMonth) {
this.playersChartImgHtmlMonth = playersChartImgHtmlMonth;
}
/**
* @return HTML String of the Week Activity graph
*/
public String getPlayersChartImgHtmlWeek() {
return playersChartImgHtmlWeek;
}
/**
* @param playersChartImgHtmlWeek HTML String of the Week Activity graph
*/
public void setPlayersChartImgHtmlWeek(String playersChartImgHtmlWeek) {
this.playersChartImgHtmlWeek = playersChartImgHtmlWeek;
}
/**
* @return HTML String of the Day Activity graph
*/
public String getPlayersChartImgHtmlDay() {
return playersChartImgHtmlDay;
}
/**
* @param playersChartImgHtmlDay HTML String of the Day Activity graph
*/
public void setPlayersChartImgHtmlDay(String playersChartImgHtmlDay) {
this.playersChartImgHtmlDay = playersChartImgHtmlDay;
}
/**
* @return HTML String of the Top50CommandsList
*/
@ -311,20 +261,6 @@ public class AnalysisData {
return averageAge;
}
/**
* @return HTML String of the GMTimes Piechart
*/
public String getGmTimesChartImgHtml() {
return gmTimesChartImgHtml;
}
/**
* @return HTML String of the Activity Piechart
*/
public String getActivityChartImgHtml() {
return activityChartImgHtml;
}
/**
* @return How many times players have joined.
*/
@ -360,20 +296,6 @@ public class AnalysisData {
this.averageAge = averageAge;
}
/**
* @param gmTimesChartImgHtml HTML String of the GMTimes Piechart
*/
public void setGmTimesChartImgHtml(String gmTimesChartImgHtml) {
this.gmTimesChartImgHtml = gmTimesChartImgHtml;
}
/**
* @param activityChartImgHtml HTML String of the Activity Piechart
*/
public void setActivityChartImgHtml(String activityChartImgHtml) {
this.activityChartImgHtml = activityChartImgHtml;
}
/**
* @param totalLoginTimes How many times playes have logged in
*/
@ -451,4 +373,12 @@ public class AnalysisData {
public void setTotaldeaths(long totaldeaths) {
this.totaldeaths = totaldeaths;
}
public String[] getPlayersDataArray() {
return playersDataArray;
}
public void setPlayersDataArray(String[] playersDataArray) {
this.playersDataArray = playersDataArray;
}
}

View File

@ -1,55 +0,0 @@
package main.java.com.djrapitops.plan.ui.graphs;
import com.googlecode.charts4j.Color;
import com.googlecode.charts4j.GCharts;
import com.googlecode.charts4j.PieChart;
import com.googlecode.charts4j.Slice;
import main.java.com.djrapitops.plan.Phrase;
import main.java.com.djrapitops.plan.ui.Html;
/**
*
* @author Rsl1122
*/
public class ActivityPieChartCreator {
/**
* Creates a image link to Activity Chart.
*
* @param totalBanned Number of Banned Players
* @param active Number of Active Players
* @param inactive Number of Inactive Players
* @param joinleaver Number of players who have joined only once
* @return Url to Image link.
*/
public static String createChart(int totalBanned, int active, int inactive, int joinleaver) {
int total = totalBanned + active + inactive + joinleaver;
int banPerc = (int) ((totalBanned * 1.0 / total) * 100);
int inacPerc = (int) ((inactive * 1.0 / total) * 100);
int actPerc = (int) ((active * 1.0 / total) * 100);
int joinlPerc = (int) ((joinleaver * 1.0 / total) * 100);
while (banPerc + inacPerc + actPerc + joinlPerc < 100) {
actPerc++;
}
while (banPerc + inacPerc + actPerc + joinlPerc > 100) {
actPerc--;
}
String labelBanned = Html.GRAPH_BANNED.parse();
String labelUnknown = Html.GRAPH_UNKNOWN.parse();
String labelInactive = Html.GRAPH_INACTIVE.parse();
String labelActive = Html.GRAPH_ACTIVE.parse();
Slice bannedSlice = Slice.newSlice((int) (banPerc), Color.newColor(Phrase.HCOLOR_ACTP_BAN + ""), labelBanned, labelBanned);
Slice joinLeaverSlice = Slice.newSlice((int) (joinlPerc), Color.newColor(Phrase.HCOLOR_ACTP_JON + ""), labelUnknown, labelUnknown);
Slice inactiveSlice = Slice.newSlice((int) (inacPerc), Color.newColor(Phrase.HCOLOR_ACTP_INA + ""), labelInactive, labelInactive);
Slice activeSlice = Slice.newSlice((int) (actPerc), Color.newColor(Phrase.HCOLOR_ACTP_ACT + ""), labelActive, labelActive);
PieChart refChart = GCharts.newPieChart(activeSlice, bannedSlice, inactiveSlice, joinLeaverSlice);
refChart.setSize(400, 150);
refChart.setThreeD(true);
String refURL = refChart.toURLString();
return refURL;
}
}

View File

@ -1,86 +0,0 @@
package main.java.com.djrapitops.plan.ui.graphs;
import com.googlecode.charts4j.Color;
import com.googlecode.charts4j.GCharts;
import com.googlecode.charts4j.PieChart;
import com.googlecode.charts4j.Slice;
import java.util.HashMap;
import main.java.com.djrapitops.plan.Phrase;
import org.bukkit.GameMode;
/**
*
* @author Rsl1122
*/
public class GMTimesPieChartCreator {
/**
* Creates a link to New image of the Gamemode usage chart without total.
*
* Calculated total is not required.
*
* @param gmTimes Map with all 4 Gamemodes and responding times spent in
* them
* @return Url of charts4j image link.
*/
public static String createChart(HashMap<GameMode, Long> gmTimes) {
Long gm3;
try {
gm3 = gmTimes.get(GameMode.SPECTATOR);
if (gm3 == null) {
gm3 = (long) 0;
}
} catch (NoSuchFieldError e) {
gm3 = (long) 0;
}
long total = gmTimes.get(GameMode.SURVIVAL) + gmTimes.get(GameMode.CREATIVE)
+ gmTimes.get(GameMode.ADVENTURE) + gm3;
return createChart(gmTimes, total);
}
/**
* Creates a link to New image of the Gamemode usage chart.
*
* @param gmTimes Map with all 4 Gamemodes and responding times spent in
* them
* @param total Time spent in all 4 gamemodes.
* @return Url of charts4j image link.
*/
public static String createChart(HashMap<GameMode, Long> gmTimes, long total) {
long gmZero = gmTimes.get(GameMode.SURVIVAL);
long gmOne = gmTimes.get(GameMode.CREATIVE);
long gmTwo = gmTimes.get(GameMode.ADVENTURE);
Long gmThree;
try {
gmThree = gmTimes.get(GameMode.SPECTATOR);
if (gmThree == null) {
gmThree = (long) 0;
}
} catch (NoSuchFieldError e) {
gmThree = (long) 0;
}
int zero = (int) ((gmZero * 1.0 / total) * 100);
int one = (int) ((gmOne * 1.0 / total) * 100);
int two = (int) ((gmTwo * 1.0 / total) * 100);
int three = (int) ((gmThree * 1.0 / total) * 100);
while (zero + one + two + three < 100) {
one++;
}
while (zero + one + two + three > 100) {
one--;
}
Slice s1 = Slice.newSlice(zero, Color.newColor(Phrase.HCOLOR_GMP_0 + ""), "Survival", "Survival");
Slice s2 = Slice.newSlice(one, Color.newColor(Phrase.HCOLOR_GMP_1 + ""), "Creative", "Creative");
Slice s3 = Slice.newSlice(two, Color.newColor(Phrase.HCOLOR_GMP_2 + ""), "Adventure", "Adventure");
Slice s4 = Slice.newSlice(three, Color.newColor(Phrase.HCOLOR_GMP_3 + ""), "Spectator", "Spectator");
PieChart refChart = GCharts.newPieChart(s1, s2, s3, s4);
refChart.setSize(400, 150);
refChart.setThreeD(true);
String refURL = refChart.toURLString();
return refURL;
}
}

View File

@ -1,21 +1,11 @@
package main.java.com.djrapitops.plan.ui.graphs;
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.Date;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import main.java.com.djrapitops.plan.Phrase;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.SessionData;
import main.java.com.djrapitops.plan.ui.Html;
import main.java.com.djrapitops.plan.utilities.FormatUtils;
import static org.bukkit.plugin.java.JavaPlugin.getPlugin;
@ -25,15 +15,9 @@ import static org.bukkit.plugin.java.JavaPlugin.getPlugin;
*/
public class PlayerActivityGraphCreator {
/**
* Creates a new url for a PlayerActivity graph.
*
* @param sessionData SessionData of Players in scale.
* @param scale Long in ms, time the graph will be limited to.
* @return Url of charts4j image link.
*/
public static String createChart(List<SessionData> sessionData, long scale) {
public static String[] generateDataArray(List<SessionData> sessionData, long scale) {
Plan plugin = getPlugin(Plan.class);
int maxPlayers = plugin.getHandler().getMaxPlayers();
long now = new Date().toInstant().getEpochSecond() * (long) 1000;
long nowMinusScale = now - scale;
CopyOnWriteArrayList<Long> sessionStarts = new CopyOnWriteArrayList<>();
@ -45,14 +29,8 @@ public class PlayerActivityGraphCreator {
sessionEnds.add(session.getSessionEnd());
sessionStarts.add(session.getSessionStart());
});
List<Double> xListDate = new ArrayList<>();
List<Double> pYList = new ArrayList<>();
List<String> xDateAxisLabels = new ArrayList<>();
List<Double> xDateAxisLabelsLocations = new ArrayList<>();
Plan plugin = getPlugin(Plan.class);
int maxPlayers = plugin.getHandler().getMaxPlayers();
List<Integer> playersOnline = new ArrayList<>();
List<String> labels = new ArrayList<>();
int lastPValue = 0;
int lastSavedPValue = -1;
@ -75,45 +53,17 @@ public class PlayerActivityGraphCreator {
.reduce(amount, Integer::sum);
lastPValue -= amount;
}
Double scaledDateValue = ((i - nowMinusScale) * 1.0 / scale) * 100;
Double scaledPlayerValue = (lastPValue * 1.0 / maxPlayers) * 100;
if (lastSavedPValue != lastPValue || i - lastSaveI > (scale / (long) 100)) {
if (lastSavedPValue != lastPValue || i - lastSaveI > (scale / (long) 75)) {
lastSaveI = i;
xListDate.add(scaledDateValue);
pYList.add((lastSavedPValue * 1.0 / maxPlayers) * 100);
labels.add("\""+FormatUtils.formatTimeStamp(i+"")+"\"");
lastSavedPValue = lastPValue;
xListDate.add(scaledDateValue);
pYList.add(scaledPlayerValue);
playersOnline.add(lastPValue);
}
}
// 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);
XYLine playerLine = Plots.newXYLine(xData, pYData, Color.newColor(Phrase.HCOLOR_ACT_ONL + ""), Html.GRAPH_ONLINE.parse());
LineChart chart = GCharts.newLineChart(playerLine);
chart.addXAxisLabels(xAxisLabels);
chart.addTopAxisLabels(AxisLabelsFactory.newAxisLabels(Html.GRAPH_PLAYERS.parse(), 1));
chart.addYAxisLabels(AxisLabelsFactory.newAxisLabels(yAxisLabels));
chart.addRightAxisLabels(AxisLabelsFactory.newAxisLabels(Html.GRAPH_DATE.parse(), 4));
chart.setSize(1000, 250);
return chart.toURLString();
playersOnline.add(0);
playersOnline.add(maxPlayers);
return new String[]{playersOnline.toString(), labels.toString()};
}
}

View File

@ -16,10 +16,12 @@ 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.ui.Html;
import main.java.com.djrapitops.plan.ui.graphs.PlayerActivityGraphCreator;
import org.bukkit.GameMode;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask;
import static org.bukkit.Bukkit.getOfflinePlayer;
import static org.bukkit.Bukkit.getOfflinePlayer;
/**
*
@ -175,8 +177,6 @@ public class Analysis {
}
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);
@ -208,8 +208,6 @@ public class Analysis {
totalGmTimes.put(GameMode.SPECTATOR, gmThree);
} catch (NoSuchFieldError e) {
}
String serverGMChartHtml = AnalysisUtils.createGMPieChart(totalGmTimes, gmTotal);
data.setGmTimesChartImgHtml(serverGMChartHtml);
data.setGm0Perc((gmZero * 1.0 / gmTotal));
data.setGm1Perc((gmOne * 1.0 / gmTotal));
data.setGm2Perc((gmTwo * 1.0 / gmTotal));
@ -218,18 +216,20 @@ public class Analysis {
private void createPlayerActivityGraphs(AnalysisData data, List<SessionData> sData, List<Long> registered) {
long now = new Date().toInstant().getEpochSecond() * (long) 1000;
long scaleMonth = (long) 2592000 * (long) 1000;
String[] urlAndNumber = AnalysisUtils.analyzeSessionData(sData, registered, scaleMonth, now);
data.setPlayersChartImgHtmlMonth(urlAndNumber[0]);
data.setNewPlayersMonth(Integer.parseInt(urlAndNumber[1]));
long scaleWeek = 604800 * 1000;
urlAndNumber = AnalysisUtils.analyzeSessionData(sData, registered, scaleWeek, now);
data.setPlayersChartImgHtmlWeek(urlAndNumber[0]);
data.setNewPlayersWeek(Integer.parseInt(urlAndNumber[1]));
long scaleDay = 86400 * 1000;
urlAndNumber = AnalysisUtils.analyzeSessionData(sData, registered, scaleDay, now);
data.setPlayersChartImgHtmlDay(urlAndNumber[0]);
data.setNewPlayersDay(Integer.parseInt(urlAndNumber[1]));
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);
}

View File

@ -10,8 +10,6 @@ import main.java.com.djrapitops.plan.Settings;
import main.java.com.djrapitops.plan.data.SessionData;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.ui.Html;
import main.java.com.djrapitops.plan.ui.graphs.ActivityPieChartCreator;
import main.java.com.djrapitops.plan.ui.graphs.GMTimesPieChartCreator;
import main.java.com.djrapitops.plan.ui.graphs.PlayerActivityGraphCreator;
import main.java.com.djrapitops.plan.ui.tables.SortableCommandUseTableCreator;
import main.java.com.djrapitops.plan.ui.tables.SortablePlayersTableCreator;
@ -24,36 +22,6 @@ import org.bukkit.GameMode;
*/
public class AnalysisUtils {
/**
* Creates a GMTimesPieChart image HTML.
*
* @param gmTimes HashMap of gamemodes and time in ms how long has been
* played in them.
* @return Html img tag with url.
*/
public static String createGMPieChart(HashMap<GameMode, Long> gmTimes) {
String url = GMTimesPieChartCreator.createChart(gmTimes);
return Html.IMG.parse(url);
}
/**
* Creates a GMTimesPieChart image HTML.
*
* @param gmTimes HashMap of gamemodes and time in ms how long has been
* played in them.
* @param total Total time played in all gamemodes
* @return Html img tag with url.
*/
public static String createGMPieChart(HashMap<GameMode, Long> gmTimes, long total) {
String url = GMTimesPieChartCreator.createChart(gmTimes, total);
return Html.IMG.parse(url);
}
static String createPlayerActivityGraph(List<SessionData> sessionData, long scale) {
String url = PlayerActivityGraphCreator.createChart(sessionData, scale);
return Html.IMG.parse(url);
}
public static boolean isActive(long lastPlayed, long playTime, int loginTimes) {
int timeToActive = Settings.ANALYSIS_MINUTES_FOR_ACTIVE.getNumber();
if (timeToActive < 0) {
@ -70,11 +38,6 @@ public class AnalysisUtils {
return false;
}
static String createActivityPieChart(int totalBanned, int active, int inactive, int joinleaver) {
String url = ActivityPieChartCreator.createChart(totalBanned, active, inactive, joinleaver);
return Html.IMG.parse(url);
}
static String createTableOutOfHashMap(HashMap<String, Integer> commandUse) {
return SortableCommandUseTableCreator.createSortedCommandUseTable(commandUse);
}
@ -103,22 +66,12 @@ public class AnalysisUtils {
return html;
}
static String[] analyzeSessionData(List<SessionData> sessionData, List<Long> registered, long scale, long now) {
String[] returnA = new String[2];
List<SessionData> inScale = new ArrayList<>();
sessionData.stream()
.filter((s) -> (s.getSessionStart() > now - scale))
.forEach((s) -> {
inScale.add(s);
});
returnA[0] = createPlayerActivityGraph(inScale, scale);
static int getNewPlayers(List<Long> registered, long scale, long now) {
int newPlayers = 0;
// Filters out register dates before scale
newPlayers = registered.stream()
.filter((reg) -> (reg > now - scale))
.map((_item) -> 1).reduce(newPlayers, Integer::sum);
returnA[1] = "" + newPlayers;
return returnA;
return newPlayers;
}
}

View File

@ -1,6 +1,7 @@
package main.java.com.djrapitops.plan.utilities;
import java.io.FileNotFoundException;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.UUID;
@ -28,8 +29,6 @@ public class PlaceholderUtils {
*/
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) + "%");
@ -39,9 +38,6 @@ public class PlaceholderUtils {
replaceMap.put("%inactive%", "" + data.getInactive());
replaceMap.put("%joinleaver%", "" + data.getJoinleaver());
replaceMap.put("%activitytotal%", "" + data.getTotal());
replaceMap.put("%playerchartmonth%", data.getPlayersChartImgHtmlMonth());
replaceMap.put("%playerchartweek%", data.getPlayersChartImgHtmlWeek());
replaceMap.put("%playerchartday%", data.getPlayersChartImgHtmlDay());
replaceMap.put("%npday%", data.getNewPlayersDay() + "");
replaceMap.put("%npweek%", data.getNewPlayersWeek() + "");
replaceMap.put("%npmonth%", data.getNewPlayersMonth() + "");
@ -61,6 +57,35 @@ public class PlaceholderUtils {
replaceMap.put("%version%", plugin.getDescription().getVersion());
replaceMap.put("%planlite%", "");
replaceMap.put("%sortabletable%", data.getSortablePlayersTable());
replaceMap.put("%dataday%", data.getPlayersDataArray()[0]);
replaceMap.put("%labelsday%", data.getPlayersDataArray()[1]);
replaceMap.put("%dataweek%", data.getPlayersDataArray()[2]);
replaceMap.put("%labelsweek%", data.getPlayersDataArray()[3]);
replaceMap.put("%datamonth%", data.getPlayersDataArray()[4]);
replaceMap.put("%labelsmonth%", data.getPlayersDataArray()[5]);
replaceMap.put("%playersgraphcolor%", Settings.HCOLOR_ACT_ONL + "");
replaceMap.put("%playersgraphfill%", Settings.HCOLOR_ACT_ONL_FILL + "");
String[] activityLabels = new String[]{
"\"" + Html.GRAPH_ACTIVE.parse() + "\"",
"\"" + Html.GRAPH_INACTIVE.parse() + "\"",
"\"" + Html.GRAPH_UNKNOWN.parse() + "\"",
"\"" + Html.GRAPH_BANNED.parse() + "\""
};
replaceMap.put("%labelsactivity%", Arrays.toString(activityLabels));
String[] activityData = new String[]{data.getActive() + "", data.getInactive() + "", data.getJoinleaver()+ "", data.getBanned() + ""};
replaceMap.put("%activitydata%", Arrays.toString(activityData));
replaceMap.put("%activitycolors%", "\"#" + Settings.HCOLOR_ACTP_ACT
+ "\",\"#" + Settings.HCOLOR_ACTP_INA + "\",\"#" + Settings.HCOLOR_ACTP_JON + "\",\"#" + Settings.HCOLOR_ACTP_BAN + "\"");
String[] gmData = new String[]{
(data.getGm0Perc() * 100) + "",
(data.getGm1Perc() * 100) + "",
(data.getGm2Perc() * 100) + "",
(data.getGm3Perc() * 100) + ""
};
replaceMap.put("%gmdata%", Arrays.toString(gmData));
replaceMap.put("%gmlabels%", "[\"Survival\", \"Creative\", \"Adventure\", \"Spectator\"]");
replaceMap.put("%gmcolors%", "\"#" + Settings.HCOLOR_GMP_0 + "\",\"#" + Settings.HCOLOR_GMP_1
+ "\",\"#" + Settings.HCOLOR_GMP_2 + "\",\"#" + Settings.HCOLOR_GMP_3 + "\"");
replaceMap.putAll(plugin.getHookHandler().getAdditionalAnalysisReplaceRules());
return replaceMap;
}
@ -86,10 +111,6 @@ public class PlaceholderUtils {
replaceMap.put("%age%", (age != -1) ? "" + age : Phrase.DEM_UNKNOWN + "");
replaceMap.put("%gender%", "" + data.getDemData().getGender().name().toLowerCase());
HashMap<GameMode, Long> gmTimes = data.getGmTimes();
replaceMap.put("%gmpiechart%", AnalysisUtils.createGMPieChart(gmTimes));
long gmZero = gmTimes.get(GameMode.SURVIVAL);
long gmOne = gmTimes.get(GameMode.CREATIVE);
long gmTwo = gmTimes.get(GameMode.ADVENTURE);
long gmThree;
try {
Long gm3 = gmTimes.get(GameMode.SPECTATOR);
@ -100,11 +121,21 @@ public class PlaceholderUtils {
} catch (NoSuchFieldError e) {
gmThree = 0;
}
long total = gmZero + gmOne + gmTwo + gmThree;
replaceMap.put("%gm0%", FormatUtils.formatTimeAmount("" + gmZero));
replaceMap.put("%gm1%", FormatUtils.formatTimeAmount("" + gmOne));
replaceMap.put("%gm2%", FormatUtils.formatTimeAmount("" + gmTwo));
replaceMap.put("%gm3%", FormatUtils.formatTimeAmount("" + gmThree));
long[] gmData = new long[]{
gmTimes.get(GameMode.SURVIVAL),
gmTimes.get(GameMode.CREATIVE),
gmTimes.get(GameMode.ADVENTURE),
gmThree
};
long total = gmData[0] + gmData[1] + gmData[2] + gmData[3];
replaceMap.put("%gm0%", FormatUtils.formatTimeAmount("" + gmData[0]));
replaceMap.put("%gm1%", FormatUtils.formatTimeAmount("" + gmData[1]));
replaceMap.put("%gm2%", FormatUtils.formatTimeAmount("" + gmData[2]));
replaceMap.put("%gm3%", FormatUtils.formatTimeAmount("" + gmData[3]));
replaceMap.put("%gmdata%", Arrays.toString(gmData));
replaceMap.put("%gmlabels%", "[\"Survival\", \"Creative\", \"Adventure\", \"Spectator\"]");
replaceMap.put("%gmcolors%", "\"#" + Settings.HCOLOR_GMP_0 + "\",\"#" + Settings.HCOLOR_GMP_1
+ "\",\"#" + Settings.HCOLOR_GMP_2 + "\",\"#" + Settings.HCOLOR_GMP_3 + "\"");
replaceMap.put("%gmtotal%", FormatUtils.formatTimeAmount("" + total));
replaceMap.put("%ips%", (showIPandUUID ? data.getIps().toString() : Html.HIDDEN.parse()));
replaceMap.put("%nicknames%", FormatUtils.swapColorsToSpan(data.getNicknames().toString()));

View File

@ -5,9 +5,7 @@
<title>Plan | Server Analysis</title>
<meta name="description" content="Player Analysis window">
<meta name="author" content="Rsl1122">
<link rel="icon" href="https://puu.sh/tK0KL/6aa2ba141b.ico" type="image/x-icon" />
<!--<script src="http://puu.sh/ubCTc/7e611ffe42.js"></script>-->
<script src="http://www.kryogenix.org/code/browser/sorttable/sorttable.js"></script>
<link rel="icon" href="https://puu.sh/tK0KL/6aa2ba141b.ico" type="image/x-icon" />
<style>
* {
box-sizing: border-box;
@ -84,6 +82,7 @@
font-weight: bold;
cursor: default;
width: 100%;
overflow: hidden;
}
table.sortable th:not(.sorttable_sorted):not(.sorttable_sorted_reverse):not(.sorttable_nosort):after {
content: " \25B4\25BE"
@ -159,7 +158,7 @@
<div class="content">
<div class="column" style="width: 60%;">
<h4>Player Activity | Last 24h - New Players: %npday%</h4>
%playerchartday%
<canvas id="playerChartDay" width="1000" height="350" style="width: 95%;"></canvas>
<div class="buttons">
<p><b>Most recent logins</b>: %recentlogins%</p>
</div>
@ -176,24 +175,23 @@
The average of known player ages is %avgage%.
%essentialswarps%</p>
<h4>Gamemode Usage</h4>
%gmpiechart%
<canvas id="gmPie" width="1000" height="600" style="width: 95%;"></canvas>
<p>Survival: %gm0% | Creative: %gm1% | Adventure: %gm2% | Spectator: %gm3%</p>
</div>
</div>
<div class="content">
<div class="column" style="width: 60%;">
<h4>Player Activity | Last 24h - New Players: %npday%</h4>
%playerchartday%
<canvas id="playerChartDay2" width="1000" height="350" style="width: 95%;"></canvas>
<h4>Player Activity | Last 7 days - New Players: %npweek%</h4>
%playerchartweek%
<canvas id="playerChartWeek" width="1000" height="350" style="width: 95%;"></canvas>
<h4>Player Activity | Last 30 days - New Players: %npmonth%</h4>
%playerchartmonth%
<canvas id="playerChartMonth" width="1000" height="350" style="width: 95%;"></canvas>
</div>
<div class="column" style="width: 40%;">
<h4>Playerbase composition</h4>
%activitypiechart%
<p>Active %active% | Inactive %inactive% | Banned %banned% | Joined once %joinleaver% <br/>
Total: %activitytotal%</p>
<h4>Playerbase composition - Total: %activitytotal%</h4>
<p>Active %active% | Inactive %inactive% | Banned %banned% | Joined once %joinleaver%</p>
<canvas id="activityPie" width="1000" height="600" style="width: 95%;"></canvas>
<div class="buttons">
<p><b>Most recent logins</b>: %recentlogins%</p>
</div>
@ -233,15 +231,193 @@
</div>
</div></div>
</body>
<script src="http://www.kryogenix.org/code/browser/sorttable/sorttable.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.bundle.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.js"></script>
<script>
// just querying the DOM...like a boss!
// Script for All charts using Chart.js
var ctxday = document.getElementById("playerChartDay");
var ctxday2 = document.getElementById("playerChartDay2");
var ctxweek = document.getElementById("playerChartWeek");
var ctxmonth = document.getElementById("playerChartMonth");
var ctxactivitypie = document.getElementById("activityPie");
var ctxgmpie = document.getElementById("gmPie");
var dataday = {
labels: %labelsday%,
datasets: [
{
label: "Players Online",
fill: true,
lineTension: 0.1,
backgroundColor: "#%playersgraphfill%",
borderColor: "#%playersgraphcolor%",
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: "#%playersgraphcolor%",
pointBackgroundColor: "#fff",
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: "#%playersgraphcolor%",
pointHoverBorderColor: "#8fabc6",
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
spanGaps: false,
data: %dataday%,
}]
}
var dataweek = {
labels: %labelsweek%,
datasets: [
{
label: "Players Online",
fill: true,
lineTension: 0.1,
backgroundColor: "#%playersgraphfill%",
borderColor: "#%playersgraphcolor%",
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: "#%playersgraphcolor%",
pointBackgroundColor: "#fff",
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: "#%playersgraphcolor%",
pointHoverBorderColor: "#8fabc6",
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
spanGaps: false,
data: %dataweek%,
}]
}
var datamonth = {
labels: %labelsmonth%,
datasets: [
{
label: "Players Online",
fill: true,
lineTension: 0.1,
backgroundColor: "#%playersgraphfill%",
borderColor: "#%playersgraphcolor%",
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: "#%playersgraphcolor%",
pointBackgroundColor: "#fff",
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: "#%playersgraphcolor%",
pointHoverBorderColor: "#8fabc6",
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
spanGaps: false,
data: %datamonth%,
}]
}
var dataActivityPie = {
labels: %labelsactivity%,
datasets: [
{
data: %activitydata%,
backgroundColor: [%activitycolors%],
hoverBackgroundColor: [%activitycolors%]
}
]
}
var ActivityPie = new Chart(ctxactivitypie, {
type: 'doughnut',
data: dataActivityPie,
options: {
legend: {
position: 'right',
labels: {
padding: 7
}
}
}
});
var dataGmPie = {
labels: %gmlabels%,
datasets: [
{
data: %gmdata%,
backgroundColor: [%gmcolors%],
hoverBackgroundColor: [%gmcolors%]
}
]
}
var GMPie = new Chart(ctxgmpie, {
type: 'doughnut',
data: dataGmPie,
options: {
legend: {
position: 'right',
labels: {
padding: 7
}
}
}
});
var playersChartDay = new Chart(ctxday, {
type: 'line',
data: dataday,
options: {
scales: {
xAxes: [{
display: false
}]
}
}
});
var playersChartDay2 = new Chart(ctxday2, {
type: 'line',
data: dataday,
options: {
scales: {
xAxes: [{
display: false
}]
}
}
});
var playersChartWeek = new Chart(ctxweek, {
type: 'line',
data: dataweek,
options: {
scales: {
xAxes: [{
display: false
}]
}
}
});
var playersChartMonth = new Chart(ctxmonth, {
type: 'line',
data: datamonth,
options: {
scales: {
xAxes: [{
display: false
}]
}
}
});
</script>
<script>
// Script for the page navigation buttons
var links = document.querySelectorAll(".itemLinks");
var wrapper = document.querySelector("#wrapper");
// the activeLink provides a pointer to the currently displayed item
// the activeLink provides a pointer to the currently displayed item
var activeLink = 0;
// setup the event listeners
// setup the event listeners
for (var i = 0; i < links.length; i++) {
var link = links[i];
link.addEventListener('click', setClickedItem, false);
@ -250,7 +426,7 @@
link.itemID = i;
}
// set first item as active
// set first item as active
links[activeLink].classList.add("active");
function setClickedItem(e) {
@ -267,8 +443,8 @@
links[i].classList.remove("active");
}
}
// Handle changing the slider position as well as ensure
// the correct link is highlighted as being active
// Handle changing the slider position as well as ensure
// the correct link is highlighted as being active
function changePosition(link) {
var position = link.getAttribute("data-pos");

View File

@ -33,6 +33,7 @@ Customization:
HTML:
ActivityGraph:
OnlinePlayers: '1E90FF'
OnlinePlayersFill: '75BBFF'
NewPlayers: '228B22'
GamemodePie:
Survival: '951800'

View File

@ -6,7 +6,6 @@
<meta name="description" content="Player inspect window">
<meta name="author" content="Rsl1122">
<link rel="icon" href="https://puu.sh/tK0KL/6aa2ba141b.ico" type="image/x-icon" />
<script src="http://www.kryogenix.org/code/browser/sorttable/sorttable.js"></script>
<style>
* {
box-sizing: border-box;
@ -43,7 +42,10 @@
display: table;
}
.info {
width: 50%;
width: 60%;
}
.graphs {
width: 40%;
}
.table {
border-collapse: collapse;
@ -139,13 +141,41 @@
%sessionstable%
</div>
<div class="column info">
<h4>Gamemode Usage</h4>
%gmpiechart%
<p>Survival: %gm0% | Creative: %gm1% | Adventure: %gm2% | Spectator: %gm3% <br/>Total: %gmtotal%</p>
<div class="column graphs">
<h4>Gamemode Usage - Total: %gmtotal%</h4>
<p>Survival: %gm0% | Creative: %gm1% | Adventure: %gm2% | Spectator: %gm3%</p>
<canvas id="gmPie" width="1000" height="600" style="width: 95%;"></canvas>
</div>
</div>
<script src="http://www.kryogenix.org/code/browser/sorttable/sorttable.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.bundle.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.js"></script>
<script>
// Script for All charts using Chart.js
var ctxgmpie = document.getElementById("gmPie");
var dataGmPie = {
labels: %gmlabels%,
datasets: [
{
data: %gmdata%,
backgroundColor: [%gmcolors%],
hoverBackgroundColor: [%gmcolors%]
}
]
}
var GMPie = new Chart(ctxgmpie, {
type: 'doughnut',
data: dataGmPie,
options: {
legend: {
position: 'right',
labels: {
padding: 7
}
}
}
});
</script>
</body>
</html>

View File

@ -1,7 +1,7 @@
name: Plan
author: Rsl1122
main: main.java.com.djrapitops.plan.Plan
version: 2.6.3
version: 2.7.0
softdepend:
- OnTime