Skip to content

Instantly share code, notes, and snippets.

@cscheid
Forked from Alex-Devoid/110_admin.geojson
Last active January 18, 2020 02:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cscheid/f6953ea9d1c8a0482d71f57ccda4c133 to your computer and use it in GitHub Desktop.
Save cscheid/f6953ea9d1c8a0482d71f57ccda4c133 to your computer and use it in GitHub Desktop.
A viz of all the "remain in Mexico" (MPP) asylum cases.
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
<head>
<title>Moving Bubble Tutorial</title>
<link rel="stylesheet" href="style/style.css" type="text/css" media="screen" />
<meta charset="utf-8">
</head>
<body>
<div id="main-wrapper">
<div id="chart"></div>
</div>
<script src="//d3js.org/d3.v4.js"></script>
<script>
var margin = {top: 16, right: 0, bottom: 0, left: 0},
width = 950 - margin.left - margin.right,
height = 700 - margin.top - margin.bottom;
var node_radius = 5,
padding = 1,
cluster_padding = 10,
num_nodes = 200;
var svg = d3.select("#chart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var mexico;
var usa;
var usa1;
var ven;
var canada;
var geoMercator = d3.geoMercator()
var path = d3.geoPath().projection(d3.geoMercator());
d3.json("110_admin.geojson", function(error, world) {
if (error) throw error;
d3.csv("mpp_courts_d3_texas.csv", function(errorData, mppData) {
if (errorData) throw errorData;
var lookup = {};
var sourceCountries = [];
//https://stackoverflow.com/questions/17780508/selecting-distinct-values-from-a-json
for (var item, i = 0; item = mppData[i++];) {
var country = item.source;
if (!(country in lookup)) {
lookup[country] = 1;
sourceCountries.push(country);
}
}
var destinations =
[{
name:'elPaso',
type: "Point",
coordinates: [-97.745015,26.020156],
},
{
name:'sanDiego',
type: "Point",
coordinates: [-117.035644,32.534302],
},
{
name:'Texas',
type: "Point",
coordinates: [-99.533056,27.455729],
}]
for (var i = 0; i < destinations.length; i++) {
destinations[i].point = geoMercator(destinations[i].coordinates)
}
console.log(sourceCountries)
var data1 = []
for (var i = 0; i < world.features.length; i++) {
for (var b = 0; b < sourceCountries.length; b++) {
if (world.features[i].properties.SOVEREIGNT === sourceCountries[b]){
data1.push({
"class": `${world.features[i].properties.SOVEREIGNT}_${destinations[0].name}`,
"source": {
"lat": path.centroid(world.features[i])[1],
"lon": path.centroid(world.features[i])[0]
},
"destination": {
"lat": destinations[0].point[1],
"lon": destinations[0].point[0]
}
},
{
"class": `${world.features[i].properties.SOVEREIGNT}_${destinations[1].name}`,
"source": {
"lat": path.centroid(world.features[i])[1],
"lon": path.centroid(world.features[i])[0]
},
"destination": {
"lat": destinations[1].point[1],
"lon": destinations[1].point[0]
}
},
{
"class": `${world.features[i].properties.SOVEREIGNT}_${destinations[2].name}`,
"source": {
"lat": path.centroid(world.features[i])[1],
"lon": path.centroid(world.features[i])[0]
},
"destination": {
"lat": destinations[2].point[1],
"lon": destinations[2].point[0]
}
}
)
}
}
}
svg.selectAll("path")
.data(world.features)
.enter().append("path")
.attr("fill", "grey")
.attr("d", path);
var projection = d3.geoMercator();
var points;
var curve = function(context) {
var custom = d3.curveLinear(context);
custom._context = context;
custom.point = function(x,y) {
x = +x, y = +y;
switch (this._point) {
case 0: this._point = 1;
this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y);
this.x0 = x; this.y0 = y;
break;
case 1: this._point = 2;
default:
var x1 = this.x0 * 0.5 + x * 0.5;
var y1 = this.y0 * 0.5 + y * 0.5;
var m = 1/(y1 - y)/(x1 - x);
var r = -100; // offset of mid point.
var k = r / Math.sqrt(1 + (m*m) );
if (m == Infinity) {
y1 += r;
}
else {
y1 += k;
x1 += m*k;
}
// this is terribly ugly
points = [[this.x0, this.y0],
[x1, y1],
[x, y]];
this._context.quadraticCurveTo(x1,y1,x,y);
this.x0 = x; this.y0 = y;
break;
}
}
return custom;
}
var line = d3.line()
.x(function(d) {
return d.lon;
})
.y(function(d) {
return d.lat;
})
.curve(curve);
var route = svg.selectAll(null)
.data(data1)
.enter()
.append("path")
.attr("class", function(d){
return d.class
})
.attr("d",function(d) {
var result = line([d.source,d.destination]);
d.node = this;
// "points" here is the global variable we defined up in
// the "curve" function. This is exceedingly ugly.
d.points = points;
// var l = path.getTotalLength();
return result;
})
// .datum(function(d) {
// return [d.source,d.destination];
// })
// .attr("d",line)
.attr("fill", "none")
.style("stroke","black")
.style("stroke-width",1.5)
//Everything runs smoothly when I use this very small test dataset.
// var testData = [{
//
// "source": "Honduras",
// "January": "10",
// "February": "5",
// "March": "10",
// "April": "0",
// "May": "10",
// "June": "10",
// "July": "10",
// "August": "10",
// "September": "10",
// "October": "10",
// "November": "10",
// "destination": "Texas"
// },
// {
//
// "source": "Venezuela",
// "January": "5",
// "February": "10",
// "March": "5",
// "April": "10",
// "May": "10",
// "June": "10",
// "July": "10",
// "August": "10",
// "September": "10",
// "October": "10",
// "November": "10",
// "destination": "Texas"
// }]
// **** this chunck is wrangling the csv into distinct datapoints
var months =["January","February","March","April","May", "June","July","August","September","October","November"]
function sumKey(bills,key){
//https://stackoverflow.com/questions/44436041/how-to-sum-value-of-two-json-object-key
var res = bills.map(bill => Number(bill[key])).reduce((acc, bill) => bill + acc);
return res
}
function getMax(arr, prop) {
var max;
for (var i=0 ; i<arr.length ; i++) {
if (max == null || parseInt(arr[i][prop]) > parseInt(max[prop]))
max = arr[i];
}
return max;
}
var newTestArray = [];
console.log(mppData);
maxMonthArray = []
for (var b = 0; b < months.length; b++) {
var maxMonth = getMax(mppData, months[b]);
maxMonthArray.push(maxMonth[months[b]])
for (var i = 0; i < mppData.length; i++) {
for (var a = 0; a < Number(mppData[i][months[b]]); a++) {
newTestArray.push({
"id": a,
"source": mppData[i].source,
"destination": mppData[i].destination,
'month': b
})
}
}
}
var circlesMonthId = [[], [], [], [], [], [], [], [], [], [], [], []];
// console.log(nodesAt);
console.log(newTestArray);
var multiCircles = svg.selectAll(".circle")
.data(newTestArray)
.enter().append("circle")
.attr("class", function(d,i){
// console.log(d)
if (circlesMonthId[d.month][d.id] === undefined)
circlesMonthId[d.month][d.id] = [];
circlesMonthId[d.month][d.id].push(this);
return `c_${d.month}_${d.id}`})
.attr("r", function(d){
return 6;
})
.attr("fill", function(d){
return 'red';
})
//https://stackoverflow.com/questions/1230233/how-to-find-the-sum-of-an-array-of-numbers
var sumMaxMonths = maxMonthArray.reduce(function(acc, val) { return Number(acc) + Number(val) }, 0);
console.log(sumMaxMonths)
//count twords the sum of the max values in each month
var counter = -1;
//migrants in a month
var a = -1;
// months
var m = 0;
//This loop transitions the circles along the correct path elements
(function loop() {
//newTestArray.length
if (counter++ > sumMaxMonths ) return;
setTimeout(function() {
if (m < 11) {
if (a++ > maxMonthArray[m]-1) {
m++
a = 0
}
}
var thisPolygon = d3.selectAll(circlesMonthId[m][a]); // `.c_${m}_${a}`)
console.log("This many circles: ", thisPolygon.nodes().length);
transition1( thisPolygon, counter);
loop()
}, 300)
}());
function transition1(elem,i) {
elem.transition()
.duration(3000)
.attrTween("transform", translateAlong);
// Returns an attrTween for translating along the specified path element.
function translateAlong(d, i, a) {
// console.log(`.${d.source}_${d.destination}`);
var path = d3.select(`.${d.source}_${d.destination}`).node();
if (path.totalLength === undefined) {
path.totalLength = path.getTotalLength();
}
var l = path.totalLength;
var t0 = 0;
function lerp(p1, p2, t, output) {
output[0] = p1[0] + (p2[0] - p1[0]) * t;
output[1] = p1[1] + (p2[1] - p1[1]) * t;
}
var d1 = [0,0], d2 = [0,0], p0 = [0,0], p = [0,0];
return function(t) {
var output = [0,0];
var q = path.__data__.points;
lerp(q[0], q[1], t0, d1);
lerp(q[1], q[2], t0, d2);
lerp(d1, d2, t0, p0);
lerp(q[0], q[1], t, d1);
lerp(q[1], q[2], t, d2);
lerp(d1, d2, t, p);
// var p0 = output0;
// var p = output;
// var p0 = path.getPointAtLength(t0 * l); //previous point
// var p = path.getPointAtLength(t * l); //current point
// debugger;
var angle = Math.atan2(p[1] - p0[1], p[0] - p0[0]) * 180 / Math.PI; //angle for tangent
t0 = t;
//Shifting center to center of arrow
// xoffset and yoffset should be half the original width and height
var xoffset = 0,
yoffset = 0;
var centerX = p[0] - xoffset;
var centerY = p[1] - yoffset;
return "translate(" + centerX + "," + centerY + ")rotate(" + angle + " " + xoffset + " " + yoffset + ")";
};
};
}
});
});
</script>
</body>
/* global d3 */
var margin = {top: 16, right: 0, bottom: 0, left: 0},
width = 950 - margin.left - margin.right,
height = 700 - margin.top - margin.bottom;
var node_radius = 5,
padding = 1,
cluster_padding = 10,
num_nodes = 200;
var svg = d3.select("#chart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var mexico;
var usa;
var usa1;
var ven;
var canada;
var geoMercator = d3.geoMercator();
var path = d3.geoPath().projection(d3.geoMercator());
function main(xhrs) {
var world = xhrs[0], mppData = xhrs[1];
var lookup = {};
var sourceCountries = [];
//https://stackoverflow.com/questions/17780508/selecting-distinct-values-from-a-json
for (var item, i = 0; item = mppData[i++];) {
var country = item.source;
if (!(country in lookup)) {
lookup[country] = 1;
sourceCountries.push(country);
}
}
var destinations =
[{
name:'elPaso',
type: "Point",
coordinates: [-97.745015,26.020156],
},
{
name:'sanDiego',
type: "Point",
coordinates: [-117.035644,32.534302],
},
{
name:'Texas',
type: "Point",
coordinates: [-99.533056,27.455729],
}];
for (var i = 0; i < destinations.length; i++) {
destinations[i].point = geoMercator(destinations[i].coordinates);
}
console.log(sourceCountries);
var data1 = [];
var pathsInfo = {};
for (var i = 0; i < world.features.length; i++) {
var sovereignT = world.features[i].properties.SOVEREIGNT;
pathsInfo[sovereignT] = {};
for (var b = 0; b < sourceCountries.length; b++) {
var sourceCountry = sourceCountries[b];
if (sovereignT === sourceCountry){
var dest0 = {
"sourceName": sovereignT,
"destName": destinations[0].name,
"class": `${world.features[i].properties.SOVEREIGNT}_${destinations[0].name}`,
"source": {
"lat": path.centroid(world.features[i])[1],
"lon": path.centroid(world.features[i])[0]
},
"destination": {
"lat": destinations[0].point[1],
"lon": destinations[0].point[0]
}
};
var dest1 = {
"sourceName": sovereignT,
"destName": destinations[1].name,
"class": `${world.features[i].properties.SOVEREIGNT}_${destinations[1].name}`,
"source": {
"lat": path.centroid(world.features[i])[1],
"lon": path.centroid(world.features[i])[0]
},
"destination": {
"lat": destinations[1].point[1],
"lon": destinations[1].point[0]
}
};
var dest2 = {
"class": `${world.features[i].properties.SOVEREIGNT}_${destinations[2].name}`,
"sourceName": sovereignT,
"destName": destinations[2].name,
"source": {
"lat": path.centroid(world.features[i])[1],
"lon": path.centroid(world.features[i])[0]
},
"destination": {
"lat": destinations[2].point[1],
"lon": destinations[2].point[0]
}
};
pathsInfo[sovereignT][destinations[0].name] = dest0;
pathsInfo[sovereignT][destinations[1].name] = dest1;
pathsInfo[sovereignT][destinations[2].name] = dest2;
data1.push(dest0, dest1, dest2);
}
}
}
svg.selectAll("path")
.data(world.features)
.enter().append("path")
.attr("fill", "grey")
.attr("d", path);
var projection = d3.geoMercator();
var curve = function(context) {
var custom = d3.curveLinear(context);
custom._context = context;
custom.point = function(x,y) {
x = +x, y = +y;
switch (this._point) {
case 0: this._point = 1;
this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y);
this.x0 = x; this.y0 = y;
break;
case 1: this._point = 2;
default:
var x1 = this.x0 * 0.5 + x * 0.5;
var y1 = this.y0 * 0.5 + y * 0.5;
var m = 1/(y1 - y)/(x1 - x);
var r = -100; // offset of mid point.
var k = r / Math.sqrt(1 + (m*m) );
if (m == Infinity) {
y1 += r;
}
else {
y1 += k;
x1 += m*k;
}
this._context.quadraticCurveTo(x1,y1,x,y);
this.x0 = x; this.y0 = y;
break;
}
};
return custom;
};
var line = d3.line()
.x(function(d) {
return d.lon;
})
.y(function(d) {
return d.lat;
})
.curve(curve);
var route = svg.selectAll(null)
.data(data1)
.enter()
.append("path")
.attr("class", function(d){
return d.class;
})
// .datum(function(d) {
// return [d.source,d.destination];
// })
.attr("d",function(d) {
let result = line([d.source,d.destination]);
d.node = this;
d.totalLength = this.getTotalLength();
// var l = path.getTotalLength();
return result;
})
.attr("fill", "none")
.style("stroke","black")
.style("stroke-width",1.5);
//Everything runs smoothly when I use this very small test dataset.
// var testData = [{
//
// "source": "Honduras",
// "January": "10",
// "February": "5",
// "March": "10",
// "April": "0",
// "May": "10",
// "June": "10",
// "July": "10",
// "August": "10",
// "September": "10",
// "October": "10",
// "November": "10",
// "destination": "Texas"
// },
// {
//
// "source": "Venezuela",
// "January": "5",
// "February": "10",
// "March": "5",
// "April": "10",
// "May": "10",
// "June": "10",
// "July": "10",
// "August": "10",
// "September": "10",
// "October": "10",
// "November": "10",
// "destination": "Texas"
// }]
// **** this chunck is wrangling the csv into distinct datapoints
var months = ["January","February","March","April","May", "June","July","August","September","October","November"];
function sumKey(bills,key){
//https://stackoverflow.com/questions/44436041/how-to-sum-value-of-two-json-object-key
var res = bills.map(bill => Number(bill[key])).reduce((acc, bill) => bill + acc);
return res;
}
function getMax(arr, prop) {
var max;
for (var i=0 ; i<arr.length ; i++) {
if (max == null || parseInt(arr[i][prop]) > parseInt(max[prop]))
max = arr[i];
}
return max;
}
var newTestArray = [];
console.log(mppData);
var maxMonthArray = [];
for (var b = 0; b < months.length; b++) {
var maxMonth = getMax(mppData, months[b]);
maxMonthArray.push(maxMonth[months[b]]);
for (var i = 0; i < mppData.length; i++) {
for (var a = 0; a < Number(mppData[i][months[b]]); a++) {
newTestArray.push({
"id": a,
"source": mppData[i].source,
"destination": mppData[i].destination,
'month': b
});
}
}
}
// console.log(nodesAt);
console.log(newTestArray);
var multiCircles = svg.selectAll(".circle")
.data(newTestArray)
.enter().append("circle")
.attr("class", function(d,i){
// console.log(d);
return `c_${d.month}_${d.id}`;
})
.attr("r", 6)
.attr("fill", "red");
//https://stackoverflow.com/questions/1230233/how-to-find-the-sum-of-an-array-of-numbers
var sumMaxMonths = maxMonthArray.reduce(function(acc, val) { return Number(acc) + Number(val); }, 0);
console.log(sumMaxMonths);
//count twords the sum of the max values in each month
var counter = -1;
//migrants in a month
var a = -1;
// months
var m = 0;
//This loop transitions the circles along the correct path elements
(function loop() {
//newTestArray.length
if (counter++ > sumMaxMonths ) return;
setTimeout(function() {
if (m < 11) {
if (a++ > maxMonthArray[m]-1) {
m++
a = 0
}
}
var thisPolygon = d3.selectAll(`.c_${m}_${a}`);
transition1( thisPolygon, counter);
loop();
}, 300);
}());
function transition1(elem,i) {
elem.transition()
.duration(3000)
.attrTween("transform", translateAlong());
// Returns an attrTween for translating along the specified path element.
function translateAlong(path1) {
return function(d, i, a) {
// console.log(`.${d.source}_${d.destination}`);
var path = pathsInfo[d.source][d.destination].node;
// var path = d3.select(`.${d.source}_${d.destination}`).node();
var l = path.__data__.totalLength;
var t0 = 0;
return function(t) {
var p0 = path.getPointAtLength(t0 * l); //previous point
var p = path.getPointAtLength(t * l); //current point
var angle = Math.atan2(p.y - p0.y, p.x - p0.x) * 180 / Math.PI; //angle for tangent
t0 = t;
//Shifting center to center of arrow
// xoffset and yoffset should be half the original width and height
var xoffset = 0,
yoffset = 0;
var centerX = p.x - xoffset;
var centerY = p.y - yoffset;
return "translate(" + centerX + "," + centerY + ")rotate(" + angle + " " + xoffset + " " + yoffset + ")";
};
};
}
}
};
Promise.all(
[d3.json("110_admin.geojson"),
d3.csv("mpp_courts_d3_texas.csv")])
.then(main);
source January February March April May June July August September October November destination
Argentina 0 0 0 0 0 0 0 0 2 0 0 Texas
Belize 0 0 0 0 0 0 0 1 0 0 1 elPaso
Belize 0 0 0 0 0 0 0 0 1 1 0 Texas
Belize 0 0 0 0 0 0 0 0 4 0 1 Texas
Bolivia 0 0 0 0 0 0 0 1 0 1 0 Texas
Bolivia 0 0 0 0 0 0 0 0 1 2 0 Texas
Brazil 0 0 0 0 0 1 0 0 0 0 0 elPaso
Brazil 0 0 0 0 0 0 0 0 3 1 0 Texas
Brazil 0 0 0 0 0 0 1 0 0 0 0 sanDiego
Chile 0 0 0 0 0 0 0 0 0 2 0 elPaso
Chile 0 0 0 0 0 0 0 0 1 0 0 Texas
Chile 0 0 0 0 0 0 0 0 2 0 0 Texas
Chile 0 0 0 0 0 0 0 0 0 1 0 sanDiego
Colombia 0 0 0 0 0 2 6 3 15 6 3 elPaso
Colombia 0 0 0 0 0 0 5 4 5 3 7 Texas
Colombia 0 0 0 0 0 0 4 6 2 3 5 Texas
Colombia 0 0 0 0 0 6 11 8 3 0 2 sanDiego
Congo 0 0 0 0 0 0 0 0 1 0 0 Texas
Costa Rica 0 0 0 0 0 1 1 1 0 0 0 elPaso
Costa Rica 0 0 0 0 0 0 0 1 0 2 1 Texas
Costa Rica 0 0 0 0 0 0 0 1 2 1 0 Texas
Croatia 0 0 0 0 0 0 0 0 0 0 1 elPaso
Cuba 0 0 1 0 4 892 1002 503 298 326 370 elPaso
Cuba 0 0 0 0 0 0 272 867 735 554 85 Texas
Cuba 0 0 0 0 0 2 384 419 125 63 44 Texas
Cuba 0 0 0 0 0 38 69 55 63 39 32 sanDiego
Cyprus 0 0 0 0 0 0 1 0 0 0 0 elPaso
Cyprus 0 0 0 0 0 0 0 1 0 0 0 Texas
Dominican Republic 0 0 0 0 0 0 3 2 1 0 0 Texas
Dominican Republic 0 0 0 0 0 0 7 10 4 1 0 Texas
Ecuador 0 0 0 0 0 204 290 180 188 1 204 elPaso
Ecuador 0 0 0 0 0 0 13 76 150 2 1 Texas
Ecuador 0 0 0 0 0 0 117 98 195 109 61 Texas
Ecuador 0 0 0 2 4 41 69 35 37 10 23 sanDiego
Egypt 0 0 0 0 0 1 0 0 0 207 0 elPaso
Egypt 0 0 0 0 0 0 0 0 0 116 104 Texas
El-Salvador 0 0 11 206 391 466 374 311 204 86 56 elPaso
El-Salvador 0 0 0 0 0 0 236 866 607 376 0 Texas
El-Salvador 0 0 0 0 0 0 448 525 295 121 73 Texas
El-Salvador 1 38 46 203 347 189 131 122 102 63 45 sanDiego
Gabon 0 0 0 0 0 2 0 0 0 0 0 elPaso
Gabon 0 0 0 0 0 0 0 0 0 0 290 Texas
Guadeloupe 0 0 0 0 0 1 1 0 1 0 0 elPaso
Guadeloupe 0 0 0 0 0 0 0 1 0 0 0 Texas
Guadeloupe 0 0 0 0 0 0 0 0 0 0 1 Texas
Guadeloupe 0 0 0 0 2 3 2 0 0 0 0 sanDiego
Guatemala 0 0 17 538 1084 831 745 798 235 127 156 elPaso
Guatemala 0 0 0 0 0 0 179 2013 424 256 252 Texas
Guatemala 0 0 0 0 0 0 689 392 320 78 59 Texas
Guatemala 1 32 62 674 1497 1260 1551 699 175 104 146 sanDiego
Guinea 0 0 0 0 0 0 1 0 0 0 0 elPaso
Guinea 0 0 0 0 0 0 1 0 0 0 0 Texas
Guyana 0 0 0 0 0 0 0 0 0 1 0 Texas
Haiti 0 0 0 0 0 2 0 0 0 0 0 sanDiego
Holland 0 0 0 0 0 0 0 1 0 0 0 elPaso
Holland 0 0 0 0 0 0 0 0 1 0 2 Texas
Holland 0 0 0 0 0 0 0 0 1 0 0 Texas
Holland 0 0 0 0 0 1 1 0 0 0 0 sanDiego
Honduras 0 0 15 363 695 812 1198 804 436 253 224 elPaso
Honduras 0 0 0 0 1 0 493 0 1983 699 488 Texas
Honduras 0 2 2 6 2 0 1109 1516 1350 761 436 Texas
Honduras 12 70 77 494 949 892 1430 502 216 164 134 sanDiego
Hong Kong 0 0 0 0 0 0 0 0 1 0 0 Texas
Hong Kong 0 0 0 0 0 0 0 0 1 0 0 Texas
Hong Kong 0 0 0 0 0 1 0 0 0 0 0 sanDiego
Laos 0 0 0 0 0 0 0 0 1 0 0 Texas
Macedonia 0 0 0 0 0 0 0 0 0 0 1 Texas
Malawi 0 0 0 0 0 0 0 1 0 0 0 Texas
Mexico 0 0 0 0 0 1 1 4 3 2 1 elPaso
Mexico 0 0 0 0 0 0 0 5 3 0 2 Texas
Mexico 0 0 0 1 0 0 4 4 1 5 2 Texas
Mexico 0 0 0 4 3 2 12 2 1 2 0 sanDiego
Namibia 0 0 0 0 0 0 0 0 1 0 0 elPaso
Namibia 0 0 0 0 0 0 0 0 1 0 0 Texas
Namibia 0 0 0 0 0 0 0 1 0 0 0 sanDiego
Nicaragua 0 0 0 0 0 95 47 49 19 36 8 elPaso
Nicaragua 0 0 0 0 0 0 44 145 161 54 73 Texas
Nicaragua 0 0 0 0 0 0 104 88 47 22 18 Texas
Nicaragua 0 0 0 1 3 39 91 60 15 10 19 sanDiego
Oman 0 0 0 0 0 0 0 0 1 0 0 Texas
Oman 0 0 0 0 0 0 0 0 0 1 0 sanDiego
Panama 0 0 0 0 0 0 0 0 0 2 0 elPaso
Panama 0 0 0 0 0 0 0 1 1 0 1 Texas
Panama 0 0 0 0 0 0 0 1 0 0 0 sanDiego
Paraguay 0 0 0 0 0 0 0 1 0 0 0 Texas
Peru 0 0 0 0 0 3 5 4 5 5 5 elPaso
Peru 0 0 0 0 0 0 5 16 6 8 2 Texas
Peru 0 0 0 0 0 0 2 6 3 10 5 Texas
Peru 0 0 0 0 0 3 4 8 2 0 0 sanDiego
San Marino 0 0 0 0 0 0 0 0 0 1 0 sanDiego
Spain 0 0 0 0 0 0 2 1 0 1 0 elPaso
Spain 0 0 0 0 0 0 0 1 3 1 0 Texas
Spain 0 0 0 0 0 0 0 0 1 0 0 Texas
Sudan 0 0 0 0 0 1 0 0 0 0 0 sanDiego
Uruguay 0 0 0 0 0 0 0 0 3 0 0 elPaso
Uruguay 0 0 0 0 0 0 0 1 0 0 0 Texas
Vanuatu 0 0 0 0 0 0 1 0 0 0 0 Texas
Venezuela 0 0 0 0 0 26 55 36 27 66 26 elPaso
Venezuela 0 0 0 0 0 0 86 164 146 78 32 Texas
Venezuela 0 0 0 0 0 0 191 170 166 180 195 Texas
Venezuela 0 0 0 0 0 17 35 26 51 24 24 sanDiego
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment