Implemented unique players graph #560

This commit is contained in:
Rsl1122 2018-07-13 16:24:08 +03:00
parent 0549ce32f5
commit 6c1e648741
7 changed files with 86 additions and 5 deletions

View File

@ -188,6 +188,17 @@ public class AnalysisContainer extends DataContainer {
putSupplier(AnalysisKeys.AVG_PLAYERS_NEW_WEEK, () -> getUnsafe(newWeek).averageNewPerDay());
putSupplier(AnalysisKeys.AVG_PLAYERS_NEW_MONTH, () -> getUnsafe(newMonth).averageNewPerDay());
putSupplier(AnalysisKeys.UNIQUE_PLAYERS_SERIES, () ->
new AbstractLineGraph(MutatorFunctions.toPoints(
getUnsafe(AnalysisKeys.SESSIONS_MUTATOR).uniqueJoinsPerDay())
).toHighChartsSeries()
);
putSupplier(AnalysisKeys.NEW_PLAYERS_SERIES, () ->
new AbstractLineGraph(MutatorFunctions.toPoints(
getUnsafe(AnalysisKeys.PLAYERS_MUTATOR).newPerDay())
).toHighChartsSeries()
);
Key<Integer> retentionDay = new Key<>(Integer.class, "RETENTION_DAY");
// compareAndFindThoseLikelyToBeRetained can throw exception.
putSupplier(retentionDay, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR).compareAndFindThoseLikelyToBeRetained(

View File

@ -127,6 +127,8 @@ public class AnalysisKeys {
public static final PlaceholderKey<String> ACTIVITY_STACK_CATEGORIES = CommonPlaceholderKeys.ACTIVITY_STACK_CATEGORIES;
public static final PlaceholderKey<String> ACTIVITY_PIE_SERIES = CommonPlaceholderKeys.ACTIVITY_PIE_SERIES;
public static final PlaceholderKey<String> CALENDAR_SERIES = new PlaceholderKey<>(String.class, "calendarSeries");
public static final PlaceholderKey<String> UNIQUE_PLAYERS_SERIES = new PlaceholderKey<>(String.class, "uniquePlayersSeries");
public static final PlaceholderKey<String> NEW_PLAYERS_SERIES = new PlaceholderKey<>(String.class, "newPlayersSeries");
// Variables used only during analysis
public static final Key<SessionsMutator> SESSIONS_MUTATOR = CommonKeys.SESSIONS_MUTATOR;
public static final Key<TPSMutator> TPS_MUTATOR = CommonKeys.TPS_MUTATOR;

View File

@ -18,6 +18,10 @@ public class DateHoldersMutator<T extends DateHolder> {
public TreeMap<Long, List<T>> groupByStartOfDay() {
TreeMap<Long, List<T>> map = new TreeMap<>();
if (dateHolders.isEmpty()) {
return map;
}
long twentyFourHours = 24L * TimeAmount.HOUR.ms();
for (T holder : dateHolders) {
long date = holder.getDate();
@ -28,11 +32,16 @@ public class DateHoldersMutator<T extends DateHolder> {
map.put(startOfDate, list);
}
// Add missing in-between dates
for (long date = map.firstKey(); date < map.lastKey(); date += twentyFourHours) {
map.putIfAbsent(date, new ArrayList<>());
// Empty map firstKey attempt causes NPE if not checked.
if (!map.isEmpty()) {
// Add missing in-between dates
long start = map.firstKey();
long now = System.currentTimeMillis();
long end = now - (now % twentyFourHours);
for (long date = map.firstKey(); date < end; date += twentyFourHours) {
map.putIfAbsent(date, new ArrayList<>());
}
}
return map;
}

View File

@ -74,7 +74,8 @@ public class AnalysisPage implements Page {
TPS_SERIES, CPU_SERIES, RAM_SERIES,
ENTITY_SERIES, CHUNK_SERIES, PUNCHCARD_SERIES,
WORLD_MAP_SERIES, ACTIVITY_STACK_SERIES, ACTIVITY_STACK_CATEGORIES,
ACTIVITY_PIE_SERIES, CALENDAR_SERIES
ACTIVITY_PIE_SERIES, CALENDAR_SERIES,
UNIQUE_PLAYERS_SERIES, NEW_PLAYERS_SERIES
);
placeholderReplacer.addAllPlaceholdersFrom(analysisContainer, FormatUtils::cutDecimals,
AVG_TPS_MONTH, AVG_TPS_WEEK, AVG_TPS_DAY,

View File

@ -121,6 +121,7 @@ public class HtmlExport extends SpecificExport {
"web/js/helpers.js",
"web/js/script.js",
"web/js/charts/activityPie.js",
"web/js/charts/lineGraph.js",
"web/js/charts/stackGraph.js",
"web/js/charts/performanceGraph.js",
"web/js/charts/playerGraph.js",

View File

@ -0,0 +1,36 @@
function lineChart(id, series) {
Highcharts.stockChart(id, {
rangeSelector: {
selected: 2,
buttons: [{
type: 'hour',
count: 12,
text: '12h'
}, {
type: 'hour',
count: 24,
text: '24h'
}, {
type: 'day',
count: 7,
text: '7d'
}, {
type: 'month',
count: 1,
text: '30d'
}, {
type: 'all',
text: 'All'
}]
},
yAxis: {
softMax: 2,
softMin: 0
},
title: {text: ''},
legend: {
enabled: true
},
series: series
});
}

View File

@ -1119,6 +1119,7 @@
<script src="js/charts/punchCard.js"></script>
<script src="js/charts/healthGauge.js"></script>
<script src="js/charts/activityPie.js"></script>
<script src="js/charts/lineGraph.js"></script>
<script src="js/charts/stackGraph.js"></script>
<script src="js/charts/worldPie.js"></script>
<script src="js/charts/performanceGraph.js"></script>
@ -1141,6 +1142,7 @@
var v = {
colors: {
playersOnline: '${playersGraphColor}',
newPlayers: '#8BC34A',
tpsLow: '${tpsLowColor}',
tpsMed: '${tpsMediumColor}',
tpsHigh: '${tpsHighColor}',
@ -1159,6 +1161,8 @@
},
data: {
playersOnline: ${playersOnlineSeries},
uniquePlayers: ${uniquePlayersSeries},
newPlayers: ${newPlayersSeries},
tps: ${tpsSeries},
cpu: ${cpuSeries},
ram: ${ramSeries},
@ -1180,6 +1184,8 @@
var s = {
name: {
playersOnline: 'Players Online',
uniquePlayers: 'Unique Players',
newPlayers: 'New Players',
tps: 'TPS',
cpu: 'CPU Usage (%)',
ram: 'RAM Usage (MB)',
@ -1220,6 +1226,20 @@
color: v.colors.playersOnline,
yAxis: 0
},
uniquePlayers: {
name: s.name.uniquePlayers,
type: s.type.spline,
tooltip: s.tooltip.zeroDecimals,
data: v.data.uniquePlayers,
color: v.colors.playersOnline
},
newPlayers: {
name: s.name.newPlayers,
type: s.type.spline,
tooltip: s.tooltip.zeroDecimals,
data: v.data.newPlayers,
color: v.colors.newPlayers
},
tps: {
name: s.name.tps,
type: s.type.spline,
@ -1346,6 +1366,7 @@
// Chart draw scripts
activityPie('activityPie', series.activityPie);
lineChart('uniqueChart', [series.uniquePlayers, series.newPlayers]);
stackChart('activityStackGraph', series.activityStackCategories, series.activityStack, 'Players');
worldPie('worldPie', series.worldPie, series.worldPieDrillDown);
playersChart('playerChartDay', series.playersOnline, 3);