website/static/workers/arc-data-decoder.js (64 lines of code) (raw):

importScripts('./util.js'); const result = []; let flowCount = 0; onmessage = function(e) { const lines = e.data.text.split('\n'); lines.forEach(function(line) { if (!line) { return; } const parts = line.split('\x01'); const f = { type: 'Feature', properties: { name: `${parts[0].slice(0, -2) }, ${ parts[0].slice(-2)}`, flows: decodeLinks(parts[1]) }, geometry: { type: 'MultiPolygon' } }; result.push(f); let sumX = 0; let sumY = 0; let len = 0; f.geometry.coordinates = parts.slice(2).map(function(str) { const coords = decodePolyline(str); coords.forEach(function(c) { sumX += c[0]; sumY += c[1]; len++; }); return [coords]; }); f.properties.centroid = [sumX / len, sumY / len, 0]; }); if (e.data.event === 'load') { result.forEach(function(f, i) { const flows = f.properties.flows; for (const toId in flows) { result[toId].properties.flows[i] = -flows[toId]; flowCount++; } }); postMessage({ action: 'add', data: result, meta: { count: result.length, flowCount } }); postMessage({action: 'end'}); } }; function decodeLinks(str) { const links = {}; const tokens = str.split(/([\x28-\x5b]+)/); for (let i = 0; i < tokens.length - 1; i += 2) { const index = decodeNumber(tokens[i], 32, 93); const flow = decodeNumber(tokens[i + 1], 52, 40); links[index] = flow; } return links; }