2022-03-29 17:42:53 -04:00
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 )
}
2018-02-21 20:29:23 -05:00
} ) ;
2022-03-29 17:42:53 -04:00
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 ,
2018-02-21 20:29:23 -05:00
} ,
2022-03-29 17:42:53 -04:00
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 ;
}
}
}
2018-02-21 20:29:23 -05:00
} ,
} ) ;
}
function refreshClientActivity ( ) {
$ ( '.server-history-row' ) . each ( function ( index ) {
let serverId = $ ( this ) . data ( "serverid" ) ;
2018-02-22 01:06:21 -05:00
$ . get ( {
url : "/server/clientactivity/" + serverId ,
cache : false
} )
2018-02-21 20:29:23 -05:00
. done ( function ( response ) {
2019-08-04 18:06:07 -04:00
const clientCount = $ ( response ) . find ( 'a' ) . length ;
2018-03-27 20:27:01 -04:00
$ ( '#server_header_' + serverId + ' .server-clientcount' ) . text ( clientCount ) ;
2018-02-21 20:29:23 -05:00
$ ( '#server_clientactivity_' + serverId ) . html ( response ) ;
} )
. fail ( function ( jqxhr , textStatus , error ) {
2019-05-17 10:02:09 -04:00
$ ( '#server_clientactivity_' + serverId ) . html ( '' ) ;
2018-02-21 20:29:23 -05:00
} ) ;
} ) ;
}
2019-07-19 15:54:39 -04:00
$ ( document ) . ready ( function ( ) {
2019-04-08 13:29:48 -04:00
$ ( '.server-join-button' ) . click ( function ( e ) {
$ ( this ) . children ( '.server-header-ip-address' ) . show ( ) ;
} ) ;
2019-08-10 18:35:34 -04:00
$ ( '.server-history-row' ) . each ( function ( index , element ) {
2021-08-29 14:10:10 -04:00
let clientHistory = $ ( this ) . data ( 'clienthistory-ex' ) ;
2019-08-10 18:35:34 -04:00
let serverId = $ ( this ) . data ( 'serverid' ) ;
let maxClients = parseInt ( $ ( '#server_header_' + serverId + ' .server-maxclients' ) . text ( ) ) ;
let width = $ ( '.server-header' ) . first ( ) . width ( ) ;
2022-03-29 17:42:53 -04:00
getPlayerHistoryChart ( clientHistory , serverId , width , maxClients ) ;
2019-08-10 18:35:34 -04:00
} ) ;
2022-03-29 17:42:53 -04:00
2021-09-14 19:12:20 -04:00
$ ( '.moment-date' ) . each ( ( index , element ) => {
const title = $ ( element ) . attr ( 'title' ) ;
2022-03-29 17:42:53 -04:00
2021-09-14 19:12:20 -04:00
if ( title !== undefined ) {
const date = new Date ( title ) ;
$ ( element ) . attr ( 'title' , moment . utc ( date ) . calendar ( ) ) ;
}
} ) ;
2019-07-19 15:54:39 -04:00
} ) ;
2019-04-08 13:29:48 -04:00
2018-04-02 23:11:19 -04:00
setInterval ( refreshClientActivity , 2000 ) ;