UNPKG

@openhps/core

Version:

Open Hybrid Positioning System - Core component

153 lines (143 loc) 5.77 kB
import { Trajectory } from '../data/position'; import { DataObject } from '../data/object/DataObject'; import { DataService } from './DataService'; import { DataServiceDriver, DataServiceOptions } from './DataServiceDriver'; import { Model } from '../Model'; import { Constructor } from 'typedjson'; /** * A trajectory service stores the position of a data object * in a continuous trajectory. */ export class TrajectoryService<T extends Trajectory = Trajectory> extends DataService<string, T> { public model: Model; protected options: TrajectoryServiceOptions; constructor(dataServiceDriver?: DataServiceDriver<string, T>, options?: TrajectoryServiceOptions) { super(dataServiceDriver as any); this.options = options || {}; this.options.autoBind = this.options.autoBind === undefined ? true : this.options.autoBind; this.options.dataService = this.options.dataService || DataObject; this.options.defaultUID = this.options.defaultUID ?? ((object) => object.uid); if (this.options.autoBind) { this.once('build', this._bindService.bind(this)); } } private _bindService(): Promise<void> { return new Promise((resolve, reject) => { if (!this.model) { // No model return resolve(); } const dataObjectService = this.model.findDataService(this.options.dataService); if (dataObjectService) { dataObjectService.on('insert', async (_, object) => { await this.appendPosition(object); }); resolve(); } else { reject(new Error(`Data object service not found for '${this.options.dataService}'`)); } }); } /** * Find the latest trajectory * @param {DataObject | string} object Data object to get trajectories for * @returns {Promise<Trajectory>} Trajectory promise if found */ public findCurrentTrajectory(object: DataObject | string): Promise<T> { return new Promise((resolve, reject) => { this.findOne( { objectUID: object instanceof DataObject ? object.uid : object, }, { sort: [['createdTimestamp', -1]], }, ) .then(resolve) .catch(reject); }); } /** * Find the trajectory of an object from start to end date * @param {DataObject | string} object Data object to get trajectory for * @param {Date | number} start Start time or date * @param {Date | number} end End time or date * @returns {Trajectory} Trajectory match */ public findTrajectoryByRange(object: DataObject | string, start?: Date | number, end?: Date | number): Promise<T> { return new Promise((resolve, reject) => { this.findOne({ objectUID: object instanceof DataObject ? object.uid : object, positions: { $elemMatch: { timestamp: { $lte: end ? (end instanceof Date ? end.getTime() : end) : Number.MAX_VALUE, $gte: start ? (start instanceof Date ? start.getTime() : start) : -1, }, }, }, }) .then((trajectory) => { resolve(trajectory); }) .catch(reject); }); } /** * Find all trajectories of an object * @param {DataObject | string} object Data object to get trajectories for * @returns {Promise<string[]>} List of trajectory UIDs */ public findTrajectories(object: DataObject | string): Promise<string[]> { return new Promise((resolve) => { this.findAll({ objectUID: object instanceof DataObject ? object.uid : object, }).then((trajectories) => { resolve(trajectories.map((trajectory) => trajectory.uid)); }); }); } /** * Append a position to the trajectory service * @param {DataObject} object Data object to store * @param {string} uid Trajectory uid * @returns {Promise<Trajectory>} Stored trajectory */ public appendPosition(object: DataObject, uid?: string): Promise<T> { return new Promise((resolve, reject) => { const position = object.getPosition(); if (position) { Promise.resolve(uid ? this.findOne({ uid }) : this.findCurrentTrajectory(object)) .then((trajectory: T) => { if (!trajectory) { trajectory = new this.driver.dataType(); trajectory.objectUID = object.uid; trajectory.uid = uid ?? this.options.defaultUID(object); } trajectory.positions.push(object.position); return this.insert(trajectory.uid, trajectory); }) .then(resolve) .catch(reject); } else { return reject(); } }); } } export interface TrajectoryServiceOptions extends DataServiceOptions { /** * Dataservice to fetch stored data objects */ dataService?: Constructor<DataObject>; /** * Automatically bind to the data object service * @default true */ autoBind?: boolean; /** * Default UID of a trajectory with autoBind = true * @default (object) => object.uid */ defaultUID?: (object: DataObject) => string; }