@@ -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;
}