Showing Voronoi with TubeMaps
London Tube Map with Voronoi
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<title>Graph map</title> | |
<meta charset="utf-8" /> | |
<style type="text/css"> | |
svg { | |
font: 10px sans-serif; | |
} | |
.axis path, .axis line { | |
fill: none; | |
stroke: #666; | |
stroke-width: 0.3; | |
} | |
path { | |
stroke: #fff; | |
} | |
circle.station { | |
stroke-width: 0.5; | |
} | |
.voronoi path { | |
stroke: #aaa; | |
} | |
circle { | |
fill: #000; | |
pointer-events: none; | |
} | |
.q0-9 { fill: #d3d3d3;} | |
.q1-9 { fill: #efefef; } | |
.q2-9 { fill: #fefefe; } | |
.q3-9 { fill: #eeeeee; } | |
.q4-9 { fill: #dedede; } | |
.q5-9 { fill: #d0d0d0; } | |
.q6-9 { fill: #eaeaea; } | |
.q7-9 { fill: #e9e9e9; } | |
.q8-9 { fill: #f2f2f2; } | |
</style> | |
</head> | |
<body> | |
<div id="map"></div> | |
<script type="text/javascript" src="tubemaps.js"></script> | |
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/d3/3.4.13/d3.js"></script> | |
<script type="text/javascript"> | |
function polygon(d) { | |
return "M" + d.join("L") + "Z"; | |
} | |
var margin = {top: 20, right: 20, bottom: 30, left: 40}, | |
w = Math.max(760, window.innerWidth) - margin.left - margin.right, | |
h = Math.max(500, window.innerHeight) - margin.top - margin.bottom; | |
var voronoi = d3.geom.voronoi() | |
.clipExtent([[0, 0], [w, h]]); | |
d3.json('london.json', function(data) { | |
data.stations.forEach(function(d) { | |
d.longitude = +d.longitude; | |
d.latitude = +d.latitude; | |
}) | |
var tube = new TubeMaps.TubeMap(data) | |
// Find min and max long and lat | |
var minLat = d3.min(tube.stations, function(d) {return d.latitude}); | |
var minLon = d3.min(tube.stations, function(d) {return d.longitude}); | |
var maxLat = d3.max(tube.stations, function(d) {return d.latitude}); | |
var maxLon = d3.max(tube.stations, function(d) {return d.longitude}); | |
// Set up the scales | |
var x = d3.scale.linear() | |
.domain([minLon, maxLon]) | |
.range([0, w]); | |
var y = d3.scale.linear() | |
.domain([minLat, maxLat]) | |
.range([h, 0]); | |
// Set up the axis | |
var xAxis = d3.svg.axis() | |
.scale(x) | |
.orient("bottom") | |
.tickSize(-h); | |
var yAxis = d3.svg.axis() | |
.scale(y) | |
.orient("left") | |
.ticks(5) | |
.tickSize(-w); | |
// Set up what will happen when zooming | |
var zoom = d3.behavior.zoom() | |
.x(x) | |
.y(y) | |
.scaleExtent([1, 10]) | |
.on("zoom", zoomed); | |
/* | |
Drawing from now on | |
*/ | |
// Setting up the canvas | |
var vis = d3.select("#map").append("svg") | |
.attr("width", w + margin.left + margin.right) | |
.attr("height", h + margin.top + margin.bottom) | |
.append("g") | |
.attr("transform", "translate(" + margin.left + "," + margin.top + ")") | |
// Make sure it is zoomable | |
d3.select("#map svg") | |
.call(zoom); | |
var vornoitube = vis.append("g") | |
.attr('class','voronoi') | |
.selectAll("path") | |
.data(voronoi(tube.stations.map(function(d) { | |
return [x(d.longitude), y(d.latitude)] | |
})), polygon); | |
vornoitube.exit().remove(); | |
vornoitube.enter().append("path") | |
.attr("class", function(d, i) { return "q" + (i % 9) + "-9"; }) | |
.attr("d", polygon); | |
vornoitube.order(); | |
// Drawing lines between stations | |
var route = vis.selectAll("line.route") | |
.data(tube.connections) | |
.enter().append("svg:line") | |
.attr("class", "route") | |
.attr("stroke", function(d) { return '#'+tube.linesById[d.line].colour; }) | |
.attr("stroke-linecap", 'round') | |
.attr("x1", function(d) { return x(d.station1.longitude); }) | |
.attr("y1", function(d) { return y(d.station1.latitude); }) | |
.attr("x2", function(d) { return x(d.station2.longitude); }) | |
.attr("y2", function(d) { return y(d.station2.latitude); }) | |
.style("opacity", 1) | |
// Striped stations (see official map) | |
var stripe = vis.selectAll("line.stripe") | |
.data(tube.connections.filter(function(d) { | |
return tube.linesById[d.line].stripe != "NULL"; | |
})) | |
.enter().append("svg:line") | |
.attr("class", "stripe") | |
.attr("stroke", function(d) { return '#'+tube.linesById[d.line].stripe; }) | |
.attr("stroke-linecap", 'round') | |
.attr("x1", function(d) { return x(d.station1.longitude); }) | |
.attr("y1", function(d) { return y(d.station1.latitude); }) | |
.attr("x2", function(d) { return x(d.station2.longitude); }) | |
.attr("y2", function(d) { return y(d.station2.latitude); }) | |
// Drawing all the stations | |
var station = vis.selectAll("circle.station") | |
.data(tube.stations) | |
.enter().append("svg:circle") | |
.attr("class", "station") | |
.attr("id", function(d) { return 'station'+d.id }) | |
.attr("cx", function(d) { return x(d.longitude); }) | |
.attr("cy", function(d) { return y(d.latitude); }) | |
.attr("data-cx", function(d) { return d.longitude; }) | |
.attr("data-cy", function(d) { return d.latitude; }) | |
.attr("title", function(d) { return d.name }) | |
.style("stroke", 'gray') | |
.style("fill", '#ffffff') | |
.style("opacity", 1) | |
.on('mouseover', function(d,i) { | |
d3.selectAll('#station'+d.id) | |
.transition() | |
.duration(25) | |
.attr("r", 3 / zoom.scale()) | |
.style("stroke", 'black') | |
.style("stroke-width", 1 / zoom.scale()) | |
.style('opacity', 1); | |
}) | |
.on('mouseout', function(d,i) { | |
d3.selectAll('#station'+d.id) | |
.transition() | |
.attr("r", 2.5 / zoom.scale()) | |
.duration(25) | |
.style("stroke-width", 0.5 / zoom.scale()) | |
.style("stroke", 'gray') | |
.style('opacity', 0.3); | |
}) | |
// Adding axis | |
vis.append("g") | |
.attr("class", "x axis") | |
.attr("transform", "translate(0," + h + ")") | |
.call(xAxis); | |
vis.append("g") | |
.attr("class", "y axis") | |
.call(yAxis); | |
zoomed() | |
function zoomed() { | |
// Reset axis | |
vis.select(".x.axis").call(xAxis); | |
vis.select(".y.axis").call(yAxis); | |
vis.selectAll("line.route") | |
.attr("stroke-width", 1 / (zoom.scale())) | |
vis.selectAll("line.stripe") | |
.attr("stroke-width", 0.5 / (zoom.scale())) | |
// Rescale circles | |
vis.selectAll("circle") | |
.attr("transform", "translate(" + zoom.translate() + ")scale(" + zoom.scale() + ")") | |
.style("stroke-width", 1 / zoom.scale()) | |
.attr("r", 2.5 / zoom.scale()); | |
// Rescale lines | |
vis.selectAll("line.route, line.stripe") | |
.attr("transform", "translate(" + zoom.translate() + ")scale(" + zoom.scale() + ")") | |
// Voronoi scale | |
vis.selectAll("g.voronoi") | |
.attr("transform", "translate(" + zoom.translate() + ")scale(" + zoom.scale() + ")") | |
vis.selectAll(".voronoi path") | |
.attr("stroke-width", 0.5 / (zoom.scale())) | |
} | |
}); | |
</script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{"connections":[{"station1":"11","station2":"163","line":"1","time":"1"},{"station1":"11","station2":"212","line":"1","time":"2"},{"station1":"49","station2":"87","line":"1","time":"1"},{"station1":"49","station2":"197","line":"1","time":"2"},{"station1":"82","station2":"163","line":"1","time":"2"},{"station1":"82","station2":"193","line":"1","time":"3"},{"station1":"84","station2":"148","line":"1","time":"3"},{"station1":"87","station2":"279","line":"1","time":"2"},{"station1":"113","station2":"246","line":"1","time":"2"},{"station1":"113","station2":"298","line":"1","time":"2"},{"station1":"114","station2":"140","line":"1","time":"2"},{"station1":"137","station2":"206","line":"1","time":"3"},{"station1":"137","station2":"298","line":"1","time":"3"},{"station1":"140","station2":"237","line":"1","time":"2"},{"station1":"143","station2":"159","line":"1","time":"2"},{"station1":"143","station2":"206","line":"1","time":"2"},{"station1":"148","station2":"279","line":"1","time":"1"},{"station1":"159","station2":"278","line":"1","time":"1"},{"station1":"185","station2":"237","line":"1","time":"2"},{"station1":"185","station2":"281","line":"1","time":"2"},{"station1":"192","station2":"197","line":"1","time":"2"},{"station1":"192","station2":"212","line":"1","time":"2"},{"station1":"193","station2":"278","line":"1","time":"2"},{"station1":"246","station2":"281","line":"1","time":"3"},{"station1":"13","station2":"156","line":"2","time":"2"},{"station1":"13","station2":"250","line":"2","time":"2"},{"station1":"16","station2":"91","line":"2","time":"2"},{"station1":"16","station2":"173","line":"2","time":"2"},{"station1":"24","station2":"156","line":"2","time":"3"},{"station1":"24","station2":"164","line":"2","time":"2"},{"station1":"28","station2":"162","line":"2","time":"1"},{"station1":"28","station2":"192","line":"2","time":"1"},{"station1":"37","station2":"158","line":"2","time":"3"},{"station1":"37","station2":"301","line":"2","time":"3"},{"station1":"48","station2":"126","line":"2","time":"1"},{"station1":"48","station2":"250","line":"2","time":"2"},{"station1":"51","station2":"103","line":"2","time":"2"},{"station1":"51","station2":"215","line":"2","time":"2"},{"station1":"68","station2":"158","line":"2","time":"2"},{"station1":"68","station2":"256","line":"2","time":"3"},{"station1":"72","station2":"286","line":"2","time":"3"},{"station1":"76","station2":"181","line":"2","time":"2"},{"station1":"76","station2":"296","line":"2","time":"3"},{"station1":"88","station2":"256","line":"2","time":"2"},{"station1":"91","station2":"109","line":"2","time":"2"},{"station1":"98","station2":"173","line":"2","time":"3"},{"station1":"98","station2":"211","line":"2","time":"2"},{"station1":"103","station2":"109","line":"2","time":"3"},{"station1":"105","station2":"177","line":"2","time":"2"},{"station1":"105","station2":"196","line":"2","time":"2"},{"station1":"112","station2":"181","line":"2","time":"3"},{"station1":"112","station2":"196","line":"2","time":"2"},{"station1":"126","station2":"259","line":"2","time":"2"},{"station1":"127","station2":"186","line":"2","time":"2"},{"station1":"127","station2":"226","line":"2","time":"1"},{"station1":"149","station2":"162","line":"2","time":"3"},{"station1":"149","station2":"208","line":"2","time":"1"},{"station1":"153","station2":"154","line":"2","time":"3"},{"station1":"153","station2":"247","line":"2","time":"2"},{"station1":"154","station2":"230","line":"2","time":"2"},{"station1":"154","station2":"275","line":"2","time":"2"},{"station1":"164","station2":"247","line":"2","time":"4"},{"station1":"177","station2":"239","line":"2","time":"3"},{"station1":"181","station2":"286","line":"2","time":"2"},{"station1":"186","station2":"208","line":"2","time":"2"},{"station1":"192","station2":"259","line":"2","time":"2"},{"station1":"211","station2":"275","line":"2","time":"2"},{"station1":"215","station2":"301","line":"2","time":"3"},{"station1":"221","station2":"239","line":"2","time":"1"},{"station1":"221","station2":"294","line":"2","time":"3"},{"station1":"226","station2":"296","line":"2","time":"3"},{"station1":"230","station2":"241","line":"2","time":"2"},{"station1":"241","station2":"301","line":"2","time":"2"},{"station1":"2","station2":"156","line":"3","time":"2"},{"station1":"2","station2":"263","line":"3","time":"4"},{"station1":"11","station2":"83","line":"3","time":"3"},{"station1":"11","station2":"104","line":"3","time":"3"},{"station1":"14","station2":"92","line":"3","time":"1"},{"station1":"14","station2":"167","line":"3","time":"2"},{"station1":"18","station2":"186","line":"3","time":"2"},{"station1":"18","station2":"193","line":"3","time":"2"},{"station1":"25","station2":"161","line":"3","time":"1"},{"station1":"25","station2":"255","line":"3","time":"2"},{"station1":"44","station2":"161","line":"3","time":"1"},{"station1":"44","station2":"166","line":"3","time":"2"},{"station1":"83","station2":"193","line":"3","time":"3"},{"station1":"87","station2":"255","line":"3","time":"2"},{"station1":"87","station2":"285","line":"3","time":"2"},{"station1":"90","station2":"104","line":"3","time":"2"},{"station1":"90","station2":"145","line":"3","time":"2"},{"station1":"92","station2":"145","line":"3","time":"4"},{"station1":"99","station2":"122","line":"3","time":"4"},{"station1":"99","station2":"236","line":"3","time":"1"},{"station1":"122","station2":"186","line":"3","time":"3"},{"station1":"156","station2":"167","line":"3","time":"2"},{"station1":"166","station2":"263","line":"3","time":"2"},{"station1":"229","station2":"236","line":"3","time":"2"},{"station1":"229","station2":"273","line":"3","time":"2"},{"station1":"248","station2":"273","line":"3","time":"2"},{"station1":"248","station2":"285","line":"3","time":"2"},{"station1":"3","station2":"263","line":"4","time":"2"},{"station1":"3","station2":"295","line":"4","time":"2"},{"station1":"15","station2":"78","line":"4","time":"4"},{"station1":"15","station2":"269","line":"4","time":"2"},{"station1":"17","station2":"110","line":"4","time":"1"},{"station1":"17","station2":"293","line":"4","time":"2"},{"station1":"18","station2":"186","line":"4","time":"2"},{"station1":"18","station2":"193","line":"4","time":"2"},{"station1":"21","station2":"67","line":"4","time":"3"},{"station1":"21","station2":"269","line":"4","time":"2"},{"station1":"25","station2":"161","line":"4","time":"1"},{"station1":"25","station2":"255","line":"4","time":"2"},{"station1":"33","station2":"36","line":"4","time":"2"},{"station1":"33","station2":"164","line":"4","time":"1"},{"station1":"36","station2":"289","line":"4","time":"2"},{"station1":"44","station2":"161","line":"4","time":"1"},{"station1":"44","station2":"166","line":"4","time":"2"},{"station1":"52","station2":"1","line":"4","time":"2"},{"station1":"52","station2":"265","line":"4","time":"2"},{"station1":"66","station2":"67","line":"4","time":"4"},{"station1":"66","station2":"85","line":"4","time":"3"},{"station1":"72","station2":"73","line":"4","time":"4"},{"station1":"73","station2":"1","line":"4","time":"2"},{"station1":"74","station2":"99","line":"4","time":"3"},{"station1":"74","station2":"122","line":"4","time":"3"},{"station1":"74","station2":"138","line":"4","time":"2"},{"station1":"74","station2":"287","line":"4","time":"2"},{"station1":"74","station2":"293","line":"4","time":"1"},{"station1":"78","station2":"270","line":"4","time":"2"},{"station1":"80","station2":"205","line":"4","time":"2"},{"station1":"80","station2":"231","line":"4","time":"2"},{"station1":"83","station2":"193","line":"4","time":"3"},{"station1":"85","station2":"129","line":"4","time":"2"},{"station1":"87","station2":"255","line":"4","time":"2"},{"station1":"87","station2":"285","line":"4","time":"2"},{"station1":"96","station2":"195","line":"4","time":"2"},{"station1":"96","station2":"287","line":"4","time":"1"},{"station1":"99","station2":"236","line":"4","time":"1"},{"station1":"108","station2":"141","line":"4","time":"3"},{"station1":"108","station2":"265","line":"4","time":"3"},{"station1":"110","station2":"209","line":"4","time":"2"},{"station1":"122","station2":"186","line":"4","time":"3"},{"station1":"129","station2":"268","line":"4","time":"2"},{"station1":"141","station2":"213","line":"4","time":"3"},{"station1":"164","station2":"244","line":"4","time":"2"},{"station1":"166","station2":"263","line":"4","time":"2"},{"station1":"195","station2":"205","line":"4","time":"3"},{"station1":"200","station2":"270","line":"4","time":"2"},{"station1":"200","station2":"289","line":"4","time":"2"},{"station1":"209","station2":"242","line":"4","time":"2"},{"station1":"229","station2":"236","line":"4","time":"2"},{"station1":"229","station2":"273","line":"4","time":"2"},{"station1":"231","station2":"300","line":"4","time":"3"},{"station1":"242","station2":"265","line":"4","time":"1"},{"station1":"244","station2":"295","line":"4","time":"3"},{"station1":"248","station2":"273","line":"4","time":"2"},{"station1":"248","station2":"285","line":"4","time":"2"},{"station1":"267","station2":"268","line":"4","time":"3"},{"station1":"299","station2":"300","line":"4","time":"3"},{"station1":"4","station2":"70","line":"13","time":"2"},{"station1":"4","station2":"201","line":"13","time":"2"},{"station1":"13","station2":"225","line":"13","time":"2"},{"station1":"19","station2":"97","line":"13","time":"2"},{"station1":"20","station2":"65","line":"13","time":"2"},{"station1":"20","station2":"217","line":"13","time":"2"},{"station1":"27","station2":"79","line":"13","time":"2"},{"station1":"27","station2":"201","line":"13","time":"2"},{"station1":"32","station2":"70","line":"13","time":"2"},{"station1":"32","station2":"204","line":"13","time":"2"},{"station1":"42","station2":"120","line":"13","time":"2"},{"station1":"42","station2":"292","line":"13","time":"2"},{"station1":"43","station2":"79","line":"13","time":"2"},{"station1":"43","station2":"219","line":"13","time":"2"},{"station1":"61","station2":"171","line":"13","time":"2"},{"station1":"61","station2":"238","line":"13","time":"2"},{"station1":"63","station2":"203","line":"13","time":"2"},{"station1":"63","station2":"219","line":"13","time":"2"},{"station1":"64","station2":"106","line":"13","time":"2"},{"station1":"64","station2":"135","line":"13","time":"2"},{"station1":"65","station2":"97","line":"13","time":"2"},{"station1":"69","station2":"86","line":"13","time":"2"},{"station1":"69","station2":"106","line":"13","time":"2"},{"station1":"86","station2":"152","line":"13","time":"2"},{"station1":"120","station2":"238","line":"13","time":"2"},{"station1":"135","station2":"171","line":"13","time":"2"},{"station1":"155","station2":"225","line":"13","time":"2"},{"station1":"155","station2":"284","line":"13","time":"2"},{"station1":"201","station2":"284","line":"13","time":"2"},{"station1":"201","station2":"292","line":"13","time":"2"},{"station1":"203","station2":"217","line":"13","time":"2"},{"station1":"204","station2":"247","line":"13","time":"2"},{"station1":"225","station2":"262","line":"13","time":"2"},{"station1":"284","station2":"292","line":"13","time":"2"},{"station1":"41","station2":"216","line":"5","time":"1"},{"station1":"41","station2":"253","line":"5","time":"2"},{"station1":"174","station2":"253","line":"5","time":"4"},{"station1":"175","station2":"253","line":"5","time":"4"},{"station1":"216","station2":"276","line":"5","time":"1"},{"station1":"225","station2":"276","line":"5","time":"1"},{"station1":"225","station2":"295","line":"5","time":"2"},{"station1":"228","station2":"295","line":"5","time":"2"},{"station1":"3","station2":"156","line":"6","time":"4"},{"station1":"3","station2":"295","line":"6","time":"2"},{"station1":"11","station2":"83","line":"6","time":"3"},{"station1":"11","station2":"104","line":"6","time":"3"},{"station1":"14","station2":"92","line":"6","time":"1"},{"station1":"14","station2":"167","line":"6","time":"2"},{"station1":"15","station2":"78","line":"6","time":"4"},{"station1":"33","station2":"36","line":"6","time":"2"},{"station1":"33","station2":"164","line":"6","time":"1"},{"station1":"36","station2":"289","line":"6","time":"2"},{"station1":"78","station2":"270","line":"6","time":"2"},{"station1":"83","station2":"193","line":"6","time":"4"},{"station1":"90","station2":"104","line":"6","time":"2"},{"station1":"90","station2":"145","line":"6","time":"2"},{"station1":"92","station2":"145","line":"6","time":"4"},{"station1":"101","station2":"110","line":"6","time":"2"},{"station1":"101","station2":"227","line":"6","time":"1"},{"station1":"147","station2":"150","line":"6","time":"1"},{"station1":"147","station2":"283","line":"6","time":"2"},{"station1":"150","station2":"227","line":"6","time":"2"},{"station1":"156","station2":"167","line":"6","time":"2"},{"station1":"164","station2":"244","line":"6","time":"2"},{"station1":"193","station2":"218","line":"6","time":"1"},{"station1":"200","station2":"270","line":"6","time":"2"},{"station1":"200","station2":"289","line":"6","time":"2"},{"station1":"218","station2":"283","line":"6","time":"2"},{"station1":"244","station2":"295","line":"6","time":"3"},{"station1":"11","station2":"28","line":"7","time":"2"},{"station1":"11","station2":"249","line":"7","time":"4"},{"station1":"23","station2":"41","line":"7","time":"2"},{"station1":"23","station2":"157","line":"7","time":"3"},{"station1":"28","station2":"107","line":"7","time":"2"},{"station1":"41","station2":"42","line":"7","time":"3"},{"station1":"42","station2":"183","line":"7","time":"3"},{"station1":"43","station2":"183","line":"7","time":"3"},{"station1":"43","station2":"289","line":"7","time":"3"},{"station1":"45","station2":"207","line":"7","time":"2"},{"station1":"45","station2":"243","line":"7","time":"2"},{"station1":"71","station2":"172","line":"7","time":"2"},{"station1":"71","station2":"297","line":"7","time":"2"},{"station1":"94","station2":"254","line":"7","time":"2"},{"station1":"94","station2":"290","line":"7","time":"1"},{"station1":"107","station2":"285","line":"7","time":"3"},{"station1":"142","station2":"290","line":"7","time":"2"},{"station1":"142","station2":"297","line":"7","time":"2"},{"station1":"144","station2":"207","line":"7","time":"2"},{"station1":"144","station2":"282","line":"7","time":"4"},{"station1":"157","station2":"233","line":"7","time":"2"},{"station1":"172","station2":"282","line":"7","time":"4"},{"station1":"233","station2":"279","line":"7","time":"1"},{"station1":"247","station2":"289","line":"7","time":"3"},{"station1":"249","station2":"254","line":"7","time":"1"},{"station1":"279","station2":"285","line":"7","time":"2"},{"station1":"2","station2":"156","line":"8","time":"2"},{"station1":"6","station2":"46","line":"8","time":"4"},{"station1":"11","station2":"94","line":"8","time":"6"},{"station1":"11","station2":"104","line":"8","time":"3"},{"station1":"14","station2":"92","line":"8","time":"1"},{"station1":"14","station2":"167","line":"8","time":"2"},{"station1":"46","station2":"50","line":"8","time":"8"},{"station1":"46","station2":"53","line":"8","time":"4"},{"station1":"53","station2":"214","line":"8","time":"4"},{"station1":"62","station2":"168","line":"8","time":"4"},{"station1":"62","station2":"280","line":"8","time":"3"},{"station1":"75","station2":"210","line":"8","time":"2"},{"station1":"75","station2":"222","line":"8","time":"2"},{"station1":"90","station2":"104","line":"8","time":"2"},{"station1":"90","station2":"145","line":"8","time":"2"},{"station1":"92","station2":"145","line":"8","time":"4"},{"station1":"94","station2":"282","line":"8","time":"7"},{"station1":"115","station2":"178","line":"8","time":"2"},{"station1":"115","station2":"184","line":"8","time":"3"},{"station1":"115","station2":"291","line":"8","time":"2"},{"station1":"125","station2":"134","line":"8","time":"2"},{"station1":"125","station2":"271","line":"8","time":"3"},{"station1":"134","station2":"220","line":"8","time":"3"},{"station1":"156","station2":"167","line":"8","time":"2"},{"station1":"168","station2":"179","line":"8","time":"3"},{"station1":"168","station2":"214","line":"8","time":"4"},{"station1":"178","station2":"202","line":"8","time":"2"},{"station1":"179","station2":"180","line":"8","time":"2"},{"station1":"180","station2":"199","line":"8","time":"2"},{"station1":"184","station2":"199","line":"8","time":"3"},{"station1":"202","station2":"282","line":"8","time":"3"},{"station1":"210","station2":"291","line":"8","time":"3"},{"station1":"220","station2":"222","line":"8","time":"2"},{"station1":"7","station2":"145","line":"9","time":"2"},{"station1":"7","station2":"188","line":"9","time":"3"},{"station1":"8","station2":"124","line":"9","time":"3"},{"station1":"8","station2":"264","line":"9","time":"2"},{"station1":"12","station2":"56","line":"9","time":"2"},{"station1":"12","station2":"257","line":"9","time":"1"},{"station1":"13","station2":"157","line":"9","time":"2"},{"station1":"13","station2":"167","line":"9","time":"3"},{"station1":"22","station2":"47","line":"9","time":"2"},{"station1":"22","station2":"111","line":"9","time":"2"},{"station1":"29","station2":"84","line":"9","time":"1"},{"station1":"29","station2":"157","line":"9","time":"2"},{"station1":"34","station2":"100","line":"9","time":"3"},{"station1":"34","station2":"119","line":"9","time":"2"},{"station1":"38","station2":"58","line":"9","time":"2"},{"station1":"38","station2":"81","line":"9","time":"3"},{"station1":"40","station2":"47","line":"9","time":"2"},{"station1":"40","station2":"89","line":"9","time":"3"},{"station1":"40","station2":"139","line":"9","time":"2"},{"station1":"40","station2":"170","line":"9","time":"1"},{"station1":"49","station2":"87","line":"9","time":"1"},{"station1":"49","station2":"151","line":"9","time":"2"},{"station1":"54","station2":"55","line":"9","time":"2"},{"station1":"54","station2":"56","line":"9","time":"2"},{"station1":"55","station2":"245","line":"9","time":"1"},{"station1":"58","station2":"119","line":"9","time":"3"},{"station1":"59","station2":"240","line":"9","time":"2"},{"station1":"59","station2":"258","line":"9","time":"2"},{"station1":"77","station2":"93","line":"9","time":"4"},{"station1":"77","station2":"124","line":"9","time":"2"},{"station1":"84","station2":"136","line":"9","time":"2"},{"station1":"87","station2":"279","line":"9","time":"2"},{"station1":"89","station2":"145","line":"9","time":"2"},{"station1":"89","station2":"170","line":"9","time":"2"},{"station1":"89","station2":"277","line":"9","time":"1"},{"station1":"93","station2":"165","line":"9","time":"3"},{"station1":"93","station2":"288","line":"9","time":"2"},{"station1":"100","station2":"111","line":"9","time":"4"},{"station1":"102","station2":"259","line":"9","time":"1"},{"station1":"102","station2":"277","line":"9","time":"2"},{"station1":"121","station2":"261","line":"9","time":"3"},{"station1":"136","station2":"191","line":"9","time":"2"},{"station1":"136","station2":"279","line":"9","time":"3"},{"station1":"139","station2":"264","line":"9","time":"2"},{"station1":"151","station2":"259","line":"9","time":"1"},{"station1":"167","station2":"188","line":"9","time":"1"},{"station1":"169","station2":"240","line":"9","time":"4"},{"station1":"191","station2":"245","line":"9","time":"3"},{"station1":"257","station2":"258","line":"9","time":"2"},{"station1":"261","station2":"302","line":"9","time":"3"},{"station1":"288","station2":"302","line":"9","time":"1"},{"station1":"1","station2":"73","line":"10","time":"2"},{"station1":"1","station2":"234","line":"10","time":"4"},{"station1":"1","station2":"265","line":"10","time":"3"},{"station1":"5","station2":"194","line":"10","time":"3"},{"station1":"5","station2":"252","line":"10","time":"2"},{"station1":"9","station2":"31","line":"10","time":"3"},{"station1":"9","station2":"232","line":"10","time":"3"},{"station1":"10","station2":"95","line":"10","time":"2"},{"station1":"10","station2":"128","line":"10","time":"1"},{"station1":"17","station2":"74","line":"10","time":"3"},{"station1":"17","station2":"110","line":"10","time":"2"},{"station1":"30","station2":"176","line":"10","time":"2"},{"station1":"30","station2":"190","line":"10","time":"3"},{"station1":"31","station2":"303","line":"10","time":"2"},{"station1":"39","station2":"128","line":"10","time":"2"},{"station1":"39","station2":"145","line":"10","time":"5"},{"station1":"57","station2":"187","line":"10","time":"4"},{"station1":"60","station2":"126","line":"10","time":"1"},{"station1":"60","station2":"151","line":"10","time":"1"},{"station1":"73","station2":"182","line":"10","time":"3"},{"station1":"74","station2":"99","line":"10","time":"2"},{"station1":"75","station2":"210","line":"10","time":"2"},{"station1":"75","station2":"222","line":"10","time":"2"},{"station1":"95","station2":"160","line":"10","time":"2"},{"station1":"99","station2":"236","line":"10","time":"1"},{"station1":"107","station2":"133","line":"10","time":"2"},{"station1":"107","station2":"197","line":"10","time":"1"},{"station1":"110","station2":"265","line":"10","time":"2"},{"station1":"116","station2":"117","line":"10","time":"3"},{"station1":"116","station2":"118","line":"10","time":"3"},{"station1":"116","station2":"132","line":"10","time":"4"},{"station1":"117","station2":"118","line":"10","time":"5"},{"station1":"125","station2":"134","line":"10","time":"2"},{"station1":"125","station2":"271","line":"10","time":"3"},{"station1":"126","station2":"223","line":"10","time":"2"},{"station1":"130","station2":"131","line":"10","time":"2"},{"station1":"130","station2":"132","line":"10","time":"2"},{"station1":"131","station2":"190","line":"10","time":"2"},{"station1":"133","station2":"146","line":"10","time":"2"},{"station1":"134","station2":"220","line":"10","time":"3"},{"station1":"145","station2":"223","line":"10","time":"2"},{"station1":"146","station2":"236","line":"10","time":"3"},{"station1":"151","station2":"197","line":"10","time":"2"},{"station1":"160","station2":"266","line":"10","time":"3"},{"station1":"176","station2":"234","line":"10","time":"1"},{"station1":"182","station2":"194","line":"10","time":"2"},{"station1":"187","station2":"232","line":"10","time":"3"},{"station1":"210","station2":"235","line":"10","time":"3"},{"station1":"220","station2":"222","line":"10","time":"2"},{"station1":"235","station2":"251","line":"10","time":"2"},{"station1":"251","station2":"252","line":"10","time":"3"},{"station1":"266","station2":"303","line":"10","time":"2"},{"station1":"26","station2":"260","line":"11","time":"2"},{"station1":"26","station2":"274","line":"11","time":"2"},{"station1":"35","station2":"245","line":"11","time":"2"},{"station1":"89","station2":"145","line":"11","time":"2"},{"station1":"89","station2":"277","line":"11","time":"1"},{"station1":"95","station2":"123","line":"11","time":"2"},{"station1":"95","station2":"224","line":"11","time":"4"},{"station1":"107","station2":"192","line":"11","time":"2"},{"station1":"107","station2":"273","line":"11","time":"2"},{"station1":"123","station2":"145","line":"11","time":"4"},{"station1":"192","station2":"277","line":"11","time":"2"},{"station1":"198","station2":"272","line":"11","time":"1"},{"station1":"198","station2":"273","line":"11","time":"3"},{"station1":"224","station2":"260","line":"11","time":"3"},{"station1":"245","station2":"272","line":"11","time":"3"},{"station1":"13","station2":"279","line":"12","time":"4"}],"lines":[{"line":"1","name":"Bakerloo Line","colour":"AE6017","stripe":"NULL"},{"line":"3","name":"Circle Line","colour":"FFE02B","stripe":"NULL"},{"line":"6","name":"Hammersmith & City Line","colour":"F491A8","stripe":"NULL"},{"line":"7","name":"Jubilee Line","colour":"949699","stripe":"NULL"},{"line":"11","name":"Victoria Line","colour":"0A9CDA","stripe":"NULL"},{"line":"2","name":"Central Line","colour":"F15B2E","stripe":"NULL"},{"line":"4","name":"District Line","colour":"00A166","stripe":"NULL"},{"line":"5","name":"East London Line","colour":"FBAE34","stripe":"NULL"},{"line":"8","name":"Metropolitan Line","colour":"91005A","stripe":"NULL"},{"line":"9","name":"Northern Line","colour":"000000","stripe":"NULL"},{"line":"10","name":"Piccadilly Line","colour":"094FA3","stripe":"NULL"},{"line":"12","name":"Waterloo & City Line","colour":"88D0C4","stripe":"NULL"},{"line":"13","name":"Docklands Light Railway","colour":"00A77E","stripe":"FFFFFF"}],"stations":[{"id":"1","latitude":"51.5028","longitude":"-0.2801","name":"Acton Town","display_name":"Acton<br />Town","zone":"3","total_lines":"2","rail":"0"},{"id":"2","latitude":"51.5143","longitude":"-0.0755","name":"Aldgate","display_name":"NULL","zone":"1","total_lines":"2","rail":"0"},{"id":"3","latitude":"51.5154","longitude":"-0.0726","name":"Aldgate East","display_name":"Aldgate<br />East","zone":"1","total_lines":"2","rail":"0"},{"id":"4","latitude":"51.5107","longitude":"-0.013","name":"All Saints","display_name":"All<br />Saints","zone":"2","total_lines":"1","rail":"0"},{"id":"5","latitude":"51.5407","longitude":"-0.2997","name":"Alperton","display_name":"NULL","zone":"4","total_lines":"1","rail":"0"},{"id":"7","latitude":"51.5322","longitude":"-0.1058","name":"Angel","display_name":"NULL","zone":"1","total_lines":"1","rail":"0"},{"id":"8","latitude":"51.5653","longitude":"-0.1353","name":"Archway","display_name":"NULL","zone":"2.5","total_lines":"1","rail":"0"},{"id":"9","latitude":"51.6164","longitude":"-0.1331","name":"Arnos Grove","display_name":"Arnos<br />Grove","zone":"4","total_lines":"1","rail":"0"},{"id":"10","latitude":"51.5586","longitude":"-0.1059","name":"Arsenal","display_name":"NULL","zone":"2","total_lines":"1","rail":"0"},{"id":"11","latitude":"51.5226","longitude":"-0.1571","name":"Baker Street","display_name":"Baker<br />Street","zone":"1","total_lines":"5","rail":"0"},{"id":"12","latitude":"51.4431","longitude":"-0.1525","name":"Balham","display_name":"NULL","zone":"3","total_lines":"1","rail":"1"},{"id":"13","latitude":"51.5133","longitude":"-0.0886","name":"Bank","display_name":"NULL","zone":"1","total_lines":"4","rail":"0"},{"id":"14","latitude":"51.5204","longitude":"-0.0979","name":"Barbican","display_name":"NULL","zone":"1","total_lines":"3","rail":"0"},{"id":"15","latitude":"51.5396","longitude":"0.081","name":"Barking","display_name":"NULL","zone":"4","total_lines":"2","rail":"1"},{"id":"16","latitude":"51.5856","longitude":"0.0887","name":"Barkingside","display_name":"NULL","zone":"5","total_lines":"1","rail":"0"},{"id":"17","latitude":"51.4905","longitude":"-0.2139","name":"Barons Court","display_name":"Barons<br />Court","zone":"2","total_lines":"2","rail":"0"},{"id":"18","latitude":"51.5121","longitude":"-0.1879","name":"Bayswater","display_name":"NULL","zone":"1","total_lines":"2","rail":"0"},{"id":"19","latitude":"51.5148","longitude":"0.0613","name":"Beckton","display_name":"NULL","zone":"3","total_lines":"1","rail":"0"},{"id":"20","latitude":"51.5087","longitude":"0.055","name":"Beckton Park","display_name":"Beckton<br />Park","zone":"3","total_lines":"1","rail":"0"},{"id":"21","latitude":"51.5403","longitude":"0.127","name":"Becontree","display_name":"NULL","zone":"5","total_lines":"1","rail":"0"},{"id":"22","latitude":"51.5504","longitude":"-0.1642","name":"Belsize Park","display_name":"Belsize<br />Park","zone":"2","total_lines":"1","rail":"0"},{"id":"24","latitude":"51.527","longitude":"-0.0549","name":"Bethnal Green","display_name":"Bethnal<br />Green","zone":"2","total_lines":"1","rail":"0"},{"id":"25","latitude":"51.512","longitude":"-0.1031","name":"Blackfriars","display_name":"NULL","zone":"1","total_lines":"2","rail":"0"},{"id":"26","latitude":"51.5867","longitude":"-0.0417","name":"Blackhorse Road","display_name":"Blackhorse<br />Road","zone":"3","total_lines":"1","rail":"1"},{"id":"27","latitude":"51.5079","longitude":"-0.0066","name":"Blackwall","display_name":"NULL","zone":"2","total_lines":"1","rail":"0"},{"id":"28","latitude":"51.5142","longitude":"-0.1494","name":"Bond Street","display_name":"Bond<br />Street","zone":"1","total_lines":"2","rail":"0"},{"id":"29","latitude":"51.5011","longitude":"-0.0943","name":"Borough","display_name":"NULL","zone":"1","total_lines":"1","rail":"0"},{"id":"30","latitude":"51.4956","longitude":"-0.325","name":"Boston Manor","display_name":"Boston<br />Manor","zone":"4","total_lines":"1","rail":"0"},{"id":"31","latitude":"51.6071","longitude":"-0.1243","name":"Bounds Green","display_name":"Bounds<br />Green","zone":"3.5","total_lines":"1","rail":"0"},{"id":"32","latitude":"51.5273","longitude":"-0.0208","name":"Bow Church","display_name":"Bow<br />Church","zone":"2","total_lines":"3","rail":"0"},{"id":"33","latitude":"51.5269","longitude":"-0.0247","name":"Bow Road","display_name":"Bow<br />Road","zone":"2","total_lines":"2","rail":"0"},{"id":"34","latitude":"51.5766","longitude":"-0.2136","name":"Brent Cross","display_name":"Brent<br />Cross","zone":"3","total_lines":"1","rail":"0"},{"id":"36","latitude":"51.5248","longitude":"-0.0119","name":"Bromley-By-Bow","display_name":"NULL","zone":"2.5","total_lines":"2","rail":"0"},{"id":"38","latitude":"51.6028","longitude":"-0.2641","name":"Burnt Oak","display_name":"Burnt<br />Oak","zone":"4","total_lines":"1","rail":"0"},{"id":"39","latitude":"51.5481","longitude":"-0.1188","name":"Caledonian Road","display_name":"Caledonian<br />Road","zone":"2","total_lines":"1","rail":"0"},{"id":"40","latitude":"51.5392","longitude":"-0.1426","name":"Camden Town","display_name":"Camden<br />Town","zone":"2","total_lines":"1","rail":"0"},{"id":"42","latitude":"51.5051","longitude":"-0.0209","name":"Canary Wharf","display_name":"Canary<br />Wharf","zone":"2","total_lines":"2","rail":"0"},{"id":"44","latitude":"51.5113","longitude":"-0.0904","name":"Cannon Street","display_name":"Cannon<br />Street","zone":"1","total_lines":"2","rail":"0"},{"id":"45","latitude":"51.6078","longitude":"-0.2947","name":"Canons Park","display_name":"Canons<br />Park","zone":"5","total_lines":"1","rail":"0"},{"id":"47","latitude":"51.5441","longitude":"-0.1538","name":"Chalk Farm","display_name":"Chalk<br />Farm","zone":"2","total_lines":"1","rail":"0"},{"id":"48","latitude":"51.5185","longitude":"-0.1111","name":"Chancery Lane","display_name":"Chancery<br />Lane","zone":"1","total_lines":"1","rail":"0"},{"id":"49","latitude":"51.508","longitude":"-0.1247","name":"Charing Cross","display_name":"Charing<br />Cross","zone":"1","total_lines":"2","rail":"1"},{"id":"51","latitude":"51.6177","longitude":"0.0755","name":"Chigwell","display_name":"NULL","zone":"5","total_lines":"1","rail":"0"},{"id":"52","latitude":"51.4946","longitude":"-0.2678","name":"Chiswick Park","display_name":"Chiswick<br />Park","zone":"3","total_lines":"1","rail":"0"},{"id":"54","latitude":"51.4618","longitude":"-0.1384","name":"Clapham Common","display_name":"Clapham<br />Common","zone":"2","total_lines":"1","rail":"0"},{"id":"55","latitude":"51.4649","longitude":"-0.1299","name":"Clapham North","display_name":"Clapham<br />North","zone":"2","total_lines":"1","rail":"0"},{"id":"56","latitude":"51.4527","longitude":"-0.148","name":"Clapham South","display_name":"Clapham<br />South","zone":"2.5","total_lines":"1","rail":"0"},{"id":"58","latitude":"51.5955","longitude":"-0.2502","name":"Colindale","display_name":"NULL","zone":"4","total_lines":"1","rail":"0"},{"id":"59","latitude":"51.418","longitude":"-0.1778","name":"Colliers Wood","display_name":"Colliers<br />Wood","zone":"3","total_lines":"1","rail":"0"},{"id":"60","latitude":"51.5129","longitude":"-0.1243","name":"Covent Garden","display_name":"Covent<br />Garden","zone":"1","total_lines":"1","rail":"0"},{"id":"61","latitude":"51.4957","longitude":"-0.0144","name":"Crossharbour & London Arena","display_name":"Crossharbour &<br />London Arena","zone":"2","total_lines":"1","rail":"0"},{"id":"63","latitude":"51.5095","longitude":"0.0276","name":"Custom House","display_name":"Custom<br />House","zone":"3","total_lines":"1","rail":"0"},{"id":"65","latitude":"51.5085","longitude":"0.064","name":"Cyprus","display_name":"NULL","zone":"3","total_lines":"1","rail":"0"},{"id":"66","latitude":"51.5443","longitude":"0.1655","name":"Dagenham East","display_name":"Dagenham<br />East","zone":"5","total_lines":"1","rail":"0"},{"id":"67","latitude":"51.5417","longitude":"0.1469","name":"Dagenham Heathway","display_name":"Dagenham<br />Heathway","zone":"5","total_lines":"1","rail":"0"},{"id":"70","latitude":"51.5223","longitude":"-0.0173","name":"Devons Road","display_name":"Devons<br />Road","zone":"2","total_lines":"1","rail":"0"},{"id":"71","latitude":"51.552","longitude":"-0.2387","name":"Dollis Hill","display_name":"Dollis<br />Hill","zone":"3","total_lines":"1","rail":"0"},{"id":"72","latitude":"51.5152","longitude":"-0.3017","name":"Ealing Broadway","display_name":"Ealing<br />Broadway","zone":"3","total_lines":"2","rail":"1"},{"id":"73","latitude":"51.5101","longitude":"-0.2882","name":"Ealing Common","display_name":"Ealing<br />Common","zone":"3","total_lines":"2","rail":"0"},{"id":"74","latitude":"51.492","longitude":"-0.1973","name":"Earl's Court","display_name":"Earl's<br />Court","zone":"1.5","total_lines":"2","rail":"0"},{"id":"75","latitude":"51.5765","longitude":"-0.397","name":"Eastcote","display_name":"NULL","zone":"5","total_lines":"2","rail":"0"},{"id":"76","latitude":"51.5168","longitude":"-0.2474","name":"East Acton","display_name":"East<br />Acton","zone":"2","total_lines":"1","rail":"0"},{"id":"77","latitude":"51.5874","longitude":"-0.165","name":"East Finchley","display_name":"East<br />Finchley","zone":"3","total_lines":"1","rail":"0"},{"id":"78","latitude":"51.5394","longitude":"0.0518","name":"East Ham","display_name":"East<br />Ham","zone":"3.5","total_lines":"2","rail":"0"},{"id":"79","latitude":"51.5093","longitude":"-0.0021","name":"East India","display_name":"East<br />India","zone":"2.5","total_lines":"1","rail":"0"},{"id":"80","latitude":"51.4586","longitude":"-0.2112","name":"East Putney","display_name":"East<br />Putney","zone":"2.5","total_lines":"1","rail":"0"},{"id":"81","latitude":"51.6137","longitude":"-0.275","name":"Edgware","display_name":"NULL","zone":"5","total_lines":"1","rail":"0"},{"id":"82","latitude":"51.5199","longitude":"-0.1679","name":"Edgware Road (B)","display_name":"Edgware<br />Road","zone":"1","total_lines":"1","rail":"0"},{"id":"83","latitude":"51.5203","longitude":"-0.17","name":"Edgware Road (C)","display_name":"Edgware<br />Road","zone":"1","total_lines":"3","rail":"0"},{"id":"84","latitude":"51.4943","longitude":"-0.1001","name":"Elephant & Castle","display_name":"Elephant &<br />Castle","zone":"1.5","total_lines":"2","rail":"1"},{"id":"85","latitude":"51.5496","longitude":"0.1977","name":"Elm Park","display_name":"Elm<br />Park","zone":"6","total_lines":"1","rail":"0"},{"id":"87","latitude":"51.5074","longitude":"-0.1223","name":"Embankment","display_name":"NULL","zone":"1","total_lines":"4","rail":"0"},{"id":"89","latitude":"51.5282","longitude":"-0.1337","name":"Euston","display_name":"NULL","zone":"1","total_lines":"2","rail":"1"},{"id":"90","latitude":"51.526","longitude":"-0.1359","name":"Euston Square","display_name":"Euston<br />Square","zone":"1","total_lines":"3","rail":"0"},{"id":"91","latitude":"51.596","longitude":"0.0912","name":"Fairlop","display_name":"NULL","zone":"5","total_lines":"1","rail":"0"},{"id":"92","latitude":"51.5203","longitude":"-0.1053","name":"Farringdon","display_name":"NULL","zone":"1","total_lines":"3","rail":"1"},{"id":"93","latitude":"51.6012","longitude":"-0.1932","name":"Finchley Central","display_name":"Finchley<br />Central","zone":"4","total_lines":"1","rail":"0"},{"id":"94","latitude":"51.5472","longitude":"-0.1803","name":"Finchley Road","display_name":"Finchley<br />Road","zone":"2","total_lines":"2","rail":"0"},{"id":"95","latitude":"51.5642","longitude":"-0.1065","name":"Finsbury Park","display_name":"Finsbury<br />Park","zone":"2","total_lines":"1","rail":"1"},{"id":"96","latitude":"51.4804","longitude":"-0.195","name":"Fulham Broadway","display_name":"Fulham<br />Broadway","zone":"2","total_lines":"1","rail":"0"},{"id":"97","latitude":"51.5096","longitude":"0.0716","name":"Gallions Reach","display_name":"Gallions<br />Reach","zone":"3","total_lines":"1","rail":"0"},{"id":"98","latitude":"51.5765","longitude":"0.0663","name":"Gants Hill","display_name":"Gants<br />Hill","zone":"4","total_lines":"1","rail":"0"},{"id":"99","latitude":"51.4945","longitude":"-0.1829","name":"Gloucester Road","display_name":"Gloucester<br />Road","zone":"1","total_lines":"3","rail":"0"},{"id":"100","latitude":"51.5724","longitude":"-0.1941","name":"Golders Green","display_name":"Golders<br />Green","zone":"3","total_lines":"1","rail":"0"},{"id":"101","latitude":"51.5018","longitude":"-0.2267","name":"Goldhawk Road","display_name":"Goldhawk<br />Road","zone":"2","total_lines":"1","rail":"0"},{"id":"102","latitude":"51.5205","longitude":"-0.1347","name":"Goodge Street","display_name":"Goodge<br />Street","zone":"1","total_lines":"1","rail":"0"},{"id":"103","latitude":"51.6132","longitude":"0.0923","name":"Grange Hill","display_name":"Grange<br />Hill","zone":"5","total_lines":"1","rail":"0"},{"id":"104","latitude":"51.5238","longitude":"-0.1439","name":"Great Portland Street","display_name":"Great<br />Portland<br />Street","zone":"1","total_lines":"3","rail":"0"},{"id":"105","latitude":"51.5423","longitude":"-0.3456","name":"Greenford","display_name":"NULL","zone":"4","total_lines":"1","rail":"1"},{"id":"107","latitude":"51.5067","longitude":"-0.1428","name":"Green Park","display_name":"Green<br />Park","zone":"1","total_lines":"3","rail":"0"},{"id":"108","latitude":"51.4915","longitude":"-0.2754","name":"Gunnersbury","display_name":"NULL","zone":"3","total_lines":"1","rail":"0"},{"id":"109","latitude":"51.603","longitude":"0.0933","name":"Hainault","display_name":"NULL","zone":"5","total_lines":"1","rail":"0"},{"id":"110","latitude":"51.4936","longitude":"-0.2251","name":"Hammersmith","display_name":"NULL","zone":"2","total_lines":"3","rail":"0"},{"id":"111","latitude":"51.5568","longitude":"-0.178","name":"Hampstead","display_name":"NULL","zone":"2.5","total_lines":"1","rail":"0"},{"id":"112","latitude":"51.5302","longitude":"-0.2933","name":"Hanger Lane","display_name":"Hanger<br />Lane","zone":"3","total_lines":"1","rail":"0"},{"id":"113","latitude":"51.5362","longitude":"-0.2575","name":"Harlesden","display_name":"NULL","zone":"3","total_lines":"1","rail":"0"},{"id":"114","latitude":"51.5925","longitude":"-0.3351","name":"Harrow & Wealdston","display_name":"Harrow &<br />Wealdston","zone":"5","total_lines":"1","rail":"1"},{"id":"115","latitude":"51.5793","longitude":"-0.3366","name":"Harrow-on-the-Hill","display_name":"Harrow-<br />on-the-Hill","zone":"5","total_lines":"1","rail":"1"},{"id":"116","latitude":"51.4669","longitude":"-0.4227","name":"Hatton Cross","display_name":"Hatton<br />Cross","zone":"5.5","total_lines":"1","rail":"0"},{"id":"117","latitude":"51.4713","longitude":"-0.4524","name":"Heathrow Terminals 1, 2 & 3","display_name":"Heathrow<br />Terminals<br />1, 2 & 3","zone":"6","total_lines":"1","rail":"0"},{"id":"118","latitude":"51.4598","longitude":"-0.4476","name":"Heathrow Terminal 4","display_name":"Heathrow<br />Terminal 4","zone":"6","total_lines":"1","rail":"0"},{"id":"119","latitude":"51.5829","longitude":"-0.2259","name":"Hendon Central","display_name":"Hendon<br />Central","zone":"3.5","total_lines":"1","rail":"0"},{"id":"120","latitude":"51.5033","longitude":"-0.0215","name":"Heron Quays","display_name":"Heron<br />Quays","zone":"2","total_lines":"1","rail":"0"},{"id":"122","latitude":"51.5009","longitude":"-0.1925","name":"High Street Kensington","display_name":"High<br />Street<br />Kensington","zone":"1","total_lines":"2","rail":"0"},{"id":"123","latitude":"51.546","longitude":"-0.104","name":"Highbury & Islington","display_name":"Highbury &<br />Islington","zone":"2","total_lines":"1","rail":"1"},{"id":"124","latitude":"51.5777","longitude":"-0.1458","name":"Highgate","display_name":"NULL","zone":"3","total_lines":"1","rail":"0"},{"id":"125","latitude":"51.5538","longitude":"-0.4499","name":"Hillingdon","display_name":"NULL","zone":"6","total_lines":"2","rail":"0"},{"id":"126","latitude":"51.5174","longitude":"-0.12","name":"Holborn","display_name":"NULL","zone":"1","total_lines":"2","rail":"0"},{"id":"127","latitude":"51.5075","longitude":"-0.206","name":"Holland Park","display_name":"Holland<br />Park","zone":"2","total_lines":"1","rail":"0"},{"id":"128","latitude":"51.5526","longitude":"-0.1132","name":"Holloway Road","display_name":"Holloway<br />Road","zone":"2","total_lines":"1","rail":"0"},{"id":"129","latitude":"51.5539","longitude":"0.2184","name":"Hornchurch","display_name":"NULL","zone":"6","total_lines":"1","rail":"0"},{"id":"130","latitude":"51.4713","longitude":"-0.3665","name":"Hounslow Central","display_name":"Hounslow<br />Central","zone":"4","total_lines":"1","rail":"0"},{"id":"131","latitude":"51.4733","longitude":"-0.3564","name":"Hounslow East","display_name":"Hounslow<br />East","zone":"4","total_lines":"1","rail":"0"},{"id":"132","latitude":"51.4734","longitude":"-0.3855","name":"Hounslow West","display_name":"Hounslow<br />West","zone":"5","total_lines":"1","rail":"0"},{"id":"133","latitude":"51.5027","longitude":"-0.1527","name":"Hyde Park Corner","display_name":"Hyde<br />Park<br />Corner","zone":"1","total_lines":"1","rail":"0"},{"id":"134","latitude":"51.5619","longitude":"-0.4421","name":"Ickenham","display_name":"NULL","zone":"6","total_lines":"2","rail":"0"},{"id":"135","latitude":"51.4871","longitude":"-0.0101","name":"Island Gardens","display_name":"Island<br />Gardens","zone":"2","total_lines":"1","rail":"0"},{"id":"136","latitude":"51.4884","longitude":"-0.1053","name":"Kennington","display_name":"NULL","zone":"2","total_lines":"1","rail":"0"},{"id":"137","latitude":"51.5304","longitude":"-0.225","name":"Kensal Green","display_name":"Kensal<br />Green","zone":"2","total_lines":"1","rail":"0"},{"id":"138","latitude":"51.4983","longitude":"-0.2106","name":"Kensington (Olympia)","display_name":"Kensington<br />(Olympia)","zone":"2","total_lines":"1","rail":"1"},{"id":"139","latitude":"51.5507","longitude":"-0.1402","name":"Kentish Town","display_name":"Kentish<br />Town","zone":"2","total_lines":"1","rail":"1"},{"id":"140","latitude":"51.5816","longitude":"-0.3162","name":"Kenton","display_name":"NULL","zone":"4","total_lines":"1","rail":"0"},{"id":"141","latitude":"51.477","longitude":"-0.285","name":"Kew Gardens","display_name":"Kew<br />Gardens","zone":"3.5","total_lines":"1","rail":"0"},{"id":"142","latitude":"51.5471","longitude":"-0.2047","name":"Kilburn","display_name":"NULL","zone":"2","total_lines":"1","rail":"0"},{"id":"143","latitude":"51.5351","longitude":"-0.1939","name":"Kilburn Park","display_name":"Kilburn<br />Park","zone":"2","total_lines":"1","rail":"0"},{"id":"144","latitude":"51.5846","longitude":"-0.2786","name":"Kingsbury","display_name":"NULL","zone":"4","total_lines":"1","rail":"0"},{"id":"145","latitude":"51.5308","longitude":"-0.1238","name":"King's Cross St. Pancras","display_name":"King's Cross<br />St. Pancras","zone":"1","total_lines":"6","rail":"1"},{"id":"146","latitude":"51.5015","longitude":"-0.1607","name":"Knightsbridge","display_name":"NULL","zone":"1","total_lines":"1","rail":"0"},{"id":"147","latitude":"51.5172","longitude":"-0.2107","name":"Ladbroke Grove","display_name":"Ladbroke<br />Grove","zone":"2","total_lines":"1","rail":"0"},{"id":"148","latitude":"51.4991","longitude":"-0.1115","name":"Lambeth North","display_name":"Lambeth<br />North","zone":"1","total_lines":"1","rail":"0"},{"id":"149","latitude":"51.5119","longitude":"-0.1756","name":"Lancaster Gate","display_name":"Lancaster<br />Gate","zone":"1","total_lines":"1","rail":"0"},{"id":"150","latitude":"51.5139","longitude":"-0.2172","name":"Latimer Road","display_name":"Latimer<br />Road","zone":"2","total_lines":"1","rail":"0"},{"id":"151","latitude":"51.5113","longitude":"-0.1281","name":"Leicester Square","display_name":"Leicester<br />Square","zone":"1","total_lines":"2","rail":"0"},{"id":"153","latitude":"51.5566","longitude":"-0.0053","name":"Leyton","display_name":"NULL","zone":"3","total_lines":"1","rail":"0"},{"id":"154","latitude":"51.5683","longitude":"0.0083","name":"Leytonstone","display_name":"NULL","zone":"3.5","total_lines":"1","rail":"0"},{"id":"155","latitude":"51.5123","longitude":"-0.0396","name":"Limehouse","display_name":"NULL","zone":"2","total_lines":"1","rail":"1"},{"id":"156","latitude":"51.5178","longitude":"-0.0823","name":"Liverpool Street","display_name":"Liverpool<br />Street","zone":"1","total_lines":"4","rail":"1"},{"id":"157","latitude":"51.5052","longitude":"-0.0864","name":"London Bridge","display_name":"London<br />Bridge","zone":"1","total_lines":"2","rail":"1"},{"id":"159","latitude":"51.53","longitude":"-0.1854","name":"Maida Vale","display_name":"Maida<br />Vale","zone":"2","total_lines":"1","rail":"0"},{"id":"160","latitude":"51.5712","longitude":"-0.0958","name":"Manor House","display_name":"Manor<br />House","zone":"2.5","total_lines":"1","rail":"0"},{"id":"161","latitude":"51.5122","longitude":"-0.094","name":"Mansion House","display_name":"Mansion<br />House","zone":"1","total_lines":"2","rail":"0"},{"id":"162","latitude":"51.5136","longitude":"-0.1586","name":"Marble Arch","display_name":"Marble<br />Arch","zone":"1","total_lines":"1","rail":"0"},{"id":"163","latitude":"51.5225","longitude":"-0.1631","name":"Marylebone","display_name":"NULL","zone":"1","total_lines":"1","rail":"1"},{"id":"164","latitude":"51.5249","longitude":"-0.0332","name":"Mile End","display_name":"Mile<br />End","zone":"2","total_lines":"3","rail":"0"},{"id":"165","latitude":"51.6082","longitude":"-0.2103","name":"Mill Hill East","display_name":"Mill<br />Hill<br />East","zone":"4","total_lines":"1","rail":"0"},{"id":"166","latitude":"51.5108","longitude":"-0.0863","name":"Monument","display_name":"NULL","zone":"1","total_lines":"2","rail":"0"},{"id":"167","latitude":"51.5186","longitude":"-0.0886","name":"Moorgate","display_name":"NULL","zone":"1","total_lines":"4","rail":"1"},{"id":"168","latitude":"51.6294","longitude":"-0.432","name":"Moor Park","display_name":"Moor<br />Park","zone":"6.5","total_lines":"1","rail":"0"},{"id":"169","latitude":"51.4022","longitude":"-0.1948","name":"Morden","display_name":"NULL","zone":"4","total_lines":"1","rail":"0"},{"id":"170","latitude":"51.5342","longitude":"-0.1387","name":"Mornington Crescent","display_name":"Mornington<br />Crescent","zone":"2","total_lines":"1","rail":"0"},{"id":"171","latitude":"51.4902","longitude":"-0.0145","name":"Mudchute","display_name":"NULL","zone":"2","total_lines":"1","rail":"0"},{"id":"172","latitude":"51.5542","longitude":"-0.2503","name":"Neasden","display_name":"NULL","zone":"3","total_lines":"1","rail":"0"},{"id":"173","latitude":"51.5756","longitude":"0.0899","name":"Newbury Park","display_name":"Newbury<br />Park","zone":"4","total_lines":"1","rail":"0"},{"id":"176","latitude":"51.4995","longitude":"-0.3142","name":"Northfields","display_name":"NULL","zone":"3","total_lines":"1","rail":"0"},{"id":"177","latitude":"51.5483","longitude":"-0.3687","name":"Northolt","display_name":"NULL","zone":"5","total_lines":"1","rail":"0"},{"id":"178","latitude":"51.5784","longitude":"-0.3184","name":"Northwick Park","display_name":"Northwick<br />Park","zone":"4","total_lines":"1","rail":"0"},{"id":"179","latitude":"51.6111","longitude":"-0.424","name":"Northwood","display_name":"NULL","zone":"6","total_lines":"1","rail":"0"},{"id":"180","latitude":"51.6004","longitude":"-0.4092","name":"Northwood Hills","display_name":"Northwood<br />Hills","zone":"6","total_lines":"1","rail":"0"},{"id":"181","latitude":"51.5237","longitude":"-0.2597","name":"North Acton","display_name":"North<br />Acton","zone":"2.5","total_lines":"1","rail":"0"},{"id":"182","latitude":"51.5175","longitude":"-0.2887","name":"North Ealing","display_name":"North<br />Ealing","zone":"3","total_lines":"1","rail":"0"},{"id":"184","latitude":"51.5846","longitude":"-0.3626","name":"North Harrow","display_name":"North<br />Harrow","zone":"5","total_lines":"1","rail":"0"},{"id":"185","latitude":"51.5621","longitude":"-0.3034","name":"North Wembley","display_name":"North<br />Wembley","zone":"4","total_lines":"1","rail":"0"},{"id":"186","latitude":"51.5094","longitude":"-0.1967","name":"Notting Hill Gate","display_name":"Notting<br />Hill Gate","zone":"1.5","total_lines":"3","rail":"0"},{"id":"188","latitude":"51.5263","longitude":"-0.0873","name":"Old Street","display_name":"Old<br />Street","zone":"1","total_lines":"1","rail":"1"},{"id":"190","latitude":"51.4813","longitude":"-0.3522","name":"Osterley","display_name":"NULL","zone":"4","total_lines":"1","rail":"0"},{"id":"191","latitude":"51.4819","longitude":"-0.113","name":"Oval","display_name":"NULL","zone":"2","total_lines":"1","rail":"0"},{"id":"192","latitude":"51.515","longitude":"-0.1415","name":"Oxford Circus","display_name":"Oxford<br />Circus","zone":"1","total_lines":"3","rail":"0"},{"id":"193","latitude":"51.5154","longitude":"-0.1755","name":"Paddington","display_name":"NULL","zone":"1","total_lines":"4","rail":"1"},{"id":"194","latitude":"51.527","longitude":"-0.2841","name":"Park Royal","display_name":"Park<br />Royal","zone":"3","total_lines":"1","rail":"0"},{"id":"195","latitude":"51.4753","longitude":"-0.2011","name":"Parsons Green","display_name":"Parsons<br />Green","zone":"2","total_lines":"1","rail":"0"},{"id":"196","latitude":"51.5366","longitude":"-0.3232","name":"Perivale","display_name":"NULL","zone":"4","total_lines":"1","rail":"0"},{"id":"197","latitude":"51.5098","longitude":"-0.1342","name":"Picadilly Circus","display_name":"Picadilly<br />Circus","zone":"1","total_lines":"2","rail":"0"},{"id":"198","latitude":"51.4893","longitude":"-0.1334","name":"Pimlico","display_name":"NULL","zone":"1","total_lines":"1","rail":"0"},{"id":"199","latitude":"51.5926","longitude":"-0.3805","name":"Pinner","display_name":"NULL","zone":"5","total_lines":"1","rail":"0"},{"id":"200","latitude":"51.5313","longitude":"0.0172","name":"Plaistow","display_name":"NULL","zone":"3","total_lines":"2","rail":"0"},{"id":"201","latitude":"51.5077","longitude":"-0.0173","name":"Poplar","display_name":"NULL","zone":"2","total_lines":"1","rail":"0"},{"id":"202","latitude":"51.572","longitude":"-0.2954","name":"Preston Road","display_name":"Preston<br />Road","zone":"4","total_lines":"1","rail":"0"},{"id":"203","latitude":"51.5093","longitude":"0.0336","name":"Prince Regent","display_name":"Prince<br />Regent","zone":"3","total_lines":"1","rail":"0"},{"id":"205","latitude":"51.4682","longitude":"-0.2089","name":"Putney Bridge","display_name":"Putney<br />Bridge","zone":"2","total_lines":"1","rail":"0"},{"id":"206","latitude":"51.5341","longitude":"-0.2047","name":"Queen's Park","display_name":"Queens<br />Park","zone":"2","total_lines":"1","rail":"1"},{"id":"207","latitude":"51.5942","longitude":"-0.2861","name":"Queensbury","display_name":"NULL","zone":"4","total_lines":"1","rail":"0"},{"id":"208","latitude":"51.5107","longitude":"-0.1877","name":"Queensway","display_name":"NULL","zone":"1","total_lines":"1","rail":"0"},{"id":"209","latitude":"51.4942","longitude":"-0.2359","name":"Ravenscourt Park","display_name":"Ravenscourt<br />Park","zone":"2","total_lines":"1","rail":"0"},{"id":"210","latitude":"51.5753","longitude":"-0.3714","name":"Rayners Lane","display_name":"Rayners<br />Lane","zone":"5","total_lines":"2","rail":"0"},{"id":"211","latitude":"51.5763","longitude":"0.0454","name":"Redbridge","display_name":"NULL","zone":"4","total_lines":"1","rail":"0"},{"id":"212","latitude":"51.5234","longitude":"-0.1466","name":"Regent's Park","display_name":"Regent's<br />Park","zone":"1","total_lines":"1","rail":"0"},{"id":"213","latitude":"51.4633","longitude":"-0.3013","name":"Richmond","display_name":"NULL","zone":"4","total_lines":"1","rail":"1"},{"id":"215","latitude":"51.6171","longitude":"0.0439","name":"Roding Valley","display_name":"Roding<br />Valley","zone":"5","total_lines":"1","rail":"0"},{"id":"216","latitude":"51.501","longitude":"-0.0525","name":"Rotherhithe","display_name":"NULL","zone":"2","total_lines":"1","rail":"0"},{"id":"217","latitude":"51.5084","longitude":"0.0465","name":"Royal Albert","display_name":"Royal<br />Albert","zone":"3","total_lines":"1","rail":"0"},{"id":"218","latitude":"51.519","longitude":"-0.188","name":"Royal Oak","display_name":"Royal<br />Oak","zone":"2","total_lines":"1","rail":"0"},{"id":"219","latitude":"51.5091","longitude":"0.0181","name":"Royal Victoria","display_name":"Royal<br />Victoria","zone":"3","total_lines":"1","rail":"0"},{"id":"220","latitude":"51.5715","longitude":"-0.4213","name":"Ruislip","display_name":"NULL","zone":"6","total_lines":"2","rail":"0"},{"id":"222","latitude":"51.5732","longitude":"-0.4125","name":"Ruislip Manor","display_name":"Ruislip<br />Manor","zone":"6","total_lines":"2","rail":"0"},{"id":"223","latitude":"51.523","longitude":"-0.1244","name":"Russell Square","display_name":"Russell<br />Square","zone":"1","total_lines":"1","rail":"0"},{"id":"224","latitude":"51.5822","longitude":"-0.0749","name":"Seven Sisters","display_name":"Seven<br />Sisters","zone":"3","total_lines":"1","rail":"1"},{"id":"225","latitude":"51.5117","longitude":"-0.056","name":"Shadwell","display_name":"NULL","zone":"2","total_lines":"2","rail":"0"},{"id":"226","latitude":"51.5046","longitude":"-0.2187","name":"Shepherd's Bush (C)","display_name":"Shepherd's<br />Bush","zone":"2","total_lines":"1","rail":"0"},{"id":"227","latitude":"51.5058","longitude":"-0.2265","name":"Shepherd's Bush (H)","display_name":"Shepherd's<br />Bush","zone":"2","total_lines":"1","rail":"0"},{"id":"228","latitude":"51.5227","longitude":"-0.0708","name":"Shoreditch","display_name":"NULL","zone":"2","total_lines":"1","rail":"0"},{"id":"229","latitude":"51.4924","longitude":"-0.1565","name":"Sloane Square","display_name":"Sloane<br />Square","zone":"1","total_lines":"2","rail":"0"},{"id":"230","latitude":"51.5808","longitude":"0.0216","name":"Snaresbrook","display_name":"NULL","zone":"4","total_lines":"1","rail":"0"},{"id":"231","latitude":"51.4454","longitude":"-0.2066","name":"Southfields","display_name":"NULL","zone":"3","total_lines":"1","rail":"0"},{"id":"234","latitude":"51.5011","longitude":"-0.3072","name":"South Ealing","display_name":"South<br />Ealing","zone":"3","total_lines":"1","rail":"0"},{"id":"235","latitude":"51.5646","longitude":"-0.3521","name":"South Harrow","display_name":"South<br />Harrow","zone":"5","total_lines":"1","rail":"0"},{"id":"236","latitude":"51.4941","longitude":"-0.1738","name":"South Kensington","display_name":"South<br />Kensington","zone":"1","total_lines":"3","rail":"0"},{"id":"237","latitude":"51.5701","longitude":"-0.3081","name":"South Kenton","display_name":"South<br />Kenton","zone":"4","total_lines":"1","rail":"0"},{"id":"238","latitude":"51.5007","longitude":"-0.0191","name":"South Quay","display_name":"South<br />Quay","zone":"2","total_lines":"1","rail":"0"},{"id":"239","latitude":"51.5569","longitude":"-0.3988","name":"South Ruislip","display_name":"South<br />Ruislip","zone":"5","total_lines":"1","rail":"1"},{"id":"240","latitude":"51.4154","longitude":"-0.1919","name":"South Wimbledon","display_name":"South<br />Wimbledon","zone":"3.5","total_lines":"1","rail":"0"},{"id":"241","latitude":"51.5917","longitude":"0.0275","name":"South Woodford","display_name":"South<br />Woodford","zone":"4","total_lines":"1","rail":"0"},{"id":"242","latitude":"51.495","longitude":"-0.2459","name":"Stamford Brook","display_name":"Stamford<br />Brook","zone":"2","total_lines":"1","rail":"0"},{"id":"243","latitude":"51.6194","longitude":"-0.3028","name":"Stanmore","display_name":"NULL","zone":"5","total_lines":"1","rail":"0"},{"id":"244","latitude":"51.5221","longitude":"-0.047","name":"Stepney Green","display_name":"Stepney<br />Green","zone":"2","total_lines":"2","rail":"0"},{"id":"245","latitude":"51.4723","longitude":"-0.123","name":"Stockwell","display_name":"NULL","zone":"2","total_lines":"2","rail":"0"},{"id":"246","latitude":"51.5439","longitude":"-0.2759","name":"Stonebridge Park","display_name":"Stonebridge<br />Park","zone":"3","total_lines":"1","rail":"0"},{"id":"247","latitude":"51.5416","longitude":"-0.0042","name":"Stratford","display_name":"NULL","zone":"3","total_lines":"3","rail":"1"},{"id":"248","latitude":"51.4994","longitude":"-0.1335","name":"St. James's Park","display_name":"St. James's<br />Park","zone":"1","total_lines":"2","rail":"0"},{"id":"249","latitude":"51.5347","longitude":"-0.174","name":"St. John's Wood","display_name":"St. John's<br />Wood","zone":"2","total_lines":"1","rail":"0"},{"id":"250","latitude":"51.5146","longitude":"-0.0973","name":"St. Paul's","display_name":"St. Paul's","zone":"1","total_lines":"1","rail":"0"},{"id":"251","latitude":"51.5569","longitude":"-0.3366","name":"Sudbury Hill","display_name":"Sudbury<br />Hill","zone":"4","total_lines":"1","rail":"0"},{"id":"252","latitude":"51.5507","longitude":"-0.3156","name":"Sudbury Town","display_name":"Sudbury<br />Town","zone":"4","total_lines":"1","rail":"0"},{"id":"253","latitude":"51.4933","longitude":"-0.0478","name":"Surrey Quays","display_name":"Surrey<br />Quays","zone":"2","total_lines":"1","rail":"0"},{"id":"254","latitude":"51.5432","longitude":"-0.1738","name":"Swiss Cottage","display_name":"Swiss<br />Cottage","zone":"2","total_lines":"2","rail":"0"},{"id":"255","latitude":"51.5111","longitude":"-0.1141","name":"Temple","display_name":"NULL","zone":"1","total_lines":"2","rail":"0"},{"id":"257","latitude":"51.4361","longitude":"-0.1598","name":"Tooting Bec","display_name":"Tooting<br />Bec","zone":"3","total_lines":"1","rail":"0"},{"id":"258","latitude":"51.4275","longitude":"-0.168","name":"Tooting Broadway","display_name":"Tooting<br />Broadway","zone":"3","total_lines":"1","rail":"0"},{"id":"259","latitude":"51.5165","longitude":"-0.131","name":"Tottenham Court Road","display_name":"Tottenham<br />Court<br />Road","zone":"1","total_lines":"2","rail":"0"},{"id":"260","latitude":"51.5882","longitude":"-0.0594","name":"Tottenham Hale","display_name":"Tottenham<br />Hale","zone":"3","total_lines":"1","rail":"1"},{"id":"262","latitude":"51.5106","longitude":"-0.0743","name":"Tower Gateway","display_name":"Tower<br />Gateway","zone":"1","total_lines":"1","rail":"0"},{"id":"263","latitude":"51.5098","longitude":"-0.0766","name":"Tower Hill","display_name":"Tower<br />Hill","zone":"1","total_lines":"2","rail":"0"},{"id":"264","latitude":"51.5567","longitude":"-0.1374","name":"Tufnell Park","display_name":"Tufnell<br />Park","zone":"2","total_lines":"1","rail":"0"},{"id":"265","latitude":"51.4951","longitude":"-0.2547","name":"Turnham Green","display_name":"Turnham<br />Green","zone":"2.5","total_lines":"2","rail":"0"},{"id":"266","latitude":"51.5904","longitude":"-0.1028","name":"Turnpike Lane","display_name":"Turnpike<br />Lane","zone":"3","total_lines":"1","rail":"0"},{"id":"267","latitude":"51.559","longitude":"0.251","name":"Upminster","display_name":"NULL","zone":"6","total_lines":"1","rail":"1"},{"id":"268","latitude":"51.5582","longitude":"0.2343","name":"Upminster Bridge","display_name":"Upminster<br />Bridge","zone":"6","total_lines":"1","rail":"0"},{"id":"269","latitude":"51.5385","longitude":"0.1014","name":"Upney","display_name":"NULL","zone":"4","total_lines":"1","rail":"0"},{"id":"270","latitude":"51.5352","longitude":"0.0343","name":"Upton Park","display_name":"Upton<br />Park","zone":"3","total_lines":"2","rail":"0"},{"id":"271","latitude":"51.5463","longitude":"-0.4786","name":"Uxbridge","display_name":"NULL","zone":"6","total_lines":"2","rail":"0"},{"id":"272","latitude":"51.4861","longitude":"-0.1253","name":"Vauxhall","display_name":"NULL","zone":"1.5","total_lines":"1","rail":"1"},{"id":"273","latitude":"51.4965","longitude":"-0.1447","name":"Victoria","display_name":"NULL","zone":"1","total_lines":"3","rail":"1"},{"id":"274","latitude":"51.583","longitude":"-0.0195","name":"Walthamstow Central","display_name":"Walthamstow<br />Central","zone":"3","total_lines":"1","rail":"1"},{"id":"275","latitude":"51.5775","longitude":"0.0288","name":"Wanstead","display_name":"NULL","zone":"4","total_lines":"1","rail":"0"},{"id":"276","latitude":"51.5043","longitude":"-0.0558","name":"Wapping","display_name":"NULL","zone":"2","total_lines":"1","rail":"0"},{"id":"277","latitude":"51.5247","longitude":"-0.1384","name":"Warren Street","display_name":"Warren<br />Street","zone":"1","total_lines":"2","rail":"0"},{"id":"278","latitude":"51.5235","longitude":"-0.1835","name":"Warwick Avenue","display_name":"Warwick<br />Avenue","zone":"2","total_lines":"1","rail":"0"},{"id":"279","latitude":"51.5036","longitude":"-0.1143","name":"Waterloo","display_name":"NULL","zone":"1","total_lines":"4","rail":"1"},{"id":"281","latitude":"51.5519","longitude":"-0.2963","name":"Wembley Central","display_name":"Wembley<br />Central","zone":"4","total_lines":"1","rail":"1"},{"id":"282","latitude":"51.5635","longitude":"-0.2795","name":"Wembley Park","display_name":"Wembley<br />Park","zone":"4","total_lines":"2","rail":"0"},{"id":"283","latitude":"51.521","longitude":"-0.2011","name":"Westbourne Park","display_name":"Westbourne<br />Park","zone":"2","total_lines":"1","rail":"0"},{"id":"284","latitude":"51.5097","longitude":"-0.0265","name":"Westferry","display_name":"NULL","zone":"2","total_lines":"1","rail":"0"},{"id":"285","latitude":"51.501","longitude":"-0.1254","name":"Westminster","display_name":"NULL","zone":"1","total_lines":"3","rail":"0"},{"id":"286","latitude":"51.518","longitude":"-0.2809","name":"West Acton","display_name":"West<br />Acton","zone":"3","total_lines":"1","rail":"0"},{"id":"287","latitude":"51.4872","longitude":"-0.1953","name":"West Brompton","display_name":"West<br />Brompton","zone":"2","total_lines":"1","rail":"1"},{"id":"288","latitude":"51.6095","longitude":"-0.1883","name":"West Finchley","display_name":"West<br />Finchley","zone":"4","total_lines":"1","rail":"0"},{"id":"289","latitude":"51.5287","longitude":"0.0056","name":"West Ham","display_name":"West<br />Ham","zone":"3","total_lines":"3","rail":"1"},{"id":"290","latitude":"51.5469","longitude":"-0.1906","name":"West Hampstead","display_name":"West<br />Hampstead","zone":"2","total_lines":"1","rail":"1"},{"id":"291","latitude":"51.5795","longitude":"-0.3533","name":"West Harrow","display_name":"West<br />Harrow","zone":"5","total_lines":"1","rail":"0"},{"id":"292","latitude":"51.507","longitude":"-0.0203","name":"West India Quay","display_name":"West<br />India<br />Quay","zone":"2","total_lines":"1","rail":"0"},{"id":"293","latitude":"51.4907","longitude":"-0.2065","name":"West Kensington","display_name":"West<br />Kensington","zone":"2","total_lines":"1","rail":"0"},{"id":"294","latitude":"51.5696","longitude":"-0.4376","name":"West Ruislip","display_name":"West<br />Ruislip","zone":"6","total_lines":"1","rail":"1"},{"id":"295","latitude":"51.5194","longitude":"-0.0612","name":"Whitechapel","display_name":"NULL","zone":"2","total_lines":"3","rail":"0"},{"id":"296","latitude":"51.512","longitude":"-0.2239","name":"White City","display_name":"White<br />City","zone":"2","total_lines":"1","rail":"0"},{"id":"297","latitude":"51.5492","longitude":"-0.2215","name":"Willesden Green","display_name":"Willesden<br />Green","zone":"2.5","total_lines":"1","rail":"0"},{"id":"298","latitude":"51.5326","longitude":"-0.2478","name":"Willesden Junction","display_name":"Willesden<br />Junction","zone":"3","total_lines":"1","rail":"1"},{"id":"299","latitude":"51.4214","longitude":"-0.2064","name":"Wimbledon","display_name":"NULL","zone":"3","total_lines":"1","rail":"1"},{"id":"300","latitude":"51.4343","longitude":"-0.1992","name":"Wimbledon Park","display_name":"Wimbledon<br />Park","zone":"3","total_lines":"1","rail":"0"},{"id":"301","latitude":"51.607","longitude":"0.0341","name":"Woodford","display_name":"NULL","zone":"4","total_lines":"1","rail":"0"},{"id":"302","latitude":"51.6179","longitude":"-0.1856","name":"Woodside Park","display_name":"Woodside<br />Park","zone":"4","total_lines":"1","rail":"0"},{"id":"303","latitude":"51.5975","longitude":"-0.1097","name":"Wood Green","display_name":"Wood<br />Green","zone":"3","total_lines":"1","rail":"0"},{"id":"35","latitude":"51.4627","longitude":"-0.1145","name":"Brixton","display_name":"NULL","zone":"2","total_lines":"1","rail":"1"},{"id":"6","latitude":"51.6736","longitude":"-0.607","name":"Amersham","display_name":"NULL","zone":"10","total_lines":"1","rail":"1"},{"id":"23","latitude":"51.4979","longitude":"-0.0637","name":"Bermondsey","display_name":"NULL","zone":"2","total_lines":"1","rail":"0"},{"id":"50","latitude":"51.7052","longitude":"-0.611","name":"Chesham","display_name":"NULL","zone":"10","total_lines":"1","rail":"0"},{"id":"46","latitude":"51.6679","longitude":"-0.561","name":"Chalfont & Latimer","display_name":"Chalfont &<br />Latimer","zone":"9","total_lines":"1","rail":"1"},{"id":"53","latitude":"51.6543","longitude":"-0.5183","name":"Chorleywood","display_name":"NULL","zone":"8","total_lines":"1","rail":"0"},{"id":"214","latitude":"51.6404","longitude":"-0.4733","name":"Rickmansworth","display_name":"NULL","zone":"7","total_lines":"1","rail":"0"},{"id":"62","latitude":"51.647","longitude":"-0.4412","name":"Croxley","display_name":"NULL","zone":"7","total_lines":"1","rail":"0"},{"id":"280","latitude":"51.6573","longitude":"-0.4177","name":"Watford","display_name":"NULL","zone":"8","total_lines":"1","rail":"0"},{"id":"221","latitude":"51.5606","longitude":"-0.4103","name":"Ruislip Gardens","display_name":"Ruislip<br />Gardens","zone":"5","total_lines":"1","rail":"0"},{"id":"121","latitude":"51.6503","longitude":"-0.1943","name":"High Barnet","display_name":"High<br />Barnet","zone":"5","total_lines":"1","rail":"0"},{"id":"261","latitude":"51.6302","longitude":"-0.1791","name":"Totteridge & Whetstone","display_name":"Totteridge<br />& Whetstone","zone":"4","total_lines":"1","rail":"0"},{"id":"57","latitude":"51.6517","longitude":"-0.1496","name":"Cockfosters","display_name":"NULL","zone":"5","total_lines":"1","rail":"0"},{"id":"187","latitude":"51.6476","longitude":"-0.1318","name":"Oakwood","display_name":"NULL","zone":"5","total_lines":"1","rail":"0"},{"id":"232","latitude":"51.6322","longitude":"-0.128","name":"Southgate","display_name":"NULL","zone":"4","total_lines":"1","rail":"0"},{"id":"88","latitude":"51.6937","longitude":"0.1139","name":"Epping","display_name":"NULL","zone":"6","total_lines":"1","rail":"0"},{"id":"256","latitude":"51.6717","longitude":"0.1033","name":"Theydon Bois","display_name":"Theydon<br />Bois","zone":"6","total_lines":"1","rail":"0"},{"id":"68","latitude":"51.6455","longitude":"0.0838","name":"Debden","display_name":"NULL","zone":"6","total_lines":"1","rail":"0"},{"id":"158","latitude":"51.6412","longitude":"0.0558","name":"Loughton","display_name":"NULL","zone":"6","total_lines":"1","rail":"0"},{"id":"37","latitude":"51.6266","longitude":"0.0471","name":"Buckhurst Hill","display_name":"Buckhurst<br />Hill","zone":"5","total_lines":"1","rail":"0"},{"id":"204","latitude":"51.5343","longitude":"-0.0139","name":"Pudding Mill Lane","display_name":"Pudding<br />Mill Lane","zone":"2.5","total_lines":"1","rail":"0"},{"id":"233","latitude":"51.501","longitude":"-0.1052","name":"Southwark","display_name":"NULL","zone":"1","total_lines":"1","rail":"0"},{"id":"41","latitude":"51.4982","longitude":"-0.0502","name":"Canada Water","display_name":"Canada<br />Water","zone":"2","total_lines":"2","rail":"0"},{"id":"43","latitude":"51.5147","longitude":"0.0082","name":"Canning Town","display_name":"Canning<br />Town","zone":"3","total_lines":"2","rail":"0"},{"id":"183","latitude":"51.5005","longitude":"0.0039","name":"North Greenwich","display_name":"North<br />Greenwich","zone":"2.5","total_lines":"1","rail":"0"},{"id":"64","latitude":"51.4827","longitude":"-0.0096","name":"Cutty Sark","display_name":"Cutty<br />Sark","zone":"2.5","total_lines":"1","rail":"0"},{"id":"106","latitude":"51.4781","longitude":"-0.0149","name":"Greenwich","display_name":"NULL","zone":"2.5","total_lines":"1","rail":"1"},{"id":"69","latitude":"51.474","longitude":"-0.0216","name":"Deptford Bridge","display_name":"Deptford<br />Bridge","zone":"2.5","total_lines":"1","rail":"0"},{"id":"86","latitude":"51.4693","longitude":"-0.0174","name":"Elverson Road","display_name":"Elverson<br />Road","zone":"2.5","total_lines":"1","rail":"0"},{"id":"152","latitude":"51.4657","longitude":"-0.0142","name":"Lewisham","display_name":"NULL","zone":"2.5","total_lines":"1","rail":"1"},{"id":"174","latitude":"51.4767","longitude":"-0.0327","name":"New Cross","display_name":"New<br />Cross","zone":"2","total_lines":"1","rail":"1"},{"id":"175","latitude":"51.4757","longitude":"-0.0402","name":"New Cross Gate","display_name":"New<br />Cross<br />Gate","zone":"2","total_lines":"1","rail":"1"}]} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.TubeMaps=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ | |
(function (__dirname){ | |
module.exports = { | |
"london": { | |
csv: { | |
connections: __dirname + '/london.connections.csv', | |
lines: __dirname + '/london.lines.csv', | |
stations: __dirname + '/london.stations.csv' | |
}, | |
json: __dirname + '/london.json' | |
} | |
}; | |
}).call(this,"/datasets") | |
},{}],2:[function(require,module,exports){ | |
var async = require('async'); | |
var fs = require('fs'); | |
var path = require('path'); | |
var JSONStream = require('JSONStream'); | |
var __ = require('highland'); | |
var datasets = require('./datasets'); | |
exports.TubeMap = TubeMap; | |
exports.Maps = Maps; | |
function Station(opts) { | |
this.id = opts.id; | |
this.conns = opts.conns || []; | |
this.name = opts.name || "Unknown"; | |
this.display_name = opts.display_name || "Unknown"; | |
this.rail = opts.rail ? parseInt(opts.rail, 10) : null; | |
this.total_lines = opts.total_lines ? parseInt(opts.total_lines, 10) : 1; | |
this.latitude = +parseFloat(opts.latitude); | |
this.longitude = +parseFloat(opts.longitude); | |
} | |
function TubeMap(opts) { | |
opts = opts || {}; | |
this.stationsById = {}; | |
this.stationsByName = {}; | |
this.linesById = {}; | |
this.linesByName = {}; | |
this.stations = opts.stations || []; | |
this.connections = opts.connections || []; | |
this.lines = opts.lines || []; | |
this.make(); | |
} | |
TubeMap.prototype.makeStation = function(s) { | |
s = new Station(s); | |
this.stationsById[s.id] = s; | |
this.stationsByName[s.name] = s; | |
}; | |
TubeMap.prototype.getAdjacent = function (root, line) { | |
var conns = root.conns; | |
if (line) { | |
conns = conns.filter(function (c) { | |
return c.line == line; | |
}); | |
} | |
return conns.map(function(c) { | |
c.station1.line = c.line; | |
c.station2.line = c.line; | |
return c.station1.id !== root.id ? c.station1 : c.station2; | |
}); | |
}; | |
TubeMap.prototype.constructPath = function (dict, path, start, destination){ | |
if (path[path.length-1] && path[path.length-1].station2 == start) { | |
return path; | |
} | |
path.push({station1: destination, station2: dict[destination.id]}); | |
return this.constructPath(dict, path, start, dict[destination.id]); | |
}; | |
TubeMap.prototype.path = function(start, destination, line){ | |
var Q = [destination]; | |
var V = {}; | |
var family = {}; | |
family[destination.id] = null; | |
while (Q.length > 0) { | |
var currentStation = Q.shift(); | |
if (currentStation.id in V) { | |
continue; | |
} | |
var conns = this.getAdjacent(currentStation, line); | |
conns.forEach(function(child) { | |
if (!(child.id in V)){ | |
Q.push(child); | |
} | |
if (!(child.id in family)){ | |
family[child.id] = currentStation; | |
} | |
}); | |
V[currentStation.id] = currentStation; | |
if (currentStation.id === start.id) { | |
var path = this.constructPath(family, [], destination, start); | |
if (line) { | |
path = path.map(function(d) { | |
d.line = line; | |
return d; | |
}); | |
} | |
return path; | |
} | |
} | |
return false; | |
}; | |
TubeMap.prototype.line = function(id) { | |
return this.connections.filter(function(d) { | |
return d.line == id; | |
}); | |
}; | |
TubeMap.prototype.makeConnection = function(c) { | |
c.station1 = this.stationsById[c.station1]; | |
c.station2 = this.stationsById[c.station2]; | |
c.time = parseInt(c.time, 10); | |
c.station1.conns.push(c); | |
c.station2.conns.push(c); | |
}; | |
TubeMap.prototype.makeLine = function(r) { | |
this.linesById[r.line] = r; | |
this.linesByName[r.name] = r; | |
}; | |
TubeMap.prototype.getLine = function(id) { | |
return this.linesById[id]; | |
}; | |
TubeMap.prototype.getLineByName = function(name) { | |
return this.linesByName[name]; | |
} | |
TubeMap.prototype.getStation = function(id) { | |
return this.stationsById[id]; | |
}; | |
TubeMap.prototype.getStationByName = function(display_name) { | |
return this.stationsByName[display_name]; | |
}; | |
TubeMap.prototype.make = function() { | |
this.stations.forEach(this.makeStation.bind(this)); | |
this.connections.forEach(this.makeConnection.bind(this)); | |
this.lines.forEach(this.makeLine.bind(this)); | |
}; | |
function Maps (city, cb) { | |
var dataset = require(datasets[city].json); | |
cb(null, new TubeMap(dataset)); | |
}; | |
},{"./datasets":1,"JSONStream":3,"async":6,"fs":8,"highland":7,"path":15}],3:[function(require,module,exports){ | |
(function (process,Buffer){ | |
var Parser = require('jsonparse') | |
, through = require('through') | |
/* | |
the value of this.stack that creationix's jsonparse has is weird. | |
it makes this code ugly, but his problem is way harder that mine, | |
so i'll forgive him. | |
*/ | |
exports.parse = function (path, map) { | |
var parser = new Parser() | |
var stream = through(function (chunk) { | |
if('string' === typeof chunk) | |
chunk = new Buffer(chunk) | |
parser.write(chunk) | |
}, | |
function (data) { | |
if(data) | |
stream.write(data) | |
stream.queue(null) | |
}) | |
if('string' === typeof path) | |
path = path.split('.').map(function (e) { | |
if (e === '*') | |
return true | |
else if (e === '') // '..'.split('.') returns an empty string | |
return {recurse: true} | |
else | |
return e | |
}) | |
var count = 0, _key | |
if(!path || !path.length) | |
path = null | |
parser.onValue = function (value) { | |
if (!this.root) | |
stream.root = value | |
if(! path) return | |
var i = 0 // iterates on path | |
var j = 0 // iterates on stack | |
while (i < path.length) { | |
var key = path[i] | |
var c | |
j++ | |
if (key && !key.recurse) { | |
c = (j === this.stack.length) ? this : this.stack[j] | |
if (!c) return | |
if (! check(key, c.key)) return | |
i++ | |
} else { | |
i++ | |
var nextKey = path[i] | |
if (! nextKey) return | |
while (true) { | |
c = (j === this.stack.length) ? this : this.stack[j] | |
if (!c) return | |
if (check(nextKey, c.key)) { i++; break} | |
j++ | |
} | |
} | |
} | |
if (j !== this.stack.length) return | |
count ++ | |
var actualPath = this.stack.slice(1).map(function(element) { return element.key }).concat([this.key]) | |
var data = this.value[this.key] | |
if(null != data) | |
if(null != (data = map ? map(data, actualPath) : data)) | |
stream.queue(data) | |
delete this.value[this.key] | |
} | |
parser._onToken = parser.onToken; | |
parser.onToken = function (token, value) { | |
parser._onToken(token, value); | |
if (this.stack.length === 0) { | |
if (stream.root) { | |
if(!path) | |
stream.queue(stream.root) | |
stream.emit('root', stream.root, count) | |
count = 0; | |
stream.root = null; | |
} | |
} | |
} | |
parser.onError = function (err) { | |
stream.emit('error', err) | |
} | |
return stream | |
} | |
function check (x, y) { | |
if ('string' === typeof x) | |
return y == x | |
else if (x && 'function' === typeof x.exec) | |
return x.exec(y) | |
else if ('boolean' === typeof x) | |
return x | |
else if ('function' === typeof x) | |
return x(y) | |
return false | |
} | |
exports.stringify = function (op, sep, cl, indent) { | |
indent = indent || 0 | |
if (op === false){ | |
op = '' | |
sep = '\n' | |
cl = '' | |
} else if (op == null) { | |
op = '[\n' | |
sep = '\n,\n' | |
cl = '\n]\n' | |
} | |
//else, what ever you like | |
var stream | |
, first = true | |
, anyData = false | |
stream = through(function (data) { | |
anyData = true | |
var json = JSON.stringify(data, null, indent) | |
if(first) { first = false ; stream.queue(op + json)} | |
else stream.queue(sep + json) | |
}, | |
function (data) { | |
if(!anyData) | |
stream.queue(op) | |
stream.queue(cl) | |
stream.queue(null) | |
}) | |
return stream | |
} | |
exports.stringifyObject = function (op, sep, cl, indent) { | |
indent = indent || 0 | |
if (op === false){ | |
op = '' | |
sep = '\n' | |
cl = '' | |
} else if (op == null) { | |
op = '{\n' | |
sep = '\n,\n' | |
cl = '\n}\n' | |
} | |
//else, what ever you like | |
var first = true | |
, anyData = false | |
stream = through(function (data) { | |
anyData = true | |
var json = JSON.stringify(data[0]) + ':' + JSON.stringify(data[1], null, indent) | |
if(first) { first = false ; this.queue(op + json)} | |
else this.queue(sep + json) | |
}, | |
function (data) { | |
if(!anyData) this.queue(op) | |
this.queue(cl) | |
this.queue(null) | |
}) | |
return stream | |
} | |
if(!module.parent && process.title !== 'browser') { | |
process.stdin | |
.pipe(exports.parse(process.argv[2])) | |
.pipe(exports.stringify('[', ',\n', ']\n', 2)) | |
.pipe(process.stdout) | |
} | |
}).call(this,require('_process'),require("buffer").Buffer) | |
},{"_process":16,"buffer":9,"jsonparse":4,"through":5}],4:[function(require,module,exports){ | |
(function (Buffer){ | |
/*global Buffer*/ | |
// Named constants with unique integer values | |
var C = {}; | |
// Tokens | |
var LEFT_BRACE = C.LEFT_BRACE = 0x1; | |
var RIGHT_BRACE = C.RIGHT_BRACE = 0x2; | |
var LEFT_BRACKET = C.LEFT_BRACKET = 0x3; | |
var RIGHT_BRACKET = C.RIGHT_BRACKET = 0x4; | |
var COLON = C.COLON = 0x5; | |
var COMMA = C.COMMA = 0x6; | |
var TRUE = C.TRUE = 0x7; | |
var FALSE = C.FALSE = 0x8; | |
var NULL = C.NULL = 0x9; | |
var STRING = C.STRING = 0xa; | |
var NUMBER = C.NUMBER = 0xb; | |
// Tokenizer States | |
var START = C.START = 0x11; | |
var TRUE1 = C.TRUE1 = 0x21; | |
var TRUE2 = C.TRUE2 = 0x22; | |
var TRUE3 = C.TRUE3 = 0x23; | |
var FALSE1 = C.FALSE1 = 0x31; | |
var FALSE2 = C.FALSE2 = 0x32; | |
var FALSE3 = C.FALSE3 = 0x33; | |
var FALSE4 = C.FALSE4 = 0x34; | |
var NULL1 = C.NULL1 = 0x41; | |
var NULL2 = C.NULL3 = 0x42; | |
var NULL3 = C.NULL2 = 0x43; | |
var NUMBER1 = C.NUMBER1 = 0x51; | |
var NUMBER2 = C.NUMBER2 = 0x52; | |
var NUMBER3 = C.NUMBER3 = 0x53; | |
var NUMBER4 = C.NUMBER4 = 0x54; | |
var NUMBER5 = C.NUMBER5 = 0x55; | |
var NUMBER6 = C.NUMBER6 = 0x56; | |
var NUMBER7 = C.NUMBER7 = 0x57; | |
var NUMBER8 = C.NUMBER8 = 0x58; | |
var STRING1 = C.STRING1 = 0x61; | |
var STRING2 = C.STRING2 = 0x62; | |
var STRING3 = C.STRING3 = 0x63; | |
var STRING4 = C.STRING4 = 0x64; | |
var STRING5 = C.STRING5 = 0x65; | |
var STRING6 = C.STRING6 = 0x66; | |
// Parser States | |
var VALUE = C.VALUE = 0x71; | |
var KEY = C.KEY = 0x72; | |
// Parser Modes | |
var OBJECT = C.OBJECT = 0x81; | |
var ARRAY = C.ARRAY = 0x82; | |
// Slow code to string converter (only used when throwing syntax errors) | |
function toknam(code) { | |
var keys = Object.keys(C); | |
for (var i = 0, l = keys.length; i < l; i++) { | |
var key = keys[i]; | |
if (C[key] === code) { return key; } | |
} | |
return code && ("0x" + code.toString(16)); | |
} | |
function Parser() { | |
this.tState = START; | |
this.value = undefined; | |
this.string = undefined; // string data | |
this.unicode = undefined; // unicode escapes | |
// For number parsing | |
this.negative = undefined; | |
this.magnatude = undefined; | |
this.position = undefined; | |
this.exponent = undefined; | |
this.negativeExponent = undefined; | |
this.key = undefined; | |
this.mode = undefined; | |
this.stack = []; | |
this.state = VALUE; | |
this.bytes_remaining = 0; // number of bytes remaining in multi byte utf8 char to read after split boundary | |
this.bytes_in_sequence = 0; // bytes in multi byte utf8 char to read | |
this.temp_buffs = { "2": new Buffer(2), "3": new Buffer(3), "4": new Buffer(4) }; // for rebuilding chars split before boundary is reached | |
} | |
var proto = Parser.prototype; | |
proto.charError = function (buffer, i) { | |
this.onError(new Error("Unexpected " + JSON.stringify(String.fromCharCode(buffer[i])) + " at position " + i + " in state " + toknam(this.tState))); | |
}; | |
proto.onError = function (err) { throw err; }; | |
proto.write = function (buffer) { | |
if (typeof buffer === "string") buffer = new Buffer(buffer); | |
//process.stdout.write("Input: "); | |
//console.dir(buffer.toString()); | |
var n; | |
for (var i = 0, l = buffer.length; i < l; i++) { | |
if (this.tState === START){ | |
n = buffer[i]; | |
if(n === 0x7b){ this.onToken(LEFT_BRACE, "{"); // { | |
}else if(n === 0x7d){ this.onToken(RIGHT_BRACE, "}"); // } | |
}else if(n === 0x5b){ this.onToken(LEFT_BRACKET, "["); // [ | |
}else if(n === 0x5d){ this.onToken(RIGHT_BRACKET, "]"); // ] | |
}else if(n === 0x3a){ this.onToken(COLON, ":"); // : | |
}else if(n === 0x2c){ this.onToken(COMMA, ","); // , | |
}else if(n === 0x74){ this.tState = TRUE1; // t | |
}else if(n === 0x66){ this.tState = FALSE1; // f | |
}else if(n === 0x6e){ this.tState = NULL1; // n | |
}else if(n === 0x22){ this.string = ""; this.tState = STRING1; // " | |
}else if(n === 0x2d){ this.negative = true; this.tState = NUMBER1; // - | |
}else if(n === 0x30){ this.magnatude = 0; this.tState = NUMBER2; // 0 | |
}else{ | |
if (n > 0x30 && n < 0x40) { // 1-9 | |
this.magnatude = n - 0x30; this.tState = NUMBER3; | |
} else if (n === 0x20 || n === 0x09 || n === 0x0a || n === 0x0d) { | |
// whitespace | |
} else { this.charError(buffer, i); } | |
} | |
}else if (this.tState === STRING1){ // After open quote | |
n = buffer[i]; // get current byte from buffer | |
// check for carry over of a multi byte char split between data chunks | |
// & fill temp buffer it with start of this data chunk up to the boundary limit set in the last iteration | |
if (this.bytes_remaining > 0) { | |
for (var j = 0; j < this.bytes_remaining; j++) { | |
this.temp_buffs[this.bytes_in_sequence][this.bytes_in_sequence - this.bytes_remaining + j] = buffer[j]; | |
} | |
this.string += this.temp_buffs[this.bytes_in_sequence].toString(); | |
this.bytes_in_sequence = this.bytes_remaining = 0; | |
i = i + j - 1; | |
} else if (this.bytes_remaining === 0 && n >= 128) { // else if no remainder bytes carried over, parse multi byte (>=128) chars one at a time | |
if ((n >= 194) && (n <= 223)) this.bytes_in_sequence = 2; | |
if ((n >= 224) && (n <= 239)) this.bytes_in_sequence = 3; | |
if ((n >= 240) && (n <= 244)) this.bytes_in_sequence = 4; | |
if ((this.bytes_in_sequence + i) > buffer.length) { // if bytes needed to complete char fall outside buffer length, we have a boundary split | |
for (var k = 0; k <= (buffer.length - 1 - i); k++) { | |
this.temp_buffs[this.bytes_in_sequence][k] = buffer[i + k]; // fill temp buffer of correct size with bytes available in this chunk | |
} | |
this.bytes_remaining = (i + this.bytes_in_sequence) - buffer.length; | |
i = buffer.length - 1; | |
} else { | |
this.string += buffer.slice(i, (i + this.bytes_in_sequence)).toString(); | |
i = i + this.bytes_in_sequence - 1; | |
} | |
} else if (n === 0x22) { this.tState = START; this.onToken(STRING, this.string); this.string = undefined; } | |
else if (n === 0x5c) { this.tState = STRING2; } | |
else if (n >= 0x20) { this.string += String.fromCharCode(n); } | |
else { this.charError(buffer, i); } | |
}else if (this.tState === STRING2){ // After backslash | |
n = buffer[i]; | |
if(n === 0x22){ this.string += "\""; this.tState = STRING1; | |
}else if(n === 0x5c){ this.string += "\\"; this.tState = STRING1; | |
}else if(n === 0x2f){ this.string += "\/"; this.tState = STRING1; | |
}else if(n === 0x62){ this.string += "\b"; this.tState = STRING1; | |
}else if(n === 0x66){ this.string += "\f"; this.tState = STRING1; | |
}else if(n === 0x6e){ this.string += "\n"; this.tState = STRING1; | |
}else if(n === 0x72){ this.string += "\r"; this.tState = STRING1; | |
}else if(n === 0x74){ this.string += "\t"; this.tState = STRING1; | |
}else if(n === 0x75){ this.unicode = ""; this.tState = STRING3; | |
}else{ | |
this.charError(buffer, i); | |
} | |
}else if (this.tState === STRING3 || this.tState === STRING4 || this.tState === STRING5 || this.tState === STRING6){ // unicode hex codes | |
n = buffer[i]; | |
// 0-9 A-F a-f | |
if ((n >= 0x30 && n < 0x40) || (n > 0x40 && n <= 0x46) || (n > 0x60 && n <= 0x66)) { | |
this.unicode += String.fromCharCode(n); | |
if (this.tState++ === STRING6) { | |
this.string += String.fromCharCode(parseInt(this.unicode, 16)); | |
this.unicode = undefined; | |
this.tState = STRING1; | |
} | |
} else { | |
this.charError(buffer, i); | |
} | |
}else if (this.tState === NUMBER1){ // after minus | |
n = buffer[i]; | |
if (n === 0x30) { this.magnatude = 0; this.tState = NUMBER2; } | |
else if (n > 0x30 && n < 0x40) { this.magnatude = n - 0x30; this.tState = NUMBER3; } | |
else { this.charError(buffer, i); } | |
}else if (this.tState === NUMBER2){ // * After initial zero | |
n = buffer[i]; | |
if(n === 0x2e){ // . | |
this.position = 0.1; this.tState = NUMBER4; | |
}else if(n === 0x65 || n === 0x45){ // e/E | |
this.exponent = 0; this.tState = NUMBER6; | |
}else{ | |
this.tState = START; | |
this.onToken(NUMBER, 0); | |
this.magnatude = undefined; | |
this.negative = undefined; | |
i--; | |
} | |
}else if (this.tState === NUMBER3){ // * After digit (before period) | |
n = buffer[i]; | |
if(n === 0x2e){ // . | |
this.position = 0.1; this.tState = NUMBER4; | |
}else if(n === 0x65 || n === 0x45){ // e/E | |
this.exponent = 0; this.tState = NUMBER6; | |
}else{ | |
if (n >= 0x30 && n < 0x40) { this.magnatude = this.magnatude * 10 + n - 0x30; } | |
else { | |
this.tState = START; | |
if (this.negative) { | |
this.magnatude = -this.magnatude; | |
this.negative = undefined; | |
} | |
this.onToken(NUMBER, this.magnatude); | |
this.magnatude = undefined; | |
i--; | |
} | |
} | |
}else if (this.tState === NUMBER4){ // After period | |
n = buffer[i]; | |
if (n >= 0x30 && n < 0x40) { // 0-9 | |
this.magnatude += this.position * (n - 0x30); | |
this.position /= 10; | |
this.tState = NUMBER5; | |
} else { this.charError(buffer, i); } | |
}else if (this.tState === NUMBER5){ // * After digit (after period) | |
n = buffer[i]; | |
if (n >= 0x30 && n < 0x40) { // 0-9 | |
this.magnatude += this.position * (n - 0x30); | |
this.position /= 10; | |
} | |
else if (n === 0x65 || n === 0x45) { this.exponent = 0; this.tState = NUMBER6; } // E/e | |
else { | |
this.tState = START; | |
if (this.negative) { | |
this.magnatude = -this.magnatude; | |
this.negative = undefined; | |
} | |
this.onToken(NUMBER, this.negative ? -this.magnatude : this.magnatude); | |
this.magnatude = undefined; | |
this.position = undefined; | |
i--; | |
} | |
}else if (this.tState === NUMBER6){ // After E | |
n = buffer[i]; | |
if (n === 0x2b || n === 0x2d) { // +/- | |
if (n === 0x2d) { this.negativeExponent = true; } | |
this.tState = NUMBER7; | |
} | |
else if (n >= 0x30 && n < 0x40) { | |
this.exponent = this.exponent * 10 + (n - 0x30); | |
this.tState = NUMBER8; | |
} | |
else { this.charError(buffer, i); } | |
}else if (this.tState === NUMBER7){ // After +/- | |
n = buffer[i]; | |
if (n >= 0x30 && n < 0x40) { // 0-9 | |
this.exponent = this.exponent * 10 + (n - 0x30); | |
this.tState = NUMBER8; | |
} | |
else { this.charError(buffer, i); } | |
}else if (this.tState === NUMBER8){ // * After digit (after +/-) | |
n = buffer[i]; | |
if (n >= 0x30 && n < 0x40) { // 0-9 | |
this.exponent = this.exponent * 10 + (n - 0x30); | |
} | |
else { | |
if (this.negativeExponent) { | |
this.exponent = -this.exponent; | |
this.negativeExponent = undefined; | |
} | |
this.magnatude *= Math.pow(10, this.exponent); | |
this.exponent = undefined; | |
if (this.negative) { | |
this.magnatude = -this.magnatude; | |
this.negative = undefined; | |
} | |
this.tState = START; | |
this.onToken(NUMBER, this.magnatude); | |
this.magnatude = undefined; | |
i--; | |
} | |
}else if (this.tState === TRUE1){ // r | |
if (buffer[i] === 0x72) { this.tState = TRUE2; } | |
else { this.charError(buffer, i); } | |
}else if (this.tState === TRUE2){ // u | |
if (buffer[i] === 0x75) { this.tState = TRUE3; } | |
else { this.charError(buffer, i); } | |
}else if (this.tState === TRUE3){ // e | |
if (buffer[i] === 0x65) { this.tState = START; this.onToken(TRUE, true); } | |
else { this.charError(buffer, i); } | |
}else if (this.tState === FALSE1){ // a | |
if (buffer[i] === 0x61) { this.tState = FALSE2; } | |
else { this.charError(buffer, i); } | |
}else if (this.tState === FALSE2){ // l | |
if (buffer[i] === 0x6c) { this.tState = FALSE3; } | |
else { this.charError(buffer, i); } | |
}else if (this.tState === FALSE3){ // s | |
if (buffer[i] === 0x73) { this.tState = FALSE4; } | |
else { this.charError(buffer, i); } | |
}else if (this.tState === FALSE4){ // e | |
if (buffer[i] === 0x65) { this.tState = START; this.onToken(FALSE, false); } | |
else { this.charError(buffer, i); } | |
}else if (this.tState === NULL1){ // u | |
if (buffer[i] === 0x75) { this.tState = NULL2; } | |
else { this.charError(buffer, i); } | |
}else if (this.tState === NULL2){ // l | |
if (buffer[i] === 0x6c) { this.tState = NULL3; } | |
else { this.charError(buffer, i); } | |
}else if (this.tState === NULL3){ // l | |
if (buffer[i] === 0x6c) { this.tState = START; this.onToken(NULL, null); } | |
else { this.charError(buffer, i); } | |
} | |
} | |
}; | |
proto.onToken = function (token, value) { | |
// Override this to get events | |
}; | |
proto.parseError = function (token, value) { | |
this.onError(new Error("Unexpected " + toknam(token) + (value ? ("(" + JSON.stringify(value) + ")") : "") + " in state " + toknam(this.state))); | |
}; | |
proto.onError = function (err) { throw err; }; | |
proto.push = function () { | |
this.stack.push({value: this.value, key: this.key, mode: this.mode}); | |
}; | |
proto.pop = function () { | |
var value = this.value; | |
var parent = this.stack.pop(); | |
this.value = parent.value; | |
this.key = parent.key; | |
this.mode = parent.mode; | |
this.emit(value); | |
if (!this.mode) { this.state = VALUE; } | |
}; | |
proto.emit = function (value) { | |
if (this.mode) { this.state = COMMA; } | |
this.onValue(value); | |
}; | |
proto.onValue = function (value) { | |
// Override me | |
}; | |
proto.onToken = function (token, value) { | |
//console.log("OnToken: state=%s token=%s %s", toknam(this.state), toknam(token), value?JSON.stringify(value):""); | |
if(this.state === VALUE){ | |
if(token === STRING || token === NUMBER || token === TRUE || token === FALSE || token === NULL){ | |
if (this.value) { | |
this.value[this.key] = value; | |
} | |
this.emit(value); | |
}else if(token === LEFT_BRACE){ | |
this.push(); | |
if (this.value) { | |
this.value = this.value[this.key] = {}; | |
} else { | |
this.value = {}; | |
} | |
this.key = undefined; | |
this.state = KEY; | |
this.mode = OBJECT; | |
}else if(token === LEFT_BRACKET){ | |
this.push(); | |
if (this.value) { | |
this.value = this.value[this.key] = []; | |
} else { | |
this.value = []; | |
} | |
this.key = 0; | |
this.mode = ARRAY; | |
this.state = VALUE; | |
}else if(token === RIGHT_BRACE){ | |
if (this.mode === OBJECT) { | |
this.pop(); | |
} else { | |
this.parseError(token, value); | |
} | |
}else if(token === RIGHT_BRACKET){ | |
if (this.mode === ARRAY) { | |
this.pop(); | |
} else { | |
this.parseError(token, value); | |
} | |
}else{ | |
this.parseError(token, value); | |
} | |
}else if(this.state === KEY){ | |
if (token === STRING) { | |
this.key = value; | |
this.state = COLON; | |
} else if (token === RIGHT_BRACE) { | |
this.pop(); | |
} else { | |
this.parseError(token, value); | |
} | |
}else if(this.state === COLON){ | |
if (token === COLON) { this.state = VALUE; } | |
else { this.parseError(token, value); } | |
}else if(this.state === COMMA){ | |
if (token === COMMA) { | |
if (this.mode === ARRAY) { this.key++; this.state = VALUE; } | |
else if (this.mode === OBJECT) { this.state = KEY; } | |
} else if (token === RIGHT_BRACKET && this.mode === ARRAY || token === RIGHT_BRACE && this.mode === OBJECT) { | |
this.pop(); | |
} else { | |
this.parseError(token, value); | |
} | |
}else{ | |
this.parseError(token, value); | |
} | |
}; | |
module.exports = Parser; | |
}).call(this,require("buffer").Buffer) | |
},{"buffer":9}],5:[function(require,module,exports){ | |
(function (process){ | |
var Stream = require('stream') | |
// through | |
// | |
// a stream that does nothing but re-emit the input. | |
// useful for aggregating a series of changing but not ending streams into one stream) | |
exports = module.exports = through | |
through.through = through | |
//create a readable writable stream. | |
function through (write, end, opts) { | |
write = write || function (data) { this.queue(data) } | |
end = end || function () { this.queue(null) } | |
var ended = false, destroyed = false, buffer = [], _ended = false | |
var stream = new Stream() | |
stream.readable = stream.writable = true | |
stream.paused = false | |
// stream.autoPause = !(opts && opts.autoPause === false) | |
stream.autoDestroy = !(opts && opts.autoDestroy === false) | |
stream.write = function (data) { | |
write.call(this, data) | |
return !stream.paused | |
} | |
function drain() { | |
while(buffer.length && !stream.paused) { | |
var data = buffer.shift() | |
if(null === data) | |
return stream.emit('end') | |
else | |
stream.emit('data', data) | |
} | |
} | |
stream.queue = stream.push = function (data) { | |
// console.error(ended) | |
if(_ended) return stream | |
if(data == null) _ended = true | |
buffer.push(data) | |
drain() | |
return stream | |
} | |
//this will be registered as the first 'end' listener | |
//must call destroy next tick, to make sure we're after any | |
//stream piped from here. | |
//this is only a problem if end is not emitted synchronously. | |
//a nicer way to do this is to make sure this is the last listener for 'end' | |
stream.on('end', function () { | |
stream.readable = false | |
if(!stream.writable && stream.autoDestroy) | |
process.nextTick(function () { | |
stream.destroy() | |
}) | |
}) | |
function _end () { | |
stream.writable = false | |
end.call(stream) | |
if(!stream.readable && stream.autoDestroy) | |
stream.destroy() | |
} | |
stream.end = function (data) { | |
if(ended) return | |
ended = true | |
if(arguments.length) stream.write(data) | |
_end() // will emit or queue | |
return stream | |
} | |
stream.destroy = function () { | |
if(destroyed) return | |
destroyed = true | |
ended = true | |
buffer.length = 0 | |
stream.writable = stream.readable = false | |
stream.emit('close') | |
return stream | |
} | |
stream.pause = function () { | |
if(stream.paused) return | |
stream.paused = true | |
return stream | |
} | |
stream.resume = function () { | |
if(stream.paused) { | |
stream.paused = false | |
stream.emit('resume') | |
} | |
drain() | |
//may have become paused again, | |
//as drain emits 'data'. | |
if(!stream.paused) | |
stream.emit('drain') | |
return stream | |
} | |
return stream | |
} | |
}).call(this,require('_process')) | |
},{"_process":16,"stream":29}],6:[function(require,module,exports){ | |
(function (process){ | |
/*! | |
* async | |
* https://github.com/caolan/async | |
* | |
* Copyright 2010-2014 Caolan McMahon | |
* Released under the MIT license | |
*/ | |
/*jshint onevar: false, indent:4 */ | |
/*global setImmediate: false, setTimeout: false, console: false */ | |
(function () { | |
var async = {}; | |
// global on the server, window in the browser | |
var root, previous_async; | |
root = this; | |
if (root != null) { | |
previous_async = root.async; | |
} | |
async.noConflict = function () { | |
root.async = previous_async; | |
return async; | |
}; | |
function only_once(fn) { | |
var called = false; | |
return function() { | |
if (called) throw new Error("Callback was already called."); | |
called = true; | |
fn.apply(root, arguments); | |
} | |
} | |
//// cross-browser compatiblity functions //// | |
var _toString = Object.prototype.toString; | |
var _isArray = Array.isArray || function (obj) { | |
return _toString.call(obj) === '[object Array]'; | |
}; | |
var _each = function (arr, iterator) { | |
if (arr.forEach) { | |
return arr.forEach(iterator); | |
} | |
for (var i = 0; i < arr.length; i += 1) { | |
iterator(arr[i], i, arr); | |
} | |
}; | |
var _map = function (arr, iterator) { | |
if (arr.map) { | |
return arr.map(iterator); | |
} | |
var results = []; | |
_each(arr, function (x, i, a) { | |
results.push(iterator(x, i, a)); | |
}); | |
return results; | |
}; | |
var _reduce = function (arr, iterator, memo) { | |
if (arr.reduce) { | |
return arr.reduce(iterator, memo); | |
} | |
_each(arr, function (x, i, a) { | |
memo = iterator(memo, x, i, a); | |
}); | |
return memo; | |
}; | |
var _keys = function (obj) { | |
if (Object.keys) { | |
return Object.keys(obj); | |
} | |
var keys = []; | |
for (var k in obj) { | |
if (obj.hasOwnProperty(k)) { | |
keys.push(k); | |
} | |
} | |
return keys; | |
}; | |
//// exported async module functions //// | |
//// nextTick implementation with browser-compatible fallback //// | |
if (typeof process === 'undefined' || !(process.nextTick)) { | |
if (typeof setImmediate === 'function') { | |
async.nextTick = function (fn) { | |
// not a direct alias for IE10 compatibility | |
setImmediate(fn); | |
}; | |
async.setImmediate = async.nextTick; | |
} | |
else { | |
async.nextTick = function (fn) { | |
setTimeout(fn, 0); | |
}; | |
async.setImmediate = async.nextTick; | |
} | |
} | |
else { | |
async.nextTick = process.nextTick; | |
if (typeof setImmediate !== 'undefined') { | |
async.setImmediate = function (fn) { | |
// not a direct alias for IE10 compatibility | |
setImmediate(fn); | |
}; | |
} | |
else { | |
async.setImmediate = async.nextTick; | |
} | |
} | |
async.each = function (arr, iterator, callback) { | |
callback = callback || function () {}; | |
if (!arr.length) { | |
return callback(); | |
} | |
var completed = 0; | |
_each(arr, function (x) { | |
iterator(x, only_once(done) ); | |
}); | |
function done(err) { | |
if (err) { | |
callback(err); | |
callback = function () {}; | |
} | |
else { | |
completed += 1; | |
if (completed >= arr.length) { | |
callback(); | |
} | |
} | |
} | |
}; | |
async.forEach = async.each; | |
async.eachSeries = function (arr, iterator, callback) { | |
callback = callback || function () {}; | |
if (!arr.length) { | |
return callback(); | |
} | |
var completed = 0; | |
var iterate = function () { | |
iterator(arr[completed], function (err) { | |
if (err) { | |
callback(err); | |
callback = function () {}; | |
} | |
else { | |
completed += 1; | |
if (completed >= arr.length) { | |
callback(); | |
} | |
else { | |
iterate(); | |
} | |
} | |
}); | |
}; | |
iterate(); | |
}; | |
async.forEachSeries = async.eachSeries; | |
async.eachLimit = function (arr, limit, iterator, callback) { | |
var fn = _eachLimit(limit); | |
fn.apply(null, [arr, iterator, callback]); | |
}; | |
async.forEachLimit = async.eachLimit; | |
var _eachLimit = function (limit) { | |
return function (arr, iterator, callback) { | |
callback = callback || function () {}; | |
if (!arr.length || limit <= 0) { | |
return callback(); | |
} | |
var completed = 0; | |
var started = 0; | |
var running = 0; | |
(function replenish () { | |
if (completed >= arr.length) { | |
return callback(); | |
} | |
while (running < limit && started < arr.length) { | |
started += 1; | |
running += 1; | |
iterator(arr[started - 1], function (err) { | |
if (err) { | |
callback(err); | |
callback = function () {}; | |
} | |
else { | |
completed += 1; | |
running -= 1; | |
if (completed >= arr.length) { | |
callback(); | |
} | |
else { | |
replenish(); | |
} | |
} | |
}); | |
} | |
})(); | |
}; | |
}; | |
var doParallel = function (fn) { | |
return function () { | |
var args = Array.prototype.slice.call(arguments); | |
return fn.apply(null, [async.each].concat(args)); | |
}; | |
}; | |
var doParallelLimit = function(limit, fn) { | |
return function () { | |
var args = Array.prototype.slice.call(arguments); | |
return fn.apply(null, [_eachLimit(limit)].concat(args)); | |
}; | |
}; | |
var doSeries = function (fn) { | |
return function () { | |
var args = Array.prototype.slice.call(arguments); | |
return fn.apply(null, [async.eachSeries].concat(args)); | |
}; | |
}; | |
var _asyncMap = function (eachfn, arr, iterator, callback) { | |
arr = _map(arr, function (x, i) { | |
return {index: i, value: x}; | |
}); | |
if (!callback) { | |
eachfn(arr, function (x, callback) { | |
iterator(x.value, function (err) { | |
callback(err); | |
}); | |
}); | |
} else { | |
var results = []; | |
eachfn(arr, function (x, callback) { | |
iterator(x.value, function (err, v) { | |
results[x.index] = v; | |
callback(err); | |
}); | |
}, function (err) { | |
callback(err, results); | |
}); | |
} | |
}; | |
async.map = doParallel(_asyncMap); | |
async.mapSeries = doSeries(_asyncMap); | |
async.mapLimit = function (arr, limit, iterator, callback) { | |
return _mapLimit(limit)(arr, iterator, callback); | |
}; | |
var _mapLimit = function(limit) { | |
return doParallelLimit(limit, _asyncMap); | |
}; | |
// reduce only has a series version, as doing reduce in parallel won't | |
// work in many situations. | |
async.reduce = function (arr, memo, iterator, callback) { | |
async.eachSeries(arr, function (x, callback) { | |
iterator(memo, x, function (err, v) { | |
memo = v; | |
callback(err); | |
}); | |
}, function (err) { | |
callback(err, memo); | |
}); | |
}; | |
// inject alias | |
async.inject = async.reduce; | |
// foldl alias | |
async.foldl = async.reduce; | |
async.reduceRight = function (arr, memo, iterator, callback) { | |
var reversed = _map(arr, function (x) { | |
return x; | |
}).reverse(); | |
async.reduce(reversed, memo, iterator, callback); | |
}; | |
// foldr alias | |
async.foldr = async.reduceRight; | |
var _filter = function (eachfn, arr, iterator, callback) { | |
var results = []; | |
arr = _map(arr, function (x, i) { | |
return {index: i, value: x}; | |
}); | |
eachfn(arr, function (x, callback) { | |
iterator(x.value, function (v) { | |
if (v) { | |
results.push(x); | |
} | |
callback(); | |
}); | |
}, function (err) { | |
callback(_map(results.sort(function (a, b) { | |
return a.index - b.index; | |
}), function (x) { | |
return x.value; | |
})); | |
}); | |
}; | |
async.filter = doParallel(_filter); | |
async.filterSeries = doSeries(_filter); | |
// select alias | |
async.select = async.filter; | |
async.selectSeries = async.filterSeries; | |
var _reject = function (eachfn, arr, iterator, callback) { | |
var results = []; | |
arr = _map(arr, function (x, i) { | |
return {index: i, value: x}; | |
}); | |
eachfn(arr, function (x, callback) { | |
iterator(x.value, function (v) { | |
if (!v) { | |
results.push(x); | |
} | |
callback(); | |
}); | |
}, function (err) { | |
callback(_map(results.sort(function (a, b) { | |
return a.index - b.index; | |
}), function (x) { | |
return x.value; | |
})); | |
}); | |
}; | |
async.reject = doParallel(_reject); | |
async.rejectSeries = doSeries(_reject); | |
var _detect = function (eachfn, arr, iterator, main_callback) { | |
eachfn(arr, function (x, callback) { | |
iterator(x, function (result) { | |
if (result) { | |
main_callback(x); | |
main_callback = function () {}; | |
} | |
else { | |
callback(); | |
} | |
}); | |
}, function (err) { | |
main_callback(); | |
}); | |
}; | |
async.detect = doParallel(_detect); | |
async.detectSeries = doSeries(_detect); | |
async.some = function (arr, iterator, main_callback) { | |
async.each(arr, function (x, callback) { | |
iterator(x, function (v) { | |
if (v) { | |
main_callback(true); | |
main_callback = function () {}; | |
} | |
callback(); | |
}); | |
}, function (err) { | |
main_callback(false); | |
}); | |
}; | |
// any alias | |
async.any = async.some; | |
async.every = function (arr, iterator, main_callback) { | |
async.each(arr, function (x, callback) { | |
iterator(x, function (v) { | |
if (!v) { | |
main_callback(false); | |
main_callback = function () {}; | |
} | |
callback(); | |
}); | |
}, function (err) { | |
main_callback(true); | |
}); | |
}; | |
// all alias | |
async.all = async.every; | |
async.sortBy = function (arr, iterator, callback) { | |
async.map(arr, function (x, callback) { | |
iterator(x, function (err, criteria) { | |
if (err) { | |
callback(err); | |
} | |
else { | |
callback(null, {value: x, criteria: criteria}); | |
} | |
}); | |
}, function (err, results) { | |
if (err) { | |
return callback(err); | |
} | |
else { | |
var fn = function (left, right) { | |
var a = left.criteria, b = right.criteria; | |
return a < b ? -1 : a > b ? 1 : 0; | |
}; | |
callback(null, _map(results.sort(fn), function (x) { | |
return x.value; | |
})); | |
} | |
}); | |
}; | |
async.auto = function (tasks, callback) { | |
callback = callback || function () {}; | |
var keys = _keys(tasks); | |
var remainingTasks = keys.length | |
if (!remainingTasks) { | |
return callback(); | |
} | |
var results = {}; | |
var listeners = []; | |
var addListener = function (fn) { | |
listeners.unshift(fn); | |
}; | |
var removeListener = function (fn) { | |
for (var i = 0; i < listeners.length; i += 1) { | |
if (listeners[i] === fn) { | |
listeners.splice(i, 1); | |
return; | |
} | |
} | |
}; | |
var taskComplete = function () { | |
remainingTasks-- | |
_each(listeners.slice(0), function (fn) { | |
fn(); | |
}); | |
}; | |
addListener(function () { | |
if (!remainingTasks) { | |
var theCallback = callback; | |
// prevent final callback from calling itself if it errors | |
callback = function () {}; | |
theCallback(null, results); | |
} | |
}); | |
_each(keys, function (k) { | |
var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]]; | |
var taskCallback = function (err) { | |
var args = Array.prototype.slice.call(arguments, 1); | |
if (args.length <= 1) { | |
args = args[0]; | |
} | |
if (err) { | |
var safeResults = {}; | |
_each(_keys(results), function(rkey) { | |
safeResults[rkey] = results[rkey]; | |
}); | |
safeResults[k] = args; | |
callback(err, safeResults); | |
// stop subsequent errors hitting callback multiple times | |
callback = function () {}; | |
} | |
else { | |
results[k] = args; | |
async.setImmediate(taskComplete); | |
} | |
}; | |
var requires = task.slice(0, Math.abs(task.length - 1)) || []; | |
var ready = function () { | |
return _reduce(requires, function (a, x) { | |
return (a && results.hasOwnProperty(x)); | |
}, true) && !results.hasOwnProperty(k); | |
}; | |
if (ready()) { | |
task[task.length - 1](taskCallback, results); | |
} | |
else { | |
var listener = function () { | |
if (ready()) { | |
removeListener(listener); | |
task[task.length - 1](taskCallback, results); | |
} | |
}; | |
addListener(listener); | |
} | |
}); | |
}; | |
async.retry = function(times, task, callback) { | |
var DEFAULT_TIMES = 5; | |
var attempts = []; | |
// Use defaults if times not passed | |
if (typeof times === 'function') { | |
callback = task; | |
task = times; | |
times = DEFAULT_TIMES; | |
} | |
// Make sure times is a number | |
times = parseInt(times, 10) || DEFAULT_TIMES; | |
var wrappedTask = function(wrappedCallback, wrappedResults) { | |
var retryAttempt = function(task, finalAttempt) { | |
return function(seriesCallback) { | |
task(function(err, result){ | |
seriesCallback(!err || finalAttempt, {err: err, result: result}); | |
}, wrappedResults); | |
}; | |
}; | |
while (times) { | |
attempts.push(retryAttempt(task, !(times-=1))); | |
} | |
async.series(attempts, function(done, data){ | |
data = data[data.length - 1]; | |
(wrappedCallback || callback)(data.err, data.result); | |
}); | |
} | |
// If a callback is passed, run this as a controll flow | |
return callback ? wrappedTask() : wrappedTask | |
}; | |
async.waterfall = function (tasks, callback) { | |
callback = callback || function () {}; | |
if (!_isArray(tasks)) { | |
var err = new Error('First argument to waterfall must be an array of functions'); | |
return callback(err); | |
} | |
if (!tasks.length) { | |
return callback(); | |
} | |
var wrapIterator = function (iterator) { | |
return function (err) { | |
if (err) { | |
callback.apply(null, arguments); | |
callback = function () {}; | |
} | |
else { | |
var args = Array.prototype.slice.call(arguments, 1); | |
var next = iterator.next(); | |
if (next) { | |
args.push(wrapIterator(next)); | |
} | |
else { | |
args.push(callback); | |
} | |
async.setImmediate(function () { | |
iterator.apply(null, args); | |
}); | |
} | |
}; | |
}; | |
wrapIterator(async.iterator(tasks))(); | |
}; | |
var _parallel = function(eachfn, tasks, callback) { | |
callback = callback || function () {}; | |
if (_isArray(tasks)) { | |
eachfn.map(tasks, function (fn, callback) { | |
if (fn) { | |
fn(function (err) { | |
var args = Array.prototype.slice.call(arguments, 1); | |
if (args.length <= 1) { | |
args = args[0]; | |
} | |
callback.call(null, err, args); | |
}); | |
} | |
}, callback); | |
} | |
else { | |
var results = {}; | |
eachfn.each(_keys(tasks), function (k, callback) { | |
tasks[k](function (err) { | |
var args = Array.prototype.slice.call(arguments, 1); | |
if (args.length <= 1) { | |
args = args[0]; | |
} | |
results[k] = args; | |
callback(err); | |
}); | |
}, function (err) { | |
callback(err, results); | |
}); | |
} | |
}; | |
async.parallel = function (tasks, callback) { | |
_parallel({ map: async.map, each: async.each }, tasks, callback); | |
}; | |
async.parallelLimit = function(tasks, limit, callback) { | |
_parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback); | |
}; | |
async.series = function (tasks, callback) { | |
callback = callback || function () {}; | |
if (_isArray(tasks)) { | |
async.mapSeries(tasks, function (fn, callback) { | |
if (fn) { | |
fn(function (err) { | |
var args = Array.prototype.slice.call(arguments, 1); | |
if (args.length <= 1) { | |
args = args[0]; | |
} | |
callback.call(null, err, args); | |
}); | |
} | |
}, callback); | |
} | |
else { | |
var results = {}; | |
async.eachSeries(_keys(tasks), function (k, callback) { | |
tasks[k](function (err) { | |
var args = Array.prototype.slice.call(arguments, 1); | |
if (args.length <= 1) { | |
args = args[0]; | |
} | |
results[k] = args; | |
callback(err); | |
}); | |
}, function (err) { | |
callback(err, results); | |
}); | |
} | |
}; | |
async.iterator = function (tasks) { | |
var makeCallback = function (index) { | |
var fn = function () { | |
if (tasks.length) { | |
tasks[index].apply(null, arguments); | |
} | |
return fn.next(); | |
}; | |
fn.next = function () { | |
return (index < tasks.length - 1) ? makeCallback(index + 1): null; | |
}; | |
return fn; | |
}; | |
return makeCallback(0); | |
}; | |
async.apply = function (fn) { | |
var args = Array.prototype.slice.call(arguments, 1); | |
return function () { | |
return fn.apply( | |
null |