Skip to content

Instantly share code, notes, and snippets.

@mpaccione
Created July 30, 2019 04:35
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 mpaccione/19b7f13ec8600bc37d2927b3ac696d84 to your computer and use it in GitHub Desktop.
Save mpaccione/19b7f13ec8600bc37d2927b3ac696d84 to your computer and use it in GitHub Desktop.
CRON Server
// Modules
const cors = require('cors'),
cron = require('node-cron'),
express = require('express'),
expressStaticGzip = require("express-static-gzip"),
path = require('path'),
request = require('request'),
THREE = require('three'),
app = express(),
// Globals
url = "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/",
urlSuffix = [
"all_hour.geojson",
"all_day.geojson",
"all_week.geojson",
"all_month.geojson"
],
quakes = {
"0": [],
"1": [],
"2": [],
"3": []
},
threeData = {
"0": null,
"1": null,
"2": null,
"3": null
}
// CORS for Local Testing
app.use(cors());
// Compression
app.use('/', expressStaticGzip(path.join(__dirname, 'build'), {
enableBrotli: true,
orderPreference: ['br', 'gz']
}))
// Routes
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'))
})
app.get('/.well-known(/*)?', function(req, res) {
res.sendFile(path.join(__dirname, '.well-known', 'assetlinks.json'))
})
app.get('/privacy-policy', function(req, res) {
res.sendFile(path.join(__dirname, 'privacy_policy.html'))
})
// API
app.get('/quakes/:index', function(req, res){
res.setHeader('Content-Type', 'application/json');
req.params.index != "all" ? res.json(quakes[req.params.index]) : res.json(quakes);
});
app.get('/threeData/:index', function(req, res){
res.setHeader('Content-Type', 'application/json');
req.params.index != "all" ? res.json(threeData[req.params.index]) : res.json(threeData);
});
app.get('/quakeData/:index', function(req, res){
// Send Specific Selection or All
const jsonArr = req.params.index != "all" ? [
quakes[req.params.index],
threeData[req.params.index]
] : [
quakes,
threeData
]
res.setHeader('Content-Type', 'application/json');
res.json(jsonArr);
});
// Cron every minute
cron.schedule('*/1 * * * *', () => {
console.log("CRON JOB - "+new Date().getMinutes());
// Loop over API urls, make AJAX reqs, store in global
for (let i = 0; i < urlSuffix.length; i++) {
request(url+urlSuffix[i], function (error, response, body) {
if (response.statusCode == 200) {
const parsedBody = JSON.parse(body),
quakeArr = new Array(parsedBody.metadata.count),
geom = new THREE.Geometry(),
cubeMat = new THREE.MeshBasicMaterial({ vertexColors: true });
// Data Parsing
for (const feature of parsedBody.features) {
// Quake Obj
const magnitude = feature.properties.mag,
location = feature.properties.place,
time = feature.properties.time,
coordinates = feature.geometry.coordinates,
quake = {
"magnitude": magnitude,
"location": location,
"time": time,
"coordinates": coordinates
},
// Three Data Obj
quakeVector = longLatToSphere(coordinates[0], coordinates[1], 600),
rgb = colorData(magnitude),
cubeColor = new THREE.Color(rgb),
cubeHeight = magnitude > 0 ? (magnitude ** 3) * 1.75 : 0,
cubeGeom = new THREE.BoxGeometry(3, 3, cubeHeight, 1, 1, 1),
cube = new THREE.Mesh(cubeGeom, cubeMat);
// set position of cube on globe, point to center, merge together for one draw call
for ( let j = 0; j < cubeGeom.faces.length; j ++ ) {
cubeGeom.faces[j].color = cubeColor;
}
cube.position.set(quakeVector.x, quakeVector.y, quakeVector.z);
cube.lookAt(new THREE.Vector3(0,0,0));
cube.updateMatrix();
geom.merge(cube.geometry, cube.matrix);
quakeArr.push(quake);
}
// Data Sorting by Highest Magnitude
quakeArr.sort((a, b) => b.magnitude - a.magnitude);
// Store in Global
quakes[i] = quakeArr;
threeData[i] = geom;
} else {
console.log(response);
console.log("error: "+response);
console.log(this);
}
})
}
})
// Three.js Viz Functions
// Intensity Coloring
colorData = percentage => {
let rgbString = "",
r = parseInt(percentage * 25.5),
g = 255 - r;
r = r < 0 ? 0 : r;
rgbString = `rgb(${r},${g}, 0)`;
return rgbString;
}
// Projection Mapping
longLatToSphere = (long, lat, radius) => {
const phi = (90-lat)*(Math.PI/180),
theta = (long+180)*(Math.PI/180),
x = -((radius) * Math.sin(phi)*Math.cos(theta)),
z = ((radius) * Math.sin(phi)*Math.sin(theta)),
y = ((radius) * Math.cos(phi));
return new THREE.Vector3(x,y,z);
}
// Listen
app.listen(8080, () => console.log("Static client listening on 8080"))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment