mirror of
https://gitlab.com/mobicoop/v3/service/matcher.git
synced 2026-01-01 08:12:40 +00:00
add geography request
This commit is contained in:
@@ -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>;
|
||||
|
||||
9
src/modules/matcher/domain/entities/actor.ts
Normal file
9
src/modules/matcher/domain/entities/actor.ts
Normal 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;
|
||||
};
|
||||
7
src/modules/matcher/domain/entities/geography.enum.ts
Normal file
7
src/modules/matcher/domain/entities/geography.enum.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export enum PointType {
|
||||
HOUSE_NUMBER = 'HOUSE_NUMBER',
|
||||
STREET_ADDRESS = 'STREET_ADDRESS',
|
||||
LOCALITY = 'LOCALITY',
|
||||
VENUE = 'VENUE',
|
||||
OTHER = 'OTHER',
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
6
src/modules/matcher/domain/entities/step.enum.ts
Normal file
6
src/modules/matcher/domain/entities/step.enum.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export enum Step {
|
||||
START = 'start',
|
||||
INTERMEDIATE = 'intermediate',
|
||||
NEUTRAL = 'neutral',
|
||||
FINISH = 'finish',
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
7
src/modules/matcher/domain/entities/waypoint.ts
Normal file
7
src/modules/matcher/domain/entities/waypoint.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { Actor } from './actor';
|
||||
import { Point } from './point.type';
|
||||
|
||||
export type Waypoint = {
|
||||
point: Point;
|
||||
actors: Array<Actor>;
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Point } from '../entities/point.type';
|
||||
|
||||
export interface IRequestGeography {
|
||||
waypoints: Array<Point>;
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
85
src/modules/matcher/tests/unit/geography.spec.ts
Normal file
85
src/modules/matcher/tests/unit/geography.spec.ts
Normal 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();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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(
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user