mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2025-03-10 13:49:17 +01:00
Rest of Analysis Graphs to HighCharts
This commit is contained in:
parent
30f8fd69e7
commit
a2cc3a332b
@ -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() {
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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("[");
|
||||
|
||||
|
@ -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};
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user