Minetrack/assets/js/site.js

562 lines
17 KiB
JavaScript
Raw Normal View History

var graphs = [];
var lastPlayerEntries = [];
2015-11-09 00:34:17 +00:00
2015-12-19 00:33:43 +00:00
var historyPlot;
var displayedGraphData;
var hiddenGraphData = [];
var isConnected = false;
var mojangServicesUpdater;
var sortServersTask;
2017-03-12 00:52:07 +00:00
var currentServerHover;
var faviconSize = 64;
2017-03-12 00:52:07 +00:00
2015-11-09 00:34:17 +00:00
function updateServerStatus(lastEntry) {
var info = lastEntry.info;
2016-03-06 07:27:47 +00:00
2015-11-09 00:34:17 +00:00
var div = $('#status_' + safeName(info.name));
var versionDiv = $('#version_' + safeName(info.name));
if (lastEntry.versions) {
var versions = '';
2016-03-06 07:27:47 +00:00
for (var i = 0; i < lastEntry.versions.length; i++) {
if (!lastEntry.versions[i]) continue;
2017-03-11 23:44:21 +00:00
versions += '<span class="version">' + publicConfig.minecraftVersions[lastEntry.info.type][lastEntry.versions[i]] + '</span>&nbsp;';
}
2016-03-06 07:27:47 +00:00
versionDiv.html(versions);
} else {
versionDiv.html('');
}
2015-11-09 00:34:17 +00:00
if (lastEntry.result) {
var result = lastEntry.result;
var newStatus = 'Players: <span style="font-weight: 500;">' + formatNumber(result.players.online) + '</span>';
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>';
}
lastPlayerEntries[info.name] = result.players.online;
div.html(newStatus);
2015-11-09 07:03:03 +00:00
} else {
var newStatus = '<span class="color-red">';
2015-11-09 07:03:03 +00:00
if (findErrorMessage(lastEntry.error)) {
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));
2017-03-11 23:44:21 +00:00
if (lastEntry.record) {
$('#record_' + safeName(info.name)).html('Record: ' + formatNumber(lastEntry.record));
}
2017-03-12 00:52:07 +00:00
updatePercentageBar();
2015-11-09 07:03:03 +00:00
}
function sortServers() {
if (categoriesVisible) {
var byCategories = getServersByCategory();
var categories = Object.keys(byCategories);
for (var i = 0; i < categories.length; i++) {
var relevantPlayers = [];
for (var x = 0; x < byCategories[categories[i]].length; x++) {
var server = byCategories[categories[i]][x];
relevantPlayers[server.name] = lastPlayerEntries[server.name];
}
2015-11-09 07:03:03 +00:00
var keys = Object.keys(relevantPlayers);
2015-11-09 07:03:03 +00:00
keys.sort(function(a, b) {
return relevantPlayers[b] - relevantPlayers[a];
});
2015-11-09 07:03:03 +00:00
for (var x = 0; x < keys.length; x++) {
2017-03-14 22:07:58 +00:00
$('#container_' + safeName(keys[x])).appendTo('#server-container-' + categories[i]);
$('#ranking_' + safeName(keys[x])).text('#' + (x + 1));
}
2016-02-06 23:34:33 +00:00
}
} else {
var serverNames = [];
var keys = Object.keys(lastPlayerEntries);
2016-02-06 23:34:33 +00:00
for (var i = 0; i < keys.length; i++) {
serverNames.push(keys[i]);
}
2016-02-06 23:34:33 +00:00
serverNames.sort(function(a, b) {
return (lastPlayerEntries[b] || 0) - (lastPlayerEntries[a] || 0);
2016-02-06 23:34:33 +00:00
});
2015-11-09 07:03:03 +00:00
for (var i = 0; i < serverNames.length; i++) {
2017-03-14 22:07:58 +00:00
$('#container_' + safeName(serverNames[i])).appendTo('#server-container-all');
$('#ranking_' + safeName(serverNames[i])).text('#' + (i + 1));
2016-02-06 23:34:33 +00:00
}
2015-11-09 00:34:17 +00:00
}
}
2017-03-12 00:52:07 +00:00
function updatePercentageBar() {
var keys = Object.keys(lastPlayerEntries);
keys.sort(function(a, b) {
return lastPlayerEntries[a] - lastPlayerEntries[b];
});
var totalPlayers = getCurrentTotalPlayers();
var parent = $('#perc-bar');
var leftPadding = 0;
for (var i = 0; i < keys.length; i++) {
(function(pos, server, length) {
var safeNameCopy = safeName(server);
var playerCount = lastPlayerEntries[server];
var div = $('#perc_bar_part_' + safeNameCopy);
// Setup the base
if (!div.length) {
$('<div/>', {
id: 'perc_bar_part_' + safeNameCopy,
class: 'perc-bar-part',
html: '',
2017-04-04 03:10:46 +00:00
style: 'background: ' + getServerColor(server) + ';'
2017-03-12 00:52:07 +00:00
}).appendTo(parent);
div = $('#perc_bar_part_' + safeNameCopy);
div.mouseover(function(e) {
currentServerHover = server;
});
div.mouseout(function(e) {
2017-03-15 02:14:26 +00:00
hideTooltip();
2017-03-12 00:52:07 +00:00
currentServerHover = undefined;
});
}
// Update our position/width
var width = (playerCount / totalPlayers) * parent.width();
div.css({
width: width + 'px',
2017-03-14 22:07:58 +00:00
left: leftPadding + 'px'
2017-03-12 00:52:07 +00:00
});
leftPadding += width;
})(i, keys[i], keys.length);
}
}
function getCurrentTotalPlayers() {
var totalPlayers = 0;
var keys = Object.keys(lastPlayerEntries);
for (var i = 0; i < keys.length; i++) totalPlayers += lastPlayerEntries[keys[i]]
return totalPlayers;
}
2015-12-19 00:33:43 +00:00
function setAllGraphVisibility(visible) {
if (visible) {
var keys = Object.keys(hiddenGraphData);
for (var i = 0; i < keys.length; i++) {
displayedGraphData[keys[i]] = hiddenGraphData[keys[i]];
}
hiddenGraphData = [];
} else {
var keys = Object.keys(displayedGraphData);
for (var i = 0; i < keys.length; i++) {
hiddenGraphData[keys[i]] = displayedGraphData[keys[i]];
}
displayedGraphData = [];
}
$('.graph-control').each(function(index, item) {
item.checked = visible;
});
historyPlot.setData(convertGraphData(displayedGraphData));
historyPlot.setupGrid();
historyPlot.draw();
2016-02-01 11:21:46 +00:00
// Update our localStorage
2016-02-01 11:23:42 +00:00
if (visible) {
resetGraphControls();
} else {
saveGraphControls(Object.keys(displayedGraphData));
}
2015-12-19 00:33:43 +00:00
}
function validateBootTime(bootTime, socket) {
$('#tagline-text').text('Validating...');
console.log('Remote bootTime is ' + bootTime + ', local is ' + publicConfig.bootTime);
if (bootTime === publicConfig.bootTime) {
$('#tagline-text').text('Loading...');
socket.emit('requestListing');
if (!isMobileBrowser()) socket.emit('requestHistoryGraph');
isConnected = true;
// Start any special updating tasks.
mojangServicesUpdater = setInterval(updateMojangServices, 1000);
sortServersTask = setInterval(sortServers, 10000);
} else {
$('#tagline-text').text('Updating...');
$.getScript('/publicConfig.json', function(data, textStatus, xhr) {
if (xhr.status === 200) {
validateBootTime(publicConfig.bootTime, socket);
} else {
2017-03-14 22:07:58 +00:00
showCaption('Failed to update! Refresh?');
}
});
}
}
function printPort(port) {
if(port == undefined || port == 25565) {
return "";
} else {
return ":" + port;
}
}
2020-03-30 05:37:49 +00:00
function updateServerPeak(name, time, playerCount) {
var safeNameCopy = safeName(name);
// hack: strip the AM/PM suffix, this could just use a date format instead
var timestamp = getTimestamp(time / 1000).split(':');
var end = timestamp.pop().split(' ')[1];
timestamp = timestamp.join(':') + ' ' + end;
$('#peak_' + safeNameCopy).html('24h Peak: ' + formatNumber(playerCount) + ' @ ' + timestamp);
}
$(document).ready(function() {
var socket = io.connect({
2015-12-01 00:12:26 +00:00
reconnect: true,
reconnectDelay: 1000,
reconnectionAttempts: 10
});
socket.on('bootTime', function(bootTime) {
validateBootTime(bootTime, socket);
});
2015-11-02 05:46:24 +00:00
2015-11-09 00:34:17 +00:00
socket.on('disconnect', function() {
if (mojangServicesUpdater) clearInterval(mojangServicesUpdater);
if (sortServersTask) clearInterval(sortServersTask);
2017-03-11 23:44:21 +00:00
lastMojangServiceUpdate = undefined;
2017-03-14 22:07:58 +00:00
showCaption('Disconnected! Refresh?');
2015-11-09 00:34:17 +00:00
lastPlayerEntries = {};
graphs = {};
2016-02-06 23:34:33 +00:00
$('#server-container-list').html('');
createdCategories = false;
2015-12-19 00:49:18 +00:00
2015-12-18 08:47:35 +00:00
$('#big-graph').html('');
2015-12-19 00:33:43 +00:00
$('#big-graph-checkboxes').html('');
2015-12-19 00:49:18 +00:00
$('#big-graph-controls').css('display', 'none');
2017-03-15 02:14:26 +00:00
$('#perc-bar').html('');
$('.mojang-status').css('background', 'transparent');
$('.mojang-status-text').text('...');
2017-03-15 02:14:26 +00:00
$("#stat_totalPlayers").text(0);
$("#stat_networks").text(0);
isConnected = false;
2015-11-09 00:34:17 +00:00
});
2015-12-18 07:45:38 +00:00
socket.on('historyGraph', function(rawData) {
2016-02-01 11:29:09 +00:00
var shownServers = loadGraphControls();
if (shownServers) {
var keys = Object.keys(rawData);
2016-02-01 11:31:00 +00:00
hiddenGraphData = [];
displayedGraphData = [];
2016-02-01 11:29:09 +00:00
for (var i = 0; i < keys.length; i++) {
var name = keys[i];
if (shownServers.indexOf(name) !== -1) {
displayedGraphData[name] = rawData[name];
} else {
hiddenGraphData[name] = rawData[name];
}
}
} else {
displayedGraphData = rawData;
}
2015-12-18 07:45:38 +00:00
2015-12-23 20:25:05 +00:00
$('#big-graph').css('height', '400px');
2015-12-19 01:05:43 +00:00
2016-02-01 11:29:09 +00:00
historyPlot = $.plot('#big-graph', convertGraphData(displayedGraphData), bigChartOptions);
2015-12-18 07:45:38 +00:00
$('#big-graph').bind('plothover', handlePlotHover);
2015-12-19 00:10:58 +00:00
var keys = Object.keys(rawData);
var sinceBreak = 0;
var html = '<table><tr>';
keys.sort();
2015-12-19 00:10:58 +00:00
for (var i = 0; i < keys.length; i++) {
2016-02-01 11:29:09 +00:00
var checkedString = '';
if (displayedGraphData[keys[i]]) {
checkedString = 'checked=checked';
}
html += '<td><input type="checkbox" class="graph-control" id="graph-controls" data-target-network="' + keys[i] + '" ' + checkedString + '> ' + keys[i] + '</input></td>';
2015-12-19 03:39:08 +00:00
if (sinceBreak >= 7) {
sinceBreak = 0;
html += '</tr><tr>';
} else {
sinceBreak++;
}
2015-12-19 00:10:58 +00:00
}
2015-12-19 00:33:43 +00:00
$('#big-graph-checkboxes').append(html + '</tr></table>');
2015-12-19 00:49:18 +00:00
$('#big-graph-controls').css('display', 'block');
2015-12-18 07:45:38 +00:00
});
socket.on('updateHistoryGraph', function(rawData) {
2015-12-19 03:23:24 +00:00
// Prevent race conditions.
2016-02-06 23:34:33 +00:00
if (!displayedGraphData || !hiddenGraphData) {
2015-12-19 03:23:24 +00:00
return;
2015-12-18 07:45:38 +00:00
}
2015-12-19 03:23:24 +00:00
// If it's not in our display group, use the hidden group instead.
2016-02-01 10:58:05 +00:00
var targetGraphData = displayedGraphData[rawData.name] ? displayedGraphData : hiddenGraphData;
2015-12-19 03:23:24 +00:00
2016-02-06 23:34:33 +00:00
trimOldPings(targetGraphData, publicConfig.graphDuration);
2015-12-18 07:45:38 +00:00
2016-02-01 10:58:05 +00:00
targetGraphData[rawData.name].push([rawData.timestamp, rawData.players]);
2015-12-19 00:10:58 +00:00
2015-12-19 03:23:24 +00:00
// Redraw if we need to.
2016-02-01 10:58:05 +00:00
if (displayedGraphData[rawData.name]) {
2015-12-19 03:23:24 +00:00
historyPlot.setData(convertGraphData(displayedGraphData));
historyPlot.setupGrid();
2015-12-18 07:45:38 +00:00
2015-12-19 03:23:24 +00:00
historyPlot.draw();
}
2015-12-18 07:45:38 +00:00
});
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;
} else if (lastEntry.result) {
lastPlayerEntries[info.name] = lastEntry.result.players.online;
}
2017-03-11 23:44:21 +00:00
var typeString = publicConfig.serverTypesVisible ? '<span class="type">' + info.type + '</span>' : '';
var safeNameCopy = safeName(info.name);
2015-11-09 00:34:17 +00:00
$('<div/>', {
2017-03-14 22:07:58 +00:00
id: 'container_' + safeNameCopy,
2015-11-09 00:34:17 +00:00
class: 'server',
2017-03-14 22:07:58 +00:00
'server-id': safeNameCopy,
2017-03-11 23:44:21 +00:00
html: '<div id="server-' + safeNameCopy + '" class="column" style="width: 80px;">\
<img id="favicon_' + safeNameCopy + '" title="' + info.name + '\n' + info.ip + printPort(info.port) + '" height="' + faviconSize + '" width="' + faviconSize + '">\
2015-11-09 07:03:03 +00:00
<br />\
2017-03-11 23:44:21 +00:00
<p class="text-center-align rank" id="ranking_' + safeNameCopy + '"></p>\
2015-11-09 00:34:17 +00:00
</div>\
2020-03-30 05:37:49 +00:00
<div class="column" style="width: 282px;">\
2017-03-11 23:44:21 +00:00
<h3>' + info.name + '&nbsp;' + typeString + '</h3>\
<span id="status_' + safeNameCopy + '">Waiting</span>\
2020-03-30 05:37:49 +00:00
<div id="version_' + safeNameCopy + '" class="color-dark-gray server-meta versions"><span class="version"></span></div>\
2020-03-30 05:43:49 +00:00
<span id="peak_' + safeNameCopy + '" class="color-dark-gray server-meta"></span>\
2020-03-30 05:37:49 +00:00
<br><span id="record_' + safeNameCopy + '" class="color-dark-gray server-meta"></span>\
2015-11-09 00:34:17 +00:00
</div>\
<div class="column" style="float: right;">\
2017-03-11 23:44:21 +00:00
<div class="chart" id="chart_' + safeNameCopy + '"></div>\
2015-11-09 00:34:17 +00:00
</div>'
2016-02-06 23:34:33 +00:00
}).appendTo("#server-container-" + getServerByIp(info.ip).category);
2015-11-09 00:34:17 +00:00
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-09 00:34:17 +00:00
graphs[lastEntry.info.name] = {
listing: listing,
2017-03-11 23:44:21 +00:00
plot: $.plot('#chart_' + safeNameCopy, [listing], smallChartOptions)
2015-11-09 00:34:17 +00:00
};
2015-11-09 07:03:03 +00:00
updateServerStatus(lastEntry);
2017-03-11 23:44:21 +00:00
$('#chart_' + safeNameCopy).bind('plothover', handlePlotHover);
2015-11-09 00:34:17 +00:00
}
2015-11-09 07:03:03 +00:00
sortServers();
2017-03-12 00:52:07 +00:00
updatePercentageBar();
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-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
});
socket.on('updateMojangServices', function(data) {
if (isConnected) {
updateMojangServices(data);
}
});
2015-12-19 00:10:58 +00:00
2020-03-30 05:37:49 +00:00
socket.on('syncComplete', function() {
hideCaption();
2020-03-30 05:37:49 +00:00
});
socket.on('updatePeak', function(data) {
updateServerPeak(data.name, data.timestamp, data.players);
});
2017-03-14 22:07:58 +00:00
2020-03-30 05:37:49 +00:00
socket.on('peaks', function(data) {
var keys = Object.keys(data);
for (var i = 0; i < keys.length; i++) {
var val = data[keys[i]];
updateServerPeak(keys[i], val[0], val[1]);
}
});
2017-03-14 22:07:58 +00:00
2015-12-19 00:10:58 +00:00
$(document).on('click', '.graph-control', function(e) {
var serverIp = $(this).attr('data-target-network');
// Restore it, or delete it - either works.
if (!this.checked) {
hiddenGraphData[serverIp] = displayedGraphData[serverIp];
delete displayedGraphData[serverIp];
} else {
displayedGraphData[serverIp] = hiddenGraphData[serverIp];
delete hiddenGraphData[serverIp];
}
2016-02-01 11:20:25 +00:00
// Redraw the graph
2015-12-19 00:10:58 +00:00
historyPlot.setData(convertGraphData(displayedGraphData));
historyPlot.setupGrid();
historyPlot.draw();
2016-02-01 11:20:25 +00:00
// Update our localStorage
2016-02-01 11:23:42 +00:00
if (Object.keys(hiddenGraphData).length === 0) {
resetGraphControls();
} else {
saveGraphControls(Object.keys(displayedGraphData));
}
2015-12-19 00:10:58 +00:00
});
2017-03-14 22:07:58 +00:00
2017-03-15 02:14:26 +00:00
$(document).on('mousemove', function(e) {
if (currentServerHover) {
var totalPlayers = getCurrentTotalPlayers();
var playerCount = lastPlayerEntries[currentServerHover];
renderTooltip(e.pageX + 10, e.pageY + 10, '<strong>' + currentServerHover + '</strong>: ' + roundToPoint(playerCount / totalPlayers * 100, 10) + '% of ' + formatNumber(totalPlayers) + ' tracked players.<br />(' + formatNumber(playerCount) + ' online.)');
2017-03-15 02:14:26 +00:00
}
});
2017-03-14 22:07:58 +00:00
$(window).on('resize', function() {
updatePercentageBar();
2017-03-15 01:48:07 +00:00
if (historyPlot) {
historyPlot.resize();
historyPlot.setupGrid();
historyPlot.draw();
}
2017-03-14 22:07:58 +00:00
});
});