Rest of Analysis Graphs to HighCharts

This commit is contained in:
Rsl1122 2017-07-30 14:20:39 +03:00
parent 30f8fd69e7
commit a2cc3a332b
7 changed files with 164 additions and 181 deletions

View File

@ -69,15 +69,12 @@ public class ActivityPart extends RawData {
final List<SessionData> sessions = joins.getAllSessions(); final List<SessionData> sessions = joins.getAllSessions();
long averageLength = MathUtils.averageLong(AnalysisUtils.transformSessionDataToLengths(sessions)); List<Long> lengths = AnalysisUtils.transformSessionDataToLengths(sessions);
long averageLength = MathUtils.averageLong(lengths);
addValue("sessionaverage", FormatUtils.formatTimeAmount(averageLength)); addValue("sessionaverage", FormatUtils.formatTimeAmount(averageLength));
String punchCardArray = PunchCardGraphCreator.generateDataArray(sessions); addValue("punchcardseries", PunchCardGraphCreator.createDataSeries(sessions));
addValue("datapunchcard", punchCardArray); addValue("sessionlengthseries", SessionLengthDistributionGraphCreator.createDataSeries(lengths));
String[] sessionDistribution = SessionLengthDistributionGraphCreator.generateDataArraySessions(sessions);
addValue("datasessiondistribution", sessionDistribution[0]);
addValue("labelssessiondistribution", sessionDistribution[1]);
} }
private void playerActivityGraphs() { private void playerActivityGraphs() {

View File

@ -40,21 +40,6 @@ public class TPSPart extends RawData {
List<TPS> week = TPSGraphCreator.filterTPS(tpsData, now - TimeAmount.WEEK.ms()); List<TPS> week = TPSGraphCreator.filterTPS(tpsData, now - TimeAmount.WEEK.ms());
List<TPS> day = TPSGraphCreator.filterTPS(tpsData, now - TimeAmount.DAY.ms()); List<TPS> day = TPSGraphCreator.filterTPS(tpsData, now - TimeAmount.DAY.ms());
String tpsScatterDay = TPSGraphCreator.buildScatterDataStringTPS(day, TimeAmount.DAY.ms());
String tpsScatterWeek = TPSGraphCreator.buildScatterDataStringTPS(week, TimeAmount.WEEK.ms());
String cpuScatterDay = CPUGraphCreator.buildScatterDataString(day, TimeAmount.DAY.ms());
String cpuScatterWeek = CPUGraphCreator.buildScatterDataString(week, TimeAmount.WEEK.ms());
String ramScatterDay = RamGraphCreator.buildScatterDataString(day, TimeAmount.DAY.ms());
String ramScatterWeek = RamGraphCreator.buildScatterDataString(week, TimeAmount.WEEK.ms());
String entityScatterDay = WorldLoadGraphCreator.buildScatterDataStringEntities(day, TimeAmount.DAY.ms());
String entityScatterWeek = WorldLoadGraphCreator.buildScatterDataStringEntities(week, TimeAmount.WEEK.ms());
String chunkScatterDay = WorldLoadGraphCreator.buildScatterDataStringChunks(day, TimeAmount.DAY.ms());
String chunkScatterWeek = WorldLoadGraphCreator.buildScatterDataStringChunks(week, TimeAmount.WEEK.ms());
addValue("tpsscatterday", tpsScatterDay);
addValue("tpsscatterweek", tpsScatterWeek);
addValue("tpsseries", TPSGraphCreator.buildSeriesDataString(tpsData)); addValue("tpsseries", TPSGraphCreator.buildSeriesDataString(tpsData));
addValue("cpuseries", CPUGraphCreator.buildSeriesDataString(tpsData)); addValue("cpuseries", CPUGraphCreator.buildSeriesDataString(tpsData));
@ -62,19 +47,6 @@ public class TPSPart extends RawData {
addValue("entityseries", WorldLoadGraphCreator.buildSeriesDataStringEntities(tpsData)); addValue("entityseries", WorldLoadGraphCreator.buildSeriesDataStringEntities(tpsData));
addValue("chunkseries", WorldLoadGraphCreator.buildSeriesDataStringChunks(tpsData)); addValue("chunkseries", WorldLoadGraphCreator.buildSeriesDataStringChunks(tpsData));
addValue("cpuscatterday", cpuScatterDay);
addValue("cpuscatterweek", cpuScatterWeek);
addValue("ramscatterday", ramScatterDay);
addValue("ramscatterweek", ramScatterWeek);
addValue("entityscatterday", entityScatterDay);
addValue("entityscatterweek", entityScatterWeek);
addValue("chunkscatterday", chunkScatterDay);
addValue("chunkscatterweek", chunkScatterWeek);
Runtime runtime = Runtime.getRuntime();
addValue("maxram", runtime.maxMemory() / 1000000);
double averageTPSWeek = MathUtils.averageDouble(week.stream().map(TPS::getTps)); double averageTPSWeek = MathUtils.averageDouble(week.stream().map(TPS::getTps));
double averageTPSDay = MathUtils.averageDouble(day.stream().map(TPS::getTps)); double averageTPSDay = MathUtils.averageDouble(day.stream().map(TPS::getTps));

View File

@ -29,6 +29,30 @@ public class PunchCardGraphCreator {
throw new IllegalStateException("Utility class"); throw new IllegalStateException("Utility class");
} }
public static String createDataSeries(Collection<SessionData> sessions) {
List<Long> sessionStarts = getSessionStarts(sessions);
List<int[]> daysAndHours = AnalysisUtils.getDaysAndHours(sessionStarts);
int[][] dataArray = createDataArray(daysAndHours);
int big = findBiggestValue(dataArray);
int[][] scaled = scale(dataArray, big);
StringBuilder arrayBuilder = new StringBuilder("[");
for (int i = 0; i < 7; i++) {
for (int j = 0; j < 24; j++) {
int value = scaled[i][j];
if (value == 0) {
continue;
}
arrayBuilder.append("{x:").append(j * 3600000).append(", y:").append(i).append(", z:").append(value).append(", marker: { radius:").append(value).append("}}");
if (i != 6 || j != 23) {
arrayBuilder.append(",");
}
}
}
arrayBuilder.append("]");
return arrayBuilder.toString();
}
/** /**
* @param data * @param data
* @return * @return

View File

@ -24,6 +24,37 @@ public class SessionLengthDistributionGraphCreator {
throw new IllegalStateException("Utility class"); throw new IllegalStateException("Utility class");
} }
/**
* Creates a data series of session lengths for Sessions bar chart.
* <p>
* Contains values from 0 up to 120 minutes
*
* @param lengths Lengths of all sessions in a list.
* @return Data for Highcharts series.
*/
public static String createDataSeries(List<Long> lengths) {
Map<Long, Integer> bars = getValues(lengths);
List<Long> keys = new ArrayList<>(bars.keySet());
Collections.sort(keys);
StringBuilder arrayBuilder = new StringBuilder("[");
int i = 0;
int size = keys.size();
for (Long key : keys) {
if (key > 120) {
break;
}
Integer value = bars.get(key);
arrayBuilder.append("['").append(key - 5).append(" - ").append(key).append(" min',").append(value).append("]");
if (i < size) {
arrayBuilder.append(", ");
}
i++;
}
arrayBuilder.append("]");
return arrayBuilder.toString();
}
/** /**
* @param data * @param data
* @return * @return
@ -86,11 +117,14 @@ public class SessionLengthDistributionGraphCreator {
Map<Long, Integer> values = new HashMap<>(); Map<Long, Integer> values = new HashMap<>();
long lengthInMinutes = 5; long lengthInMinutes = 5;
while (!unused.isEmpty() && lengthInMinutes < 120) { while (!unused.isEmpty() || lengthInMinutes <= 120) {
long length = lengthInMinutes * 60 * 1000; long length = lengthInMinutes * 60 * 1000;
List<Long> lessThan = unused.stream().filter(l -> l < length).collect(Collectors.toList()); List<Long> lessThan = unused.stream().filter(l -> l < length).collect(Collectors.toList());
values.put(lengthInMinutes, lessThan.size()); int amount = lessThan.size();
unused.removeAll(lessThan); if (amount != 0) {
values.put(lengthInMinutes, amount);
unused.removeAll(lessThan);
}
lengthInMinutes += 5; lengthInMinutes += 5;
} }
return values; return values;

View File

@ -4,6 +4,19 @@ import java.util.Map;
public class WorldMapCreator { public class WorldMapCreator {
/**
* Constructor used to hide the public constructor
*/
private WorldMapCreator() {
throw new IllegalStateException("Utility class");
}
/**
* Creates a data series with iso-a3 specification of Country codes.
*
* @param geoCodeCounts
* @return
*/
public static String createDataSeries(Map<String, Integer> geoCodeCounts) { public static String createDataSeries(Map<String, Integer> geoCodeCounts) {
StringBuilder arrayBuilder = new StringBuilder("["); StringBuilder arrayBuilder = new StringBuilder("[");

View File

@ -283,23 +283,28 @@ public class AnalysisUtils {
} }
/** /**
* @param sessionStarts * Transforms the session start list into a list of int arrays.
* @return * <p>
* First number signifies the Day of Week. (0 = Monday, 6 = Sunday)
* Second number signifies the Hour of Day. (0 = 0 AM, 23 = 11 PM)
*
* @param sessionStarts List of Session start Epoch ms.
* @return list of int arrays.
*/ */
public static List<int[]> getDaysAndHours(List<Long> sessionStarts) { public static List<int[]> getDaysAndHours(List<Long> sessionStarts) {
return sessionStarts.stream().map((Long start) -> { return sessionStarts.stream().map((Long start) -> {
Calendar day = Calendar.getInstance(); Calendar day = Calendar.getInstance();
day.setTimeInMillis(start); day.setTimeInMillis(start);
int hourOfDay = day.get(Calendar.HOUR_OF_DAY); int hourOfDay = day.get(Calendar.HOUR_OF_DAY); // 0 AM is 0
int dayOfWeek = day.get(Calendar.DAY_OF_WEEK) - 2; int dayOfWeek = day.get(Calendar.DAY_OF_WEEK) - 2; // Monday is 0, Sunday is -1
if (hourOfDay == 24) { if (hourOfDay == 24) { // Check if hour is 24 (Should be impossible but.)
hourOfDay = 0; hourOfDay = 0;
dayOfWeek += 1; dayOfWeek += 1;
} }
if (dayOfWeek > 6) { if (dayOfWeek > 6) { // If Hour added a day on Sunday, move to Monday
dayOfWeek = 0; dayOfWeek = 0;
} }
if (dayOfWeek < 0) { if (dayOfWeek < 0) { // Move Sunday to 6
dayOfWeek = 6; dayOfWeek = 6;
} }
return new int[]{dayOfWeek, hourOfDay}; return new int[]{dayOfWeek, hourOfDay};

View File

@ -406,7 +406,7 @@
<div class="info-icon"> <div class="info-icon">
<i class="fa fa-user-plus" aria-hidden="true"></i> <i class="fa fa-user-plus" aria-hidden="true"></i>
</div> </div>
<div class="info-text"> <div class="info-text" style="width: 60%;">
<div class="info-number"> <div class="info-number">
%newperdaymonth% %newperdaymonth%
</div> </div>
@ -491,7 +491,7 @@
</div> </div>
</div> </div>
</div> </div>
<canvas id="punchcard" width="1000" height="600" style="width: 95%;"></canvas> <div id="punchcard" style="width: 100%; height:400px;"></div>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
@ -515,7 +515,7 @@
</div> </div>
</div> </div>
</div> </div>
<canvas id="sessiondistribution" width="1000" height="600" style="width: 95%;"></canvas> <div id="sessionDistribution" style="width: 100%; height:400px;"></div>
</div> </div>
</div> </div>
</div> </div>
@ -773,6 +773,16 @@
data: %geomapseries%, data: %geomapseries%,
joinBy: ['iso-a3', 'code'] joinBy: ['iso-a3', 'code']
}; };
var sessionLengthSeries = {
name: 'Sessions',
color: '#89c471',
data: %sessionlengthseries%
};
var punchcardSeries = {
name: 'Relative Activity',
color: '#222',
data: %punchcardseries%
};
</script> </script>
<script> <script>
function playersChart() { function playersChart() {
@ -958,7 +968,7 @@
</script> </script>
<script> <script>
function gmPie() { function gmPie() {
var myChart = Highcharts.chart('gmPie', { Highcharts.chart('gmPie', {
chart: { chart: {
plotBackgroundColor: null, plotBorderWidth: null, plotShadow: false, plotBackgroundColor: null, plotBorderWidth: null, plotShadow: false,
type: 'pie' type: 'pie'
@ -984,139 +994,64 @@
}; };
</script> </script>
<script> <script>
// Session start puchcard bubblechart function punchCard() {
function day(i) { Highcharts.chart('punchcard' , {
switch (i) { chart: {
case 0: defaultSeriesType: 'scatter'
return 'Monday'; },
case 1: title: {
return 'Tuesday'; text: 'Player Join PunchCard'
case 2: },
return 'Wednesday'; xAxis: {
case 3: type: 'datetime',
return 'Thursday'; dateTimeLabelFormats: {
case 4: hour: '%I %P'
return 'Friday'; },
case 5: tickInterval: 3600000
return 'Saturday'; },
case 6: yAxis: {
return 'Sunday'; categories: ['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday'],
default: },
return ''; tooltip: {
} pointFormat: 'Activity: {point.z}'
} },
function hour(i) { series: [punchcardSeries]
switch (i) { });
case 25: }
case - 1: </script>
case - 2:
case - 3:
case - 4:
case - 5:
return '';
default:
return i + ':00';
}
}
var ctxpunch = document.getElementById("punchcard");
var datapunch = {
datasets: [
{
label: 'Player Join Punchcard',
data: %datapunchcard% ,
backgroundColor: "#222",
hoverBackgroundColor: "#333",
}]
};
var punchcardChart = new Chart(ctxpunch, {
type: 'bubble',
data: datapunch,
options: {
tooltips: {
callbacks: {
label: function(tooltipItems, data) {
return day(tooltipItems.yLabel) + ': ' + hour(tooltipItems.xLabel);
}
}
},
scales: {
xAxes: [{
showXLabels: 1,
ticks: {
callback: function(value, index, values) {
return hour(value);
},
suggestedMax: 25,
suggestedMin: - 1
}
}],
yAxes: [{
ticks: {
callback: function(value, index, values) {
return day(value);
},
suggestedMax: 7,
suggestedMin: - 1
}
}]
}
}
});
</script>
<script> <script>
// Session length distribution barchart function sessionDistributionChart() {
var ctxDistribution = document.getElementById("sessiondistribution"); Highcharts.chart('sessionDistribution', {
var dataDistr = { chart: {
labels: %labelssessiondistribution%, type: 'column'
datasets: [ },
{ title: {
label: 'Session Length Distribution', text: 'Session Length Distribution'
data: %datasessiondistribution% , },
backgroundColor: "#89c471", xAxis: {
fill: true, type: 'category',
borderColor: "#348e0f", labels: {
borderCapStyle: 'butt', rotation: -45
borderDash: [], }
borderDashOffset: 0.0, },
borderJoinStyle: 'miter', yAxis: {
pointBorderColor: "#348e0f", min: 0,
pointBackgroundColor: "#fff", title: {
pointBorderWidth: 1, text: 'Sessions'
pointHoverRadius: 5, }
pointHoverBackgroundColor: "#348e0f", },
pointHoverBorderColor: "#348e0f", legend: {
pointHoverBorderWidth: 2, enabled: false
pointRadius: 1, },
pointHitRadius: 10, plotOptions: {
spanGaps: false, series: {
}] groupPadding: 0
}; },
var sessionDistributions = new Chart(ctxDistribution, { pointPadding: 0
type: 'bar', },
data: dataDistr, series: [sessionLengthSeries]
options: { });
tooltips: { };
callbacks: {
label: function(tooltipItems, data) {
return tooltipItems.xLabel + 'utes: ' + tooltipItems.yLabel + ' sessions';
}
}
},
scales: {
yAxes: [{
ticks: {
callback: function(value, index, values) {
return value + '';
}
}
}]
}
}
});
</script> </script>
<script> <script>
function worldMap() { function worldMap() {
@ -1173,7 +1108,10 @@
playersChart2(); playersChart2();
tpsChart(); tpsChart();
resourceChart(); resourceChart();
worldChart();
worldMap(); worldMap();
sessionDistributionChart();
punchCard();
countUpTimer(); countUpTimer();
function openFunc(i) { function openFunc(i) {