diff --git a/html/serverInfo.html b/html/serverInfo.html index 52c4180..ecdd567 100644 --- a/html/serverInfo.html +++ b/html/serverInfo.html @@ -1,4 +1,4 @@ -
+
@@ -17,8 +17,74 @@
- - + +
+
+ +

+ Server Performance +

+
+
+
+ +
+
+
+ +
+
+ + +

+ Server Networking +

+
+
+
+ +
+
+
+ +
+
+ +

+ Players +

+
+
+
+ +
+
+
+
diff --git a/index.html b/index.html index 761d301..76ecddf 100644 --- a/index.html +++ b/index.html @@ -51,8 +51,8 @@ - - + + diff --git a/js/serverInfo.js b/js/serverInfo.js index 08cb728..8dacc45 100644 --- a/js/serverInfo.js +++ b/js/serverInfo.js @@ -1,9 +1,10 @@ app.controller('ServerInfoController', ServerInfoController); -function ServerInfoController($scope, rconService, $routeParams, $interval) { +var DATA_LIMIT = 100; +var recordedData = []; - var fpsData = []; - var netData = []; +function ServerInfoController($scope, rconService, $routeParams, $interval) { + $scope.useCharts = false; // TODO: move serverinfo to service $scope.serverinfo = {}; @@ -11,43 +12,98 @@ function ServerInfoController($scope, rconService, $routeParams, $interval) { $scope.playersChart = { options: { chart: { - type: "pieChart", - height: 400, + type: 'pieChart', + height: 250, + margin: { + top: 0, + right: 75, + bottom: 0, + left: 75 + }, + donut: true, x: function(d) { return d.key; }, 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: [] }; - $scope.fpsChart = { + $scope.performanceChart = { options: { chart: { - type: 'lineChart', + type: 'multiChart', height: 200, - y: function(d) { - return d.y; + margin: { + top: 30, + right: 75, + bottom: 40, + left: 75 + }, + color: [ + 'darkred', 'yellowgreen' + ], + duration: 0, + lines1: { + duration: 0 + }, + lines2: { + duration: 0 }, useInteractiveGuideline: true, - showXAxis: false, - duration: 0, - yAxis: { - axisLabel: 'FPS', + yAxis1: { + axisLabel: 'Framerate', 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: [ { - values: [], - key: 'FPS' + key: 'Framerate', + 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 = { options: { chart: { - "type": "stackedAreaChart", - "height": 250, - "useVoronoi": false, - "duration": 0, - "useInteractiveGuideline": true, - showXAxis: false, - "yAxis": { + type: 'stackedAreaChart', + height: 250, + margin: { + top: 0, + right: 75, + bottom: 40, + left: 75 + }, + useVoronoi: false, + duration: 0, + useInteractiveGuideline: true, + yAxis: { 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) { - 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) { $scope.serverinfo = data; - $scope.playersChart.data.push({'players': data.Players, 'queued': data.Queued, 'joining': data.Joining}); - - _collectChartData(data); - _generateChartData(); + if ($scope.useCharts) { + _collectChartData(data); + _generateChartData(); + } } function _collectChartData(data) { - fpsData.push(data.Framerate); - if (fpsData.length > 100) { - fpsData.shift(); - } + // player chart + $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)) + } + ]; - netData.push({in: data.NetworkIn, out: data.NetworkOut}); - if (netData.length > 100) { - netData.shift(); + recordedData.push({ts: Date.now(), data: data}); + if (recordedData.length > DATA_LIMIT) { + recordedData = recordedData.slice(Math.max(recordedData.length - DATA_LIMIT, 1)); } } function _generateChartData() { + var fpsChartValues = []; - for (var i = 0; i < fpsData.length; i++) { - fpsChartValues.push({x: i, y: fpsData[i]}); - } - $scope.fpsChart.data[0].values = fpsChartValues; + var entChartValues = []; var netInChartValues = []; var netOutChartValues = []; - for (var i = 0; i < netData.length; i++) { - netInChartValues.push({x: i, y: netData[i]. in}); - netOutChartValues.push({x: i, y: netData[i].out}); + + for (var i = 0; i < recordedData.length; i++) { + 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[1].values = netOutChartValues; }