improve server clientcount/activity graph on server overview

This commit is contained in:
RaidMax
2022-03-29 16:42:53 -05:00
parent 31123d9a33
commit 180a4911bc
21 changed files with 5253 additions and 135 deletions

View File

@ -1,64 +1,163 @@
function getPlayerHistoryChart(playerHistory, i, width, color, maxClients) {
///////////////////////////////////////
// thanks to canvasjs :(
playerHistory.forEach(function (item, i) {
playerHistory[i].x = new Date(playerHistory[i].timeString);
playerHistory[i].y = playerHistory[i].clientCount;
function createDiagonalPattern(color = 'black') {
let shape = document.createElement('canvas');
shape.width = 10;
shape.height = 10;
let c = shape.getContext('2d');
c.strokeStyle = color;
c.beginPath();
c.moveTo(2, 0);
c.lineTo(10, 8);
c.stroke();
c.beginPath();
c.moveTo(0, 8);
c.lineTo(2, 10);
c.stroke();
return c.createPattern(shape, 'repeat');
}
function getPlayerHistoryChart(playerHistory, i, width, maxClients) {
const primaryColor = $('title').css('background-color');
const rgb = primaryColor.match(/\d+/g);
const fillColor = `rgba(${rgb[0]}, ${rgb[1]}, ${rgb[2]}, 0.66)`;
const offlineFillColor = 'rgba(255, 96, 96, 0.55)';
const onlineTime = [];
const offlineTime = [];
const mapChange = [];
let lastMap = '';
playerHistory.forEach((elem, i) => {
if (elem.map !== lastMap) {
mapChange.push(i);
lastMap = elem.map;
}
if (elem.connectionInterrupted) {
offlineTime.push({
clientCount: maxClients,
timeString: elem.timeString
});
onlineTime.push({
clientCount: 0,
timeString: elem.timeString
})
} else {
offlineTime.push({
clientCount: 0,
timeString: elem.timeString
});
onlineTime.push(elem)
}
});
return new CanvasJS.Chart(`server_history_${i}`, {
backgroundColor: '#191919',
height: 100,
width: width,
animationEnabled: true,
toolTip: {
contentFormatter: function (e) {
const date = moment.utc(e.entries[0].dataPoint.x);
return date.local().calendar() + " - " + e.entries[0].dataPoint.y + " players";
let animationProgress = 0;
let initialAnimationComplete = false;
const originalLineDraw = Chart.controllers.line.prototype.draw;
Chart.helpers.extend(Chart.controllers.line.prototype, {
draw: function () {
originalLineDraw.apply(this, arguments);
const chart = this.chart;
const ctx = chart.chart.ctx;
chart.config.data.lineAtIndexes.forEach((elem, index) => {
const xScale = chart.scales['x-axis-0'];
const yScale = chart.scales['y-axis-0'];
ctx.save();
ctx.beginPath();
ctx.moveTo(xScale.getPixelForValue(undefined, elem), yScale.getPixelForValue(playerHistory[elem].clientCount) / (initialAnimationComplete ? 1 : animationProgress));
ctx.strokeStyle = 'rgba(255, 255, 255, 0.1)';
ctx.lineTo(xScale.getPixelForValue(undefined, elem), yScale.bottom);
ctx.stroke();
ctx.restore();
});
}
});
const canvas = document.getElementById(`server_history_canvas_${i}`);
canvas.setAttribute('width', width);
return new Chart(document.getElementById(`server_history_canvas_${i}`), {
type: 'line',
data: {
labels: playerHistory.map(history => history.timeString),
datasets: [{
data: onlineTime.map(history => history.clientCount),
backgroundColor: fillColor,
borderColor: primaryColor,
borderWidth: 2,
hoverBorderColor: 'white',
hoverBorderWidth: 2
},
{
data: offlineTime.map(history => history.clientCount),
backgroundColor: createDiagonalPattern(offlineFillColor),
borderColor: offlineFillColor,
borderWidth: 2,
hoverBorderColor: 'white',
hoverBorderWidth: 2
}],
lineAtIndexes: mapChange,
},
options: {
responsive: true,
maintainAspectRatio: false,
onResize: function(chart, size) {
console.log(size);
},
legend: false,
defaultFontFamily: '-apple-system, BlinkMacSystemFont, "Open Sans", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"',
tooltips: {
callbacks: {
// todo: localization at some point
label: context => context.datasetIndex !== 1 ? `${context.value} players on ${playerHistory[context.index].mapAlias}` : context.value === '0' ? '' : 'Server Unreachable!',
title: context => context[0].datasetIndex !== 1 ? moment(context[0].label).local().calendar() : ''
},
mode: 'nearest',
intersect: false,
animationDuration: 0,
cornerRadius: 0,
displayColors: false
},
scales: {
xAxes: [{
display: false,
}],
yAxes: [{
display: false,
gridLines: {
display: false
},
ticks: {
max: 1,
min: maxClients + 2
}
}]
},
hover: {
mode: 'nearest',
intersect: false
},
elements: {
point: {
radius: 0
}
},
animation: {
duration: 1000,
onProgress: function (context) {
animationProgress = context.currentStep / context.numSteps;
if (animationProgress >= 1) {
initialAnimationComplete = true;
}
}
}
},
axisX: {
interval: 1,
gridThickness: 0,
lineThickness: 0,
tickThickness: 0,
margin: 0,
valueFormatString: " "
},
axisY: {
gridThickness: 0,
lineThickness: 0,
tickThickness: 0,
minimum: 0,
maximum: maxClients + 1,
margin: 0,
valueFormatString: " ",
labelMaxWidth: 0
},
legend: {
maxWidth: 0,
maxHeight: 0,
dockInsidePlotArea: true
},
data: [{
showInLegend: false,
type: "splineArea",
color: color,
markerSize: 0,
dataPoints: playerHistory
}]
});
//////////////////////////////////////
}
var charts = {};
$(window).resize(function () {
$('.server-history-row').each(function (index) {
let serverId = $(this).data('serverid');
charts[serverId].options.width = $('.server-header').first().width();
charts[serverId].render();
});
});
function refreshClientActivity() {
$('.server-history-row').each(function (index) {
@ -88,17 +187,13 @@ $(document).ready(function () {
let clientHistory = $(this).data('clienthistory-ex');
let serverId = $(this).data('serverid');
let maxClients = parseInt($('#server_header_' + serverId + ' .server-maxclients').text());
let primaryColor = $('title').css('background-color');
let color = $(this).data('online') === 'True' ? primaryColor : '#ff6060';
let width = $('.server-header').first().width();
let historyChart = getPlayerHistoryChart(clientHistory, serverId, width, color, maxClients);
historyChart.render();
charts[serverId] = historyChart;
getPlayerHistoryChart(clientHistory, serverId, width, maxClients);
});
$('.moment-date').each((index, element) => {
const title = $(element).attr('title');
if (title !== undefined) {
const date = new Date(title);
$(element).attr('title', moment.utc(date).calendar());