UNPKG

@furkot/export-gpx

Version:

Generate GPX files from Furkot trip data.

270 lines (227 loc) 6.08 kB
const { generator } = require('gexode'); const { getSchema, getTimestamp, getDeparture, getComment, streetAddress, isStop } = require('./tools'); module.exports = render; const precision = 6; const emptyTarget = { getWptCmt: getComment, getWptSym() {}, getWptType() {}, getTrkType() {}, hasWptExt() {}, hasRteExt() {}, hasRtePtExt() {}, hasTrkExt() {} }; const targets = [ ['standard', { getWptSym: require('@furkot/garmin-data').getWptSym }], ['galileo', require('@furkot/guru-data')], ['garmin', require('@furkot/garmin-data')], ['osmand', require('@furkot/osmand-data')] ].reduce((result, [key, value]) => { result[key] = Object.assign({}, emptyTarget, value); return result; }, {}); function pickTarget({ options }) { return targets[options] || targets.standard; } function* each(array, fn, thisArg) { if (!array) { return; } for (let i = 0; i < array.length; i++) { yield* fn.call(thisArg, array[i], i, array); } } function* render(ctx) { const gen = Object.assign({ ctx, precision, each }, generator({ pretty: true })); const { header, start, el, end, elIfText } = gen; const { schema, getWptCmt, getWptSym, getWptType, getTrkType, hasWptExt, getWptExt, hasRteExt, getRteExt, hasRtePtExt, getRtePtExt, hasTrkExt, getTrkExt } = pickTarget(ctx); const $wpt_ext = getWptExt?.(gen); const $rte_ext = getRteExt?.(gen); const $rtept_ext = getRtePtExt?.(gen); const $trk_ext = getTrkExt?.(gen); const $name = elIfText.bind(undefined, 'name'); function* $link(url) { if (url) { yield* el('link', { href: url }); } } function* $cmt(cmt) { if (cmt) { yield* el('cmt', null, cmt); yield* el('desc', null, cmt); } } const $desc = elIfText.bind(undefined, 'desc'); function* $author(author) { if (!author) { return; } yield* start('author'); yield* $name(author.name); if (author.email) { yield* el('email', { id: author.email.id, domain: author.email.domain }); } if (author.link) { yield* start('link', { href: author.link }); yield* elIfText('text', author.short_name); yield* end(); } yield* end(); } function* $metadata(metadata) { yield* start('metadata'); yield* $name(metadata.name); yield* $desc(metadata.desc); yield* $author(metadata.author); yield* $link(metadata.link); yield* end(); } function* $waypoints(waypoints) { yield* each(waypoints, function* (step) { if (!step.coordinates) { return; } yield* start('wpt', { lat: step.coordinates.lat.toFixed(precision), lon: step.coordinates.lon.toFixed(precision) }); yield* $waypoint(step, function* () { if (hasWptExt(step)) { yield* start('extensions'); step.stopStreetAddress = step.stopStreetAddress || streetAddress(step); yield* $wpt_ext(step); yield* end(); } }); yield* end(); }); } function* $routes(routes) { yield* each(routes, $rte); } function* $tracks(tracks) { yield* each(tracks, $trk); } function* $waypoint(step, block) { if (step.arrival_time) { yield* elIfText('time', getTimestamp(step)); } yield* $name(step.name); yield* $cmt(getWptCmt(step)); yield* $link(step.url); yield* elIfText('sym', getWptSym(step)); yield* elIfText('type', getWptType(step)); yield* block(); } function* $rte(route) { yield* start('rte'); yield* $name(route.name); yield* $desc(route.desc); yield* $link(route.link); if (hasRteExt(route)) { yield* start('extensions'); if (route.arrival_time) { route.routeTimestamp = route.routeTimestamp || getTimestamp(route); } yield* $rte_ext(route); yield* end(); } yield* each(route.points, function* (step, index) { if (!step.coordinates) { return; } yield* start('rtept', { lat: step.coordinates.lat.toFixed(precision), lon: step.coordinates.lon.toFixed(precision) }); yield* $waypoint(step, function* () { if (hasRtePtExt(step)) { if (step.stopIsActualStop === undefined) { step.stopIsActualStop = isStop(step); } if (step.departure_time) { step.stopDeparture = step.stopDeparture || getDeparture(step); } if (step.arrival_time) { step.stopTimestamp = step.stopTimestamp || getTimestamp(step); } yield* start('extensions'); yield* $rtept_ext(route, step, index, route.points[index + 1]); yield* end(); } }); yield* end(); }); yield* end(); } function* $trk(track) { yield* start('trk'); yield* $name(track.name); yield* $desc(track.desc); yield* $link(track.link); if (track.points) { yield* elIfText('type', getTrkType(track)); if (hasTrkExt(track)) { yield* start('extensions'); yield* $trk_ext(track); yield* end(); } yield* each(track.points, function* (step) { const expanded = step.track; if (expanded && expanded.length) { yield* start('trkseg'); yield* each(expanded, function* (p) { yield* el('trkpt', { lat: p[1].toFixed(precision), lon: p[0].toFixed(precision) }); }); yield* end(); } }); } yield* end(); } function* generate() { yield* header(); yield* start('gpx', getSchema({ xmlns: 'http://www.topografix.com/GPX/1/1', creator: 'http://furkot.com/', version: '1.1', 'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance' }, schema)); yield* $metadata(ctx.metadata); yield* $waypoints(ctx.waypoints); yield* $routes(ctx.routes); yield* $tracks(ctx.tracks); yield* end(); } yield* generate(); }