add default params, time transformer
This commit is contained in:
parent
336ffe2cf5
commit
cde1760099
|
@ -1,23 +1,8 @@
|
|||
import { ExtendedRepositoryPort } from '@mobicoop/ddd-library';
|
||||
import { AdEntity } from '../../domain/ad.entity';
|
||||
import { AlgorithmType, Candidate } from '../types/algorithm.types';
|
||||
import { Frequency } from '../../domain/ad.types';
|
||||
import { Candidate } from '../types/algorithm.types';
|
||||
import { MatchQuery } from '../queries/match/match.query';
|
||||
|
||||
export type AdRepositoryPort = ExtendedRepositoryPort<AdEntity> & {
|
||||
getCandidates(query: CandidateQuery): Promise<Candidate[]>;
|
||||
};
|
||||
|
||||
export type CandidateQuery = {
|
||||
driver: boolean;
|
||||
passenger: boolean;
|
||||
strict: boolean;
|
||||
frequency: Frequency;
|
||||
fromDate: string;
|
||||
toDate: string;
|
||||
schedule: {
|
||||
day?: number;
|
||||
time: string;
|
||||
margin?: number;
|
||||
}[];
|
||||
algorithmType: AlgorithmType;
|
||||
getCandidates(query: MatchQuery): Promise<Candidate[]>;
|
||||
};
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import { AlgorithmType } from '../types/algorithm.types';
|
||||
|
||||
export type DefaultParams = {
|
||||
DRIVER: boolean;
|
||||
PASSENGER: boolean;
|
||||
|
@ -5,5 +7,13 @@ export type DefaultParams = {
|
|||
SEATS_REQUESTED: number;
|
||||
DEPARTURE_TIME_MARGIN: number;
|
||||
STRICT: boolean;
|
||||
DEFAULT_TIMEZONE: string;
|
||||
TIMEZONE: string;
|
||||
ALGORITHM_TYPE: AlgorithmType;
|
||||
REMOTENESS: number;
|
||||
USE_PROPORTION: boolean;
|
||||
PROPORTION: number;
|
||||
USE_AZIMUTH: boolean;
|
||||
AZIMUTH_MARGIN: number;
|
||||
MAX_DETOUR_DISTANCE_RATIO: number;
|
||||
MAX_DETOUR_DURATION_RATIO: number;
|
||||
};
|
||||
|
|
|
@ -5,15 +5,44 @@ import { PassengerOrientedAlgorithm } from './passenger-oriented-algorithm';
|
|||
import { AlgorithmType } from '../../types/algorithm.types';
|
||||
import { Inject } from '@nestjs/common';
|
||||
import { AdRepositoryPort } from '@modules/ad/core/application/ports/ad.repository.port';
|
||||
import { AD_REPOSITORY } from '@modules/ad/ad.di-tokens';
|
||||
import { AD_REPOSITORY, PARAMS_PROVIDER } from '@modules/ad/ad.di-tokens';
|
||||
import { MatchEntity } from '@modules/ad/core/domain/match.entity';
|
||||
import { DefaultParamsProviderPort } from '../../ports/default-params-provider.port';
|
||||
import { DefaultParams } from '../../ports/default-params.type';
|
||||
|
||||
@QueryHandler(MatchQuery)
|
||||
export class MatchQueryHandler implements IQueryHandler {
|
||||
private readonly _defaultParams: DefaultParams;
|
||||
|
||||
constructor(
|
||||
@Inject(PARAMS_PROVIDER)
|
||||
private readonly defaultParamsProvider: DefaultParamsProviderPort,
|
||||
@Inject(AD_REPOSITORY) private readonly repository: AdRepositoryPort,
|
||||
) {}
|
||||
) {
|
||||
this._defaultParams = defaultParamsProvider.getParams();
|
||||
}
|
||||
|
||||
execute = async (query: MatchQuery): Promise<MatchEntity[]> => {
|
||||
query
|
||||
.setMissingMarginDurations(this._defaultParams.DEPARTURE_TIME_MARGIN)
|
||||
.setMissingStrict(this._defaultParams.STRICT)
|
||||
.setDefaultDriverAndPassengerParameters({
|
||||
driver: this._defaultParams.DRIVER,
|
||||
passenger: this._defaultParams.PASSENGER,
|
||||
seatsProposed: this._defaultParams.SEATS_PROPOSED,
|
||||
seatsRequested: this._defaultParams.SEATS_REQUESTED,
|
||||
})
|
||||
.setDefaultAlgorithmParameters({
|
||||
algorithmType: this._defaultParams.ALGORITHM_TYPE,
|
||||
remoteness: 0,
|
||||
useProportion: false,
|
||||
proportion: 0,
|
||||
useAzimuth: false,
|
||||
azimuthMargin: 0,
|
||||
maxDetourDistanceRatio: 0,
|
||||
maxDetourDurationRatio: 0,
|
||||
});
|
||||
|
||||
let algorithm: Algorithm;
|
||||
switch (query.algorithmType) {
|
||||
case AlgorithmType.PASSENGER_ORIENTED:
|
||||
|
|
|
@ -1,21 +1,32 @@
|
|||
import { QueryBase } from '@mobicoop/ddd-library';
|
||||
import { AlgorithmType } from '../../types/algorithm.types';
|
||||
import { Waypoint } from '../../types/waypoint.type';
|
||||
import { ScheduleItem } from '../../types/schedule-item.type';
|
||||
import { Frequency } from '@modules/ad/core/domain/ad.types';
|
||||
import { MatchRequestDto } from '@modules/ad/interface/grpc-controllers/dtos/match.request.dto';
|
||||
|
||||
export class MatchQuery extends QueryBase {
|
||||
readonly driver: boolean;
|
||||
readonly passenger: boolean;
|
||||
driver?: boolean;
|
||||
passenger?: boolean;
|
||||
readonly frequency: Frequency;
|
||||
readonly fromDate: string;
|
||||
readonly toDate: string;
|
||||
readonly schedule: ScheduleItem[];
|
||||
readonly strict: boolean;
|
||||
schedule: ScheduleItem[];
|
||||
seatsProposed?: number;
|
||||
seatsRequested?: number;
|
||||
strict?: boolean;
|
||||
readonly waypoints: Waypoint[];
|
||||
readonly algorithmType: AlgorithmType;
|
||||
algorithmType?: AlgorithmType;
|
||||
remoteness?: number;
|
||||
useProportion?: boolean;
|
||||
proportion?: number;
|
||||
useAzimuth?: boolean;
|
||||
azimuthMargin?: number;
|
||||
maxDetourDistanceRatio?: number;
|
||||
maxDetourDurationRatio?: number;
|
||||
readonly page?: number;
|
||||
readonly perPage?: number;
|
||||
|
||||
constructor(props: MatchQuery) {
|
||||
constructor(props: MatchRequestDto) {
|
||||
super();
|
||||
this.driver = props.driver;
|
||||
this.passenger = props.passenger;
|
||||
|
@ -23,8 +34,98 @@ export class MatchQuery extends QueryBase {
|
|||
this.fromDate = props.fromDate;
|
||||
this.toDate = props.toDate;
|
||||
this.schedule = props.schedule;
|
||||
this.seatsProposed = props.seatsProposed;
|
||||
this.seatsRequested = props.seatsRequested;
|
||||
this.strict = props.strict;
|
||||
this.waypoints = props.waypoints;
|
||||
this.algorithmType = props.algorithmType;
|
||||
this.remoteness = props.remoteness;
|
||||
this.useProportion = props.useProportion;
|
||||
this.proportion = props.proportion;
|
||||
this.useAzimuth = props.useAzimuth;
|
||||
this.azimuthMargin = props.azimuthMargin;
|
||||
this.maxDetourDistanceRatio = props.maxDetourDistanceRatio;
|
||||
this.maxDetourDurationRatio = props.maxDetourDurationRatio;
|
||||
this.page = props.page ?? 1;
|
||||
this.perPage = props.perPage ?? 10;
|
||||
}
|
||||
|
||||
setMissingMarginDurations = (defaultMarginDuration: number): MatchQuery => {
|
||||
this.schedule.forEach((day: ScheduleItem) => {
|
||||
if (day.margin === undefined) day.margin = defaultMarginDuration;
|
||||
});
|
||||
return this;
|
||||
};
|
||||
|
||||
setMissingStrict = (strict: boolean): MatchQuery => {
|
||||
if (this.strict === undefined) this.strict = strict;
|
||||
return this;
|
||||
};
|
||||
|
||||
setDefaultDriverAndPassengerParameters = (
|
||||
defaultDriverAndPassengerParameters: DefaultDriverAndPassengerParameters,
|
||||
): MatchQuery => {
|
||||
this.driver = !!this.driver;
|
||||
this.passenger = !!this.passenger;
|
||||
if (!this.driver && !this.passenger) {
|
||||
this.driver = defaultDriverAndPassengerParameters.driver;
|
||||
this.seatsProposed = defaultDriverAndPassengerParameters.seatsProposed;
|
||||
this.passenger = defaultDriverAndPassengerParameters.passenger;
|
||||
this.seatsRequested = defaultDriverAndPassengerParameters.seatsRequested;
|
||||
return this;
|
||||
}
|
||||
if (!this.seatsProposed || this.seatsProposed <= 0)
|
||||
this.seatsProposed = defaultDriverAndPassengerParameters.seatsProposed;
|
||||
if (!this.seatsRequested || this.seatsRequested <= 0)
|
||||
this.seatsRequested = defaultDriverAndPassengerParameters.seatsRequested;
|
||||
return this;
|
||||
};
|
||||
|
||||
setDefaultAlgorithmParameters = (
|
||||
defaultAlgorithmParameters: DefaultAlgorithmParameters,
|
||||
): MatchQuery => {
|
||||
if (!this.algorithmType)
|
||||
this.algorithmType = defaultAlgorithmParameters.algorithmType;
|
||||
if (!this.remoteness)
|
||||
this.remoteness = defaultAlgorithmParameters.remoteness;
|
||||
if (this.useProportion == undefined)
|
||||
this.useProportion = defaultAlgorithmParameters.useProportion;
|
||||
if (!this.proportion)
|
||||
this.proportion = defaultAlgorithmParameters.proportion;
|
||||
if (this.useAzimuth == undefined)
|
||||
this.useAzimuth = defaultAlgorithmParameters.useAzimuth;
|
||||
if (!this.azimuthMargin)
|
||||
this.azimuthMargin = defaultAlgorithmParameters.azimuthMargin;
|
||||
if (!this.maxDetourDistanceRatio)
|
||||
this.maxDetourDistanceRatio =
|
||||
defaultAlgorithmParameters.maxDetourDistanceRatio;
|
||||
if (!this.maxDetourDurationRatio)
|
||||
this.maxDetourDurationRatio =
|
||||
defaultAlgorithmParameters.maxDetourDurationRatio;
|
||||
return this;
|
||||
};
|
||||
}
|
||||
|
||||
type ScheduleItem = {
|
||||
day?: number;
|
||||
time: string;
|
||||
margin?: number;
|
||||
};
|
||||
|
||||
interface DefaultDriverAndPassengerParameters {
|
||||
driver: boolean;
|
||||
passenger: boolean;
|
||||
seatsProposed: number;
|
||||
seatsRequested: number;
|
||||
}
|
||||
|
||||
interface DefaultAlgorithmParameters {
|
||||
algorithmType: AlgorithmType;
|
||||
remoteness: number;
|
||||
useProportion: boolean;
|
||||
proportion: number;
|
||||
useAzimuth: boolean;
|
||||
azimuthMargin: number;
|
||||
maxDetourDistanceRatio: number;
|
||||
maxDetourDurationRatio: number;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
export type ScheduleItem = {
|
||||
day?: number;
|
||||
day: number;
|
||||
time: string;
|
||||
margin?: number;
|
||||
margin: number;
|
||||
};
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import { AlgorithmType } from '../application/types/algorithm.types';
|
||||
|
||||
// All properties that a Match has
|
||||
export interface MatchProps {
|
||||
adId: string;
|
||||
|
@ -7,3 +9,20 @@ export interface MatchProps {
|
|||
export interface CreateMatchProps {
|
||||
adId: string;
|
||||
}
|
||||
|
||||
export interface DefaultMatchQueryProps {
|
||||
driver: boolean;
|
||||
passenger: boolean;
|
||||
marginDuration: number;
|
||||
strict: boolean;
|
||||
seatsProposed: number;
|
||||
seatsRequested: number;
|
||||
algorithmType?: AlgorithmType;
|
||||
remoteness?: number;
|
||||
useProportion?: boolean;
|
||||
proportion?: number;
|
||||
useAzimuth?: boolean;
|
||||
azimuthMargin?: number;
|
||||
maxDetourDistanceRatio?: number;
|
||||
maxDetourDurationRatio?: number;
|
||||
}
|
||||
|
|
|
@ -10,13 +10,13 @@ import {
|
|||
* */
|
||||
|
||||
export interface ScheduleItemProps {
|
||||
day?: number;
|
||||
day: number;
|
||||
time: string;
|
||||
margin?: number;
|
||||
margin: number;
|
||||
}
|
||||
|
||||
export class ScheduleItem extends ValueObject<ScheduleItemProps> {
|
||||
get day(): number | undefined {
|
||||
get day(): number {
|
||||
return this.props.day;
|
||||
}
|
||||
|
||||
|
@ -24,13 +24,13 @@ export class ScheduleItem extends ValueObject<ScheduleItemProps> {
|
|||
return this.props.time;
|
||||
}
|
||||
|
||||
get margin(): number | undefined {
|
||||
get margin(): number {
|
||||
return this.props.margin;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
protected validate(props: ScheduleItemProps): void {
|
||||
if (props.day !== undefined && (props.day < 0 || props.day > 6))
|
||||
if (props.day < 0 || props.day > 6)
|
||||
throw new ArgumentOutOfRangeException('day must be between 0 and 6');
|
||||
if (props.time.split(':').length != 2)
|
||||
throw new ArgumentInvalidException('time is invalid');
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
import { Inject, Injectable, Logger } from '@nestjs/common';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import {
|
||||
AdRepositoryPort,
|
||||
CandidateQuery,
|
||||
} from '../core/application/ports/ad.repository.port';
|
||||
import { AdRepositoryPort } from '../core/application/ports/ad.repository.port';
|
||||
import { LoggerBase, MessagePublisherPort } from '@mobicoop/ddd-library';
|
||||
import { PrismaService } from './prisma.service';
|
||||
import { AD_MESSAGE_PUBLISHER } from '../ad.di-tokens';
|
||||
|
@ -13,6 +10,7 @@ import { ExtendedPrismaRepositoryBase } from '@mobicoop/ddd-library/dist/db/pris
|
|||
import { Frequency, Role } from '../core/domain/ad.types';
|
||||
import { Candidate } from '../core/application/types/algorithm.types';
|
||||
import { AdSelector } from './ad.selector';
|
||||
import { MatchQuery } from '../core/application/queries/match/match.query';
|
||||
|
||||
export type AdBaseModel = {
|
||||
uuid: string;
|
||||
|
@ -93,7 +91,7 @@ export class AdRepository
|
|||
);
|
||||
}
|
||||
|
||||
getCandidates = async (query: CandidateQuery): Promise<Candidate[]> => {
|
||||
getCandidates = async (query: MatchQuery): Promise<Candidate[]> => {
|
||||
// let candidates: Candidate[] = [];
|
||||
const sqlQueries: QueryRole[] = [];
|
||||
if (query.driver)
|
||||
|
@ -115,7 +113,7 @@ export class AdRepository
|
|||
} as AdsRole),
|
||||
),
|
||||
);
|
||||
console.log(results[0].ads);
|
||||
// console.log(results[0].ads);
|
||||
return [];
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { CandidateQuery } from '../core/application/ports/ad.repository.port';
|
||||
import { MatchQuery } from '../core/application/queries/match/match.query';
|
||||
import { AlgorithmType } from '../core/application/types/algorithm.types';
|
||||
import { Role } from '../core/domain/ad.types';
|
||||
|
||||
export class AdSelector {
|
||||
static select = (role: Role, query: CandidateQuery): string => {
|
||||
static select = (role: Role, query: MatchQuery): string => {
|
||||
switch (query.algorithmType) {
|
||||
case AlgorithmType.PASSENGER_ORIENTED:
|
||||
default:
|
||||
|
|
|
@ -2,32 +2,84 @@ import { Injectable } from '@nestjs/common';
|
|||
import { ConfigService } from '@nestjs/config';
|
||||
import { DefaultParamsProviderPort } from '../core/application/ports/default-params-provider.port';
|
||||
import { DefaultParams } from '../core/application/ports/default-params.type';
|
||||
import { AlgorithmType } from '../core/application/types/algorithm.types';
|
||||
|
||||
const DEFAULT_SEATS_PROPOSED = 3;
|
||||
const DEFAULT_SEATS_REQUESTED = 1;
|
||||
const DEFAULT_DEPARTURE_TIME_MARGIN = 900;
|
||||
const DEFAULT_TIMEZONE = 'Europe/Paris';
|
||||
const DRIVER = false;
|
||||
const PASSENGER = true;
|
||||
const SEATS_PROPOSED = 3;
|
||||
const SEATS_REQUESTED = 1;
|
||||
const DEPARTURE_TIME_MARGIN = 900;
|
||||
const TIMEZONE = 'Europe/Paris';
|
||||
const ALGORITHM_TYPE = 'PASSENGER_ORIENTED';
|
||||
const REMOTENESS = 15000;
|
||||
const USE_PROPORTION = true;
|
||||
const PROPORTION = 0.3;
|
||||
const USE_AZIMUTH = true;
|
||||
const AZIMUTH_MARGIN = 10;
|
||||
const MAX_DETOUR_DISTANCE_RATIO = 0.3;
|
||||
const MAX_DETOUR_DURATION_RATIO = 0.3;
|
||||
|
||||
@Injectable()
|
||||
export class DefaultParamsProvider implements DefaultParamsProviderPort {
|
||||
constructor(private readonly _configService: ConfigService) {}
|
||||
getParams = (): DefaultParams => ({
|
||||
DRIVER: this._configService.get('ROLE') == 'driver',
|
||||
DRIVER:
|
||||
this._configService.get('ROLE') !== undefined
|
||||
? this._configService.get('ROLE') == 'driver'
|
||||
: DRIVER,
|
||||
SEATS_PROPOSED:
|
||||
this._configService.get('SEATS_PROPOSED') !== undefined
|
||||
? parseInt(this._configService.get('SEATS_PROPOSED') as string)
|
||||
: DEFAULT_SEATS_PROPOSED,
|
||||
PASSENGER: this._configService.get('ROLE') == 'passenger',
|
||||
: SEATS_PROPOSED,
|
||||
PASSENGER:
|
||||
this._configService.get('ROLE') !== undefined
|
||||
? this._configService.get('ROLE') == 'passenger'
|
||||
: PASSENGER,
|
||||
SEATS_REQUESTED:
|
||||
this._configService.get('SEATS_REQUESTED') !== undefined
|
||||
? parseInt(this._configService.get('SEATS_REQUESTED') as string)
|
||||
: DEFAULT_SEATS_REQUESTED,
|
||||
: SEATS_REQUESTED,
|
||||
DEPARTURE_TIME_MARGIN:
|
||||
this._configService.get('DEPARTURE_TIME_MARGIN') !== undefined
|
||||
? parseInt(this._configService.get('DEPARTURE_TIME_MARGIN') as string)
|
||||
: DEFAULT_DEPARTURE_TIME_MARGIN,
|
||||
: DEPARTURE_TIME_MARGIN,
|
||||
STRICT: this._configService.get('STRICT_FREQUENCY') == 'true',
|
||||
DEFAULT_TIMEZONE:
|
||||
this._configService.get('DEFAULT_TIMEZONE') ?? DEFAULT_TIMEZONE,
|
||||
TIMEZONE: this._configService.get('TIMEZONE') ?? TIMEZONE,
|
||||
ALGORITHM_TYPE:
|
||||
AlgorithmType[
|
||||
this._configService.get('ALGORITHM_TYPE') as AlgorithmType
|
||||
] ?? AlgorithmType[ALGORITHM_TYPE],
|
||||
REMOTENESS:
|
||||
this._configService.get('REMOTENESS') !== undefined
|
||||
? parseInt(this._configService.get('REMOTENESS') as string)
|
||||
: REMOTENESS,
|
||||
USE_PROPORTION:
|
||||
this._configService.get('USE_PROPORTION') !== undefined
|
||||
? this._configService.get('USE_PROPORTION') == 'true'
|
||||
: USE_PROPORTION,
|
||||
PROPORTION:
|
||||
this._configService.get('PROPORTION') !== undefined
|
||||
? parseFloat(this._configService.get('PROPORTION') as string)
|
||||
: PROPORTION,
|
||||
USE_AZIMUTH:
|
||||
this._configService.get('USE_AZIMUTH') !== undefined
|
||||
? this._configService.get('USE_AZIMUTH') == 'true'
|
||||
: USE_AZIMUTH,
|
||||
AZIMUTH_MARGIN:
|
||||
this._configService.get('AZIMUTH_MARGIN') !== undefined
|
||||
? parseInt(this._configService.get('AZIMUTH_MARGIN') as string)
|
||||
: AZIMUTH_MARGIN,
|
||||
MAX_DETOUR_DISTANCE_RATIO:
|
||||
this._configService.get('MAX_DETOUR_DISTANCE_RATIO') !== undefined
|
||||
? parseFloat(
|
||||
this._configService.get('MAX_DETOUR_DISTANCE_RATIO') as string,
|
||||
)
|
||||
: MAX_DETOUR_DISTANCE_RATIO,
|
||||
MAX_DETOUR_DURATION_RATIO:
|
||||
this._configService.get('MAX_DETOUR_DURATION_RATIO') !== undefined
|
||||
? parseFloat(
|
||||
this._configService.get('MAX_DETOUR_DURATION_RATIO') as string,
|
||||
)
|
||||
: MAX_DETOUR_DURATION_RATIO,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ export class InputDateTimeTransformer implements DateTimeTransformerPort {
|
|||
private readonly timezoneFinder: TimezoneFinderPort,
|
||||
@Inject(TIME_CONVERTER) private readonly timeConverter: TimeConverterPort,
|
||||
) {
|
||||
this._defaultTimezone = defaultParamsProvider.getParams().DEFAULT_TIMEZONE;
|
||||
this._defaultTimezone = defaultParamsProvider.getParams().TIMEZONE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,10 +2,13 @@ import {
|
|||
ArrayMinSize,
|
||||
IsArray,
|
||||
IsBoolean,
|
||||
IsDecimal,
|
||||
IsEnum,
|
||||
IsISO8601,
|
||||
IsInt,
|
||||
IsOptional,
|
||||
Max,
|
||||
Min,
|
||||
ValidateNested,
|
||||
} from 'class-validator';
|
||||
import { Type } from 'class-transformer';
|
||||
|
@ -18,13 +21,13 @@ import { Frequency } from '@modules/ad/core/domain/ad.types';
|
|||
import { AlgorithmType } from '@modules/ad/core/application/types/algorithm.types';
|
||||
|
||||
export class MatchRequestDto {
|
||||
// @IsOptional()
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
driver: boolean;
|
||||
driver?: boolean;
|
||||
|
||||
// @IsOptional()
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
passenger: boolean;
|
||||
passenger?: boolean;
|
||||
|
||||
@IsEnum(Frequency)
|
||||
@HasDay('schedule', {
|
||||
|
@ -53,17 +56,17 @@ export class MatchRequestDto {
|
|||
@ValidateNested({ each: true })
|
||||
schedule: ScheduleItemDto[];
|
||||
|
||||
// @IsOptional()
|
||||
// @IsInt()
|
||||
// seatsProposed?: number;
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
seatsProposed?: number;
|
||||
|
||||
// @IsOptional()
|
||||
// @IsInt()
|
||||
// seatsRequested?: number;
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
seatsRequested?: number;
|
||||
|
||||
// @IsOptional()
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
strict: boolean;
|
||||
strict?: boolean;
|
||||
|
||||
@Type(() => WaypointDto)
|
||||
@IsArray()
|
||||
|
@ -72,45 +75,45 @@ export class MatchRequestDto {
|
|||
@ValidateNested({ each: true })
|
||||
waypoints: WaypointDto[];
|
||||
|
||||
// @IsOptional()
|
||||
@IsOptional()
|
||||
@IsEnum(AlgorithmType)
|
||||
algorithmType: AlgorithmType;
|
||||
algorithmType?: AlgorithmType;
|
||||
|
||||
// @IsOptional()
|
||||
// @IsInt()
|
||||
// remoteness?: number;
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
remoteness?: number;
|
||||
|
||||
// @IsOptional()
|
||||
// @IsBoolean()
|
||||
// useProportion?: boolean;
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
useProportion?: boolean;
|
||||
|
||||
// @IsOptional()
|
||||
// @IsDecimal()
|
||||
// @Min(0)
|
||||
// @Max(1)
|
||||
// proportion?: number;
|
||||
@IsOptional()
|
||||
@IsDecimal()
|
||||
@Min(0)
|
||||
@Max(1)
|
||||
proportion?: number;
|
||||
|
||||
// @IsOptional()
|
||||
// @IsBoolean()
|
||||
// useAzimuth?: boolean;
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
useAzimuth?: boolean;
|
||||
|
||||
// @IsOptional()
|
||||
// @IsInt()
|
||||
// @Min(0)
|
||||
// @Max(359)
|
||||
// azimuthMargin?: number;
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@Min(0)
|
||||
@Max(359)
|
||||
azimuthMargin?: number;
|
||||
|
||||
// @IsOptional()
|
||||
// @IsDecimal()
|
||||
// @Min(0)
|
||||
// @Max(1)
|
||||
// maxDetourDistanceRatio?: number;
|
||||
@IsOptional()
|
||||
@IsDecimal()
|
||||
@Min(0)
|
||||
@Max(1)
|
||||
maxDetourDistanceRatio?: number;
|
||||
|
||||
// @IsOptional()
|
||||
// @IsDecimal()
|
||||
// @Min(0)
|
||||
// @Max(1)
|
||||
// maxDetourDurationRatio?: number;
|
||||
@IsOptional()
|
||||
@IsDecimal()
|
||||
@Min(0)
|
||||
@Max(1)
|
||||
maxDetourDurationRatio?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import { AD_REPOSITORY } from '@modules/ad/ad.di-tokens';
|
||||
import { AD_REPOSITORY, PARAMS_PROVIDER } from '@modules/ad/ad.di-tokens';
|
||||
import { DefaultParamsProviderPort } from '@modules/ad/core/application/ports/default-params-provider.port';
|
||||
import { MatchQuery } from '@modules/ad/core/application/queries/match/match.query';
|
||||
import { MatchQueryHandler } from '@modules/ad/core/application/queries/match/match.query-handler';
|
||||
import { AlgorithmType } from '@modules/ad/core/application/types/algorithm.types';
|
||||
import { Waypoint } from '@modules/ad/core/application/types/waypoint.type';
|
||||
import { Frequency } from '@modules/ad/core/domain/ad.types';
|
||||
import { Frequency, Role } from '@modules/ad/core/domain/ad.types';
|
||||
import { MatchEntity } from '@modules/ad/core/domain/match.entity';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
|
||||
|
@ -27,7 +28,36 @@ const destinationWaypoint: Waypoint = {
|
|||
};
|
||||
|
||||
const mockAdRepository = {
|
||||
getCandidates: jest.fn(),
|
||||
getCandidates: jest.fn().mockImplementation(() => [
|
||||
{
|
||||
ad: {
|
||||
id: 'cc260669-1c6d-441f-80a5-19cd59afb777',
|
||||
},
|
||||
role: Role.DRIVER,
|
||||
},
|
||||
]),
|
||||
};
|
||||
|
||||
const mockDefaultParamsProvider: DefaultParamsProviderPort = {
|
||||
getParams: () => {
|
||||
return {
|
||||
DEPARTURE_TIME_MARGIN: 900,
|
||||
DRIVER: false,
|
||||
SEATS_PROPOSED: 3,
|
||||
PASSENGER: true,
|
||||
SEATS_REQUESTED: 1,
|
||||
STRICT: false,
|
||||
TIMEZONE: 'Europe/Paris',
|
||||
ALGORITHM_TYPE: AlgorithmType.PASSENGER_ORIENTED,
|
||||
REMOTENESS: 15000,
|
||||
USE_PROPORTION: true,
|
||||
PROPORTION: 0.3,
|
||||
USE_AZIMUTH: true,
|
||||
AZIMUTH_MARGIN: 10,
|
||||
MAX_DETOUR_DISTANCE_RATIO: 0.3,
|
||||
MAX_DETOUR_DURATION_RATIO: 0.3,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
describe('Match Query Handler', () => {
|
||||
|
@ -41,6 +71,10 @@ describe('Match Query Handler', () => {
|
|||
provide: AD_REPOSITORY,
|
||||
useValue: mockAdRepository,
|
||||
},
|
||||
{
|
||||
provide: PARAMS_PROVIDER,
|
||||
useValue: mockDefaultParamsProvider,
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import { MatchQuery } from '@modules/ad/core/application/queries/match/match.que
|
|||
import { PassengerOrientedAlgorithm } from '@modules/ad/core/application/queries/match/passenger-oriented-algorithm';
|
||||
import { AlgorithmType } from '@modules/ad/core/application/types/algorithm.types';
|
||||
import { Waypoint } from '@modules/ad/core/application/types/waypoint.type';
|
||||
import { Frequency } from '@modules/ad/core/domain/ad.types';
|
||||
import { Frequency, Role } from '@modules/ad/core/domain/ad.types';
|
||||
import { MatchEntity } from '@modules/ad/core/domain/match.entity';
|
||||
|
||||
const originWaypoint: Waypoint = {
|
||||
|
@ -52,7 +52,14 @@ const mockMatcherRepository: AdRepositoryPort = {
|
|||
count: jest.fn(),
|
||||
healthCheck: jest.fn(),
|
||||
queryRawUnsafe: jest.fn(),
|
||||
getCandidates: jest.fn(),
|
||||
getCandidates: jest.fn().mockImplementation(() => [
|
||||
{
|
||||
ad: {
|
||||
id: 'cc260669-1c6d-441f-80a5-19cd59afb777',
|
||||
},
|
||||
role: Role.DRIVER,
|
||||
},
|
||||
]),
|
||||
};
|
||||
|
||||
describe('Passenger oriented algorithm', () => {
|
||||
|
|
|
@ -16,8 +16,24 @@ const mockConfigService = {
|
|||
return 1;
|
||||
case 'STRICT_FREQUENCY':
|
||||
return 'false';
|
||||
case 'DEFAULT_TIMEZONE':
|
||||
case 'TIMEZONE':
|
||||
return 'Europe/Paris';
|
||||
case 'ALGORITHM_TYPE':
|
||||
return 'PASSENGER_ORIENTED';
|
||||
case 'REMOTENESS':
|
||||
return 15000;
|
||||
case 'USE_PROPORTION':
|
||||
return 'true';
|
||||
case 'PROPORTION':
|
||||
return 0.3;
|
||||
case 'USE_AZIMUTH':
|
||||
return 'true';
|
||||
case 'AZIMUTH_MARGIN':
|
||||
return 10;
|
||||
case 'MAX_DETOUR_DISTANCE_RATIO':
|
||||
return 0.3;
|
||||
case 'MAX_DETOUR_DURATION_RATIO':
|
||||
return 0.3;
|
||||
default:
|
||||
return 'some_default_value';
|
||||
}
|
||||
|
@ -53,6 +69,14 @@ describe('DefaultParamsProvider', () => {
|
|||
expect(params.DEPARTURE_TIME_MARGIN).toBe(900);
|
||||
expect(params.PASSENGER).toBeTruthy();
|
||||
expect(params.DRIVER).toBeFalsy();
|
||||
expect(params.DEFAULT_TIMEZONE).toBe('Europe/Paris');
|
||||
expect(params.TIMEZONE).toBe('Europe/Paris');
|
||||
expect(params.ALGORITHM_TYPE).toBe('PASSENGER_ORIENTED');
|
||||
expect(params.REMOTENESS).toBe(15000);
|
||||
expect(params.USE_PROPORTION).toBeTruthy();
|
||||
expect(params.PROPORTION).toBe(0.3);
|
||||
expect(params.USE_AZIMUTH).toBeTruthy();
|
||||
expect(params.AZIMUTH_MARGIN).toBe(10);
|
||||
expect(params.MAX_DETOUR_DISTANCE_RATIO).toBe(0.3);
|
||||
expect(params.MAX_DETOUR_DURATION_RATIO).toBe(0.3);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -7,6 +7,7 @@ import { Frequency } from '@modules/ad/core/application/ports/datetime-transform
|
|||
import { DefaultParamsProviderPort } from '@modules/ad/core/application/ports/default-params-provider.port';
|
||||
import { TimeConverterPort } from '@modules/ad/core/application/ports/time-converter.port';
|
||||
import { TimezoneFinderPort } from '@modules/ad/core/application/ports/timezone-finder.port';
|
||||
import { AlgorithmType } from '@modules/ad/core/application/types/algorithm.types';
|
||||
import { InputDateTimeTransformer } from '@modules/ad/infrastructure/input-datetime-transformer';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
|
||||
|
@ -19,7 +20,15 @@ const mockDefaultParamsProvider: DefaultParamsProviderPort = {
|
|||
PASSENGER: true,
|
||||
SEATS_REQUESTED: 1,
|
||||
STRICT: false,
|
||||
DEFAULT_TIMEZONE: 'Europe/Paris',
|
||||
TIMEZONE: 'Europe/Paris',
|
||||
ALGORITHM_TYPE: AlgorithmType.PASSENGER_ORIENTED,
|
||||
REMOTENESS: 15000,
|
||||
USE_PROPORTION: true,
|
||||
PROPORTION: 0.3,
|
||||
USE_AZIMUTH: true,
|
||||
AZIMUTH_MARGIN: 10,
|
||||
MAX_DETOUR_DISTANCE_RATIO: 0.3,
|
||||
MAX_DETOUR_DURATION_RATIO: 0.3,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue