diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..5b4213d
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,5 @@
+**2.0.0**
+- Servers are now referenced by their name on the graph controls instead of their IP.
+- Servers now display their name on hover instead of their IP.
+- Graph controls are now saved and loaded automatically.
+- Moved server configuration into servers.json from config.json.
diff --git a/README.md b/README.md
index 08d09b7..a2757be 100644
--- a/README.md
+++ b/README.md
@@ -16,6 +16,9 @@ You can see an up-to-date copy of the master branch running on http://minetrack.
Database logging is disabled by default. You can enable it in ```config.json``` by setting ```logToDatabase``` to true.
This requires sqlite3 drivers to be installed.
+#### What's being changed?
+For the changelog, check out the [CHANGELOG](CHANGELOG.md) file.
+
#### How do I get added?
At the moment, the main "minetrack.me" site is only accepting networks that average roughly 1,000 players at peak for **PC** servers, and 100 players at peak for **PE** servers. This is due to limited capacity and it's functionality. If you fit this description, you're welcome to open a Pull Request adding the network to ```config.json```.
diff --git a/app.js b/app.js
index 6501a98..7b235c1 100644
--- a/app.js
+++ b/app.js
@@ -104,15 +104,16 @@ function handlePing(network, res, err) {
// Don't have too much data!
util.trimOldPings(graphData);
- if (!graphData[network.ip]) {
- graphData[network.ip] = [];
+ if (!graphData[network.name]) {
+ graphData[network.name] = [];
}
- graphData[network.ip].push([timeMs, res ? res.players.online : 0]);
+ graphData[network.name].push([timeMs, res ? res.players.online : 0]);
// Send the update.
server.io.sockets.emit('updateHistoryGraph', {
ip: network.ip,
+ name: network.name,
players: (res ? res.players.online : 0),
timestamp: timeMs
});
diff --git a/assets/js/site.js b/assets/js/site.js
index 11d9e8f..0175218 100644
--- a/assets/js/site.js
+++ b/assets/js/site.js
@@ -214,6 +214,13 @@ function setAllGraphVisibility(visible) {
historyPlot.setupGrid();
historyPlot.draw();
+
+ // Update our localStorage
+ if (visible) {
+ resetGraphControls();
+ } else {
+ saveGraphControls(Object.keys(displayedGraphData));
+ }
}
function toggleControlsDrawer() {
@@ -270,11 +277,30 @@ $(document).ready(function() {
});
socket.on('historyGraph', function(rawData) {
- displayedGraphData = rawData;
+ var shownServers = loadGraphControls();
+
+ if (shownServers) {
+ var keys = Object.keys(rawData);
+
+ hiddenGraphData = [];
+ displayedGraphData = [];
+
+ 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;
+ }
$('#big-graph').css('height', '400px');
- historyPlot = $.plot('#big-graph', convertGraphData(rawData), bigChartOptions);
+ historyPlot = $.plot('#big-graph', convertGraphData(displayedGraphData), bigChartOptions);
$('#big-graph').bind('plothover', handlePlotHover);
@@ -286,7 +312,13 @@ $(document).ready(function() {
keys.sort();
for (var i = 0; i < keys.length; i++) {
- html += '
' + keys[i] + '
';
+ var checkedString = '';
+
+ if (displayedGraphData[keys[i]]) {
+ checkedString = 'checked=checked';
+ }
+
+ html += '
' + keys[i] + '
';
if (sinceBreak >= 7) {
sinceBreak = 0;
@@ -303,19 +335,19 @@ $(document).ready(function() {
socket.on('updateHistoryGraph', function(rawData) {
// Prevent race conditions.
- if (!graphDuration) {
+ if (!graphDuration || !displayedGraphData || !hiddenGraphData) {
return;
}
// If it's not in our display group, use the hidden group instead.
- var targetGraphData = displayedGraphData[rawData.ip] ? displayedGraphData : hiddenGraphData;
+ var targetGraphData = displayedGraphData[rawData.name] ? displayedGraphData : hiddenGraphData;
trimOldPings(targetGraphData, graphDuration);
- targetGraphData[rawData.ip].push([rawData.timestamp, rawData.players]);
+ targetGraphData[rawData.name].push([rawData.timestamp, rawData.players]);
// Redraw if we need to.
- if (displayedGraphData[rawData.ip]) {
+ if (displayedGraphData[rawData.name]) {
historyPlot.setData(convertGraphData(displayedGraphData));
historyPlot.setupGrid();
@@ -460,9 +492,17 @@ $(document).ready(function() {
delete hiddenGraphData[serverIp];
}
+ // Redraw the graph
historyPlot.setData(convertGraphData(displayedGraphData));
historyPlot.setupGrid();
historyPlot.draw();
+
+ // Update our localStorage
+ if (Object.keys(hiddenGraphData).length === 0) {
+ resetGraphControls();
+ } else {
+ saveGraphControls(Object.keys(displayedGraphData));
+ }
});
});
diff --git a/assets/js/util.js b/assets/js/util.js
index b128990..449effc 100644
--- a/assets/js/util.js
+++ b/assets/js/util.js
@@ -2,6 +2,30 @@ var MISSING_FAVICON_BASE64 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAA
var tooltip = $('#tooltip');
+function saveGraphControls(displayedServers) {
+ if (typeof(localStorage) !== undefined) {
+ var json = JSON.stringify(displayedServers);
+
+ localStorage.setItem('displayedServers', json);
+ }
+}
+
+function loadGraphControls() {
+ if (typeof(localStorage) !== undefined) {
+ var item = localStorage.getItem('displayedServers');
+
+ if (item) {
+ return JSON.parse(item);
+ }
+ }
+}
+
+function resetGraphControls() {
+ if (typeof(localStorage) !== undefined) {
+ localStorage.removeItem('displayedServers');
+ }
+}
+
function getTimestamp(ms, timeOnly) {
var date = new Date(0);
@@ -96,7 +120,7 @@ function convertGraphData(rawData) {
function stringToColor(base) {
var hash;
- for (var i = 0, hash = 0; i < base.length; i++) {
+ for (var i = base.length - 1, hash = 0; i >= 0; i--) {
hash = base.charCodeAt(i) + ((hash << 5) - hash);
}
diff --git a/lib/util.js b/lib/util.js
index 0e9914b..de946a1 100644
--- a/lib/util.js
+++ b/lib/util.js
@@ -1,17 +1,39 @@
+var logger = require('./logger');
+
var config = require('../config.json');
var servers = require('../servers.json');
-// Checks if we have a server in config.json with the IP.
-function serverWithIpExists(ip) {
+var serverNameLookup = {};
+
+// Finds a server in servers.json with a matching IP.
+// If it finds one, it caches the result for faster future lookups.
+function getServerNameByIp(ip) {
+ var lookupName = serverNameLookup[ip];
+
+ if (lookupName) {
+ return lookupName;
+ }
+
for (var i = 0; i < servers.length; i++) {
var entry = servers[i];
if (entry.ip === ip) {
- return true;
+ serverNameLookup[entry.ip] = entry.name;
+
+ return entry.name;
}
}
+}
- return false;
+// Returns a list of configured server IPs from servers.json
+function getServerIps() {
+ var ips = [];
+
+ for (var i = 0; i < servers.length; i++) {
+ ips.push(servers[i].ip);
+ }
+
+ return ips;
}
// This method is a monstrosity.
@@ -20,16 +42,7 @@ function serverWithIpExists(ip) {
function trimUselessPings(data) {
var keys = Object.keys(data);
- var keysToRemove = [];
-
for (var i = 0; i < keys.length; i++) {
- // Don't bother we servers we deleted from config.json
- if (!serverWithIpExists(keys[i])) {
- keysToRemove.push(keys[i]);
-
- continue;
- }
-
var listing = data[keys[i]];
var lastTimestamp = 0;
@@ -55,11 +68,6 @@ function trimUselessPings(data) {
data[keys[i]] = filteredListing;
}
-
- // Delete data for any networks we don't care about anymore.
- for (var i = 0; i < keysToRemove.length; i++) {
- delete data[keysToRemove[i]];
- }
}
exports.trimOldPings = function(data) {
@@ -98,16 +106,25 @@ exports.setIntervalNoDelay = function(func, delay) {
};
exports.convertPingsToGraph = function(sqlData) {
+ var serverIps = getServerIps();
var graphData = {};
+ var startTime = exports.getCurrentTimeMs();
+
for (var i = 0; i < sqlData.length; i++) {
var entry = sqlData[i];
- if (!graphData[entry.ip]) {
- graphData[entry.ip] = [];
+ if (serverIps.indexOf(entry.ip) === -1) {
+ continue;
}
- graphData[entry.ip].push([entry.timestamp, entry.playerCount]);
+ var name = getServerNameByIp(entry.ip);
+
+ if (!graphData[name]) {
+ graphData[name] = [];
+ }
+
+ graphData[name].push([entry.timestamp, entry.playerCount]);
}
// Break it into minutes.
@@ -116,5 +133,7 @@ exports.convertPingsToGraph = function(sqlData) {
// Drop old data.
exports.trimOldPings(graphData);
+ logger.info('Converted data structure in ' + (exports.getCurrentTimeMs() - startTime) + 'ms');
+
return graphData;
};
\ No newline at end of file
diff --git a/package.json b/package.json
index b277459..f33df8b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "minetrack",
- "version": "1.0.0",
+ "version": "2.0.0",
"description": "A Minecraft server tracker that lets you focus on the basics.",
"main": "app.js",
"dependencies": {