feat: ignore bad distances when measuring track length

This commit is contained in:
Paul Bienkowski 2020-12-02 21:10:41 +01:00
parent 5770229945
commit d5f617e25c
2 changed files with 78 additions and 33 deletions

View file

@ -0,0 +1,65 @@
function* pairwise(iter) {
let last;
let firstLoop = true;
for (const it of iter) {
if (firstLoop) {
firstLoop = false;
} else {
yield [last, it];
}
last = it;
}
}
function* enumerate(iter) {
let i = 0;
for (const it of iter) {
yield [i, it];
i++;
}
}
const map = (fn) =>
function* (iter) {
for (const [i, it] of enumerate(iter)) {
yield fn(it, i);
}
};
const filter = (fn) =>
function* (iter) {
for (const it of iter) {
if (fn(it)) {
yield it;
}
}
};
const reduce = (fn, init) => (iter) => {
let acc = init;
for (const it of iter) {
acc = fn(acc, it);
}
return acc;
};
const scan = (fn) =>
function* (iter, init) {
let acc = init;
for (const it of iter) {
acc = fn(acc, it);
yield acc;
}
};
const flow = (...reducers) => (input) => reducers.reduce((c, fn) => fn(c), input);
module.exports = {
filter,
map,
enumerate,
pairwise,
flow,
reduce,
scan,
};

View file

@ -2,6 +2,8 @@ const mongoose = require('mongoose');
const uniqueValidator = require('mongoose-unique-validator');
const turf = require('turf');
const { flow, filter, map, pairwise, reduce } = require('../_helpers/generators');
const schema = new mongoose.Schema(
{
slug: { type: String, lowercase: true, unique: true },
@ -76,12 +78,17 @@ class TrackData extends mongoose.Model {
}
measureTrackLength() {
let totalLength = 0;
for (const [a, b] of pairwise(map(this.points, (p) => turf.point([p.longitude, p.latitude])))) {
const legLengthMeters = turf.distance(a, b) * 1000;
totalLength += legLengthMeters;
}
return totalLength;
return flow(
filter((p) => p.latitude != null && p.longitude != null),
map((p) => turf.point([p.longitude, p.latitude])),
pairwise,
map(([a, b]) => turf.distance(a, b) * 1000),
// Ignore distances between two points that are bigger than 100m, this
// must be a gap in the data or a mistake.
filter((d) => d <= 100),
reduce((c, d) => c + d, 0),
)(this.points);
}
get duration() {
@ -93,33 +100,6 @@ class TrackData extends mongoose.Model {
}
}
function* pairwise(iter) {
let last;
let firstLoop = true;
for (const it of iter) {
if (firstLoop) {
firstLoop = false;
} else {
yield [last, it];
}
last = it;
}
}
function* enumerate(iter) {
let i = 0;
for (const it of iter) {
yield [i, it];
i++;
}
}
function* map(iter, fn) {
for (const [i, it] of enumerate(iter)) {
yield fn(it, i);
}
}
mongoose.model(TrackData, schema);
module.exports = TrackData;