Skip to content

Instantly share code, notes, and snippets.

@nicola
Last active April 30, 2023 13:50
Show Gist options
  • Save nicola/10e25b18aca0bc05b192 to your computer and use it in GitHub Desktop.
Save nicola/10e25b18aca0bc05b192 to your computer and use it in GitHub Desktop.
London Tube Map with Voronoi
<!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>
{"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"}]}
!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, args.concat(Array.prototype.slice.call(arguments))
);
};
};
var _concat = function (eachfn, arr, fn, callback) {
var r = [];
eachfn(arr, function (x, cb) {
fn(x, function (err, y) {
r = r.concat(y || []);
cb(err);
});
}, function (err) {
callback(err, r);
});
};
async.concat = doParallel(_concat);
async.concatSeries = doSeries(_concat);
async.whilst = function (test, iterator, callback) {
if (test()) {
iterator(function (err) {
if (err) {
return callback(err);
}
async.whilst(test, iterator, callback);
});
}
else {
callback();
}
};
async.doWhilst = function (iterator, test, callback) {
iterator(function (err) {
if (err) {
return callback(err);
}
var args = Array.prototype.slice.call(arguments, 1);
if (test.apply(null, args)) {
async.doWhilst(iterator, test, callback);
}
else {
callback();
}
});
};
async.until = function (test, iterator, callback) {
if (!test()) {
iterator(function (err) {
if (err) {
return callback(err);
}
async.until(test, iterator, callback);
});
}
else {
callback();
}
};
async.doUntil = function (iterator, test, callback) {
iterator(function (err) {
if (err) {
return callback(err);
}
var args = Array.prototype.slice.call(arguments, 1);
if (!test.apply(null, args)) {
async.doUntil(iterator, test, callback);
}
else {
callback();
}
});
};
async.queue = function (worker, concurrency) {
if (concurrency === undefined) {
concurrency = 1;
}
function _insert(q, data, pos, callback) {
if (!q.started){
q.started = true;
}
if (!_isArray(data)) {
data = [data];
}
if(data.length == 0) {
// call drain immediately if there are no tasks
return async.setImmediate(function() {
if (q.drain) {
q.drain();
}
});
}
_each(data, function(task) {
var item = {
data: task,
callback: typeof callback === 'function' ? callback : null
};
if (pos) {
q.tasks.unshift(item);
} else {
q.tasks.push(item);
}
if (q.saturated && q.tasks.length === q.concurrency) {
q.saturated();
}
async.setImmediate(q.process);
});
}
var workers = 0;
var q = {
tasks: [],
concurrency: concurrency,
saturated: null,
empty: null,
drain: null,
started: false,
paused: false,
push: function (data, callback) {
_insert(q, data, false, callback);
},
kill: function () {
q.drain = null;
q.tasks = [];
},
unshift: function (data, callback) {
_insert(q, data, true, callback);
},
process: function () {
if (!q.paused && workers < q.concurrency && q.tasks.length) {
var task = q.tasks.shift();
if (q.empty && q.tasks.length === 0) {
q.empty();
}
workers += 1;
var next = function () {
workers -= 1;
if (task.callback) {
task.callback.apply(task, arguments);
}
if (q.drain && q.tasks.length + workers === 0) {
q.drain();
}
q.process();
};
var cb = only_once(next);
worker(task.data, cb);
}
},
length: function () {
return q.tasks.length;
},
running: function () {
return workers;
},
idle: function() {
return q.tasks.length + workers === 0;
},
pause: function () {
if (q.paused === true) { return; }
q.paused = true;
q.process();
},
resume: function () {
if (q.paused === false) { return; }
q.paused = false;
q.process();
}
};
return q;
};
async.priorityQueue = function (worker, concurrency) {
function _compareTasks(a, b){
return a.priority - b.priority;
};
function _binarySearch(sequence, item, compare) {
var beg = -1,
end = sequence.length - 1;
while (beg < end) {
var mid = beg + ((end - beg + 1) >>> 1);
if (compare(item, sequence[mid]) >= 0) {
beg = mid;
} else {
end = mid - 1;
}
}
return beg;
}
function _insert(q, data, priority, callback) {
if (!q.started){
q.started = true;
}
if (!_isArray(data)) {
data = [data];
}
if(data.length == 0) {
// call drain immediately if there are no tasks
return async.setImmediate(function() {
if (q.drain) {
q.drain();
}
});
}
_each(data, function(task) {
var item = {
data: task,
priority: priority,
callback: typeof callback === 'function' ? callback : null
};
q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item);
if (q.saturated && q.tasks.length === q.concurrency) {
q.saturated();
}
async.setImmediate(q.process);
});
}
// Start with a normal queue
var q = async.queue(worker, concurrency);
// Override push to accept second parameter representing priority
q.push = function (data, priority, callback) {
_insert(q, data, priority, callback);
};
// Remove unshift function
delete q.unshift;
return q;
};
async.cargo = function (worker, payload) {
var working = false,
tasks = [];
var cargo = {
tasks: tasks,
payload: payload,
saturated: null,
empty: null,
drain: null,
drained: true,
push: function (data, callback) {
if (!_isArray(data)) {
data = [data];
}
_each(data, function(task) {
tasks.push({
data: task,
callback: typeof callback === 'function' ? callback : null
});
cargo.drained = false;
if (cargo.saturated && tasks.length === payload) {
cargo.saturated();
}
});
async.setImmediate(cargo.process);
},
process: function process() {
if (working) return;
if (tasks.length === 0) {
if(cargo.drain && !cargo.drained) cargo.drain();
cargo.drained = true;
return;
}
var ts = typeof payload === 'number'
? tasks.splice(0, payload)
: tasks.splice(0, tasks.length);
var ds = _map(ts, function (task) {
return task.data;
});
if(cargo.empty) cargo.empty();
working = true;
worker(ds, function () {
working = false;
var args = arguments;
_each(ts, function (data) {
if (data.callback) {
data.callback.apply(null, args);
}
});
process();
});
},
length: function () {
return tasks.length;
},
running: function () {
return working;
}
};
return cargo;
};
var _console_fn = function (name) {
return function (fn) {
var args = Array.prototype.slice.call(arguments, 1);
fn.apply(null, args.concat([function (err) {
var args = Array.prototype.slice.call(arguments, 1);
if (typeof console !== 'undefined') {
if (err) {
if (console.error) {
console.error(err);
}
}
else if (console[name]) {
_each(args, function (x) {
console[name](x);
});
}
}
}]));
};
};
async.log = _console_fn('log');
async.dir = _console_fn('dir');
/*async.info = _console_fn('info');
async.warn = _console_fn('warn');
async.error = _console_fn('error');*/
async.memoize = function (fn, hasher) {
var memo = {};
var queues = {};
hasher = hasher || function (x) {
return x;
};
var memoized = function () {
var args = Array.prototype.slice.call(arguments);
var callback = args.pop();
var key = hasher.apply(null, args);
if (key in memo) {
async.nextTick(function () {
callback.apply(null, memo[key]);
});
}
else if (key in queues) {
queues[key].push(callback);
}
else {
queues[key] = [callback];
fn.apply(null, args.concat([function () {
memo[key] = arguments;
var q = queues[key];
delete queues[key];
for (var i = 0, l = q.length; i < l; i++) {
q[i].apply(null, arguments);
}
}]));
}
};
memoized.memo = memo;
memoized.unmemoized = fn;
return memoized;
};
async.unmemoize = function (fn) {
return function () {
return (fn.unmemoized || fn).apply(null, arguments);
};
};
async.times = function (count, iterator, callback) {
var counter = [];
for (var i = 0; i < count; i++) {
counter.push(i);
}
return async.map(counter, iterator, callback);
};
async.timesSeries = function (count, iterator, callback) {
var counter = [];
for (var i = 0; i < count; i++) {
counter.push(i);
}
return async.mapSeries(counter, iterator, callback);
};
async.seq = function (/* functions... */) {
var fns = arguments;
return function () {
var that = this;
var args = Array.prototype.slice.call(arguments);
var callback = args.pop();
async.reduce(fns, args, function (newargs, fn, cb) {
fn.apply(that, newargs.concat([function () {
var err = arguments[0];
var nextargs = Array.prototype.slice.call(arguments, 1);
cb(err, nextargs);
}]))
},
function (err, results) {
callback.apply(that, [err].concat(results));
});
};
};
async.compose = function (/* functions... */) {
return async.seq.apply(null, Array.prototype.reverse.call(arguments));
};
var _applyEach = function (eachfn, fns /*args...*/) {
var go = function () {
var that = this;
var args = Array.prototype.slice.call(arguments);
var callback = args.pop();
return eachfn(fns, function (fn, cb) {
fn.apply(that, args.concat([cb]));
},
callback);
};
if (arguments.length > 2) {
var args = Array.prototype.slice.call(arguments, 2);
return go.apply(this, args);
}
else {
return go;
}
};
async.applyEach = doParallel(_applyEach);
async.applyEachSeries = doSeries(_applyEach);
async.forever = function (fn, callback) {
function next(err) {
if (err) {
if (callback) {
return callback(err);
}
throw err;
}
fn(next);
}
next();
};
// Node.js
if (typeof module !== 'undefined' && module.exports) {
module.exports = async;
}
// AMD / RequireJS
else if (typeof define !== 'undefined' && define.amd) {
define([], function () {
return async;
});
}
// included directly via <script> tag
else {
root.async = async;
}
}());
}).call(this,require('_process'))
},{"_process":16}],7:[function(require,module,exports){
(function (process,global){
/**
* Highland: the high-level streams library
*
* Highland may be freely distributed under the Apache 2.0 license.
* http://github.com/caolan/highland
* Copyright (c) Caolan McMahon
*
*/
var inherits = require('util').inherits;
var EventEmitter = require('events').EventEmitter;
var Decoder = require('string_decoder').StringDecoder;
/**
* The Stream constructor, accepts an array of values or a generator function
* as an optional argument. This is typically the entry point to the Highland
* APIs, providing a convenient way of chaining calls together.
*
* **Arrays -** Streams created from Arrays will emit each value of the Array
* and then emit a [nil](#nil) value to signal the end of the Stream.
*
* **Generators -** These are functions which provide values for the Stream.
* They are lazy and can be infinite, they can also be asynchronous (for
* example, making a HTTP request). You emit values on the Stream by calling
* `push(err, val)`, much like a standard Node.js callback. Once it has been
* called, the generator function will not be called again unless you call
* `next()`. This call to `next()` will signal you've finished processing the
* current data and allow for the generator function to be called again. If the
* Stream is still being consumed the generator function will then be called
* again.
*
* You can also redirect a generator Stream by passing a new source Stream
* to read from to next. For example: `next(other_stream)` - then any subsequent
* calls will be made to the new source.
*
* **Node Readable Stream -** Pass in a Node Readable Stream object to wrap
* it with the Highland API. Reading from the resulting Highland Stream will
* begin piping the data from the Node Stream to the Highland Stream.
*
* **EventEmitter / jQuery Elements -** Pass in both an event name and an
* event emitter as the two arguments to the constructor and the first
* argument emitted to the event handler will be written to the new Stream.
*
* You can also pass as an optional third parameter a function, an array of strings
* or a number. In this case the event handler will try to wrap the arguments emitted
* to it and write this object to the new stream.
*
* **Promise -** Accepts an ES6 / jQuery style promise and returns a
* Highland Stream which will emit a single value (or an error).
*
* @id _(source)
* @section Stream Objects
* @name _(source)
* @param {Array | Function | Readable Stream | Promise} source - (optional) source to take values from from
* @api public
*
* // from an Array
* _([1, 2, 3, 4]);
*
* // using a generator function
* _(function (push, next) {
* push(null, 1);
* push(err);
* next();
* });
*
* // a stream with no source, can pipe node streams through it etc.
* var through = _();
*
* // wrapping a Node Readable Stream so you can easily manipulate it
* _(readable).filter(hasSomething).pipe(writeable);
*
* // creating a stream from events
* _('click', btn).each(handleEvent);
*
* // creating a stream from events with mapping
* _('request', httpServer, ['req', 'res']).each(handleEvent);
*
* // from a Promise object
* var foo = _($.getJSON('/api/foo'));
*/
exports = module.exports = function (/*optional*/xs, /*optional*/ee, /*optional*/ mappingHint) {
return new Stream(xs, ee, mappingHint);
};
var _ = exports;
// Save bytes in the minified (but not gzipped) version:
var ArrayProto = Array.prototype,
ObjProto = Object.prototype;
// Create quick reference variables for speed access to core prototypes.
var slice = ArrayProto.slice,
toString = ObjProto.toString;
_.isFunction = function (x) {
return typeof x === 'function';
};
_.isObject = function (x) {
return typeof x === 'object' && x !== null;
};
_.isString = function (x) {
return typeof x === 'string';
};
_.isArray = Array.isArray || function (x) {
return toString.call(x) === '[object Array]';
};
// setImmediate implementation with browser and older node fallbacks
if (typeof setImmediate === 'undefined') {
if (typeof process === 'undefined' || !(process.nextTick)) {
_.setImmediate = function (fn) {
setTimeout(fn, 0);
};
}
else {
// use nextTick on old node versions
_.setImmediate = process.nextTick;
}
}
// check no process.stdout to detect browserify
else if (typeof process === 'undefined' || !(process.stdout)) {
// modern browser - but not a direct alias for IE10 compatibility
_.setImmediate = function (fn) {
setImmediate(fn);
};
}
else {
_.setImmediate = setImmediate;
}
/**
* The end of stream marker. This is sent along the data channel of a Stream
* to tell consumers that the Stream has ended. See the example map code for
* an example of detecting the end of a Stream.
*
* Note: `nil` is setup as a global where possible. This makes it convenient
* to access, but more importantly lets Streams from different Highland
* instances work together and detect end-of-stream properly. This is mostly
* useful for NPM where you may have many different Highland versions installed.
*
* @id nil
* @section Utils
* @name _.nil
* @api public
*
* var map = function (iter, source) {
* return source.consume(function (err, val, push, next) {
* if (err) {
* push(err);
* next();
* }
* else if (val === _.nil) {
* push(null, val);
* }
* else {
* push(null, iter(val));
* next();
* }
* });
* };
*/
// set up a global nil object in cases where you have multiple Highland
// instances installed (often via npm)
var _global = this;
if (typeof global !== 'undefined') {
_global = global;
}
else if (typeof window !== 'undefined') {
_global = window;
}
if (!_global.nil) {
_global.nil = {};
}
var nil = _.nil = _global.nil;
/**
* Transforms a function with specific arity (all arguments must be
* defined) in a way that it can be called as a chain of functions until
* the arguments list is saturated.
*
* This function is not itself curryable.
*
* @id curry
* @name curry(fn, [*arguments])
* @section Functions
* @param {Function} fn - the function to curry
* @param args.. - any number of arguments to pre-apply to the function
* @returns Function
* @api public
*
* fn = curry(function (a, b, c) {
* return a + b + c;
* });
*
* fn(1)(2)(3) == fn(1, 2, 3)
* fn(1, 2)(3) == fn(1, 2, 3)
* fn(1)(2, 3) == fn(1, 2, 3)
*/
_.curry = function (fn /* args... */) {
var args = slice.call(arguments);
return _.ncurry.apply(this, [fn.length].concat(args));
};
/**
* Same as `curry` but with a specific number of arguments. This can be
* useful when functions do not explicitly define all its parameters.
*
* This function is not itself curryable.
*
* @id ncurry
* @name ncurry(n, fn, [args...])
* @section Functions
* @param {Number} n - the number of arguments to wait for before apply fn
* @param {Function} fn - the function to curry
* @param args... - any number of arguments to pre-apply to the function
* @returns Function
* @api public
*
* fn = ncurry(3, function () {
* return Array.prototype.join.call(arguments, '.');
* });
*
* fn(1, 2, 3) == '1.2.3';
* fn(1, 2)(3) == '1.2.3';
* fn(1)(2)(3) == '1.2.3';
*/
_.ncurry = function (n, fn /* args... */) {
var largs = slice.call(arguments, 2);
if (largs.length >= n) {
return fn.apply(this, largs.slice(0, n));
}
return function () {
var args = largs.concat(slice.call(arguments));
if (args.length < n) {
return _.ncurry.apply(this, [n, fn].concat(args));
}
return fn.apply(this, args.slice(0, n));
};
};
/**
* Partially applies the function (regardless of whether it has had curry
* called on it). This will always postpone execution until at least the next
* call of the partially applied function.
*
* @id partial
* @name partial(fn, args...)
* @section Functions
* @param {Function} fn - function to partial apply
* @param args... - the arguments to apply to the function
* @api public
*
* var addAll = function () {
* var args = Array.prototype.slice.call(arguments);
* return foldl1(add, args);
* };
* var f = partial(addAll, 1, 2);
* f(3, 4) == 10
*/
_.partial = function (f /* args... */) {
var args = slice.call(arguments, 1);
return function () {
return f.apply(this, args.concat(slice.call(arguments)));
};
};
/**
* Evaluates the function `fn` with the argument positions swapped. Only
* works with functions that accept two arguments.
*
* @id flip
* @name flip(fn, [x, y])
* @section Functions
* @param {Function} f - function to flip argument application for
* @param x - parameter to apply to the right hand side of f
* @param y - parameter to apply to the left hand side of f
* @api public
*
* div(2, 4) == 0.5
* flip(div, 2, 4) == 2
* flip(div)(2, 4) == 2
*/
_.flip = _.curry(function (fn, x, y) { return fn(y, x); });
/**
* Creates a composite function, which is the application of function1 to
* the results of function2. You can pass an arbitrary number of arguments
* and have them composed. This means you can't partially apply the compose
* function itself.
*
* @id compose
* @name compose(fn1, fn2, ...)
* @section Functions
* @api public
*
* var add1 = add(1);
* var mul3 = mul(3);
*
* var add1mul3 = compose(mul3, add1);
* add1mul3(2) == 9
*/
_.compose = function (/*functions...*/) {
var fns = slice.call(arguments).reverse();
return _.seq.apply(null, fns);
};
/**
* The reversed version of compose. Where arguments are in the order of
* application.
*
* @id seq
* @name seq(fn1, fn2, ...)
* @section Functions
* @api public
*
* var add1 = add(1);
* var mul3 = mul(3);
*
* var add1mul3 = seq(add1, mul3);
* add1mul3(2) == 9
*/
_.seq = function () {
var fns = slice.call(arguments);
return function () {
if (!fns.length) {
return;
}
var r = fns[0].apply(this, arguments);
for (var i = 1; i < fns.length; i++) {
r = fns[i].call(this, r);
}
return r;
};
};
/**
* Actual Stream constructor wrapped the the main exported function
*/
function Stream(/*optional*/xs, /*optional*/ee, /*optional*/mappingHint) {
if (xs && _.isStream(xs)) {
// already a Stream
return xs;
}
EventEmitter.call(this);
var self = this;
// used to detect Highland Streams using isStream(x), this
// will work even in cases where npm has installed multiple
// versions, unlike an instanceof check
self.__HighlandStream__ = true;
self.id = ('' + Math.random()).substr(2, 6);
this.paused = true;
this._incoming = [];
this._outgoing = [];
this._consumers = [];
this._observers = [];
this._destructors = [];
this._send_events = false;
this._delegate = null;
this.source = null;
// Old-style node Stream.pipe() checks for this
this.writable = true;
self.on('newListener', function (ev) {
if (ev === 'data') {
self._send_events = true;
_.setImmediate(self.resume.bind(self));
}
else if (ev === 'end') {
// this property avoids us checking the length of the
// listners subscribed to each event on each _send() call
self._send_events = true;
}
});
// TODO: write test to cover this removeListener code
self.on('removeListener', function (ev) {
if (ev === 'end' || ev === 'data') {
var end_listeners = self.listeners('end').length;
var data_listeners = self.listeners('data').length;
if (end_listeners + data_listeners === 0) {
// stop emitting events
self._send_events = false;
}
}
});
if (xs === undefined) {
// nothing else to do
}
else if (_.isArray(xs)) {
self._incoming = xs.concat([nil]);
}
else if (typeof xs === 'function') {
this._generator = xs;
this._generator_push = function (err, x) {
self.write(err ? new StreamError(err): x);
};
this._generator_next = function (s) {
if (s) {
// we MUST pause to get the redirect object into the _incoming
// buffer otherwise it would be passed directly to _send(),
// which does not handle StreamRedirect objects!
var _paused = self.paused;
if (!_paused) {
self.pause();
}
self.write(new StreamRedirect(s));
if (!_paused) {
self.resume();
}
}
else {
self._generator_running = false;
}
if (!self.paused) {
self.resume();
}
};
}
else if (_.isObject(xs)) {
if (_.isFunction(xs.then)) {
// probably a promise
return _(function (push) {
xs.then(function (value) {
push(null, value);
return push(null, nil);
},
function (err) {
push(err);
return push(null, nil);
});
});
}
else {
// write any errors into the stream
xs.on('error', function (err) {
self.write(new StreamError(err));
});
// assume it's a pipeable stream as a source
xs.pipe(self);
}
}
else if (typeof xs === 'string') {
var mappingHintType = (typeof mappingHint);
var mapper;
if (mappingHintType === 'function') {
mapper = mappingHint;
} else if (mappingHintType === 'number') {
mapper = function () {
return slice.call(arguments, 0, mappingHint);
};
} else if (_.isArray(mappingHint)) {
mapper = function () {
var args = arguments;
return mappingHint.reduce(function (ctx, hint, idx) {
ctx[hint] = args[idx];
return ctx;
}, {});
};
} else {
mapper = function (x) { return x; };
}
ee.on(xs, function () {
var ctx = mapper.apply(this, arguments);
self.write(ctx);
});
}
else {
throw new Error(
'Unexpected argument type to Stream(): ' + (typeof xs)
);
}
}
inherits(Stream, EventEmitter);
/**
* adds a top-level _.foo(mystream) style export for Stream methods
*/
function exposeMethod(name) {
var f = Stream.prototype[name];
var n = f.length;
_[name] = _.ncurry(n + 1, function () {
var args = Array.prototype.slice.call(arguments);
var s = _(args.pop());
return f.apply(s, args);
});
}
/**
* Used as an Error marker when writing to a Stream's incoming buffer
*/
function StreamError(err) {
this.__HighlandStreamError__ = true;
this.error = err;
}
/**
* Used as a Redirect marker when writing to a Stream's incoming buffer
*/
function StreamRedirect(to) {
this.__HighlandStreamRedirect__ = true;
this.to = to;
}
/**
* Returns true if `x` is a Highland Stream.
*
* @id isStream
* @section Utils
* @name _.isStream(x)
* @param x - the object to test
* @api public
*
* _.isStream('foo') // => false
* _.isStream(_([1,2,3])) // => true
*/
_.isStream = function (x) {
return _.isObject(x) && x.__HighlandStream__;
};
_._isStreamError = function (x) {
return _.isObject(x) && x.__HighlandStreamError__;
};
_._isStreamRedirect = function (x) {
return _.isObject(x) && x.__HighlandStreamRedirect__;
};
/**
* Sends errors / data to consumers, observers and event handlers
*/
Stream.prototype._send = function (err, x) {
//console.log(['_send', this.id, err, x]);
if (x === nil) {
this.ended = true;
}
if (this._consumers.length) {
for (var i = 0, len = this._consumers.length; i < len; i++) {
var c = this._consumers[i];
if (err) {
c.write(new StreamError(err));
}
else {
c.write(x);
}
}
}
if (this._observers.length) {
for (var j = 0, len2 = this._observers.length; j < len2; j++) {
this._observers[j].write(x);
}
}
if (this._send_events) {
if (x === nil) {
this.emit('end');
}
else {
this.emit('data', x);
}
}
};
/**
* Pauses the stream. All Highland Streams start in the paused state.
*
* @id pause
* @section Stream Objects
* @name Stream.pause()
* @api public
*
* var xs = _(generator);
* xs.pause();
*/
Stream.prototype.pause = function () {
//console.log(['pause', this.id]);
this.paused = true;
if (this.source) {
this.source._checkBackPressure();
}
};
/**
* When there is a change in downstream consumers, it will often ask
* the parent Stream to re-check it's state and pause/resume accordingly.
*/
Stream.prototype._checkBackPressure = function () {
if (!this._consumers.length) {
return this.pause();
}
for (var i = 0, len = this._consumers.length; i < len; i++) {
if (this._consumers[i].paused) {
return this.pause();
}
}
return this.resume();
};
/**
* Starts pull values out of the incoming buffer and sending them downstream,
* this will exit early if this causes a downstream consumer to pause.
*/
Stream.prototype._readFromBuffer = function () {
//console.log(['_readFromBuffer', this.id, this.paused, this._incoming]);
var len = this._incoming.length;
var i = 0;
while (i < len && !this.paused) {
var x = this._incoming[i];
if (_._isStreamError(x)) {
this._send(x.error);
}
else if (_._isStreamRedirect(x)) {
this._redirect(x.to);
}
else {
this._send(null, x);
}
i++;
}
// remove processed data from _incoming buffer
this._incoming.splice(0, i);
};
/**
* Starts pull values out of the incoming buffer and sending them downstream,
* this will exit early if this causes a downstream consumer to pause.
*/
Stream.prototype._sendOutgoing = function () {
//console.log(['_sendOutgoing', this.id, this.paused, this._outgoing]);
var len = this._outgoing.length;
var i = 0;
while (i < len && !this.paused) {
var x = this._outgoing[i];
if (_._isStreamError(x)) {
Stream.prototype._send.call(this, x.error);
}
else if (_._isStreamRedirect(x)) {
this._redirect(x.to);
}
else {
Stream.prototype._send.call(this, null, x);
}
i++;
}
// remove processed data from _outgoing buffer
this._outgoing.splice(0, i);
};
/**
* Resumes a paused Stream. This will either read from the Stream's incoming
* buffer or request more data from an upstream source.
*
* @id resume
* @section Stream Objects
* @name Stream.resume()
* @api public
*
* var xs = _(generator);
* xs.resume();
*/
Stream.prototype.resume = function () {
//console.log(['resume', this.id]);
if (this._resume_running) {
//console.log(['resume already processing _incoming buffer, ignore resume call']);
// already processing _incoming buffer, ignore resume call
this._repeat_resume = true;
return;
}
this._resume_running = true;
do {
// use a repeat flag to avoid recursing resume() calls
this._repeat_resume = false;
this.paused = false;
// send values from outgoing buffer first
this._sendOutgoing();
// send values from incoming buffer before reading from source
this._readFromBuffer();
// we may have paused while reading from buffer
if (!this.paused) {
// ask parent for more data
if (this.source) {
//console.log(['ask parent for more data']);
this.source._checkBackPressure();
}
// run _generator to fill up _incoming buffer
else if (this._generator) {
//console.log(['run generator to fill up _incoming buffer']);
this._runGenerator();
}
else {
// perhaps a node stream is being piped in
this.emit('drain');
}