2015-11-09 00:34:17 +00:00
|
|
|
var smallChartOptions = {
|
|
|
|
series: {
|
|
|
|
shadowSize: 0
|
|
|
|
},
|
|
|
|
xaxis: {
|
|
|
|
font: {
|
|
|
|
color: "#E3E3E3"
|
|
|
|
},
|
|
|
|
show: false
|
|
|
|
},
|
|
|
|
yaxis: {
|
2015-11-09 07:03:03 +00:00
|
|
|
minTickSize: 75,
|
2015-11-09 00:34:17 +00:00
|
|
|
tickDecimals: 0,
|
|
|
|
show: true,
|
|
|
|
tickLength: 10,
|
|
|
|
tickFormatter: function(value) {
|
|
|
|
return formatNumber(value);
|
|
|
|
},
|
|
|
|
font: {
|
|
|
|
color: "#E3E3E3"
|
|
|
|
},
|
|
|
|
labelWidth: -10
|
|
|
|
},
|
|
|
|
grid: {
|
|
|
|
hoverable: true,
|
2015-11-09 07:03:03 +00:00
|
|
|
color: "#696969"
|
2015-11-09 00:34:17 +00:00
|
|
|
},
|
|
|
|
colors: [
|
|
|
|
"#E9E581"
|
|
|
|
]
|
|
|
|
};
|
|
|
|
|
2015-12-18 07:45:38 +00:00
|
|
|
var bigChartOptions = {
|
|
|
|
series: {
|
|
|
|
shadowSize: 0
|
|
|
|
},
|
|
|
|
xaxis: {
|
|
|
|
font: {
|
|
|
|
color: "#E3E3E3"
|
|
|
|
},
|
|
|
|
show: false
|
|
|
|
},
|
|
|
|
yaxis: {
|
|
|
|
show: true,
|
|
|
|
tickLength: 10,
|
|
|
|
tickFormatter: function(value) {
|
|
|
|
return formatNumber(value);
|
|
|
|
},
|
|
|
|
font: {
|
|
|
|
color: "#E3E3E3"
|
|
|
|
},
|
|
|
|
labelWidth: -5
|
|
|
|
},
|
|
|
|
grid: {
|
|
|
|
hoverable: true,
|
|
|
|
color: "#696969"
|
|
|
|
},
|
|
|
|
legend: {
|
|
|
|
show: false
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-11-25 22:40:13 +00:00
|
|
|
var lastMojangServiceUpdate;
|
|
|
|
|
2015-11-09 00:34:17 +00:00
|
|
|
var graphs = {};
|
|
|
|
var lastLatencyEntries = {};
|
|
|
|
var lastPlayerEntries = {};
|
|
|
|
|
|
|
|
// Generate (and set) the HTML that displays Mojang status.
|
|
|
|
function updateMojangServices() {
|
2015-11-09 07:03:03 +00:00
|
|
|
if (!lastMojangServiceUpdate) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-11-09 00:34:17 +00:00
|
|
|
var keys = Object.keys(lastMojangServiceUpdate);
|
|
|
|
var newStatus = 'Mojang Services: ';
|
|
|
|
var serviceCountByType = {
|
|
|
|
Online: 0,
|
|
|
|
Unstable: 0,
|
|
|
|
Offline: 0
|
|
|
|
};
|
|
|
|
|
|
|
|
for (var i = 0; i < keys.length; i++) {
|
|
|
|
var entry = lastMojangServiceUpdate[keys[i]];
|
|
|
|
|
|
|
|
serviceCountByType[entry.title] += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (serviceCountByType['Online'] === keys.length) {
|
|
|
|
$('#tagline').attr('class', 'status-online');
|
2015-11-26 01:09:17 +00:00
|
|
|
|
2015-11-09 00:34:17 +00:00
|
|
|
newStatus += 'All systems operational.';
|
|
|
|
} else {
|
|
|
|
if (serviceCountByType['Unstable'] > serviceCountByType['Offline']) {
|
|
|
|
$('#tagline').attr('class', 'status-unstable');
|
|
|
|
} else {
|
|
|
|
$('#tagline').attr('class', 'status-offline');
|
|
|
|
}
|
|
|
|
|
|
|
|
for (var i = 0; i < keys.length; i++) {
|
|
|
|
var entry = lastMojangServiceUpdate[keys[i]];
|
|
|
|
|
|
|
|
if (entry.startTime) {
|
2015-12-14 23:17:34 +00:00
|
|
|
newStatus += entry.name + ' ' + entry.title.toLowerCase() + ' for ' + msToTime((new Date()).getTime() - entry.startTime + ' ');
|
2015-11-09 00:34:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$('#tagline-text').text(newStatus);
|
|
|
|
}
|
|
|
|
|
2015-11-09 07:03:03 +00:00
|
|
|
function findErrorMessage(error) {
|
|
|
|
if (error.description) {
|
|
|
|
return error.description;
|
|
|
|
} else if (error.errno) {
|
|
|
|
return error.errno;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-09 00:34:17 +00:00
|
|
|
function updateServerStatus(lastEntry) {
|
|
|
|
var info = lastEntry.info;
|
|
|
|
var div = $('#status_' + safeName(info.name));
|
|
|
|
|
|
|
|
if (lastEntry.result) {
|
|
|
|
var result = lastEntry.result;
|
2015-11-09 07:38:18 +00:00
|
|
|
var newStatus = '<br />Players: ' + formatNumber(result.players.online);
|
2015-11-09 07:03:03 +00:00
|
|
|
|
|
|
|
var listing = graphs[lastEntry.info.name].listing;
|
2015-11-09 00:34:17 +00:00
|
|
|
|
2015-11-09 07:03:03 +00:00
|
|
|
if (listing.length > 0) {
|
2015-11-09 00:34:17 +00:00
|
|
|
newStatus += '<span class="color-gray"> (';
|
|
|
|
|
2015-11-09 07:03:03 +00:00
|
|
|
var playerDifference = listing[listing.length - 1][1] - listing[0][1];
|
2015-11-09 00:34:17 +00:00
|
|
|
|
|
|
|
if (playerDifference >= 0) {
|
|
|
|
newStatus += '+';
|
|
|
|
}
|
|
|
|
|
|
|
|
newStatus += playerDifference + ')</span>';
|
|
|
|
}
|
|
|
|
|
2015-11-09 07:38:18 +00:00
|
|
|
/*if (lastLatencyEntries[info.name]) {
|
2015-11-09 00:34:17 +00:00
|
|
|
newStatus += '<br />';
|
|
|
|
|
|
|
|
var latencyDifference = lastLatencyEntries[info.name] - result.latency;
|
|
|
|
|
|
|
|
if (latencyDifference >= 0) {
|
|
|
|
newStatus += '+';
|
|
|
|
}
|
|
|
|
|
|
|
|
newStatus += latencyDifference + 'ms';
|
2015-11-09 07:38:18 +00:00
|
|
|
}*/
|
2015-11-09 00:34:17 +00:00
|
|
|
|
|
|
|
lastPlayerEntries[info.name] = result.players.online;
|
|
|
|
lastLatencyEntries[info.name] = result.latency;
|
|
|
|
|
|
|
|
div.html(newStatus);
|
2015-11-09 07:03:03 +00:00
|
|
|
} else {
|
2015-11-24 23:34:28 +00:00
|
|
|
var newStatus = '<br /><span class="color-red">';
|
2015-11-09 07:03:03 +00:00
|
|
|
|
|
|
|
if (findErrorMessage(lastEntry.error)) {
|
2015-11-24 23:34:28 +00:00
|
|
|
newStatus += findErrorMessage(lastEntry.error);
|
|
|
|
} else {
|
|
|
|
newStatus += 'Failed to ping!';
|
2015-11-09 07:03:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
div.html(newStatus + '</span>');
|
|
|
|
}
|
2015-11-30 20:00:47 +00:00
|
|
|
|
|
|
|
var keys = Object.keys(lastPlayerEntries);
|
|
|
|
var totalPlayers = 0;
|
|
|
|
|
|
|
|
for (var i = 0; i < keys.length; i++) {
|
|
|
|
totalPlayers += lastPlayerEntries[keys[i]];
|
|
|
|
}
|
|
|
|
|
|
|
|
$("#stat_totalPlayers").text(formatNumber(totalPlayers));
|
|
|
|
$("#stat_networks").text(formatNumber(keys.length));
|
2015-11-09 07:03:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function sortServers() {
|
|
|
|
var keys = Object.keys(lastPlayerEntries);
|
|
|
|
var nameList = [];
|
|
|
|
|
|
|
|
keys.sort(function(a, b) {
|
|
|
|
return lastPlayerEntries[b] - lastPlayerEntries[a];
|
|
|
|
});
|
|
|
|
|
|
|
|
keys.reverse();
|
|
|
|
|
|
|
|
for (var i = 0; i < keys.length; i++) {
|
|
|
|
$('#' + safeName(keys[i])).prependTo('#server-container');
|
|
|
|
|
|
|
|
$('#ranking_' + safeName(keys[i])).text('#' + (keys.length - i));
|
2015-11-09 00:34:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function safeName(name) {
|
2015-11-25 22:40:13 +00:00
|
|
|
return name.replace(/ /g, '');
|
2015-11-09 00:34:17 +00:00
|
|
|
}
|
|
|
|
|
2015-12-18 07:45:38 +00:00
|
|
|
function handlePlotHover(event, pos, item) {
|
|
|
|
if (item) {
|
|
|
|
var text = getTimestamp(item.datapoint[0] / 1000) + '\
|
|
|
|
<br />\
|
|
|
|
' + formatNumber(item.datapoint[1]) + ' Players';
|
|
|
|
|
|
|
|
if (item.series && item.series.label) {
|
|
|
|
text = item.series.label + '<br />' + text;
|
|
|
|
}
|
|
|
|
|
|
|
|
renderTooltip(item.pageX + 5, item.pageY + 5, text);
|
|
|
|
} else {
|
|
|
|
hideTooltip();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function convertGraphData(rawData) {
|
|
|
|
var data = [];
|
|
|
|
|
|
|
|
var keys = Object.keys(rawData);
|
|
|
|
|
|
|
|
for (var i = 0; i < keys.length; i++) {
|
|
|
|
data.push({
|
|
|
|
data: rawData[keys[i]],
|
|
|
|
yaxis: 1,
|
|
|
|
label: keys[i]
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
2015-11-02 05:19:27 +00:00
|
|
|
$(document).ready(function() {
|
2015-11-26 06:32:20 +00:00
|
|
|
var socket = io.connect({
|
2015-12-01 00:12:26 +00:00
|
|
|
reconnect: true,
|
|
|
|
reconnectDelay: 1000,
|
|
|
|
reconnectionAttempts: 10
|
2015-11-26 06:32:20 +00:00
|
|
|
});
|
2015-11-25 22:40:13 +00:00
|
|
|
|
2015-11-09 00:34:17 +00:00
|
|
|
var mojangServicesUpdater;
|
2015-11-25 22:40:13 +00:00
|
|
|
var sortServersTask;
|
2015-11-02 05:19:27 +00:00
|
|
|
|
2015-12-18 07:45:38 +00:00
|
|
|
var historyPlot;
|
|
|
|
var historyData;
|
|
|
|
|
2015-11-02 05:19:27 +00:00
|
|
|
socket.on('connect', function() {
|
2015-11-09 00:34:17 +00:00
|
|
|
$('#tagline-text').text('Loading...');
|
2015-11-02 05:19:27 +00:00
|
|
|
});
|
2015-11-02 05:46:24 +00:00
|
|
|
|
2015-11-09 00:34:17 +00:00
|
|
|
socket.on('disconnect', function() {
|
|
|
|
if (mojangServicesUpdater) {
|
|
|
|
clearInterval(mojangServicesUpdater);
|
|
|
|
}
|
|
|
|
|
2015-11-25 22:40:13 +00:00
|
|
|
if (sortServersTask) {
|
|
|
|
clearInterval(sortServersTask);
|
|
|
|
}
|
|
|
|
|
2015-11-09 07:03:03 +00:00
|
|
|
$('#tagline').attr('class', 'status-offline');
|
|
|
|
$('#tagline-text').text('Disconnected! Refresh?');
|
2015-11-09 00:34:17 +00:00
|
|
|
|
|
|
|
lastPlayerEntries = {};
|
|
|
|
lastLatencyEntries = {};
|
|
|
|
graphs = {};
|
|
|
|
|
|
|
|
$('#server-container').html('');
|
2015-11-25 22:40:13 +00:00
|
|
|
$('#quick-jump-container').html('');
|
2015-11-09 00:34:17 +00:00
|
|
|
});
|
|
|
|
|
2015-12-18 07:45:38 +00:00
|
|
|
socket.on('historyGraph', function(rawData) {
|
|
|
|
historyData = rawData;
|
|
|
|
|
|
|
|
historyPlot = $.plot('#big-graph', convertGraphData(rawData), bigChartOptions);
|
|
|
|
|
|
|
|
$('#big-graph').bind('plothover', handlePlotHover);
|
|
|
|
});
|
|
|
|
|
|
|
|
socket.on('updateHistoryGraph', function(rawData) {
|
|
|
|
if (historyData[rawData.ip].length > 24 * 60) {
|
|
|
|
historyData[rawData.ip].shift();
|
|
|
|
}
|
|
|
|
|
|
|
|
historyData[rawData.ip].push([rawData.timestamp, rawData.players]);
|
|
|
|
|
|
|
|
historyPlot.setData(convertGraphData(historyData));
|
|
|
|
historyPlot.setupGrid();
|
|
|
|
|
|
|
|
historyPlot.draw();
|
|
|
|
});
|
|
|
|
|
2015-11-02 05:46:24 +00:00
|
|
|
socket.on('add', function(servers) {
|
2015-11-09 00:34:17 +00:00
|
|
|
for (var i = 0; i < servers.length; i++) {
|
|
|
|
var history = servers[i];
|
|
|
|
var listing = [];
|
|
|
|
|
|
|
|
for (var x = 0; x < history.length; x++) {
|
|
|
|
var point = history[x];
|
|
|
|
|
|
|
|
if (point.result) {
|
|
|
|
listing.push([point.timestamp, point.result.players.online]);
|
|
|
|
} else if (point.error) {
|
|
|
|
listing.push([point.timestamp, 0]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var lastEntry = history[history.length - 1];
|
|
|
|
var info = lastEntry.info;
|
|
|
|
|
2015-11-09 07:03:03 +00:00
|
|
|
if (lastEntry.error) {
|
|
|
|
lastPlayerEntries[info.name] = 0;
|
|
|
|
lastLatencyEntries[info.name] = 0;
|
|
|
|
} else if (lastEntry.result) {
|
|
|
|
lastPlayerEntries[info.name] = lastEntry.result.players.online;
|
|
|
|
lastLatencyEntries[info.name] = lastEntry.result.latency;
|
|
|
|
}
|
|
|
|
|
2015-11-09 00:34:17 +00:00
|
|
|
$('<div/>', {
|
|
|
|
id: safeName(info.name),
|
|
|
|
class: 'server',
|
2015-11-25 22:40:13 +00:00
|
|
|
html: '<div id="server-' + safeName(info.name) + '" class="column" style="width: 80px;">\
|
2015-12-04 22:26:07 +00:00
|
|
|
<img id="favicon_' + safeName(info.name) + '">\
|
2015-11-09 07:03:03 +00:00
|
|
|
<br />\
|
2015-12-04 22:26:07 +00:00
|
|
|
<p class="text-center-align rank" id="ranking_' + safeName(info.name) + '"></p>\
|
2015-11-09 00:34:17 +00:00
|
|
|
</div>\
|
2015-11-26 01:32:39 +00:00
|
|
|
<div class="column" style="width: 280px;">\
|
|
|
|
<h3>' + info.name + ' <span class="type">' + info.type + '</span></h3>\
|
2015-11-09 00:34:17 +00:00
|
|
|
<span class="color-gray">' + info.ip + '</span>\
|
|
|
|
<br />\
|
|
|
|
<span id="status_' + safeName(info.name) + '">Waiting</span>\
|
|
|
|
</div>\
|
|
|
|
<div class="column" style="float: right;">\
|
|
|
|
<div class="chart" id="chart_' + safeName(info.name) + '"></div>\
|
|
|
|
</div>'
|
|
|
|
}).appendTo("#server-container");
|
|
|
|
|
2015-11-09 00:45:18 +00:00
|
|
|
var favicon = MISSING_FAVICON_BASE64;
|
|
|
|
|
2015-11-09 00:34:17 +00:00
|
|
|
if (lastEntry.result && lastEntry.result.favicon) {
|
2015-11-09 00:45:18 +00:00
|
|
|
favicon = lastEntry.result.favicon;
|
2015-11-09 00:34:17 +00:00
|
|
|
}
|
2015-11-02 05:46:24 +00:00
|
|
|
|
2015-11-09 00:45:18 +00:00
|
|
|
$('#favicon_' + safeName(info.name)).attr('src', favicon);
|
|
|
|
|
2015-11-26 01:36:41 +00:00
|
|
|
$('#quick-jump-container').append('<img id="quick-jump-' + safeName(info.name) + '" data-target-network="' + safeName(info.name) + '" title="' + info.name + '" alt="' + info.name + '" class="quick-jump-icon" src="' + favicon + '">');
|
2015-11-25 22:40:13 +00:00
|
|
|
|
2015-11-09 00:34:17 +00:00
|
|
|
graphs[lastEntry.info.name] = {
|
|
|
|
listing: listing,
|
|
|
|
plot: $.plot('#chart_' + safeName(info.name), [listing], smallChartOptions)
|
|
|
|
};
|
|
|
|
|
2015-11-09 07:03:03 +00:00
|
|
|
updateServerStatus(lastEntry);
|
|
|
|
|
2015-12-18 07:45:38 +00:00
|
|
|
$('#chart_' + safeName(info.name)).bind('plothover', handlePlotHover);
|
2015-11-09 00:34:17 +00:00
|
|
|
}
|
2015-11-09 07:03:03 +00:00
|
|
|
|
|
|
|
sortServers();
|
2015-11-09 00:34:17 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
socket.on('update', function(update) {
|
2015-11-09 07:03:03 +00:00
|
|
|
// Prevent weird race conditions.
|
|
|
|
if (!graphs[update.info.name]) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We have a new favicon, update the old one.
|
|
|
|
if (update.result && update.result.favicon) {
|
|
|
|
$('#favicon_' + safeName(update.info.name)).attr('src', update.result.favicon);
|
2015-11-25 22:40:13 +00:00
|
|
|
$('#quick-jump-' + safeName(update.info.name)).attr('src', update.result.favicon);
|
2015-11-09 07:03:03 +00:00
|
|
|
}
|
|
|
|
|
2015-11-09 00:34:17 +00:00
|
|
|
var graph = graphs[update.info.name];
|
|
|
|
|
|
|
|
updateServerStatus(update);
|
|
|
|
|
2015-11-09 22:33:56 +00:00
|
|
|
if (update.result) {
|
|
|
|
graph.listing.push([update.info.timestamp, update.result ? update.result.players.online : 0]);
|
2015-11-09 00:34:17 +00:00
|
|
|
|
2015-11-09 22:33:56 +00:00
|
|
|
if (graph.listing.length > 72) {
|
|
|
|
graph.listing.shift();
|
|
|
|
}
|
2015-11-09 00:34:17 +00:00
|
|
|
|
2015-11-09 22:33:56 +00:00
|
|
|
graph.plot.setData([graph.listing]);
|
|
|
|
graph.plot.setupGrid();
|
2015-11-09 00:34:17 +00:00
|
|
|
|
2015-11-09 22:33:56 +00:00
|
|
|
graph.plot.draw();
|
|
|
|
}
|
2015-11-02 05:46:24 +00:00
|
|
|
});
|
|
|
|
|
2015-11-09 00:34:17 +00:00
|
|
|
socket.on('updateMojangServices', function(data) {
|
|
|
|
// Store the update and force an update.
|
|
|
|
lastMojangServiceUpdate = data;
|
2015-11-02 05:46:24 +00:00
|
|
|
|
2015-11-09 00:34:17 +00:00
|
|
|
updateMojangServices();
|
2015-11-02 05:46:24 +00:00
|
|
|
});
|
2015-11-09 00:34:17 +00:00
|
|
|
|
|
|
|
// Start any special updating tasks.
|
|
|
|
mojangServicesUpdater = setInterval(function() {
|
|
|
|
updateMojangServices();
|
|
|
|
}, 1000);
|
2015-11-09 07:03:03 +00:00
|
|
|
|
2015-11-25 22:40:13 +00:00
|
|
|
sortServersTask = setInterval(function() {
|
2015-11-09 07:03:03 +00:00
|
|
|
sortServers();
|
2015-12-18 07:45:38 +00:00
|
|
|
}, 10 * 1000);
|
2015-11-25 22:40:13 +00:00
|
|
|
|
|
|
|
// Our super fancy scrolly thing!
|
|
|
|
$(document).on('click', '.quick-jump-icon', function(e) {
|
|
|
|
var serverName = $(this).attr('data-target-network');
|
|
|
|
var target = $('#server-' + serverName);
|
|
|
|
|
|
|
|
$('html, body').animate({
|
|
|
|
scrollTop: target.offset().top
|
|
|
|
}, 100);
|
|
|
|
});
|
2015-11-26 01:09:17 +00:00
|
|
|
});
|