diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/trips.ts | 115 | ||||
-rw-r--r-- | lib/useEvent.ts | 20 | ||||
-rw-r--r-- | lib/util.ts | 30 |
3 files changed, 0 insertions, 165 deletions
diff --git a/lib/trips.ts b/lib/trips.ts deleted file mode 100644 index 40a71a4..0000000 --- a/lib/trips.ts +++ /dev/null @@ -1,115 +0,0 @@ -import path from 'path'; -import fs from 'fs'; -import { DOMParser } from 'xmldom'; -import { FeatureCollection, LineString } from 'geojson'; -import { gpx } from '@tmcw/togeojson'; -import gb from 'geojson-bounds'; -import * as ExifReader from 'exifreader'; -import _ from 'lodash'; - -import { Trip, Photo } from 'models'; -import { distanceBetween } from 'lib/util'; - -const tripsDirectory = path.join(process.cwd(), 'trips'); - -// extract photo metadata from EXIF -function getPhotoMetadata(filePath: string) { - const buffer = fs.readFileSync(filePath); - const tags = ExifReader.load(buffer, { expanded: true }); - - return { - latitude: tags.gps.Latitude, - longitude: tags.gps.Longitude, - time: tags.exif.DateTime.description.replace(':', '-').replace(':', '-'), - }; -} - -/** - * Reads GPX files and photos from trips folder. - */ -export default function getTripsData(): Trip[] { - // get folder names under /trips - const dirs = fs - .readdirSync(tripsDirectory, { withFileTypes: true }) - .filter((dirent) => dirent.isDirectory()) - .map((dirent) => dirent.name); - const allTripsData = dirs.map((dir: string) => { - const dirPath = path.join(tripsDirectory, dir); - const files = fs.readdirSync(dirPath); - - const gpxFiles = files.filter((f) => f.endsWith('.gpx')); - - // read GPX file as string - const fullPath = path.join(dirPath, gpxFiles[0]); - const fileContents = fs.readFileSync(fullPath, 'utf8'); - const contentsWithoutNS = fileContents.replace(/\sxmlns[^"]+"[^"]+"/g, ''); - - // create DOM from string - const doc = new DOMParser().parseFromString(contentsWithoutNS); - - // convert GPX to GeoJSON - const track: FeatureCollection = gpx(doc); - - // add bounding box - track.bbox = [gb.xMin(track), gb.yMin(track), gb.xMax(track), gb.yMax(track)]; - - const { coordTimes } = track.features[0].properties; - - // time of the first point - const start = coordTimes[0]; - - // time of the last point - const end = coordTimes[coordTimes.length - 1]; - - // total duration in seconds - const duration = (new Date(end).getTime() - new Date(start).getTime()) / 1000; - - // distance and speed - let totalDistance = 0; - const speeds = []; - const coords = (track.features[0].geometry as LineString).coordinates; - - for (let i = 0; i < coords.length - 1; i += 1) { - const a = [coords[i][1], coords[i][0]]; - const b = [coords[i + 1][1], coords[i + 1][0]]; - const distance = distanceBetween(a, b); - if (distance > 0) { - totalDistance += distance; - const timeBetween = - new Date(coordTimes[i + 1]).getTime() - new Date(coordTimes[i]).getTime(); - speeds.push(distance / timeBetween); - } - } - - // total distance in km - const distance = Math.floor(totalDistance / 10) / 100; - - // average speed in km/h - const speedMps = speeds.reduce((acc, val) => acc + val) / speeds.length; - const speed = Math.floor(speedMps * 3600 * 100) / 100; - - // photos - const photoFiles = files.filter((f) => f.endsWith('.jpg')); - const photos: Photo[] = photoFiles.map((p) => { - // eslint-disable-next-line global-require, import/no-dynamic-require, @typescript-eslint/no-var-requires - return { - name: _.kebabCase(p), - src: require(`trips/${dir}/${p}`).src, - thumbnail: require(`trips/${dir}/${p}?resize&sizes[]=36`).src, - ...getPhotoMetadata(path.join(dirPath, p)), - }; - }); - - const trip: Trip = { name: dir, track, distance, start, end, duration, speed, photos }; - - return trip; - }); - - // sort trips by name - return allTripsData.sort((a, b) => { - if (a.name < b.name) { - return 1; - } - return -1; - }); -} diff --git a/lib/useEvent.ts b/lib/useEvent.ts deleted file mode 100644 index 70d51b1..0000000 --- a/lib/useEvent.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { useEffect } from 'react'; - -/** - * A hook for creating event handlers. - */ -export default function useEvent( - event: string, - handler: (e: KeyboardEvent | MouseEvent) => void, - passive = false, -): void { - useEffect(() => { - // initiate the event handler - window.addEventListener(event, handler, passive); - - // this will clean up the event every time the component is re-rendered - return function cleanup() { - window.removeEventListener(event, handler); - }; - }); -} diff --git a/lib/util.ts b/lib/util.ts deleted file mode 100644 index 5a00aed..0000000 --- a/lib/util.ts +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Converts time in seconds to HH:mm format. - * @param time Time to convert in seconds. - */ -export function secondsToTimeString(time: number): string { - const h = Math.floor(time / 3600); - const m = Math.floor((time % 3600) / 60); - - return `${h < 10 ? `0${h}` : h}:${m < 10 ? `0${m}` : m}`; -} - -/** - * Calculates distance between two geographical points. - * @param latlng1 Coordinates of the first point. - * @param latlng2 Coordinates of the second point. - */ -export function distanceBetween(latlng1: number[], latlng2: number[]): number { - const R = 6371000; - const rad = Math.PI / 180; - const lat1 = latlng1[0] * rad; - const lat2 = latlng2[0] * rad; - const sinDLat = Math.sin(((latlng2[0] - latlng1[0]) * rad) / 2); - const sinDLon = Math.sin(((latlng2[1] - latlng1[1]) * rad) / 2); - const a = sinDLat * sinDLat + Math.cos(lat1) * Math.cos(lat2) * sinDLon * sinDLon; - const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); - - return R * c; -} - -export default { secondsToTimeString, distanceBetween }; |