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();
long averageLength = MathUtils.averageLong(AnalysisUtils.transformSessionDataToLengths(sessions));
List<Long> lengths = AnalysisUtils.transformSessionDataToLengths(sessions);
long averageLength = MathUtils.averageLong(lengths);
addValue("sessionaverage", FormatUtils.formatTimeAmount(averageLength));
String punchCardArray = PunchCardGraphCreator.generateDataArray(sessions);
addValue("datapunchcard", punchCardArray);
String[] sessionDistribution = SessionLengthDistributionGraphCreator.generateDataArraySessions(sessions);
addValue("datasessiondistribution", sessionDistribution[0]);
addValue("labelssessiondistribution", sessionDistribution[1]);
addValue("punchcardseries", PunchCardGraphCreator.createDataSeries(sessions));
addValue("sessionlengthseries", SessionLengthDistributionGraphCreator.createDataSeries(lengths));
}
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> 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("cpuseries", CPUGraphCreator.buildSeriesDataString(tpsData));
@ -62,19 +47,6 @@ public class TPSPart extends RawData {
addValue("entityseries", WorldLoadGraphCreator.buildSeriesDataStringEntities(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 averageTPSDay = MathUtils.averageDouble(day.stream().map(TPS::getTps));

View File

@ -29,6 +29,30 @@ public class PunchCardGraphCreator {
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
* @return

View File

@ -24,6 +24,37 @@ public class SessionLengthDistributionGraphCreator {
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
* @return
@ -86,11 +117,14 @@ public class SessionLengthDistributionGraphCreator {
Map<Long, Integer> values = new HashMap<>();
long lengthInMinutes = 5;
while (!unused.isEmpty() && lengthInMinutes < 120) {
while (!unused.isEmpty() || lengthInMinutes <= 120) {
long length = lengthInMinutes * 60 * 1000;
List<Long> lessThan = unused.stream().filter(l -> l < length).collect(Collectors.toList());
values.put(lengthInMinutes, lessThan.size());
unused.removeAll(lessThan);
int amount = lessThan.size();
if (amount != 0) {
values.put(lengthInMinutes, amount);
unused.removeAll(lessThan);
}
lengthInMinutes += 5;
}
return values;

View File

@ -4,6 +4,19 @@ import java.util.Map;
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) {
StringBuilder arrayBuilder = new StringBuilder("[");

View File

@ -283,23 +283,28 @@ public class AnalysisUtils {
}
/**
* @param sessionStarts
* @return
* Transforms the session start list into a list of int arrays.
* <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) {
return sessionStarts.stream().map((Long start) -> {
Calendar day = Calendar.getInstance();
day.setTimeInMillis(start);
int hourOfDay = day.get(Calendar.HOUR_OF_DAY);
int dayOfWeek = day.get(Calendar.DAY_OF_WEEK) - 2;
if (hourOfDay == 24) {
int hourOfDay = day.get(Calendar.HOUR_OF_DAY); // 0 AM is 0
int dayOfWeek = day.get(Calendar.DAY_OF_WEEK) - 2; // Monday is 0, Sunday is -1
if (hourOfDay == 24) { // Check if hour is 24 (Should be impossible but.)
hourOfDay = 0;
dayOfWeek += 1;
}
if (dayOfWeek > 6) {
if (dayOfWeek > 6) { // If Hour added a day on Sunday, move to Monday
dayOfWeek = 0;
}
if (dayOfWeek < 0) {
if (dayOfWeek < 0) { // Move Sunday to 6
dayOfWeek = 6;
}
return new int[]{dayOfWeek, hourOfDay};

View File

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