function get(url) { return new Promise(function(resolve, reject) { var req = new XMLHttpRequest(); req.open('GET', url); req.onload = function() { if (req.status == 200) { resolve(req.response); } else { reject(Error(req.statusText)); } }; req.onerror = function() { reject(Error("Network Error")); }; req.send(); }); } function getJSON(url) { return get(url).then(JSON.parse) } function sortByKey(key, d) { return d.slice().sort( function (a, b) { return a[key] - b[key] }).reverse() } function limit(key, m, d) { return d.filter( function (d) { return d[key].isAfter(m) }) } function sum(a) { return a.reduce( function (a, b) { return a + b }, 0) } function one() { return 1 } function trueDefault(d) { return d === undefined ? true : d } function dictGet(dict, key) { var k = key.shift() if (!(k in dict)) return null if (key.length == 0) return dict[k] return dictGet(dict[k], key) } /* Helpers working with nodes */ function offline(d) { return !d.flags.online } function online(d) { return d.flags.online } function has_location(d) { return "location" in d.nodeinfo } function subtract(a, b) { var ids = {} b.forEach( function (d) { ids[d.nodeinfo.node_id] = true }) return a.filter( function (d) { return !(d.nodeinfo.node_id in ids) }) } /* Helpers working with links */ function showDistance(d) { if (isNaN(d.distance)) return return (new Intl.NumberFormat("de-DE", {maximumFractionDigits: 0}).format(d.distance)) + " m" } function showTq(d) { var opts = { maximumFractionDigits: 0 } return (new Intl.NumberFormat("de-DE", opts).format(100/d.tq)) + "%" } function linkId(d) { var ids = [d.source.node.nodeinfo.node_id, d.target.node.nodeinfo.node_id] return ids.sort().join("-") }