add geography request

This commit is contained in:
sbriat
2023-04-11 16:28:22 +02:00
parent 1e4aa0eadc
commit b90db67ed0
13 changed files with 382 additions and 8 deletions

View File

@@ -16,8 +16,11 @@ import { MarginDurations } from '../entities/margin-durations.type';
import { Algorithm } from './algorithm.enum';
import { IRequestTime } from '../interfaces/time-request.interface';
import { IRequestPerson } from '../interfaces/person-request.interface';
import { IRequestGeography } from '../interfaces/geography-request.interface';
export class MatchRequest implements IRequestTime, IRequestPerson {
export class MatchRequest
implements IRequestTime, IRequestPerson, IRequestGeography
{
@IsArray()
@AutoMap()
waypoints: Array<Point>;

View File

@@ -0,0 +1,9 @@
import { Person } from './person';
import { Role } from './role.enum';
import { Step } from './step.enum';
export type Actor = {
person: Person;
role: Role;
step: Step;
};

View File

@@ -0,0 +1,7 @@
export enum PointType {
HOUSE_NUMBER = 'HOUSE_NUMBER',
STREET_ADDRESS = 'STREET_ADDRESS',
LOCALITY = 'LOCALITY',
VENUE = 'VENUE',
OTHER = 'OTHER',
}

View File

@@ -1,11 +1,63 @@
import { MatcherException } from '../../exceptions/matcher.exception';
import { IRequestGeography } from '../interfaces/geography-request.interface';
import { PointType } from './geography.enum';
import { Point } from './point.type';
import { Route } from './route';
import { find } from 'geo-tz';
import { Waypoint } from './waypoint';
export class Geography {
waypoints: Array<Point>;
originType: number;
destinationType: number;
timezone: string;
_geographyRequest: IRequestGeography;
waypoints: Array<Waypoint>;
originType: PointType;
destinationType: PointType;
timeZones: Array<string>;
driverRoute: Route;
passengerRoute: Route;
constructor(geographyRequest: IRequestGeography) {
this._geographyRequest = geographyRequest;
this.waypoints = [];
this.originType = PointType.OTHER;
this.destinationType = PointType.OTHER;
}
init() {
this._validateWaypoints();
this._setTimeZones();
}
_validateWaypoints() {
if (this._geographyRequest.waypoints.length < 2) {
throw new MatcherException(3, 'At least 2 waypoints are required');
}
this._geographyRequest.waypoints.map((point) => {
if (!this._isValidPoint(point)) {
throw new MatcherException(
3,
`Waypoint { Lon: ${point.lon}, Lat: ${point.lat} } is not valid`,
);
}
this.waypoints.push({
point,
actors: [],
});
});
}
_setTimeZones() {
this.timeZones = find(
this._geographyRequest.waypoints[0].lat,
this._geographyRequest.waypoints[0].lon,
);
}
_isValidPoint = (point: Point): boolean =>
this._isValidLongitude(point.lon) && this._isValidLatitude(point.lat);
_isValidLongitude = (longitude: number): boolean =>
longitude >= -180 && longitude <= 180;
_isValidLatitude = (latitude: number): boolean =>
latitude >= -90 && latitude <= 90;
}

View File

@@ -0,0 +1,6 @@
export enum Step {
START = 'start',
INTERMEDIATE = 'intermediate',
NEUTRAL = 'neutral',
FINISH = 'finish',
}

View File

@@ -70,6 +70,9 @@ export class Time {
if (!this._isDate(this.toDate)) {
throw new MatcherException(3, 'Wrong toDate');
}
if (this.toDate < this.fromDate) {
throw new MatcherException(3, 'toDate must be after fromDate');
}
}
if (this._timeRequest.fromDate) {
this._validateSchedule();

View File

@@ -0,0 +1,7 @@
import { Actor } from './actor';
import { Point } from './point.type';
export type Waypoint = {
point: Point;
actors: Array<Actor>;
};

View File

@@ -0,0 +1,5 @@
import { Point } from '../entities/point.type';
export interface IRequestGeography {
waypoints: Array<Point>;
}

View File

@@ -13,8 +13,8 @@ export class MatchQuery {
person: Person;
roles: Array<Role>;
time: Time;
exclusions: Array<number>;
geography: Geography;
exclusions: Array<number>;
requirement: Requirement;
settings: Settings;
@@ -24,12 +24,12 @@ export class MatchQuery {
this._setPerson();
this._setRoles();
this._setTime();
this._setGeography();
this._initialize();
this._setExclusions();
}
_initialize() {
this.geography = new Geography();
this.requirement = new Requirement();
this.settings = new Settings();
}
@@ -59,6 +59,11 @@ export class MatchQuery {
this.time.init();
}
_setGeography() {
this.geography = new Geography(this._matchRequest);
this.geography.init();
}
_setExclusions() {
this.exclusions = [];
if (this._matchRequest.identifier)

View File

@@ -0,0 +1,85 @@
import { Geography } from '../../domain/entities/geography';
describe('Geography entity', () => {
it('should be defined', () => {
const geography = new Geography({
waypoints: [
{
lat: 49.440041,
lon: 1.093912,
},
{
lat: 50.630992,
lon: 3.045432,
},
],
});
expect(geography).toBeDefined();
});
describe('init', () => {
it('should initialize a geography request', () => {
const geography = new Geography({
waypoints: [
{
lat: 49.440041,
lon: 1.093912,
},
{
lat: 50.630992,
lon: 3.045432,
},
],
});
geography.init();
expect(geography.waypoints.length).toBe(2);
});
it('should throw an exception if waypoints are empty', () => {
const geography = new Geography({
waypoints: [],
});
expect(() => geography.init()).toThrow();
});
it('should throw an exception if only one waypoint is provided', () => {
const geography = new Geography({
waypoints: [
{
lat: 49.440041,
lon: 1.093912,
},
],
});
expect(() => geography.init()).toThrow();
});
it('should throw an exception if a waypoint has invalid longitude', () => {
const geography = new Geography({
waypoints: [
{
lat: 49.440041,
lon: 201.093912,
},
{
lat: 50.630992,
lon: 3.045432,
},
],
});
expect(() => geography.init()).toThrow();
});
it('should throw an exception if a waypoint has invalid latitude', () => {
const geography = new Geography({
waypoints: [
{
lat: 49.440041,
lon: 1.093912,
},
{
lat: 250.630992,
lon: 3.045432,
},
],
});
expect(() => geography.init()).toThrow();
});
});
});

View File

@@ -123,6 +123,17 @@ describe('Time entity', () => {
);
expect(() => time.init()).toThrow();
});
it('should throw an exception if recurrent toDate is before fromDate', () => {
const time = new Time(
{
fromDate: '2023-04-01',
toDate: '2023-03-01',
},
MARGIN_DURATION,
VALIDITY_DURATION,
);
expect(() => time.init()).toThrow();
});
it('should throw an exception if schedule is missing', () => {
const time = new Time(
{