WIP create query
This commit is contained in:
parent
f3ca813dd6
commit
d6a12e4d0e
|
@ -2,17 +2,18 @@ import { Mapper } from '@automapper/core';
|
|||
import { InjectMapper } from '@automapper/nestjs';
|
||||
import { Controller, UsePipes } from '@nestjs/common';
|
||||
import { QueryBus } from '@nestjs/cqrs';
|
||||
import { GrpcMethod } from '@nestjs/microservices';
|
||||
import { GrpcMethod, RpcException } from '@nestjs/microservices';
|
||||
import { RpcValidationPipe } from 'src/modules/utils/pipes/rpc.validation-pipe';
|
||||
import { MatchRequest } from '../../domain/dtos/match.request';
|
||||
import { ICollection } from 'src/modules/database/src/interfaces/collection.interface';
|
||||
import { Match } from '../../domain/entities/match';
|
||||
import { MatchQuery } from '../../queries/match.query';
|
||||
import { MatchPresenter } from '../secondaries/match.presenter';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
|
||||
@UsePipes(
|
||||
new RpcValidationPipe({
|
||||
whitelist: true,
|
||||
whitelist: false,
|
||||
forbidUnknownValues: false,
|
||||
}),
|
||||
)
|
||||
|
@ -20,17 +21,27 @@ import { MatchPresenter } from '../secondaries/match.presenter';
|
|||
export class MatcherController {
|
||||
constructor(
|
||||
private readonly _queryBus: QueryBus,
|
||||
private readonly _configService: ConfigService,
|
||||
@InjectMapper() private readonly _mapper: Mapper,
|
||||
) {}
|
||||
|
||||
@GrpcMethod('MatcherService', 'Match')
|
||||
async match(data: MatchRequest): Promise<ICollection<Match>> {
|
||||
const matchCollection = await this._queryBus.execute(new MatchQuery(data));
|
||||
return Promise.resolve({
|
||||
data: matchCollection.data.map((match: Match) =>
|
||||
this._mapper.map(match, Match, MatchPresenter),
|
||||
),
|
||||
total: matchCollection.total,
|
||||
});
|
||||
try {
|
||||
const matchCollection = await this._queryBus.execute(
|
||||
new MatchQuery(data, this._configService),
|
||||
);
|
||||
return Promise.resolve({
|
||||
data: matchCollection.data.map((match: Match) =>
|
||||
this._mapper.map(match, Match, MatchPresenter),
|
||||
),
|
||||
total: matchCollection.total,
|
||||
});
|
||||
} catch (e) {
|
||||
throw new RpcException({
|
||||
code: e.code,
|
||||
message: e.message,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,27 @@ service MatcherService {
|
|||
|
||||
message MatchRequest {
|
||||
repeated Point waypoints = 1;
|
||||
string departure = 2;
|
||||
string fromDate = 3;
|
||||
Schedule schedule = 4;
|
||||
bool driver = 5;
|
||||
bool passenger = 6;
|
||||
string toDate = 7;
|
||||
int32 marginDuration = 8;
|
||||
MarginDurations marginDurations = 9;
|
||||
int32 seatsPassenger = 10;
|
||||
int32 seatsDriver = 11;
|
||||
bool strict = 12;
|
||||
Algorithm algorithm = 13;
|
||||
int32 remoteness = 14;
|
||||
bool useProportion = 15;
|
||||
int32 proportion = 16;
|
||||
bool useAzimuth = 17;
|
||||
int32 azimuthMargin = 18;
|
||||
int32 maxDetourDistanceRatio = 19;
|
||||
int32 maxDetourDurationRatio = 20;
|
||||
repeated int32 exclusions = 21;
|
||||
int32 identifier = 22;
|
||||
}
|
||||
|
||||
message Point {
|
||||
|
@ -15,6 +36,30 @@ message Point {
|
|||
float lat = 2;
|
||||
}
|
||||
|
||||
message Schedule {
|
||||
string mon = 1;
|
||||
string tue = 2;
|
||||
string wed = 3;
|
||||
string thu = 4;
|
||||
string fri = 5;
|
||||
string sat = 6;
|
||||
string sun = 7;
|
||||
}
|
||||
|
||||
message MarginDurations {
|
||||
int32 mon = 1;
|
||||
int32 tue = 2;
|
||||
int32 wed = 3;
|
||||
int32 thu = 4;
|
||||
int32 fri = 5;
|
||||
int32 sat = 6;
|
||||
int32 sun = 7;
|
||||
}
|
||||
|
||||
enum Algorithm {
|
||||
CLASSIC = 0;
|
||||
}
|
||||
|
||||
message Match {
|
||||
string uuid = 1;
|
||||
}
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
import {
|
||||
IsArray,
|
||||
IsBoolean,
|
||||
IsDate,
|
||||
IsEnum,
|
||||
IsInt,
|
||||
IsNumber,
|
||||
IsOptional,
|
||||
IsString,
|
||||
Max,
|
||||
Min,
|
||||
} from 'class-validator';
|
||||
import { AutoMap } from '@automapper/classes';
|
||||
import { Point } from '../entities/point.type';
|
||||
import { Schedule } from '../entities/schedule.type';
|
||||
import { MarginDurations } from '../entities/margin_durations.type';
|
||||
import { Schedule } from './schedule.type';
|
||||
import { MarginDurations } from './margin-durations.type';
|
||||
import { Algorithm } from './algorithm.enum';
|
||||
|
||||
export class MatchRequest {
|
||||
|
@ -20,15 +20,15 @@ export class MatchRequest {
|
|||
@AutoMap()
|
||||
waypoints: Array<Point>;
|
||||
|
||||
@IsDate()
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@AutoMap()
|
||||
departure: Date;
|
||||
departure: number;
|
||||
|
||||
@IsDate()
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@AutoMap()
|
||||
fromDate: Date;
|
||||
fromDate: number;
|
||||
|
||||
@IsOptional()
|
||||
@AutoMap()
|
||||
|
@ -45,9 +45,9 @@ export class MatchRequest {
|
|||
passenger: boolean;
|
||||
|
||||
@IsOptional()
|
||||
@IsDate()
|
||||
@IsInt()
|
||||
@AutoMap()
|
||||
toDate: Date;
|
||||
toDate: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
|
@ -123,4 +123,9 @@ export class MatchRequest {
|
|||
@IsOptional()
|
||||
@IsArray()
|
||||
exclusions: Array<number>;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@AutoMap()
|
||||
identifier: number;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
import { Point } from './point.type';
|
||||
import { Route } from './route';
|
||||
|
||||
export class Geography {
|
||||
waypoints: Array<Point>;
|
||||
originType: number;
|
||||
destinationType: number;
|
||||
timezone: string;
|
||||
driverRoute: Route;
|
||||
passengerRoute: Route;
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
import { MatchRequest } from '../dtos/match.request';
|
||||
|
||||
export class Person {
|
||||
_matchRequest: MatchRequest;
|
||||
_defaultIdentifier: number;
|
||||
_defaultMarginDuration: number;
|
||||
identifier: number;
|
||||
marginDurations: Array<number>;
|
||||
|
||||
constructor(
|
||||
matchRequest: MatchRequest,
|
||||
defaultIdentifier: number,
|
||||
defaultMarginDuration: number,
|
||||
) {
|
||||
this._matchRequest = matchRequest;
|
||||
this._defaultIdentifier = defaultIdentifier;
|
||||
this._defaultMarginDuration = defaultMarginDuration;
|
||||
}
|
||||
|
||||
init() {
|
||||
this.setIdentifier(
|
||||
this._matchRequest.identifier ?? this._defaultIdentifier,
|
||||
);
|
||||
this.setMarginDurations([
|
||||
this._defaultMarginDuration,
|
||||
this._defaultMarginDuration,
|
||||
this._defaultMarginDuration,
|
||||
this._defaultMarginDuration,
|
||||
this._defaultMarginDuration,
|
||||
this._defaultMarginDuration,
|
||||
this._defaultMarginDuration,
|
||||
]);
|
||||
}
|
||||
|
||||
setIdentifier(identifier: number) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
setMarginDurations(marginDurations: Array<number>) {
|
||||
this.marginDurations = marginDurations;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
export class Requirement {
|
||||
seatsDriver: number;
|
||||
seatsPassenger: number;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export class Route {}
|
|
@ -0,0 +1,14 @@
|
|||
import { Georouter } from '../interfaces/georouter.interface';
|
||||
|
||||
export class Settings {
|
||||
algorithm: Algorithm;
|
||||
restrict: boolean;
|
||||
remoteness: number;
|
||||
useProportion: boolean;
|
||||
proportion: number;
|
||||
useAzimuth: boolean;
|
||||
azimuthMargin: number;
|
||||
maxDetourDurationRatio: number;
|
||||
maxDetourDistanceRatio: number;
|
||||
georouter: Georouter;
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
import { MatcherException } from '../../exceptions/matcher.exception';
|
||||
import { MatchRequest } from '../dtos/match.request';
|
||||
import { TimingFrequency } from './timing';
|
||||
|
||||
export class Time {
|
||||
_matchRequest: MatchRequest;
|
||||
_defaultMarginDuration: number;
|
||||
_defaultValidityDuration: number;
|
||||
frequency: TimingFrequency;
|
||||
fromDate: Date;
|
||||
toDate: Date;
|
||||
schedule: Array<Date>;
|
||||
marginDurations: Array<number>;
|
||||
|
||||
constructor(
|
||||
matchRequest: MatchRequest,
|
||||
defaultMarginDuration: number,
|
||||
defaultValidityDuration: number,
|
||||
) {
|
||||
this._matchRequest = matchRequest;
|
||||
this._defaultMarginDuration = defaultMarginDuration;
|
||||
this._defaultValidityDuration = defaultValidityDuration;
|
||||
}
|
||||
|
||||
init() {
|
||||
this._validatePunctualDate();
|
||||
this._validateRecurrentDate();
|
||||
}
|
||||
|
||||
_validatePunctualDate() {
|
||||
if (!this._matchRequest.departure && !this._matchRequest.fromDate) {
|
||||
throw new MatcherException(3, 'departure or fromDate is Required');
|
||||
}
|
||||
if (this._matchRequest.departure) {
|
||||
this.fromDate = new Date(this._matchRequest.departure);
|
||||
if (!this._isDate(this.fromDate)) {
|
||||
throw new MatcherException(3, 'Wrong departure date');
|
||||
}
|
||||
console.log(this.fromDate);
|
||||
}
|
||||
}
|
||||
|
||||
_validateRecurrentDate() {
|
||||
console.log('validate recurrent date');
|
||||
}
|
||||
|
||||
_isDate(date: Date) {
|
||||
return date instanceof Date && isFinite(+date);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
export enum TimingFrequency {
|
||||
FREQUENCY_PUNCTUAL = 1,
|
||||
FREQUENCY_RECURRENT = 2,
|
||||
}
|
||||
|
||||
export enum TimingDays {
|
||||
'mon',
|
||||
'tue',
|
||||
'wed',
|
||||
'thu',
|
||||
'fri',
|
||||
'sat',
|
||||
'sun',
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
export interface Georouter {
|
||||
type: string;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
export class MatcherException implements Error {
|
||||
name: string;
|
||||
message: string;
|
||||
|
||||
constructor(private _code: number, private _message: string) {
|
||||
this.name = 'MatcherException';
|
||||
this.message = _message;
|
||||
}
|
||||
|
||||
get code(): number {
|
||||
return this._code;
|
||||
}
|
||||
}
|
|
@ -1,9 +1,85 @@
|
|||
import { ConfigService } from '@nestjs/config';
|
||||
import { MatchRequest } from '../domain/dtos/match.request';
|
||||
import { Geography } from '../domain/entities/geography';
|
||||
import { Person } from '../domain/entities/person';
|
||||
import { Requirement } from '../domain/entities/requirement';
|
||||
import { Role } from '../domain/entities/role.enum';
|
||||
import { Settings } from '../domain/entities/settings';
|
||||
import { Time } from '../domain/entities/time';
|
||||
import { MatcherException } from '../exceptions/matcher.exception';
|
||||
|
||||
export class MatchQuery {
|
||||
matchRequest: MatchRequest;
|
||||
private readonly _matchRequest: MatchRequest;
|
||||
private readonly _configService: ConfigService;
|
||||
person: Person;
|
||||
exclusions: Array<number>;
|
||||
time: Time;
|
||||
geography: Geography;
|
||||
roles: Array<Role>;
|
||||
requirement: Requirement;
|
||||
settings: Settings;
|
||||
|
||||
constructor(matchRequest?: MatchRequest) {
|
||||
this.matchRequest = matchRequest;
|
||||
constructor(matchRequest: MatchRequest, configService: ConfigService) {
|
||||
this._matchRequest = matchRequest;
|
||||
this._configService = configService;
|
||||
this._validate();
|
||||
this._initialize();
|
||||
this._setPerson();
|
||||
this._setExclusions();
|
||||
this._setRoles();
|
||||
this._setTime();
|
||||
// console.log(this);
|
||||
}
|
||||
|
||||
_validate() {
|
||||
if (!this._matchRequest.departure) {
|
||||
if (!this._matchRequest.fromDate)
|
||||
throw new MatcherException(3, 'departure or fromDate is Required');
|
||||
if (!this._matchRequest.schedule)
|
||||
throw new MatcherException(3, 'schedule is Required');
|
||||
}
|
||||
}
|
||||
|
||||
_initialize() {
|
||||
if (
|
||||
this._matchRequest.driver === undefined &&
|
||||
this._matchRequest.passenger === undefined
|
||||
)
|
||||
this._matchRequest.passenger = true;
|
||||
this.geography = new Geography();
|
||||
this.requirement = new Requirement();
|
||||
this.settings = new Settings();
|
||||
}
|
||||
|
||||
_setPerson() {
|
||||
this.person = new Person(
|
||||
this._matchRequest,
|
||||
this._configService.get<number>('DEFAULT_IDENTIFIER'),
|
||||
this._configService.get<number>('MARGIN_DURATION'),
|
||||
);
|
||||
this.person.init();
|
||||
}
|
||||
|
||||
_setExclusions() {
|
||||
this.exclusions = [];
|
||||
if (this._matchRequest.identifier)
|
||||
this.exclusions.push(this._matchRequest.identifier);
|
||||
if (this._matchRequest.exclusions)
|
||||
this.exclusions.push(...this._matchRequest.exclusions);
|
||||
}
|
||||
|
||||
_setRoles() {
|
||||
this.roles = [];
|
||||
if (this._matchRequest.driver) this.roles.push(Role.DRIVER);
|
||||
if (this._matchRequest.passenger) this.roles.push(Role.PASSENGER);
|
||||
}
|
||||
|
||||
_setTime() {
|
||||
this.time = new Time(
|
||||
this._matchRequest,
|
||||
this._configService.get<number>('MARGIN_DURATION'),
|
||||
this._configService.get<number>('VALIDITY_DURATION'),
|
||||
);
|
||||
this.time.init();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue