basic RouteCompleter
This commit is contained in:
parent
a277a9547f
commit
067854b697
|
@ -20,6 +20,7 @@ export abstract class Algorithm {
|
||||||
for (const processor of this.processors) {
|
for (const processor of this.processors) {
|
||||||
this.candidates = await processor.execute(this.candidates);
|
this.candidates = await processor.execute(this.candidates);
|
||||||
}
|
}
|
||||||
|
// console.log(JSON.stringify(this.candidates, null, 2));
|
||||||
return this.candidates.map((candidate: CandidateEntity) =>
|
return this.candidates.map((candidate: CandidateEntity) =>
|
||||||
MatchEntity.create({ adId: candidate.id }),
|
MatchEntity.create({ adId: candidate.id }),
|
||||||
);
|
);
|
||||||
|
@ -43,9 +44,6 @@ export abstract class Selector {
|
||||||
* A processor processes candidates information
|
* A processor processes candidates information
|
||||||
*/
|
*/
|
||||||
export abstract class Processor {
|
export abstract class Processor {
|
||||||
protected readonly query: MatchQuery;
|
constructor(protected readonly query: MatchQuery) {}
|
||||||
constructor(query: MatchQuery) {
|
|
||||||
this.query = query;
|
|
||||||
}
|
|
||||||
abstract execute(candidates: CandidateEntity[]): Promise<CandidateEntity[]>;
|
abstract execute(candidates: CandidateEntity[]): Promise<CandidateEntity[]>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,6 @@ export class PassengerOrientedCarpoolPathCompleter extends Completer {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
candidate.setCarpoolPath(carpoolPathCreator.carpoolPath());
|
candidate.setCarpoolPath(carpoolPathCreator.carpoolPath());
|
||||||
// console.log(JSON.stringify(candidate, null, 2));
|
|
||||||
});
|
});
|
||||||
return candidates;
|
return candidates;
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
import { CandidateEntity } from '@modules/ad/core/domain/candidate.entity';
|
||||||
|
import { Completer } from './completer.abstract';
|
||||||
|
import { MatchQuery } from '../match.query';
|
||||||
|
import { WayStep } from '@modules/ad/core/domain/value-objects/waystep.value-object';
|
||||||
|
|
||||||
|
export class RouteCompleter extends Completer {
|
||||||
|
protected readonly type: RouteCompleterType;
|
||||||
|
constructor(query: MatchQuery, type: RouteCompleterType) {
|
||||||
|
super(query);
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
complete = async (
|
||||||
|
candidates: CandidateEntity[],
|
||||||
|
): Promise<CandidateEntity[]> => {
|
||||||
|
await Promise.all(
|
||||||
|
candidates.map(async (candidate: CandidateEntity) => {
|
||||||
|
const candidateRoute = await this.query.routeProvider.getBasic(
|
||||||
|
(candidate.getProps().carpoolSteps as WayStep[]).map(
|
||||||
|
(wayStep: WayStep) => wayStep.point,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
candidate.setMetrics(candidateRoute.distance, candidateRoute.duration);
|
||||||
|
return candidate;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
return candidates;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum RouteCompleterType {
|
||||||
|
BASIC = 'basic',
|
||||||
|
DETAILED = 'detailed',
|
||||||
|
}
|
|
@ -7,7 +7,6 @@ import { Inject } from '@nestjs/common';
|
||||||
import { AdRepositoryPort } from '@modules/ad/core/application/ports/ad.repository.port';
|
import { AdRepositoryPort } from '@modules/ad/core/application/ports/ad.repository.port';
|
||||||
import {
|
import {
|
||||||
AD_REPOSITORY,
|
AD_REPOSITORY,
|
||||||
AD_ROUTE_PROVIDER,
|
|
||||||
INPUT_DATETIME_TRANSFORMER,
|
INPUT_DATETIME_TRANSFORMER,
|
||||||
PARAMS_PROVIDER,
|
PARAMS_PROVIDER,
|
||||||
} from '@modules/ad/ad.di-tokens';
|
} from '@modules/ad/ad.di-tokens';
|
||||||
|
@ -15,7 +14,6 @@ import { MatchEntity } from '@modules/ad/core/domain/match.entity';
|
||||||
import { DefaultParamsProviderPort } from '../../ports/default-params-provider.port';
|
import { DefaultParamsProviderPort } from '../../ports/default-params-provider.port';
|
||||||
import { DefaultParams } from '../../ports/default-params.type';
|
import { DefaultParams } from '../../ports/default-params.type';
|
||||||
import { DateTimeTransformerPort } from '../../ports/datetime-transformer.port';
|
import { DateTimeTransformerPort } from '../../ports/datetime-transformer.port';
|
||||||
import { RouteProviderPort } from '../../ports/route-provider.port';
|
|
||||||
|
|
||||||
@QueryHandler(MatchQuery)
|
@QueryHandler(MatchQuery)
|
||||||
export class MatchQueryHandler implements IQueryHandler {
|
export class MatchQueryHandler implements IQueryHandler {
|
||||||
|
@ -27,8 +25,6 @@ export class MatchQueryHandler implements IQueryHandler {
|
||||||
@Inject(AD_REPOSITORY) private readonly repository: AdRepositoryPort,
|
@Inject(AD_REPOSITORY) private readonly repository: AdRepositoryPort,
|
||||||
@Inject(INPUT_DATETIME_TRANSFORMER)
|
@Inject(INPUT_DATETIME_TRANSFORMER)
|
||||||
private readonly datetimeTransformer: DateTimeTransformerPort,
|
private readonly datetimeTransformer: DateTimeTransformerPort,
|
||||||
@Inject(AD_ROUTE_PROVIDER)
|
|
||||||
private readonly routeProvider: RouteProviderPort,
|
|
||||||
) {
|
) {
|
||||||
this._defaultParams = defaultParamsProvider.getParams();
|
this._defaultParams = defaultParamsProvider.getParams();
|
||||||
}
|
}
|
||||||
|
@ -54,7 +50,7 @@ export class MatchQueryHandler implements IQueryHandler {
|
||||||
maxDetourDurationRatio: this._defaultParams.MAX_DETOUR_DURATION_RATIO,
|
maxDetourDurationRatio: this._defaultParams.MAX_DETOUR_DURATION_RATIO,
|
||||||
})
|
})
|
||||||
.setDatesAndSchedule(this.datetimeTransformer);
|
.setDatesAndSchedule(this.datetimeTransformer);
|
||||||
await query.setRoutes(this.routeProvider);
|
await query.setRoutes();
|
||||||
|
|
||||||
let algorithm: Algorithm;
|
let algorithm: Algorithm;
|
||||||
switch (query.algorithmType) {
|
switch (query.algorithmType) {
|
||||||
|
|
|
@ -39,8 +39,9 @@ export class MatchQuery extends QueryBase {
|
||||||
passengerRoute?: Route;
|
passengerRoute?: Route;
|
||||||
backAzimuth?: number;
|
backAzimuth?: number;
|
||||||
private readonly originWaypoint: Waypoint;
|
private readonly originWaypoint: Waypoint;
|
||||||
|
routeProvider: RouteProviderPort;
|
||||||
|
|
||||||
constructor(props: MatchRequestDto) {
|
constructor(props: MatchRequestDto, routeProvider: RouteProviderPort) {
|
||||||
super();
|
super();
|
||||||
this.driver = props.driver;
|
this.driver = props.driver;
|
||||||
this.passenger = props.passenger;
|
this.passenger = props.passenger;
|
||||||
|
@ -65,6 +66,7 @@ export class MatchQuery extends QueryBase {
|
||||||
this.originWaypoint = this.waypoints.filter(
|
this.originWaypoint = this.waypoints.filter(
|
||||||
(waypoint: Waypoint) => waypoint.position == 0,
|
(waypoint: Waypoint) => waypoint.position == 0,
|
||||||
)[0];
|
)[0];
|
||||||
|
this.routeProvider = routeProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
setMissingMarginDurations = (defaultMarginDuration: number): MatchQuery => {
|
setMissingMarginDurations = (defaultMarginDuration: number): MatchQuery => {
|
||||||
|
@ -178,7 +180,7 @@ export class MatchQuery extends QueryBase {
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
setRoutes = async (routeProvider: RouteProviderPort): Promise<MatchQuery> => {
|
setRoutes = async (): Promise<MatchQuery> => {
|
||||||
const roles: Role[] = [];
|
const roles: Role[] = [];
|
||||||
if (this.driver) roles.push(Role.DRIVER);
|
if (this.driver) roles.push(Role.DRIVER);
|
||||||
if (this.passenger) roles.push(Role.PASSENGER);
|
if (this.passenger) roles.push(Role.PASSENGER);
|
||||||
|
@ -197,7 +199,7 @@ export class MatchQuery extends QueryBase {
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
pathCreator.getBasePaths().map(async (path: Path) => ({
|
pathCreator.getBasePaths().map(async (path: Path) => ({
|
||||||
type: path.type,
|
type: path.type,
|
||||||
route: await routeProvider.getBasic(path.waypoints),
|
route: await this.routeProvider.getBasic(path.waypoints),
|
||||||
})),
|
})),
|
||||||
)
|
)
|
||||||
).forEach((typedRoute: TypedRoute) => {
|
).forEach((typedRoute: TypedRoute) => {
|
||||||
|
|
|
@ -4,6 +4,10 @@ import { PassengerOrientedCarpoolPathCompleter } from './completer/passenger-ori
|
||||||
import { PassengerOrientedGeoFilter } from './filter/passenger-oriented-geo.filter';
|
import { PassengerOrientedGeoFilter } from './filter/passenger-oriented-geo.filter';
|
||||||
import { AdRepositoryPort } from '../../ports/ad.repository.port';
|
import { AdRepositoryPort } from '../../ports/ad.repository.port';
|
||||||
import { PassengerOrientedSelector } from './selector/passenger-oriented.selector';
|
import { PassengerOrientedSelector } from './selector/passenger-oriented.selector';
|
||||||
|
import {
|
||||||
|
RouteCompleter,
|
||||||
|
RouteCompleterType,
|
||||||
|
} from './completer/route.completer';
|
||||||
|
|
||||||
export class PassengerOrientedAlgorithm extends Algorithm {
|
export class PassengerOrientedAlgorithm extends Algorithm {
|
||||||
constructor(
|
constructor(
|
||||||
|
@ -14,6 +18,7 @@ export class PassengerOrientedAlgorithm extends Algorithm {
|
||||||
this.selector = new PassengerOrientedSelector(query, repository);
|
this.selector = new PassengerOrientedSelector(query, repository);
|
||||||
this.processors = [
|
this.processors = [
|
||||||
new PassengerOrientedCarpoolPathCompleter(query),
|
new PassengerOrientedCarpoolPathCompleter(query),
|
||||||
|
new RouteCompleter(query, RouteCompleterType.BASIC),
|
||||||
new PassengerOrientedGeoFilter(query),
|
new PassengerOrientedGeoFilter(query),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,11 @@ export class CandidateEntity extends AggregateRoot<CandidateProps> {
|
||||||
this.props.carpoolSteps = waySteps;
|
this.props.carpoolSteps = waySteps;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
setMetrics = (distance: number, duration: number): void => {
|
||||||
|
this.props.distance = distance;
|
||||||
|
this.props.duration = duration;
|
||||||
|
};
|
||||||
|
|
||||||
validate(): void {
|
validate(): void {
|
||||||
// entity business rules validation to protect it's invariant before saving entity to a database
|
// entity business rules validation to protect it's invariant before saving entity to a database
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,8 @@ export interface CandidateProps {
|
||||||
driverDistance: number;
|
driverDistance: number;
|
||||||
driverDuration: number;
|
driverDuration: number;
|
||||||
carpoolSteps?: WayStepProps[]; // carpool path for the crew (driver + passenger)
|
carpoolSteps?: WayStepProps[]; // carpool path for the crew (driver + passenger)
|
||||||
|
distance?: number;
|
||||||
|
duration?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Properties that are needed for a Candidate creation
|
// Properties that are needed for a Candidate creation
|
||||||
|
@ -22,11 +24,6 @@ export interface CreateCandidateProps {
|
||||||
passengerWaypoints: PointProps[];
|
passengerWaypoints: PointProps[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Spacetime = {
|
|
||||||
duration: number;
|
|
||||||
distance?: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export enum Target {
|
export enum Target {
|
||||||
START = 'START',
|
START = 'START',
|
||||||
INTERMEDIATE = 'INTERMEDIATE',
|
INTERMEDIATE = 'INTERMEDIATE',
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Controller, UsePipes } from '@nestjs/common';
|
import { Controller, Inject, UsePipes } from '@nestjs/common';
|
||||||
import { GrpcMethod, RpcException } from '@nestjs/microservices';
|
import { GrpcMethod, RpcException } from '@nestjs/microservices';
|
||||||
import { ResponseBase, RpcValidationPipe } from '@mobicoop/ddd-library';
|
import { ResponseBase, RpcValidationPipe } from '@mobicoop/ddd-library';
|
||||||
import { RpcExceptionCode } from '@mobicoop/ddd-library';
|
import { RpcExceptionCode } from '@mobicoop/ddd-library';
|
||||||
|
@ -7,6 +7,8 @@ import { QueryBus } from '@nestjs/cqrs';
|
||||||
import { MatchRequestDto } from './dtos/match.request.dto';
|
import { MatchRequestDto } from './dtos/match.request.dto';
|
||||||
import { MatchQuery } from '@modules/ad/core/application/queries/match/match.query';
|
import { MatchQuery } from '@modules/ad/core/application/queries/match/match.query';
|
||||||
import { MatchEntity } from '@modules/ad/core/domain/match.entity';
|
import { MatchEntity } from '@modules/ad/core/domain/match.entity';
|
||||||
|
import { AD_ROUTE_PROVIDER } from '@modules/ad/ad.di-tokens';
|
||||||
|
import { RouteProviderPort } from '@modules/ad/core/application/ports/route-provider.port';
|
||||||
|
|
||||||
@UsePipes(
|
@UsePipes(
|
||||||
new RpcValidationPipe({
|
new RpcValidationPipe({
|
||||||
|
@ -16,13 +18,17 @@ import { MatchEntity } from '@modules/ad/core/domain/match.entity';
|
||||||
)
|
)
|
||||||
@Controller()
|
@Controller()
|
||||||
export class MatchGrpcController {
|
export class MatchGrpcController {
|
||||||
constructor(private readonly queryBus: QueryBus) {}
|
constructor(
|
||||||
|
private readonly queryBus: QueryBus,
|
||||||
|
@Inject(AD_ROUTE_PROVIDER)
|
||||||
|
private readonly routeProvider: RouteProviderPort,
|
||||||
|
) {}
|
||||||
|
|
||||||
@GrpcMethod('MatcherService', 'Match')
|
@GrpcMethod('MatcherService', 'Match')
|
||||||
async match(data: MatchRequestDto): Promise<MatchPaginatedResponseDto> {
|
async match(data: MatchRequestDto): Promise<MatchPaginatedResponseDto> {
|
||||||
try {
|
try {
|
||||||
const matches: MatchEntity[] = await this.queryBus.execute(
|
const matches: MatchEntity[] = await this.queryBus.execute(
|
||||||
new MatchQuery(data),
|
new MatchQuery(data, this.routeProvider),
|
||||||
);
|
);
|
||||||
return new MatchPaginatedResponseDto({
|
return new MatchPaginatedResponseDto({
|
||||||
data: matches.map((match: MatchEntity) => ({
|
data: matches.map((match: MatchEntity) => ({
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import {
|
import {
|
||||||
AD_REPOSITORY,
|
AD_REPOSITORY,
|
||||||
AD_ROUTE_PROVIDER,
|
|
||||||
INPUT_DATETIME_TRANSFORMER,
|
INPUT_DATETIME_TRANSFORMER,
|
||||||
PARAMS_PROVIDER,
|
PARAMS_PROVIDER,
|
||||||
} from '@modules/ad/ad.di-tokens';
|
} from '@modules/ad/ad.di-tokens';
|
||||||
|
@ -114,10 +113,6 @@ describe('Match Query Handler', () => {
|
||||||
provide: INPUT_DATETIME_TRANSFORMER,
|
provide: INPUT_DATETIME_TRANSFORMER,
|
||||||
useValue: mockInputDateTimeTransformer,
|
useValue: mockInputDateTimeTransformer,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
provide: AD_ROUTE_PROVIDER,
|
|
||||||
useValue: mockRouteProvider,
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
}).compile();
|
}).compile();
|
||||||
|
|
||||||
|
@ -129,7 +124,8 @@ describe('Match Query Handler', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return a Match entity', async () => {
|
it('should return a Match entity', async () => {
|
||||||
const matchQuery = new MatchQuery({
|
const matchQuery = new MatchQuery(
|
||||||
|
{
|
||||||
algorithmType: AlgorithmType.PASSENGER_ORIENTED,
|
algorithmType: AlgorithmType.PASSENGER_ORIENTED,
|
||||||
driver: false,
|
driver: false,
|
||||||
passenger: true,
|
passenger: true,
|
||||||
|
@ -145,7 +141,9 @@ describe('Match Query Handler', () => {
|
||||||
],
|
],
|
||||||
strict: false,
|
strict: false,
|
||||||
waypoints: [originWaypoint, destinationWaypoint],
|
waypoints: [originWaypoint, destinationWaypoint],
|
||||||
});
|
},
|
||||||
|
mockRouteProvider,
|
||||||
|
);
|
||||||
const matches: MatchEntity[] = await matchQueryHandler.execute(matchQuery);
|
const matches: MatchEntity[] = await matchQueryHandler.execute(matchQuery);
|
||||||
expect(matches.length).toBeGreaterThanOrEqual(0);
|
expect(matches.length).toBeGreaterThanOrEqual(0);
|
||||||
});
|
});
|
||||||
|
|
|
@ -108,7 +108,8 @@ const mockRouteProvider: RouteProviderPort = {
|
||||||
|
|
||||||
describe('Match Query', () => {
|
describe('Match Query', () => {
|
||||||
it('should set default values', async () => {
|
it('should set default values', async () => {
|
||||||
const matchQuery = new MatchQuery({
|
const matchQuery = new MatchQuery(
|
||||||
|
{
|
||||||
frequency: Frequency.PUNCTUAL,
|
frequency: Frequency.PUNCTUAL,
|
||||||
fromDate: '2023-08-28',
|
fromDate: '2023-08-28',
|
||||||
toDate: '2023-08-28',
|
toDate: '2023-08-28',
|
||||||
|
@ -118,7 +119,9 @@ describe('Match Query', () => {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
waypoints: [originWaypoint, destinationWaypoint],
|
waypoints: [originWaypoint, destinationWaypoint],
|
||||||
});
|
},
|
||||||
|
mockRouteProvider,
|
||||||
|
);
|
||||||
matchQuery
|
matchQuery
|
||||||
.setMissingMarginDurations(defaultParams.DEPARTURE_TIME_MARGIN)
|
.setMissingMarginDurations(defaultParams.DEPARTURE_TIME_MARGIN)
|
||||||
.setMissingStrict(defaultParams.STRICT)
|
.setMissingStrict(defaultParams.STRICT)
|
||||||
|
@ -159,7 +162,8 @@ describe('Match Query', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set good values for seats', async () => {
|
it('should set good values for seats', async () => {
|
||||||
const matchQuery = new MatchQuery({
|
const matchQuery = new MatchQuery(
|
||||||
|
{
|
||||||
frequency: Frequency.PUNCTUAL,
|
frequency: Frequency.PUNCTUAL,
|
||||||
fromDate: '2023-08-28',
|
fromDate: '2023-08-28',
|
||||||
toDate: '2023-08-28',
|
toDate: '2023-08-28',
|
||||||
|
@ -171,7 +175,9 @@ describe('Match Query', () => {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
waypoints: [originWaypoint, destinationWaypoint],
|
waypoints: [originWaypoint, destinationWaypoint],
|
||||||
});
|
},
|
||||||
|
mockRouteProvider,
|
||||||
|
);
|
||||||
matchQuery.setDefaultDriverAndPassengerParameters({
|
matchQuery.setDefaultDriverAndPassengerParameters({
|
||||||
driver: defaultParams.DRIVER,
|
driver: defaultParams.DRIVER,
|
||||||
passenger: defaultParams.PASSENGER,
|
passenger: defaultParams.PASSENGER,
|
||||||
|
@ -183,7 +189,8 @@ describe('Match Query', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set route for a driver only', async () => {
|
it('should set route for a driver only', async () => {
|
||||||
const matchQuery = new MatchQuery({
|
const matchQuery = new MatchQuery(
|
||||||
|
{
|
||||||
driver: true,
|
driver: true,
|
||||||
passenger: false,
|
passenger: false,
|
||||||
frequency: Frequency.PUNCTUAL,
|
frequency: Frequency.PUNCTUAL,
|
||||||
|
@ -195,14 +202,17 @@ describe('Match Query', () => {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
waypoints: [originWaypoint, destinationWaypoint],
|
waypoints: [originWaypoint, destinationWaypoint],
|
||||||
});
|
},
|
||||||
await matchQuery.setRoutes(mockRouteProvider);
|
mockRouteProvider,
|
||||||
|
);
|
||||||
|
await matchQuery.setRoutes();
|
||||||
expect(matchQuery.driverRoute?.distance).toBe(350101);
|
expect(matchQuery.driverRoute?.distance).toBe(350101);
|
||||||
expect(matchQuery.passengerRoute).toBeUndefined();
|
expect(matchQuery.passengerRoute).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set route for a passenger only', async () => {
|
it('should set route for a passenger only', async () => {
|
||||||
const matchQuery = new MatchQuery({
|
const matchQuery = new MatchQuery(
|
||||||
|
{
|
||||||
driver: false,
|
driver: false,
|
||||||
passenger: true,
|
passenger: true,
|
||||||
frequency: Frequency.PUNCTUAL,
|
frequency: Frequency.PUNCTUAL,
|
||||||
|
@ -214,14 +224,17 @@ describe('Match Query', () => {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
waypoints: [originWaypoint, destinationWaypoint],
|
waypoints: [originWaypoint, destinationWaypoint],
|
||||||
});
|
},
|
||||||
await matchQuery.setRoutes(mockRouteProvider);
|
mockRouteProvider,
|
||||||
|
);
|
||||||
|
await matchQuery.setRoutes();
|
||||||
expect(matchQuery.passengerRoute?.distance).toBe(340102);
|
expect(matchQuery.passengerRoute?.distance).toBe(340102);
|
||||||
expect(matchQuery.driverRoute).toBeUndefined();
|
expect(matchQuery.driverRoute).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set route for a driver and passenger', async () => {
|
it('should set route for a driver and passenger', async () => {
|
||||||
const matchQuery = new MatchQuery({
|
const matchQuery = new MatchQuery(
|
||||||
|
{
|
||||||
driver: true,
|
driver: true,
|
||||||
passenger: true,
|
passenger: true,
|
||||||
frequency: Frequency.PUNCTUAL,
|
frequency: Frequency.PUNCTUAL,
|
||||||
|
@ -233,14 +246,17 @@ describe('Match Query', () => {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
waypoints: [originWaypoint, destinationWaypoint],
|
waypoints: [originWaypoint, destinationWaypoint],
|
||||||
});
|
},
|
||||||
await matchQuery.setRoutes(mockRouteProvider);
|
mockRouteProvider,
|
||||||
|
);
|
||||||
|
await matchQuery.setRoutes();
|
||||||
expect(matchQuery.driverRoute?.distance).toBe(350101);
|
expect(matchQuery.driverRoute?.distance).toBe(350101);
|
||||||
expect(matchQuery.passengerRoute?.distance).toBe(350101);
|
expect(matchQuery.passengerRoute?.distance).toBe(350101);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set route for a driver and passenger with 3 waypoints', async () => {
|
it('should set route for a driver and passenger with 3 waypoints', async () => {
|
||||||
const matchQuery = new MatchQuery({
|
const matchQuery = new MatchQuery(
|
||||||
|
{
|
||||||
driver: true,
|
driver: true,
|
||||||
passenger: true,
|
passenger: true,
|
||||||
frequency: Frequency.PUNCTUAL,
|
frequency: Frequency.PUNCTUAL,
|
||||||
|
@ -256,14 +272,17 @@ describe('Match Query', () => {
|
||||||
intermediateWaypoint,
|
intermediateWaypoint,
|
||||||
{ ...destinationWaypoint, position: 2 },
|
{ ...destinationWaypoint, position: 2 },
|
||||||
],
|
],
|
||||||
});
|
},
|
||||||
await matchQuery.setRoutes(mockRouteProvider);
|
mockRouteProvider,
|
||||||
|
);
|
||||||
|
await matchQuery.setRoutes();
|
||||||
expect(matchQuery.driverRoute?.distance).toBe(350101);
|
expect(matchQuery.driverRoute?.distance).toBe(350101);
|
||||||
expect(matchQuery.passengerRoute?.distance).toBe(340102);
|
expect(matchQuery.passengerRoute?.distance).toBe(340102);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an exception if route is not found', async () => {
|
it('should throw an exception if route is not found', async () => {
|
||||||
const matchQuery = new MatchQuery({
|
const matchQuery = new MatchQuery(
|
||||||
|
{
|
||||||
driver: true,
|
driver: true,
|
||||||
passenger: false,
|
passenger: false,
|
||||||
frequency: Frequency.PUNCTUAL,
|
frequency: Frequency.PUNCTUAL,
|
||||||
|
@ -275,9 +294,9 @@ describe('Match Query', () => {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
waypoints: [originWaypoint, destinationWaypoint],
|
waypoints: [originWaypoint, destinationWaypoint],
|
||||||
});
|
},
|
||||||
await expect(
|
mockRouteProvider,
|
||||||
matchQuery.setRoutes(mockRouteProvider),
|
);
|
||||||
).rejects.toBeInstanceOf(Error);
|
await expect(matchQuery.setRoutes()).rejects.toBeInstanceOf(Error);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -25,7 +25,8 @@ const destinationWaypoint: Waypoint = {
|
||||||
country: 'France',
|
country: 'France',
|
||||||
};
|
};
|
||||||
|
|
||||||
const matchQuery = new MatchQuery({
|
const matchQuery = new MatchQuery(
|
||||||
|
{
|
||||||
algorithmType: AlgorithmType.PASSENGER_ORIENTED,
|
algorithmType: AlgorithmType.PASSENGER_ORIENTED,
|
||||||
driver: false,
|
driver: false,
|
||||||
passenger: true,
|
passenger: true,
|
||||||
|
@ -39,7 +40,14 @@ const matchQuery = new MatchQuery({
|
||||||
],
|
],
|
||||||
strict: false,
|
strict: false,
|
||||||
waypoints: [originWaypoint, destinationWaypoint],
|
waypoints: [originWaypoint, destinationWaypoint],
|
||||||
});
|
},
|
||||||
|
{
|
||||||
|
getBasic: jest.fn().mockImplementation(() => ({
|
||||||
|
duration: 6500,
|
||||||
|
distance: 89745,
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
const mockMatcherRepository: AdRepositoryPort = {
|
const mockMatcherRepository: AdRepositoryPort = {
|
||||||
insertExtra: jest.fn(),
|
insertExtra: jest.fn(),
|
||||||
|
|
|
@ -24,7 +24,8 @@ const destinationWaypoint: Waypoint = {
|
||||||
country: 'France',
|
country: 'France',
|
||||||
};
|
};
|
||||||
|
|
||||||
const matchQuery = new MatchQuery({
|
const matchQuery = new MatchQuery(
|
||||||
|
{
|
||||||
algorithmType: AlgorithmType.PASSENGER_ORIENTED,
|
algorithmType: AlgorithmType.PASSENGER_ORIENTED,
|
||||||
driver: true,
|
driver: true,
|
||||||
passenger: true,
|
passenger: true,
|
||||||
|
@ -38,7 +39,11 @@ const matchQuery = new MatchQuery({
|
||||||
],
|
],
|
||||||
strict: false,
|
strict: false,
|
||||||
waypoints: [originWaypoint, destinationWaypoint],
|
waypoints: [originWaypoint, destinationWaypoint],
|
||||||
});
|
},
|
||||||
|
{
|
||||||
|
getBasic: jest.fn(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
const candidates: CandidateEntity[] = [
|
const candidates: CandidateEntity[] = [
|
||||||
CandidateEntity.create({
|
CandidateEntity.create({
|
||||||
|
|
|
@ -24,7 +24,8 @@ const destinationWaypoint: Waypoint = {
|
||||||
country: 'France',
|
country: 'France',
|
||||||
};
|
};
|
||||||
|
|
||||||
const matchQuery = new MatchQuery({
|
const matchQuery = new MatchQuery(
|
||||||
|
{
|
||||||
algorithmType: AlgorithmType.PASSENGER_ORIENTED,
|
algorithmType: AlgorithmType.PASSENGER_ORIENTED,
|
||||||
driver: true,
|
driver: true,
|
||||||
passenger: true,
|
passenger: true,
|
||||||
|
@ -38,7 +39,11 @@ const matchQuery = new MatchQuery({
|
||||||
],
|
],
|
||||||
strict: false,
|
strict: false,
|
||||||
waypoints: [originWaypoint, destinationWaypoint],
|
waypoints: [originWaypoint, destinationWaypoint],
|
||||||
});
|
},
|
||||||
|
{
|
||||||
|
getBasic: jest.fn(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
const candidates: CandidateEntity[] = [
|
const candidates: CandidateEntity[] = [
|
||||||
CandidateEntity.create({
|
CandidateEntity.create({
|
||||||
|
|
|
@ -25,7 +25,8 @@ const destinationWaypoint: Waypoint = {
|
||||||
country: 'France',
|
country: 'France',
|
||||||
};
|
};
|
||||||
|
|
||||||
const matchQuery = new MatchQuery({
|
const matchQuery = new MatchQuery(
|
||||||
|
{
|
||||||
algorithmType: AlgorithmType.PASSENGER_ORIENTED,
|
algorithmType: AlgorithmType.PASSENGER_ORIENTED,
|
||||||
driver: true,
|
driver: true,
|
||||||
passenger: true,
|
passenger: true,
|
||||||
|
@ -45,7 +46,11 @@ const matchQuery = new MatchQuery({
|
||||||
],
|
],
|
||||||
strict: false,
|
strict: false,
|
||||||
waypoints: [originWaypoint, destinationWaypoint],
|
waypoints: [originWaypoint, destinationWaypoint],
|
||||||
});
|
},
|
||||||
|
{
|
||||||
|
getBasic: jest.fn(),
|
||||||
|
},
|
||||||
|
);
|
||||||
matchQuery.driverRoute = {
|
matchQuery.driverRoute = {
|
||||||
distance: 150120,
|
distance: 150120,
|
||||||
duration: 6540,
|
duration: 6540,
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
import { RpcExceptionCode } from '@mobicoop/ddd-library';
|
import { RpcExceptionCode } from '@mobicoop/ddd-library';
|
||||||
|
import { AD_ROUTE_PROVIDER } from '@modules/ad/ad.di-tokens';
|
||||||
|
import { RouteProviderPort } from '@modules/ad/core/application/ports/route-provider.port';
|
||||||
import { AlgorithmType } from '@modules/ad/core/application/types/algorithm.types';
|
import { AlgorithmType } from '@modules/ad/core/application/types/algorithm.types';
|
||||||
import { Frequency } from '@modules/ad/core/domain/ad.types';
|
import { Frequency } from '@modules/ad/core/domain/ad.types';
|
||||||
import { MatchEntity } from '@modules/ad/core/domain/match.entity';
|
import { MatchEntity } from '@modules/ad/core/domain/match.entity';
|
||||||
|
@ -62,6 +64,10 @@ const mockQueryBus = {
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const mockRouteProvider: RouteProviderPort = {
|
||||||
|
getBasic: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
describe('Match Grpc Controller', () => {
|
describe('Match Grpc Controller', () => {
|
||||||
let matchGrpcController: MatchGrpcController;
|
let matchGrpcController: MatchGrpcController;
|
||||||
|
|
||||||
|
@ -73,6 +79,10 @@ describe('Match Grpc Controller', () => {
|
||||||
provide: QueryBus,
|
provide: QueryBus,
|
||||||
useValue: mockQueryBus,
|
useValue: mockQueryBus,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
provide: AD_ROUTE_PROVIDER,
|
||||||
|
useValue: mockRouteProvider,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}).compile();
|
}).compile();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue