diff --git a/.gitignore b/.gitignore index 726e6d6..c9e6f76 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ yarn-error.log* .zanata-cache po/*.po po/*.pot +tests/*.gpx # Editor directories and files .idea diff --git a/README.md b/README.md index f5dc055..4d7d239 100644 --- a/README.md +++ b/README.md @@ -141,6 +141,12 @@ python -m server to spawn the server-side part, listening on `localhost:8081`. +### Useful scripts for dev + +You can run `scripts/gps_to_gpx.py` on your GPX trace to create a +`src/tools/mock_gpx.json` file ready to be used as a mocking source for the +position data (just edit the `src/constants.js` file accordingly). + ## Translating diff --git a/scripts/gps_to_js.py b/scripts/gps_to_js.py new file mode 100644 index 0000000..0a8ffe8 --- /dev/null +++ b/scripts/gps_to_js.py @@ -0,0 +1,34 @@ +import json +import os +import sys + +import gpxpy + +if __name__ == "__main__": + if len(sys.argv) < 2: + sys.exit('Usage: %s GPX_FILE' % sys.argv[0]) + + with open (sys.argv[1], 'r') as fh: + gpx = gpxpy.parse(fh) + + json_out = [] + for track in gpx.tracks: + for segment in track.segments: + for point in segment.points: + # TODO: Other fields + json_out.append({ + 'time': point.time.isoformat(), + 'coords': { + 'accuracy': point.horizontal_dilution, + 'altitudeAccuracy': point.vertical_dilution, + 'heading': None, + 'latitude': point.latitude, + 'longitude': point.longitude + } + }) + break + break + + script_dir = os.path.dirname(os.path.realpath(__file__)) + with open(os.path.join(script_dir, '../src/tools/mock_gpx.json'), 'w') as fh: + json.dump(json_out, fh) diff --git a/src/constants.js b/src/constants.js index 43cbec9..e274ad0 100644 --- a/src/constants.js +++ b/src/constants.js @@ -113,7 +113,21 @@ export const REPORT_TYPES_ORDER = ['gcum', 'interrupt', 'obstacle', 'pothole', ' export const MIN_DISTANCE_REPORT_DETAILS = 40; // in meters export const MOCK_LOCATION = false; +export const MOCK_LOCATION_USE_GPX = true; +export const MOCK_LOCATION_GPX_PLAYBACK_SPEED = 2.0; export const MOCK_LOCATION_UPDATE_INTERVAL = 5 * 1000; // in milliseconds +// Small area in Montrouge +export const MOCK_LOCATION_LAT_MIN = 48.81788; +export const MOCK_LOCATION_LNG_MIN = 2.31723; +export const MOCK_LOCATION_LAT_MAX = 48.81952; +export const MOCK_LOCATION_LNG_MAX = 2.32077; +// Paris +/* +export const MOCK_LOCATION_LAT_MIN = 48.854031; +export const MOCK_LOCATION_LNG_MIN = 2.281279; +export const MOCK_LOCATION_LAT_MAX = 48.886123; +export const MOCK_LOCATION_LNG_MAX = 2.392742; +*/ export const UPDATE_REPORTS_DISTANCE_THRESHOLD = 500; // in meters diff --git a/src/tools/index.js b/src/tools/index.js index 208369b..a228545 100644 --- a/src/tools/index.js +++ b/src/tools/index.js @@ -1,4 +1,18 @@ -import { EARTH_RADIUS } from '@/constants'; +import moment from 'moment'; + +import { + EARTH_RADIUS, + MOCK_LOCATION_GPX_PLAYBACK_SPEED, + MOCK_LOCATION_UPDATE_INTERVAL, + MOCK_LOCATION_USE_GPX, + MOCK_LOCATION_LAT_MIN, MOCK_LOCATION_LAT_MAX, + MOCK_LOCATION_LNG_MIN, MOCK_LOCATION_LNG_MAX, +} from '@/constants'; + +let mockGPX = null; +if (process.env.NODE_ENV !== 'production') { + mockGPX = require('@/tools/mock_gpx.json'); // eslint-disable-line global-require +} export function distance(latLng1, latLng2) { const lat1 = (latLng1[0] * Math.PI) / 180; @@ -16,21 +30,7 @@ export function distance(latLng1, latLng2) { return EARTH_RADIUS * c; } -export function mockLocation() { - // Over Paris - /* - const LAT_MIN = 48.854031; - const LNG_MIN = 2.281279; - const LAT_MAX = 48.886123; - const LNG_MAX = 2.392742; - */ - - // Over small area - const LAT_MIN = 48.81788; - const LNG_MIN = 2.31723; - const LAT_MAX = 48.81952; - const LNG_MAX = 2.32077; - +export function mockLocationRandom() { let heading = null; if (Math.random() > 0.25) { heading = Math.random() * 360; @@ -38,8 +38,14 @@ export function mockLocation() { const newLocation = { coords: { accuracy: 10, // In meters - latitude: (Math.random() * (LAT_MAX - LAT_MIN)) + LAT_MIN, - longitude: (Math.random() * (LNG_MAX - LNG_MIN)) + LNG_MIN, + latitude: ( + (Math.random() * (MOCK_LOCATION_LAT_MAX - MOCK_LOCATION_LAT_MIN)) + + MOCK_LOCATION_LAT_MIN + ), + longitude: ( + (Math.random() * (MOCK_LOCATION_LNG_MAX - MOCK_LOCATION_LNG_MIN)) + + MOCK_LOCATION_LNG_MIN + ), heading, }, timestamp: new Date().getTime(), @@ -48,6 +54,32 @@ export function mockLocation() { return newLocation; } +export function mockLocationWithGPX(index, setPosition) { + setPosition(mockGPX[index]); + if (index < mockGPX.length) { + const delay = ( + moment(mockGPX[index + 1].time).valueOf() + - moment(mockGPX[index].time).valueOf() + ); + setTimeout( + () => mockLocationWithGPX(index + 1, setPosition), + delay / MOCK_LOCATION_GPX_PLAYBACK_SPEED, + ); + } +} + +export function mockLocation(setPosition) { + if (MOCK_LOCATION_USE_GPX) { + mockLocationWithGPX(0, setPosition); + return null; + } + setPosition(mockLocationRandom()); + return setInterval( + () => setPosition(mockLocationRandom()), + MOCK_LOCATION_UPDATE_INTERVAL, + ); +} + export function storageAvailable(type) { let storage; try { diff --git a/src/tools/mock_gpx.json b/src/tools/mock_gpx.json new file mode 100644 index 0000000..fe51488 --- /dev/null +++ b/src/tools/mock_gpx.json @@ -0,0 +1 @@ +[] diff --git a/src/views/Map.vue b/src/views/Map.vue index 2133b41..d3b899a 100644 --- a/src/views/Map.vue +++ b/src/views/Map.vue @@ -166,11 +166,7 @@ export default { // Set up a watcher let watchID = null; if (constants.MOCK_LOCATION) { - setPosition(mockLocation()); - watchID = setInterval( - () => setPosition(mockLocation()), - constants.MOCK_LOCATION_UPDATE_INTERVAL, - ); + watchID = mockLocation(setPosition); } else { if (!('geolocation' in navigator)) { const $t = this.$t.bind(this); diff --git a/tests/.gitkeep b/tests/.gitkeep new file mode 100644 index 0000000..e69de29