mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2025-02-02 05:21:36 +01:00
Bugfix for playergraph not showing & restoring backup from different server.
This commit is contained in:
parent
51c5a7e7b6
commit
01d9cc8da3
@ -22,6 +22,10 @@ public class AnalysisData {
|
|||||||
private String top20ActivePlayers;
|
private String top20ActivePlayers;
|
||||||
private String recentPlayers;
|
private String recentPlayers;
|
||||||
|
|
||||||
|
private int newPlayersMonth;
|
||||||
|
private int newPlayersWeek;
|
||||||
|
private int newPlayersDay;
|
||||||
|
|
||||||
private double gm0Perc;
|
private double gm0Perc;
|
||||||
private double gm1Perc;
|
private double gm1Perc;
|
||||||
private double gm2Perc;
|
private double gm2Perc;
|
||||||
@ -42,7 +46,7 @@ public class AnalysisData {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Class constructor.
|
* Class constructor.
|
||||||
*
|
*
|
||||||
* All data has to be set with setters to avoid NPE.
|
* All data has to be set with setters to avoid NPE.
|
||||||
*/
|
*/
|
||||||
public AnalysisData() {
|
public AnalysisData() {
|
||||||
@ -71,7 +75,8 @@ public class AnalysisData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param planLiteEnabled true if PlanLite was enabled at the time of Analysis
|
* @param planLiteEnabled true if PlanLite was enabled at the time of
|
||||||
|
* Analysis
|
||||||
*/
|
*/
|
||||||
public void setPlanLiteEnabled(boolean planLiteEnabled) {
|
public void setPlanLiteEnabled(boolean planLiteEnabled) {
|
||||||
this.planLiteEnabled = planLiteEnabled;
|
this.planLiteEnabled = planLiteEnabled;
|
||||||
@ -79,8 +84,9 @@ public class AnalysisData {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the PlanLiteAnalyzedData.
|
* Retrieve the PlanLiteAnalyzedData.
|
||||||
*
|
*
|
||||||
* null if planLiteEnabled = false
|
* null if planLiteEnabled = false
|
||||||
|
*
|
||||||
* @return Seperate object used to save PlanLiteData
|
* @return Seperate object used to save PlanLiteData
|
||||||
*/
|
*/
|
||||||
public PlanLiteAnalyzedData getPlanLiteData() {
|
public PlanLiteAnalyzedData getPlanLiteData() {
|
||||||
@ -89,6 +95,7 @@ public class AnalysisData {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the PlanLiteAnalyzedData.
|
* Set the PlanLiteAnalyzedData.
|
||||||
|
*
|
||||||
* @param planLiteData Seperate object used to save PlanLiteData
|
* @param planLiteData Seperate object used to save PlanLiteData
|
||||||
*/
|
*/
|
||||||
public void setPlanLiteData(PlanLiteAnalyzedData planLiteData) {
|
public void setPlanLiteData(PlanLiteAnalyzedData planLiteData) {
|
||||||
@ -167,9 +174,9 @@ public class AnalysisData {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the amount of active players.
|
* Retrieve the amount of active players.
|
||||||
*
|
*
|
||||||
* Activity is determined by AnalysisUtils.isActive()
|
* Activity is determined by AnalysisUtils.isActive()
|
||||||
*
|
*
|
||||||
* @return Amount of active players
|
* @return Amount of active players
|
||||||
*/
|
*/
|
||||||
public int getActive() {
|
public int getActive() {
|
||||||
@ -178,9 +185,9 @@ public class AnalysisData {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the amount of active players.
|
* Set the amount of active players.
|
||||||
*
|
*
|
||||||
* Activity is determined by AnalysisUtils.isActive()
|
* Activity is determined by AnalysisUtils.isActive()
|
||||||
*
|
*
|
||||||
* @param active Amount of active players
|
* @param active Amount of active players
|
||||||
*/
|
*/
|
||||||
public void setActive(int active) {
|
public void setActive(int active) {
|
||||||
@ -250,7 +257,7 @@ public class AnalysisData {
|
|||||||
return gm2Perc;
|
return gm2Perc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param gm2Perc Percentage of Gamemode usage time as a whole
|
* @param gm2Perc Percentage of Gamemode usage time as a whole
|
||||||
*/
|
*/
|
||||||
public void setGm2Perc(double gm2Perc) {
|
public void setGm2Perc(double gm2Perc) {
|
||||||
@ -412,7 +419,28 @@ public class AnalysisData {
|
|||||||
public void setRecentPlayers(String recentPlayers) {
|
public void setRecentPlayers(String recentPlayers) {
|
||||||
this.recentPlayers = recentPlayers;
|
this.recentPlayers = recentPlayers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public int getNewPlayersMonth() {
|
||||||
|
return newPlayersMonth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNewPlayersMonth(int newPlayersMonth) {
|
||||||
|
this.newPlayersMonth = newPlayersMonth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNewPlayersWeek() {
|
||||||
|
return newPlayersWeek;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNewPlayersWeek(int newPlayersWeek) {
|
||||||
|
this.newPlayersWeek = newPlayersWeek;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNewPlayersDay() {
|
||||||
|
return newPlayersDay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNewPlayersDay(int newPlayersDay) {
|
||||||
|
this.newPlayersDay = newPlayersDay;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -778,17 +778,23 @@ public abstract class SQLDB extends Database {
|
|||||||
+ locationColumnWorld
|
+ locationColumnWorld
|
||||||
+ ") VALUES (?, ?, ?, ?)");
|
+ ") VALUES (?, ?, ?, ?)");
|
||||||
boolean commitRequired = false;
|
boolean commitRequired = false;
|
||||||
for (Location location : locations) {
|
if (!locations.isEmpty()) {
|
||||||
saveStatement.setInt(1, userId);
|
for (Location location : locations) {
|
||||||
saveStatement.setInt(2, (int) location.getBlockX());
|
saveStatement.setInt(1, userId);
|
||||||
saveStatement.setInt(3, (int) location.getBlockZ());
|
saveStatement.setInt(2, (int) location.getBlockX());
|
||||||
saveStatement.setString(4, location.getWorld().getName());
|
saveStatement.setInt(3, (int) location.getBlockZ());
|
||||||
saveStatement.addBatch();
|
World world = location.getWorld();
|
||||||
commitRequired = true;
|
if (world == null) {
|
||||||
}
|
continue;
|
||||||
saveStatement.executeBatch();
|
}
|
||||||
if (commitRequired) {
|
saveStatement.setString(4, world.getName());
|
||||||
connection.commit();
|
saveStatement.addBatch();
|
||||||
|
commitRequired = true;
|
||||||
|
}
|
||||||
|
saveStatement.executeBatch();
|
||||||
|
if (commitRequired) {
|
||||||
|
connection.commit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
saveStatement.close();
|
saveStatement.close();
|
||||||
|
|
||||||
|
@ -35,7 +35,6 @@ public class PlayerActivityGraphCreator {
|
|||||||
|
|
||||||
List<Double> xListDate = new ArrayList<>();
|
List<Double> xListDate = new ArrayList<>();
|
||||||
List<Double> pYList = new ArrayList<>();
|
List<Double> pYList = new ArrayList<>();
|
||||||
List<Double> nYList = new ArrayList<>();
|
|
||||||
|
|
||||||
List<String> xDateAxisLabels = new ArrayList<>();
|
List<String> xDateAxisLabels = new ArrayList<>();
|
||||||
List<Double> xDateAxisLabelsLocations = new ArrayList<>();
|
List<Double> xDateAxisLabelsLocations = new ArrayList<>();
|
||||||
@ -46,30 +45,23 @@ public class PlayerActivityGraphCreator {
|
|||||||
long nowMinusScale = now - scale;
|
long nowMinusScale = now - scale;
|
||||||
|
|
||||||
int lastPValue = 0;
|
int lastPValue = 0;
|
||||||
int lastNValue = 0;
|
|
||||||
int lastSavedPValue = -1;
|
int lastSavedPValue = -1;
|
||||||
int lastSavedNValue = -1;
|
|
||||||
long lastSaveI = 0;
|
long lastSaveI = 0;
|
||||||
for (long i = nowMinusScale; i <= now; i += 1000) {
|
for (long i = nowMinusScale; i <= now; i += 1000) {
|
||||||
if (rawServerData.containsKey(i)) {
|
if (rawServerData.containsKey(i)) {
|
||||||
ServerData serverData = rawServerData.get(i);
|
ServerData serverData = rawServerData.get(i);
|
||||||
lastPValue = serverData.getPlayersOnline();
|
lastPValue = serverData.getPlayersOnline();
|
||||||
lastNValue = serverData.getNewPlayers();
|
|
||||||
}
|
}
|
||||||
Double scaledDateValue = ((i - nowMinusScale) * 1.0 / scale) * 100;
|
Double scaledDateValue = ((i - nowMinusScale) * 1.0 / scale) * 100;
|
||||||
Double scaledPlayerValue = (lastPValue * 1.0 / maxPlayers) * 100;
|
Double scaledPlayerValue = (lastPValue * 1.0 / maxPlayers) * 100;
|
||||||
Double scaledNewPValue = (lastNValue * 1.0 / maxPlayers) * 100;
|
|
||||||
|
|
||||||
if (lastSavedPValue != lastPValue || lastSavedNValue != lastNValue || i - lastSaveI > (scale / (long) 50)) {
|
if (lastSavedPValue != lastPValue || i - lastSaveI > (scale / (long) 50)) {
|
||||||
lastSaveI = i;
|
lastSaveI = i;
|
||||||
xListDate.add(scaledDateValue);
|
xListDate.add(scaledDateValue);
|
||||||
pYList.add((lastSavedPValue * 1.0 / maxPlayers) * 100);
|
pYList.add((lastSavedPValue * 1.0 / maxPlayers) * 100);
|
||||||
nYList.add((lastSavedNValue * 1.0 / maxPlayers) * 100);
|
|
||||||
lastSavedPValue = lastPValue;
|
lastSavedPValue = lastPValue;
|
||||||
lastSavedNValue = lastNValue;
|
|
||||||
xListDate.add(scaledDateValue);
|
xListDate.add(scaledDateValue);
|
||||||
pYList.add(scaledPlayerValue);
|
pYList.add(scaledPlayerValue);
|
||||||
nYList.add(scaledNewPValue);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,11 +82,9 @@ public class PlayerActivityGraphCreator {
|
|||||||
AxisLabels xAxisLabels = AxisLabelsFactory.newAxisLabels(xDateAxisLabels, xDateAxisLabelsLocations);
|
AxisLabels xAxisLabels = AxisLabelsFactory.newAxisLabels(xDateAxisLabels, xDateAxisLabelsLocations);
|
||||||
Data xData = Data.newData(xListDate);
|
Data xData = Data.newData(xListDate);
|
||||||
Data pYData = Data.newData(pYList);
|
Data pYData = Data.newData(pYList);
|
||||||
Data nYData = Data.newData(nYList);
|
|
||||||
|
|
||||||
XYLine playerLine = Plots.newXYLine(xData, pYData, Color.newColor(Phrase.HCOLOR_ACT_ONL + ""), "Online Players");
|
XYLine playerLine = Plots.newXYLine(xData, pYData, Color.newColor(Phrase.HCOLOR_ACT_ONL + ""), "Players Online");
|
||||||
XYLine newPlayerLine = Plots.newXYLine(xData, nYData, Color.newColor(Phrase.HCOLOR_ACT_NEW + ""), "New Players");
|
LineChart chart = GCharts.newLineChart(playerLine);
|
||||||
LineChart chart = GCharts.newLineChart(playerLine, newPlayerLine);
|
|
||||||
chart.addXAxisLabels(xAxisLabels);
|
chart.addXAxisLabels(xAxisLabels);
|
||||||
chart.addTopAxisLabels(AxisLabelsFactory.newAxisLabels("Players", 1));
|
chart.addTopAxisLabels(AxisLabelsFactory.newAxisLabels("Players", 1));
|
||||||
chart.addYAxisLabels(AxisLabelsFactory.newAxisLabels(yAxisLabels));
|
chart.addYAxisLabels(AxisLabelsFactory.newAxisLabels(yAxisLabels));
|
||||||
|
@ -9,6 +9,7 @@ import com.djrapitops.plan.data.UserData;
|
|||||||
import com.djrapitops.plan.data.cache.AnalysisCacheHandler;
|
import com.djrapitops.plan.data.cache.AnalysisCacheHandler;
|
||||||
import com.djrapitops.plan.data.cache.InspectCacheHandler;
|
import com.djrapitops.plan.data.cache.InspectCacheHandler;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -66,8 +67,8 @@ public class Analysis {
|
|||||||
plugin.log(Phrase.ANALYSIS_FAIL_NO_PLAYERS + "");
|
plugin.log(Phrase.ANALYSIS_FAIL_NO_PLAYERS + "");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<UUID> uuids = fetchPlayersInDB(offlinePlayers);
|
List<UUID> uuids = fetchPlayersInDB(offlinePlayers);
|
||||||
if (uuids.isEmpty()) {
|
if (uuids.isEmpty()) {
|
||||||
plugin.log(Phrase.ANALYSIS_FAIL_NO_DATA + "");
|
plugin.log(Phrase.ANALYSIS_FAIL_NO_DATA + "");
|
||||||
return;
|
return;
|
||||||
@ -186,7 +187,7 @@ public class Analysis {
|
|||||||
// Save Dataset to AnalysisData
|
// Save Dataset to AnalysisData
|
||||||
data.setTop20ActivePlayers(AnalysisUtils.createActivePlayersTable(playtimes, 20));
|
data.setTop20ActivePlayers(AnalysisUtils.createActivePlayersTable(playtimes, 20));
|
||||||
data.setRecentPlayers(AnalysisUtils.createListStringOutOfHashMapLong(latestLogins, 20));
|
data.setRecentPlayers(AnalysisUtils.createListStringOutOfHashMapLong(latestLogins, 20));
|
||||||
|
|
||||||
addPlanLiteToData(planLiteEnabled, plData, factionMap, townMap, totalVotes, totalMoney, data);
|
addPlanLiteToData(planLiteEnabled, plData, factionMap, townMap, totalVotes, totalMoney, data);
|
||||||
|
|
||||||
data.setTotalPlayTime(totalPlaytime);
|
data.setTotalPlayTime(totalPlaytime);
|
||||||
@ -194,9 +195,9 @@ public class Analysis {
|
|||||||
data.setTotalLoginTimes(totalLoginTimes);
|
data.setTotalLoginTimes(totalLoginTimes);
|
||||||
|
|
||||||
createActivityVisalization(totalBanned, active, inactive, joinleaver, data);
|
createActivityVisalization(totalBanned, active, inactive, joinleaver, data);
|
||||||
|
|
||||||
data.setOps(ops);
|
data.setOps(ops);
|
||||||
|
|
||||||
analyzeAverageAge(ages, data);
|
analyzeAverageAge(ages, data);
|
||||||
createGamemodeUsageVisualization(gmZero, gmOne, gmTwo, gmThree, data);
|
createGamemodeUsageVisualization(gmZero, gmOne, gmTwo, gmThree, data);
|
||||||
createCommandUseTable(data);
|
createCommandUseTable(data);
|
||||||
@ -292,12 +293,60 @@ public class Analysis {
|
|||||||
long scaleMonth = (long) 2592000 * (long) 1000;
|
long scaleMonth = (long) 2592000 * (long) 1000;
|
||||||
String playerActivityHtmlMonth = AnalysisUtils.createPlayerActivityGraph(rawServerData, scaleMonth);
|
String playerActivityHtmlMonth = AnalysisUtils.createPlayerActivityGraph(rawServerData, scaleMonth);
|
||||||
data.setPlayersChartImgHtmlMonth(playerActivityHtmlMonth);
|
data.setPlayersChartImgHtmlMonth(playerActivityHtmlMonth);
|
||||||
|
data.setNewPlayersMonth(getHighestNPValueForScale(scaleMonth));
|
||||||
long scaleWeek = 604800 * 1000;
|
long scaleWeek = 604800 * 1000;
|
||||||
String playerActivityHtmlWeek = AnalysisUtils.createPlayerActivityGraph(rawServerData, scaleWeek);
|
String playerActivityHtmlWeek = AnalysisUtils.createPlayerActivityGraph(rawServerData, scaleWeek);
|
||||||
data.setPlayersChartImgHtmlWeek(playerActivityHtmlWeek);
|
data.setPlayersChartImgHtmlWeek(playerActivityHtmlWeek);
|
||||||
|
data.setNewPlayersWeek(getHighestNPValueForScale(scaleWeek));
|
||||||
long scaleDay = 86400 * 1000;
|
long scaleDay = 86400 * 1000;
|
||||||
String playerActivityHtmlDay = AnalysisUtils.createPlayerActivityGraph(rawServerData, scaleDay);
|
String playerActivityHtmlDay = AnalysisUtils.createPlayerActivityGraph(rawServerData, scaleDay);
|
||||||
data.setPlayersChartImgHtmlDay(playerActivityHtmlDay);
|
data.setPlayersChartImgHtmlDay(playerActivityHtmlDay);
|
||||||
|
data.setNewPlayersDay(getHighestNPValueForScale(scaleDay));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getHighestNPValueForScale(long scale) {
|
||||||
|
List<List<ServerData>> sDataForEachDay = sortServerDatasByDay(scale);
|
||||||
|
int NPTotalInsideScaleTimeFrame = 0;
|
||||||
|
NPTotalInsideScaleTimeFrame = sDataForEachDay.parallelStream()
|
||||||
|
.map((serverDataList) -> {
|
||||||
|
int highestNPValue = 0;
|
||||||
|
for (ServerData serverData : serverDataList) {
|
||||||
|
int newPlayers = serverData.getNewPlayers();
|
||||||
|
if (newPlayers > highestNPValue) {
|
||||||
|
highestNPValue = newPlayers;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return highestNPValue;
|
||||||
|
}).map((highestNPValue) -> highestNPValue)
|
||||||
|
.reduce(NPTotalInsideScaleTimeFrame, Integer::sum);
|
||||||
|
return NPTotalInsideScaleTimeFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<List<ServerData>> sortServerDatasByDay(long scale) {
|
||||||
|
List<List<ServerData>> sDataForEachDay = new ArrayList<>();
|
||||||
|
Date lastStartOfDay = null;
|
||||||
|
List<Long> keys = new ArrayList<>();
|
||||||
|
keys.addAll(rawServerData.keySet());
|
||||||
|
Collections.sort(keys);
|
||||||
|
for (long date : keys) {
|
||||||
|
Date startOfDate = MiscUtils.getStartOfDate(new Date(date));
|
||||||
|
if (lastStartOfDay == null) {
|
||||||
|
sDataForEachDay.add(new ArrayList<>());
|
||||||
|
lastStartOfDay = startOfDate;
|
||||||
|
}
|
||||||
|
// If data is older than one month, ignore
|
||||||
|
if (new Date().getTime() - startOfDate.getTime() > scale) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (startOfDate.getTime() != lastStartOfDay.getTime()) {
|
||||||
|
sDataForEachDay.add(new ArrayList<>());
|
||||||
|
}
|
||||||
|
int lastIndex = sDataForEachDay.size() - 1;
|
||||||
|
ServerData serverData = rawServerData.get(date);
|
||||||
|
sDataForEachDay.get(lastIndex).add(serverData);
|
||||||
|
lastStartOfDay = startOfDate;
|
||||||
|
}
|
||||||
|
return sDataForEachDay;
|
||||||
}
|
}
|
||||||
}).runTaskAsynchronously(plugin);
|
}).runTaskAsynchronously(plugin);
|
||||||
}
|
}
|
||||||
|
@ -142,6 +142,9 @@ public class AnalysisUtils {
|
|||||||
replaceMap.put("%playerchartmonth%", data.getPlayersChartImgHtmlMonth());
|
replaceMap.put("%playerchartmonth%", data.getPlayersChartImgHtmlMonth());
|
||||||
replaceMap.put("%playerchartweek%", data.getPlayersChartImgHtmlWeek());
|
replaceMap.put("%playerchartweek%", data.getPlayersChartImgHtmlWeek());
|
||||||
replaceMap.put("%playerchartday%", data.getPlayersChartImgHtmlDay());
|
replaceMap.put("%playerchartday%", data.getPlayersChartImgHtmlDay());
|
||||||
|
replaceMap.put("%npday%", data.getNewPlayersDay()+"");
|
||||||
|
replaceMap.put("%npweek%", data.getNewPlayersWeek()+"");
|
||||||
|
replaceMap.put("%npmonth%", data.getNewPlayersMonth()+"");
|
||||||
replaceMap.put("%top50commands%", data.getTop50CommandsListHtml());
|
replaceMap.put("%top50commands%", data.getTop50CommandsListHtml());
|
||||||
replaceMap.put("%avgage%", (data.getAverageAge() != -1) ? "" + data.getAverageAge() : Phrase.DEM_UNKNOWN + "");
|
replaceMap.put("%avgage%", (data.getAverageAge() != -1) ? "" + data.getAverageAge() : Phrase.DEM_UNKNOWN + "");
|
||||||
replaceMap.put("%avgplaytime%", FormatUtils.formatTimeAmount("" + data.getAveragePlayTime()));
|
replaceMap.put("%avgplaytime%", FormatUtils.formatTimeAmount("" + data.getAveragePlayTime()));
|
||||||
|
@ -108,8 +108,13 @@ public class MiscUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isOnSameDay(Date first, Date second) {
|
public static boolean isOnSameDay(Date first, Date second) {
|
||||||
Date startOfFirst = new Date(first.getTime() - (first.getTime() % 86400000));
|
Date startOfFirst = getStartOfDate(first);
|
||||||
Date startOfSecond = new Date(second.getTime() - (second.getTime() % 86400000));
|
Date startOfSecond = getStartOfDate(second);
|
||||||
return (startOfFirst != startOfSecond);
|
return (startOfFirst != startOfSecond);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Date getStartOfDate(Date date) {
|
||||||
|
Date startOfDate = new Date(date.getTime() - (date.getTime() % 86400000));
|
||||||
|
return startOfDate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,11 +95,11 @@
|
|||||||
<div class="clearfix">
|
<div class="clearfix">
|
||||||
<div class="column graphs">
|
<div class="column graphs">
|
||||||
|
|
||||||
<h4>Player Activity - Last 24h</h4>
|
<h4>Player Activity | Last 24h - New Players: %npday%</h4>
|
||||||
%playerchartday%
|
%playerchartday%
|
||||||
<h4>Player Activity - Last 7 days</h4>
|
<h4>Player Activity | Last 7 days - New Players: %npweek%</h4>
|
||||||
%playerchartweek%
|
%playerchartweek%
|
||||||
<h4>Player Activity - Last 30 days</h4>
|
<h4>Player Activity | Last 30 days - New Players: %npmonth%</h4>
|
||||||
%playerchartmonth%
|
%playerchartmonth%
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<p><b>Most recent logins</b>: %recentlogins%</p>
|
<p><b>Most recent logins</b>: %recentlogins%</p>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
name: Plan
|
name: Plan
|
||||||
author: Rsl1122
|
author: Rsl1122
|
||||||
main: com.djrapitops.plan.Plan
|
main: com.djrapitops.plan.Plan
|
||||||
version: 2.4.0
|
version: 2.4.1
|
||||||
|
|
||||||
commands:
|
commands:
|
||||||
plan:
|
plan:
|
||||||
|
Loading…
Reference in New Issue
Block a user