Skip to content

Commit

Permalink
make sequence a class! make travis just run all active tests!!!
Browse files Browse the repository at this point in the history
ref #10-splitter-adapter
  • Loading branch information
maxgrossman committed Aug 7, 2018
1 parent 4ef4feb commit cacf6f7
Show file tree
Hide file tree
Showing 16 changed files with 192 additions and 380 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ testData/
.vscode
node_modules/
yarn-error.log
coverage/
.nyc_output/
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ services:
- docker

before_install:
- npm run clean-migrations && docker build -t posm-paths .
- npm run migrate:clean && docker build -t posm-paths .

script:
- docker run posm-paths /bin/bash -c 'npm install --build-from-sources && SPATIALITE_LOCATION=/usr/lib/x86_64-linux-gnu ENVIRONMENT=test npm run test:migrate'
- docker run posm-paths /bin/bash -c 'npm install --build-from-sources && SPATIALITE_LOCATION=/usr/lib/x86_64-linux-gnu ENVIRONMENT=test npm run test'
3 changes: 0 additions & 3 deletions adapters/sequence/README.md

This file was deleted.

13 changes: 0 additions & 13 deletions adapters/sequence/build.js

This file was deleted.

50 changes: 0 additions & 50 deletions adapters/sequence/helpers.js

This file was deleted.

179 changes: 139 additions & 40 deletions adapters/sequence/index.js
Original file line number Diff line number Diff line change
@@ -1,52 +1,151 @@
'use strict';

const fs = require('fs-extra');
Promise = require('bluebird')

const readdir = require('fs-extra').readdir;
const path = require('path');
const buildSequences = require('./build');
const { ExifTool } = require('exiftool-vendored');
const exif = new ExifTool();
const uuidv4 = require('uuid/v4');
const dayjs = require('dayjs');
const flatten = require('../../helpers').flatten;

Promise = require('bluebird')
let instance;

/**
*
* @param {array} paths list of directory paths holding images to make sequences of
* @param {number} maxCutDist maximum distance allowed between two photos
* @param {number} minCutDist minimum distance allowed between two photos
* @param {number} cutTime maximum time between two images
* @param {number} cutSize maximum size of a sequence.
* @param {string} userId (optional) userId that when present attached to each sequence
* @return {array} array of sequence configuration objects
*/

module.exports = (paths, minCutDist, maxCutDist, maxDelta, sequenceSize, userId) => {
return new Promise((resolve, reject) => {
Promise.map(paths, async (p) => {
const images = await fs.readdir(p);
return images.map(f => path.join(p, f));
})
.then(async (images) => {
try {
const params = {
maxDist: maxCutDist,
minDist: minCutDist,
maxDelta: maxDelta,
size: sequenceSize
};

let sequences = await buildSequences(flatten(images), params);
if (userId) {
sequences = sequences.map(sequence => {
sequence.userId = userId
return sequence
});
class Sequence {
constructor () {
if (!Sequence.instance) {
Sequence.instance = this;
}
return Sequence.instance;
}

addSequence (sequences, sequence) {
sequences.push({ sequenceId: uuidv4(), sequence: sequence });
return sequences;
}

build (source, type, minCutDist, maxCutDist, maxDelta, seqSize, userId) {
return this.fromSource(source, type).then(images => {
const params = {
maxDist: maxCutDist,
minDist: minCutDist,
maxDelta: maxDelta,
size: seqSize
}
return this.cut(flatten(images), params).then(sequences => {
if (userId) {
sequences.map(sequence => {
sequence.userId = userId;
return sequence;
})
}
return sequences
})
.catch((err) => { throw err; })
})
.catch((err) => { throw err; })
}

calcDelta(date, nextDate) {
return nextDate.diff(date) / 1000;
}

resolve(sequences);
} catch (e) {
reject(e);
// https://gist.github.com/rochacbruno/2883505
calcDistance(loc, nextLoc) {
const R = 6371e3;
const diffLat = this.toRadian(nextLoc.lat) - this.toRadian(loc.lat);
const diffLon = this.toRadian(nextLoc.lon) - this.toRadian(loc.lon);
const a = Math.sin(diffLat / 2) * Math.sin(diffLat / 2) + Math.cos(this.toRadian(loc.lat)) *
Math.cos(this.toRadian(nextLoc.lat)) * Math.sin(diffLon / 2) * Math.sin(diffLon / 2);

const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return R * c;
}

cut(images, params) {
return Promise
.map(images, (image) => this.meta(image))
.then(metas => this.split(metas, params))
}

fromSource(source, type) {
if (type === 'directory') {
return Promise.map(source, (dir) => {
return readdir(dir)
.then(files => files.map(f => path.join(dir, f)))
})
}
}

makeDate(tags) {
return dayjs(tags.GPSDateTime.toString());
}

makeLoc(tags) {
return {
lon: Number(tags.GPSLongitude),
lat: Number(tags.GPSLatitude)
}
}

meta(image) {
return exif.read(image).then(tags => {
return {
image: image,
loc: this.makeLoc(tags),
timestamp: this.makeDate(tags),
id: uuidv4()
}
})
.catch(err => { throw err; });
}

toRadian(coord) {
return coord * (Math.PI / 100)
}

split(metas, params) {
const sortedMetas = metas.sort((a, b) => a.timestamp - b.timestamp);
const pelIndex = sortedMetas.length - 2;
const sequences = [];
const maxDist = params.maxDist;
const maxDelta = params.maxDelta;
const maxSize = params.maxSize;
const minDist = params.minDist;
let currentSequence = [];

sortedMetas.slice(0 , pelIndex).forEach((meta, i) => {
const partnerMeta = sortedMetas[i + 1],
distance = this.calcDistance(meta.loc, partnerMeta.loc),
tooClose = distance < minDist;

// ... if image is not too close to its partner, add it to a sequence.
if (!tooClose) {
// ... if the current sequence length matches the maximum size,
// or images are too far apart (in space or time),
// add the current sequence to the sequence map, then make a new sequence.
const delta = this.calcDelta(meta.timestamp, partnerMeta.timestamp),
needNewSequence = currentSequence.length === maxSize || distance > maxDist || delta > maxDelta;

if (needNewSequence) {
this.addSequence(sequences, currentSequence);
currentSequence = [];

}

// add a uuid then add it to the sequence!
meta.id = uuidv4();
currentSequence.push(meta);

}
})
})
}

if (currentSequence.length > 0) this.addSequence(sequences, currentSequence);
return sequences;
}
}

instance = new Sequence();
Object.freeze(instance);
module.exports = instance;
12 changes: 0 additions & 12 deletions adapters/sequence/make.js

This file was deleted.

30 changes: 0 additions & 30 deletions adapters/sequence/meta.js

This file was deleted.

Loading

0 comments on commit cacf6f7

Please sign in to comment.