-
Notifications
You must be signed in to change notification settings - Fork 18
/
index.js
141 lines (129 loc) · 4.6 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
var express = require('express'),
app = express(),
hat = require('hat'),
ss = require('simple-statistics'),
turf = require('turf'),
request = require('request');
// Dynamically set the port that this application runs on so that Heroku
// can properly wrap the way that it connects to the outside network
app.set('port', (process.env.PORT || 3000));
// Set expressjs to trust the proxy so that we can get the external
// client IP address in the req.ips variable
app.enable('trust proxy');
// Create the GeoJSON FeatureCollection of points in which we'll store
// the results of the bandwidth tests.
var points = { type: 'FeatureCollection', features: [] };
var checks = {};
app.get('/first', function(req, res) {
var random_long_string = '';
for (i = 0; i < 100; i++) random_long_string += Math.random();
var key = hat();
checks[key] = +new Date();
// ensure that this number is deleted so checks doesn't grow always
setTimeout(function() {
delete checks[key];
}, 1000 * 60);
res.send({
random: random_long_string,
key: key
});
});
// This is the endpoint through which new computers add themselves to the
// map by downloading a test payload
app.get('/add/:key', function(req, res) {
var key = req.params.key;
var timing = +new Date() - checks[key] || 0;
var ip = (req.ip === '127.0.0.1') ? '199.188.195.78' : req.ip;
// get the external client IP - this variable is filled because
// we enabled 'trust proxy' earlier.
if (req.ips && req.ips.length) ip = req.ips[0];
// Use Mapbox for figuring out user locations: in production use,
// you would want to use MaxMind or another geoip library directly.
request('https://www.mapbox.com/api/Location/' + ip, {
json: true
}, function(err, place) {
// Check that Mapbox was able to locate the IP address at all
// before trying to add it to the map.
if (!err &&
place.body &&
place.body.lat !== undefined &&
place.body.lat !== 0) {
var i;
var random_long_string = '';
for (i = 0; i < 100; i++) random_long_string += Math.random();
var start = process.hrtime();
var self = {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [place.body.lon, place.body.lat]
},
properties: {
speed: timing
}
};
res.send(self);
// avoid duplicating results that land in the same exact latitude
// and longitude position.
for (i = 0; i < points.features.length; i++) {
if (points.features[i].geometry.coordinates[0] == place.body.lon &&
points.features[i].geometry.coordinates[1] == place.body.lat) {
// avoid duplicates
return;
}
}
points.features.push(self);
if (points.features.length > 1000) points.features.shift();
} else {
console.log(err, place);
res.end('done');
}
});
});
// Get the non-triangulated points. We calculate marker colors here
// to keep the front end code simple.
app.get('/points', function(req, res) {
var pts = JSON.parse(JSON.stringify(points));
var values = [];
pts.features.forEach(function(f) {
values.push(f.properties.speed);
});
var min = ss.min(values), max = ss.max(values);
pts.features.forEach(function(f) {
var s = (f.properties.speed - min) / (max - min);
f.properties['marker-size'] = 'small';
f.properties['marker-color'] =
(s > 0.8 ? '#d7301f' :
(s > 0.5 ? '#fc8d59' :
(s > 0.3 ? '#fdcc8a' :
'#fef0d9')));
});
res.send(pts);
});
app.get('/tin', function(req, res) {
var tin = turf.tin(points, 'speed');
var values = [];
tin.features.forEach(function(f) {
f.properties.total = f.properties.a + f.properties.b + f.properties.c;
values.push(f.properties.total);
});
// use simple-statistics to calculate minimum and maximum values
// for a quick scale
var min = ss.min(values), max = ss.max(values);
tin.features.forEach(function(f) {
f.properties.scaled = (f.properties.total - min) / (max - min);
var s = f.properties.scaled;
f.properties.fill =
(s > 0.8 ? '#d7301f' :
(s > 0.5 ? '#fc8d59' :
(s > 0.3 ? '#fdcc8a' :
'#fef0d9')));
});
res.send(tin);
});
app.use(express.static(__dirname + '/public'));
var server = app.listen(app.get('port'), function () {
var host = server.address().address;
var port = server.address().port;
console.log('running %s %s', host, port);
});