var map = new Datamap({ element: document.getElementById('container'), scope: 'usa', geographyConfig: { highlightOnHover: false, popupOnHover: false }, fills: { "Redemption": "#FA2AE9", "Point Added": "#F6A23A", "New Member": "#1284FF", "defaultFill": "#ABDDA4" } }); map.legend(); var DELAY = 4000; // delay on live streaming [ms] var DT = 180; // group blips into bins [ms] var ENDPOINT = location.href + 'alldata/'; var lastIDs = {}; var serverToLocalTimeOffset; var thrownAway = 0; var blipQueue = []; var failGif = null; function loadFailGif() { if (failGif !== null) return; failGif = document.createElement("img"); failGif.src = "img/rocket-explosion.gif"; failGif.style.height = "100%"; failGif.style.width = "100%"; failGif.style.left = "0px"; failGif.style.top = "0px"; failGif.style.position = "absolute"; failGif.id = "fail-gif"; document.body.appendChild(failGif); } function blip() { window.setInterval(function() { if (!serverToLocalTimeOffset) { return; } var endAtServerTime = (new Date()).getTime() + serverToLocalTimeOffset - DELAY; var nextBlock = []; var nextTime = !!blipQueue.length ? blipQueue[0].time : null; if (blipQueue.length === 0) { setTimeout(function() { // if still empty after 1 min if (blipQueue.length === 0) { loadFailGif(); } }, 60000); } else if (failGif !== null){ location.reload(); } while (!!nextTime && nextTime < endAtServerTime) { if (nextTime < endAtServerTime - DT - 1000) { // this means that we have fallen behind somehow... // just ignore data till we are caught up? // console.log('fell behind by', endAtServerTime - DT - nextTime); blipQueue.shift(); thrownAway++; } else { nextBlock.push(blipQueue.shift()); } nextTime = !!blipQueue.length ? blipQueue[0].time : null; } if (!!nextBlock.length) { map.blips(nextBlock); } }, DT); }; var started = false; // make requests twice as fast as our delay window.setInterval(function() { var requestTime = (new Date()).getTime(); $.get(ENDPOINT, lastIDs, function(data) { lastIDs = data.last_ids; if (!started) { blip(); started = true; } else { var lastDbTimeSeen = data.events.length ? data.events[data.events.length - 1].time : null; if (!!lastDbTimeSeen) { if (!serverToLocalTimeOffset) { serverToLocalTimeOffset = lastDbTimeSeen - requestTime; } else { serverToLocalTimeOffset = Math.max( lastDbTimeSeen - requestTime, serverToLocalTimeOffset ); } } } Array.prototype.push.apply(blipQueue, data.events); }) }, DELAY/2);