const axios = require('axios'); const moment = require('moment'); const express = require('express'); const config = require('./config'); const db = require('./db'); let router = express.Router(); module.exports = router; router.get('/associations/:association.gpx', (req, res) => { res.cacheControl = { noCache: true }; res.set('Content-Type', 'application/gpx+xml'); res.set('Content-Disposition', 'attachment; filename="' + req.params.association + '.gpx"'); gpxForQuery('^' + req.params.association + '/', `SOTA Association ${req.params.association}`, req.query, (err, gpx) => { if (err) { console.error(err); res.status(500).end(); return; } res.send(gpx).end(); }); }); router.get('/associations/:association.kml', (req, res) => { res.cacheControl = { noCache: true }; res.set('Content-Type', 'application/vnd.google-earth.kml+xml'); res.set('Content-Disposition', 'attachment; filename="' + req.params.association + '.kml"'); kmlForAssociation(req.params.association, req.query, (err, kml) => { if (err) { console.error(err); res.status(500).end(); return; } if (!kml) { res.status(404).end(); return; } res.send(kml).end(); }); }); router.get('/associations/:association.geojson', (req, res) => { res.cacheControl = { noCache: true }; res.set('Content-Type', 'application/geo+json'); res.set('Content-Disposition', 'attachment; filename="' + req.params.association + '.geojson"'); geoJsonForQuery('^' + req.params.association + '/', req.query, (err, geoJson) => { if (err) { console.error(err); res.status(500).end(); return; } res.json(geoJson).end(); }); }); router.get('/regions/:association/:region.gpx', (req, res) => { res.cacheControl = { noCache: true }; res.set('Content-Type', 'application/gpx+xml'); res.set('Content-Disposition', 'attachment; filename="' + req.params.association + '_' + req.params.region + '.gpx"'); gpxForQuery('^' + req.params.association + '/' + req.params.region + '-', `SOTA Region ${req.params.association + '/' + req.params.region}`, req.query, (err, gpx) => { if (err) { console.error(err); res.status(500).end(); return; } res.send(gpx).end(); }); }); router.get('/regions/:association/:region.kml', (req, res) => { res.cacheControl = { noCache: true }; res.set('Content-Type', 'application/vnd.google-earth.kml+xml'); res.set('Content-Disposition', 'attachment; filename="' + req.params.association + '_' + req.params.region + '.kml"'); kmlForRegion(req.params.association, req.params.region, req.query, (err, kml) => { if (err) { console.error(err); res.status(500).end(); return; } if (!kml) { res.status(404).end(); return; } res.send(kml).end(); }); }); router.get('/regions/:association/:region.geojson', (req, res) => { res.cacheControl = { noCache: true }; res.set('Content-Type', 'application/geo+json'); res.set('Content-Disposition', 'attachment; filename="' + req.params.association + '_' + req.params.region + '.geojson"'); geoJsonForQuery('^' + req.params.association + '/' + req.params.region + '-', req.query, (err, geoJson) => { if (err) { console.error(err); res.status(500).end(); return; } res.json(geoJson).end(); }); }); function gpxForQuery(query, name, options, callback) { let filter = {code: {$regex: query}}; if (!options.inactive) { filter.validFrom = {$lte: new Date()}; filter.validTo = {$gte: new Date()}; } db.getDb().collection('summits').find(filter).sort({code: 1}).toArray((err, summits) => { if (err) { callback(err); return; } let minlat, minlon, maxlat, maxlon; summits.forEach(summit => { if (!minlat || summit.coordinates.latitude < minlat) { minlat = summit.coordinates.latitude; } if (!minlon || summit.coordinates.longitude < minlon) { minlon = summit.coordinates.longitude; } if (!maxlat || summit.coordinates.latitude > maxlat) { maxlat = summit.coordinates.latitude; } if (!maxlon || summit.coordinates.longitude > maxlon) { maxlon = summit.coordinates.longitude; } }); let now = moment.utc(); let gpx = ` ${name} SOTLAS SOTLAS `; summits.forEach(summit => { gpx += ` ${summit.altitude} SOTA${('0' + summit.points).substr(-2)} Summit `; }); gpx += ""; callback(null, gpx); }); } function kmlForAssociation(associationCode, options, callback) { db.getDb().collection('associations').findOne({code: associationCode}, (err, association) => { if (err) { callback(err); return; } if (!association) { callback(null, null); return; } let filter = {code: {$regex: "^" + association.code + "/"}}; if (!options.inactive) { filter.validFrom = {$lte: new Date()}; filter.validTo = {$gte: new Date()}; } db.getDb().collection('summits').find(filter).sort({code: 1}).toArray((err, summits) => { let now = moment.utc(); let kmlName = 'SOTA Association ' + association.code + ' - ' + association.name; let kml = ` ${now.toISOString()} `; association.regions.forEach(region => { kml += ` `; summits.filter(summit => {return summit.code.startsWith(association.code + '/' + region.code)}).forEach(summit => { kml += kmlForSummit(summit, options); }); kml += ` `; }); kml += ` `; callback(null, kml); }); }); } function kmlForRegion(associationCode, regionCode, options, callback) { db.getDb().collection('associations').findOne({code: associationCode}, (err, association) => { if (err) { callback(err); return; } if (!association) { callback(null, null); return; } let filter = {code: {$regex: "^" + association.code + "/" + regionCode + '-'}}; if (!options.inactive) { filter.validFrom = {$lte: new Date()}; filter.validTo = {$gte: new Date()}; } db.getDb().collection('summits').find(filter).sort({code: 1}).toArray((err, summits) => { let now = moment.utc(); let kmlName = 'SOTA Region ' + associationCode + '/' + regionCode; let kml = ` ${now.toISOString()} `; association.regions.forEach(region => { if (regionCode && region.code !== regionCode) { return; } kml += ` SOTA Region `; summits.filter(summit => {return summit.code.startsWith(association.code + '/' + region.code)}).forEach(summit => { kml += kmlForSummit(summit, options); }); }); kml += ` `; callback(null, kml); }); }); } function geoJsonForQuery(query, options, callback) { let filter = {code: {$regex: query}}; if (!options.inactive) { filter.validFrom = {$lte: new Date()}; filter.validTo = {$gte: new Date()}; } db.getDb().collection('summits').find(filter).sort({code: 1}).toArray((err, summits) => { if (err) { callback(err); return; } let features = summits.map(summit => { return { type: 'Feature', geometry: { type: 'Point', coordinates: [summit.coordinates.longitude, summit.coordinates.latitude] }, id: summit.code, properties: { code: summit.code, name: summit.name, title: summitName(summit, options) } } }) let geojson = { type: 'FeatureCollection', features } callback(null, geojson); }); } function summitName(summit, options) { let name = summit.code; let nameopts = []; if (options.nameopts) { nameopts = options.nameopts.split(',') } if (nameopts.includes('name')) { name += ' - ' + summit.name; } if (nameopts.includes('altitude')) { name += ', ' + summit.altitude + 'm'; } if (nameopts.includes('points')) { name += ', ' + summit.points + 'pt'; } return name; } function kmlForSummit(summit, options) { return ` ${summit.coordinates.longitude},${summit.coordinates.latitude},${summit.altitude} `; }