change charts

change data collection
charts are collapsible
show fps and entity count in one chart
improve network chart
add player chart (queued, joining, playing, free)
This commit is contained in:
alexfriesen
2017-04-25 19:03:03 +02:00
parent 12a5ec279b
commit cab65aeab7
3 changed files with 210 additions and 49 deletions
+68 -2
View File
@@ -1,4 +1,4 @@
<div ng-controller="ServerInfoController" flex layout="column" id="ServerInfoController"> <div ng-controller="ServerInfoController" id="ServerInfoController" data-ng-init="useCharts=true;">
<div class="row"> <div class="row">
@@ -17,9 +17,75 @@
<div class="row"> <div class="row">
<div class="col-sm-12"> <div class="col-sm-12">
<nvd3 options="fpsChart.options" data="fpsChart.data"></nvd3>
<div class="panel panel-default">
<div class="panel-heading" id="headingPerformance">
<button
class="btn btn-xs btn-primary pull-right"
role="button"
data-toggle="collapse"
data-target="#performanceCollapse"
aria-expanded="true"
aria-controls="performanceCollapse">
toggle
</button>
<h4 class="panel-title">
Server Performance
</h4>
</div>
<div id="performanceCollapse" class="panel-collapse collapse in" aria-labelledby="headingPerformance">
<div class="panel-body">
<nvd3 options="performanceChart.options" data="performanceChart.data"></nvd3>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading" id="headingNetwork">
<button
class="btn btn-xs btn-primary pull-right"
role="button"
data-toggle="collapse"
data-target="#networkCollapse"
aria-expanded="true"
aria-controls="networkCollapse">
toggle
</button>
<h4 class="panel-title">
Server Networking
</h4>
</div>
<div id="networkCollapse" class="panel-collapse collapse in" aria-labelledby="headingNetwork">
<div class="panel-body">
<nvd3 options="netChart.options" data="netChart.data"></nvd3> <nvd3 options="netChart.options" data="netChart.data"></nvd3>
</div> </div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading" id="headingPlayers">
<button
class="btn btn-xs btn-primary pull-right"
role="button"
data-toggle="collapse"
data-target="#playersCollapse"
aria-expanded="true"
aria-controls="playersCollapse">
toggle
</button>
<h4 class="panel-title">
Players
</h4>
</div>
<div id="playersCollapse" class="panel-collapse collapse in" aria-labelledby="headingPlayers">
<div class="panel-body">
<nvd3 options="playersChart.options" data="playersChart.data"></nvd3>
</div>
</div>
</div>
</div>
</div> </div>
+2 -2
View File
@@ -51,8 +51,8 @@
<!-- For charts --> <!-- For charts -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.16/d3.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.16/d3.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.2/nv.d3.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.1/nv.d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-nvd3/1.0.5/angular-nvd3.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-nvd3/1.0.9/angular-nvd3.min.js"></script>
<!-- Data manipulation --> <!-- Data manipulation -->
<script src="js/linq.min.js"></script> <script src="js/linq.min.js"></script>
+138 -43
View File
@@ -1,9 +1,10 @@
app.controller('ServerInfoController', ServerInfoController); app.controller('ServerInfoController', ServerInfoController);
function ServerInfoController($scope, rconService, $routeParams, $interval) { var DATA_LIMIT = 100;
var recordedData = [];
var fpsData = []; function ServerInfoController($scope, rconService, $routeParams, $interval) {
var netData = []; $scope.useCharts = false;
// TODO: move serverinfo to service // TODO: move serverinfo to service
$scope.serverinfo = {}; $scope.serverinfo = {};
@@ -11,43 +12,98 @@ function ServerInfoController($scope, rconService, $routeParams, $interval) {
$scope.playersChart = { $scope.playersChart = {
options: { options: {
chart: { chart: {
type: "pieChart", type: 'pieChart',
height: 400, height: 250,
margin: {
top: 0,
right: 75,
bottom: 0,
left: 75
},
donut: true,
x: function(d) { x: function(d) {
return d.key; return d.key;
}, },
y: function(d) { y: function(d) {
return d.value; return d.y;
}, },
showLabels: false yAxis: {
axisLabel: 'Slots',
tickFormat: function(d) {
return d3.format('.d')(d);
}
},
showLabels: true,
pie: {
startAngle: function(d) {
return d.startAngle / 2 - Math.PI / 2
},
endAngle: function(d) {
return d.endAngle / 2 - Math.PI / 2
}
},
duration: 500
} }
}, },
data: [] data: []
}; };
$scope.fpsChart = { $scope.performanceChart = {
options: { options: {
chart: { chart: {
type: 'lineChart', type: 'multiChart',
height: 200, height: 200,
y: function(d) { margin: {
return d.y; top: 30,
right: 75,
bottom: 40,
left: 75
},
color: [
'darkred', 'yellowgreen'
],
duration: 0,
lines1: {
duration: 0
},
lines2: {
duration: 0
}, },
useInteractiveGuideline: true, useInteractiveGuideline: true,
showXAxis: false, yAxis1: {
duration: 0, axisLabel: 'Framerate',
yAxis: {
axisLabel: 'FPS',
tickFormat: function(d) { tickFormat: function(d) {
return d3.format('.d')(d); return d3.format(',d')(d);
}
},
yAxis2: {
axisLabel: 'Entities',
tickFormat: function(d) {
return d3.format(',d')(d);
},
// axisLabelDistance: 12
},
xAxis: {
axisLabel: "Time",
tickFormat: function(d) {
return d3.time.format('%H:%M:%S')(new Date(d))
} }
} }
} }
}, },
data: [ data: [
{ {
values: [], key: 'Framerate',
key: 'FPS' type: "line",
duration: 0,
yAxis: 1,
values: []
}, {
key: 'Entities',
type: 'line',
duration: 0,
yAxis: 2,
values: []
} }
] ]
}; };
@@ -55,16 +111,36 @@ function ServerInfoController($scope, rconService, $routeParams, $interval) {
$scope.netChart = { $scope.netChart = {
options: { options: {
chart: { chart: {
"type": "stackedAreaChart", type: 'stackedAreaChart',
"height": 250, height: 250,
"useVoronoi": false, margin: {
"duration": 0, top: 0,
"useInteractiveGuideline": true, right: 75,
showXAxis: false, bottom: 40,
"yAxis": { left: 75
},
useVoronoi: false,
duration: 0,
useInteractiveGuideline: true,
yAxis: {
axisLabel: 'Network', axisLabel: 'Network',
tickFormat: function(bytes) {
var fmt = d3.format('.0f');
if (bytes < 1024) {
return fmt(bytes) + 'B';
} else if (bytes < 1024 * 1024) {
return fmt(bytes / 1024) + 'kB';
} else if (bytes < 1024 * 1024 * 1024) {
return fmt(bytes / 1024 / 1024) + 'MB';
} else {
return fmt(bytes / 1024 / 1024 / 1024) + 'GB';
}
}
},
xAxis: {
axisLabel: "Time",
tickFormat: function(d) { tickFormat: function(d) {
return d3.format('.d')(d) + 'kb'; return d3.time.format('%H:%M:%S')(new Date(d))
} }
} }
} }
@@ -98,37 +174,56 @@ function ServerInfoController($scope, rconService, $routeParams, $interval) {
function _updateData(data) { function _updateData(data) {
$scope.serverinfo = data; $scope.serverinfo = data;
$scope.playersChart.data.push({'players': data.Players, 'queued': data.Queued, 'joining': data.Joining}); if ($scope.useCharts) {
_collectChartData(data); _collectChartData(data);
_generateChartData(); _generateChartData();
} }
function _collectChartData(data) {
fpsData.push(data.Framerate);
if (fpsData.length > 100) {
fpsData.shift();
} }
netData.push({in: data.NetworkIn, out: data.NetworkOut}); function _collectChartData(data) {
if (netData.length > 100) { // player chart
netData.shift(); $scope.playersChart.data = [
{
key: 'Queued',
y: data.Queued
}, {
key: 'Joining',
y: data.Joining
}, {
key: 'Players',
y: data.Players
}, {
key: 'Free',
y: (data.MaxPlayers - (data.Joining + data.Players))
}
];
recordedData.push({ts: Date.now(), data: data});
if (recordedData.length > DATA_LIMIT) {
recordedData = recordedData.slice(Math.max(recordedData.length - DATA_LIMIT, 1));
} }
} }
function _generateChartData() { function _generateChartData() {
var fpsChartValues = []; var fpsChartValues = [];
for (var i = 0; i < fpsData.length; i++) { var entChartValues = [];
fpsChartValues.push({x: i, y: fpsData[i]});
}
$scope.fpsChart.data[0].values = fpsChartValues;
var netInChartValues = []; var netInChartValues = [];
var netOutChartValues = []; var netOutChartValues = [];
for (var i = 0; i < netData.length; i++) {
netInChartValues.push({x: i, y: netData[i]. in}); for (var i = 0; i < recordedData.length; i++) {
netOutChartValues.push({x: i, y: netData[i].out}); var record = recordedData[i];
fpsChartValues.push({x: record.ts, y: record.data.Framerate});
entChartValues.push({x: record.ts, y: record.data.EntityCount});
netInChartValues.push({x: record.ts, y: record.data.NetworkIn});
netOutChartValues.push({x: record.ts, y: record.data.NetworkOut});
} }
$scope.performanceChart.data[0].values = fpsChartValues;
$scope.performanceChart.data[1].values = entChartValues;
$scope.netChart.data[0].values = netInChartValues; $scope.netChart.data[0].values = netInChartValues;
$scope.netChart.data[1].values = netOutChartValues; $scope.netChart.data[1].values = netOutChartValues;
} }