detailed route provider

This commit is contained in:
sbriat 2023-09-18 17:09:19 +02:00
parent 32d5ec25b9
commit 075a856d09
19 changed files with 103 additions and 21 deletions

View File

@ -4,6 +4,9 @@ export const AD_MESSAGE_PUBLISHER = Symbol('AD_MESSAGE_PUBLISHER');
export const AD_GET_BASIC_ROUTE_CONTROLLER = Symbol( export const AD_GET_BASIC_ROUTE_CONTROLLER = Symbol(
'AD_GET_BASIC_ROUTE_CONTROLLER', 'AD_GET_BASIC_ROUTE_CONTROLLER',
); );
export const AD_GET_DETAILED_ROUTE_CONTROLLER = Symbol(
'AD_GET_DETAILED_ROUTE_CONTROLLER',
);
export const AD_ROUTE_PROVIDER = Symbol('AD_ROUTE_PROVIDER'); export const AD_ROUTE_PROVIDER = Symbol('AD_ROUTE_PROVIDER');
export const PARAMS_PROVIDER = Symbol('PARAMS_PROVIDER'); export const PARAMS_PROVIDER = Symbol('PARAMS_PROVIDER');
export const TIMEZONE_FINDER = Symbol('TIMEZONE_FINDER'); export const TIMEZONE_FINDER = Symbol('TIMEZONE_FINDER');

View File

@ -10,6 +10,7 @@ import {
TIMEZONE_FINDER, TIMEZONE_FINDER,
TIME_CONVERTER, TIME_CONVERTER,
INPUT_DATETIME_TRANSFORMER, INPUT_DATETIME_TRANSFORMER,
AD_GET_DETAILED_ROUTE_CONTROLLER,
} from './ad.di-tokens'; } from './ad.di-tokens';
import { MessageBrokerPublisher } from '@mobicoop/message-broker-module'; import { MessageBrokerPublisher } from '@mobicoop/message-broker-module';
import { AdRepository } from './infrastructure/ad.repository'; import { AdRepository } from './infrastructure/ad.repository';
@ -27,6 +28,7 @@ import { DefaultParamsProvider } from './infrastructure/default-params-provider'
import { TimezoneFinder } from './infrastructure/timezone-finder'; import { TimezoneFinder } from './infrastructure/timezone-finder';
import { TimeConverter } from './infrastructure/time-converter'; import { TimeConverter } from './infrastructure/time-converter';
import { InputDateTimeTransformer } from './infrastructure/input-datetime-transformer'; import { InputDateTimeTransformer } from './infrastructure/input-datetime-transformer';
import { GetDetailedRouteController } from '@modules/geography/interface/controllers/get-detailed-route.controller';
const grpcControllers = [MatchGrpcController]; const grpcControllers = [MatchGrpcController];
@ -67,6 +69,10 @@ const adapters: Provider[] = [
provide: AD_GET_BASIC_ROUTE_CONTROLLER, provide: AD_GET_BASIC_ROUTE_CONTROLLER,
useClass: GetBasicRouteController, useClass: GetBasicRouteController,
}, },
{
provide: AD_GET_DETAILED_ROUTE_CONTROLLER,
useClass: GetDetailedRouteController,
},
{ {
provide: PARAMS_PROVIDER, provide: PARAMS_PROVIDER,
useClass: DefaultParamsProvider, useClass: DefaultParamsProvider,

View File

@ -3,7 +3,17 @@ import { Point } from '../types/point.type';
export interface RouteProviderPort { export interface RouteProviderPort {
/** /**
* Get a basic route with points and overall duration / distance * Get a basic route :
* - simple points (coordinates only)
* - overall duration
* - overall distance
*/ */
getBasic(waypoints: Point[]): Promise<Route>; getBasic(waypoints: Point[]): Promise<Route>;
/**
* Get a detailed route :
* - detailed points (coordinates and time / distance to reach the point)
* - overall duration
* - overall distance
*/
getDetailed(waypoints: Point[]): Promise<Route>;
} }

View File

@ -15,12 +15,31 @@ export class RouteCompleter extends Completer {
): Promise<CandidateEntity[]> => { ): Promise<CandidateEntity[]> => {
await Promise.all( await Promise.all(
candidates.map(async (candidate: CandidateEntity) => { candidates.map(async (candidate: CandidateEntity) => {
const candidateRoute = await this.query.routeProvider.getBasic( switch (this.type) {
case RouteCompleterType.BASIC:
const basicCandidateRoute = await this.query.routeProvider.getBasic(
(candidate.getProps().carpoolSteps as WayStep[]).map( (candidate.getProps().carpoolSteps as WayStep[]).map(
(wayStep: WayStep) => wayStep.point, (wayStep: WayStep) => wayStep.point,
), ),
); );
candidate.setMetrics(candidateRoute.distance, candidateRoute.duration); candidate.setMetrics(
basicCandidateRoute.distance,
basicCandidateRoute.duration,
);
break;
case RouteCompleterType.DETAILED:
const detailedCandidateRoute =
await this.query.routeProvider.getBasic(
(candidate.getProps().carpoolSteps as WayStep[]).map(
(wayStep: WayStep) => wayStep.point,
),
);
candidate.setMetrics(
detailedCandidateRoute.distance,
detailedCandidateRoute.duration,
);
break;
}
return candidate; return candidate;
}), }),
); );

View File

@ -1,6 +1,6 @@
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import { RouteProviderPort } from '../core/application/ports/route-provider.port'; import { RouteProviderPort } from '../core/application/ports/route-provider.port';
import { GetBasicRouteControllerPort } from '@modules/geography/core/application/ports/get-basic-route-controller.port'; import { GetRouteControllerPort } from '@modules/geography/core/application/ports/get-route-controller.port';
import { AD_GET_BASIC_ROUTE_CONTROLLER } from '../ad.di-tokens'; import { AD_GET_BASIC_ROUTE_CONTROLLER } from '../ad.di-tokens';
import { Point, Route } from '@modules/geography/core/domain/route.types'; import { Point, Route } from '@modules/geography/core/domain/route.types';
@ -8,11 +8,16 @@ import { Point, Route } from '@modules/geography/core/domain/route.types';
export class RouteProvider implements RouteProviderPort { export class RouteProvider implements RouteProviderPort {
constructor( constructor(
@Inject(AD_GET_BASIC_ROUTE_CONTROLLER) @Inject(AD_GET_BASIC_ROUTE_CONTROLLER)
private readonly getBasicRouteController: GetBasicRouteControllerPort, private readonly getBasicRouteController: GetRouteControllerPort,
) {} ) {}
getBasic = async (waypoints: Point[]): Promise<Route> => getBasic = async (waypoints: Point[]): Promise<Route> =>
await this.getBasicRouteController.get({ await this.getBasicRouteController.get({
waypoints, waypoints,
}); });
getDetailed = async (waypoints: Point[]): Promise<Route> =>
await this.getBasicRouteController.get({
waypoints,
});
} }

View File

@ -93,6 +93,7 @@ const mockRouteProvider: RouteProviderPort = {
}, },
], ],
})), })),
getDetailed: jest.fn(),
}; };
describe('create-ad.service', () => { describe('create-ad.service', () => {

View File

@ -92,6 +92,7 @@ const mockRouteProvider: RouteProviderPort = {
distanceAzimuth: 336544, distanceAzimuth: 336544,
points: [], points: [],
})), })),
getDetailed: jest.fn(),
}; };
describe('Match Query Handler', () => { describe('Match Query Handler', () => {

View File

@ -104,6 +104,7 @@ const mockRouteProvider: RouteProviderPort = {
.mockImplementationOnce(() => { .mockImplementationOnce(() => {
throw new Error(); throw new Error();
}), }),
getDetailed: jest.fn(),
}; };
describe('Match Query', () => { describe('Match Query', () => {

View File

@ -46,6 +46,7 @@ const matchQuery = new MatchQuery(
duration: 6500, duration: 6500,
distance: 89745, distance: 89745,
})), })),
getDetailed: jest.fn(),
}, },
); );

View File

@ -42,6 +42,7 @@ const matchQuery = new MatchQuery(
}, },
{ {
getBasic: jest.fn(), getBasic: jest.fn(),
getDetailed: jest.fn(),
}, },
); );

View File

@ -42,6 +42,7 @@ const matchQuery = new MatchQuery(
}, },
{ {
getBasic: jest.fn(), getBasic: jest.fn(),
getDetailed: jest.fn(),
}, },
); );

View File

@ -49,6 +49,7 @@ const matchQuery = new MatchQuery(
}, },
{ {
getBasic: jest.fn(), getBasic: jest.fn(),
getDetailed: jest.fn(),
}, },
); );
matchQuery.driverRoute = { matchQuery.driverRoute = {

View File

@ -75,6 +75,7 @@ const mockDirectionEncoder: DirectionEncoderPort = {
const mockRouteProvider: RouteProviderPort = { const mockRouteProvider: RouteProviderPort = {
getBasic: jest.fn(), getBasic: jest.fn(),
getDetailed: jest.fn(),
}; };
const mockPrismaService = { const mockPrismaService = {

View File

@ -1,7 +1,7 @@
import { AD_GET_BASIC_ROUTE_CONTROLLER } from '@modules/ad/ad.di-tokens'; import { AD_GET_BASIC_ROUTE_CONTROLLER } from '@modules/ad/ad.di-tokens';
import { Point } from '@modules/ad/core/application/types/point.type'; import { Point } from '@modules/ad/core/application/types/point.type';
import { RouteProvider } from '@modules/ad/infrastructure/route-provider'; import { RouteProvider } from '@modules/ad/infrastructure/route-provider';
import { GetBasicRouteControllerPort } from '@modules/geography/core/application/ports/get-basic-route-controller.port'; import { GetRouteControllerPort } from '@modules/geography/core/application/ports/get-route-controller.port';
import { Route } from '@modules/geography/core/domain/route.types'; import { Route } from '@modules/geography/core/domain/route.types';
import { Test, TestingModule } from '@nestjs/testing'; import { Test, TestingModule } from '@nestjs/testing';
@ -14,7 +14,7 @@ const destinationPoint: Point = {
lon: 2.3522, lon: 2.3522,
}; };
const mockGetBasicRouteController: GetBasicRouteControllerPort = { const mockGetBasicRouteController: GetRouteControllerPort = {
get: jest.fn().mockImplementationOnce(() => ({ get: jest.fn().mockImplementationOnce(() => ({
distance: 350101, distance: 350101,
duration: 14422, duration: 14422,
@ -59,7 +59,7 @@ describe('Route provider', () => {
expect(routeProvider).toBeDefined(); expect(routeProvider).toBeDefined();
}); });
it('should provide a route', async () => { it('should provide a basic route', async () => {
const route: Route = await routeProvider.getBasic([ const route: Route = await routeProvider.getBasic([
originPoint, originPoint,
destinationPoint, destinationPoint,

View File

@ -66,6 +66,7 @@ const mockQueryBus = {
const mockRouteProvider: RouteProviderPort = { const mockRouteProvider: RouteProviderPort = {
getBasic: jest.fn(), getBasic: jest.fn(),
getDetailed: jest.fn(),
}; };
describe('Match Grpc Controller', () => { describe('Match Grpc Controller', () => {

View File

@ -1,6 +1,6 @@
import { GetRouteRequestDto } from '@modules/geography/interface/controllers/dtos/get-route.request.dto'; import { GetRouteRequestDto } from '@modules/geography/interface/controllers/dtos/get-route.request.dto';
import { RouteResponseDto } from '@modules/geography/interface/dtos/route.response.dto'; import { RouteResponseDto } from '@modules/geography/interface/dtos/route.response.dto';
export interface GetBasicRouteControllerPort { export interface GetRouteControllerPort {
get(data: GetRouteRequestDto): Promise<RouteResponseDto>; get(data: GetRouteRequestDto): Promise<RouteResponseDto>;
} }

View File

@ -6,7 +6,14 @@ export class GetRouteQuery extends QueryBase {
readonly waypoints: Point[]; readonly waypoints: Point[];
readonly georouterSettings: GeorouterSettings; readonly georouterSettings: GeorouterSettings;
constructor(waypoints: Point[], georouterSettings: GeorouterSettings) { constructor(
waypoints: Point[],
georouterSettings: GeorouterSettings = {
detailedDistance: false,
detailedDuration: false,
points: true,
},
) {
super(); super();
this.waypoints = waypoints; this.waypoints = waypoints;
this.georouterSettings = georouterSettings; this.georouterSettings = georouterSettings;

View File

@ -5,10 +5,10 @@ import { RouteEntity } from '@modules/geography/core/domain/route.entity';
import { GetRouteQuery } from '@modules/geography/core/application/queries/get-route/get-route.query'; import { GetRouteQuery } from '@modules/geography/core/application/queries/get-route/get-route.query';
import { RouteMapper } from '@modules/geography/route.mapper'; import { RouteMapper } from '@modules/geography/route.mapper';
import { Controller } from '@nestjs/common'; import { Controller } from '@nestjs/common';
import { GetBasicRouteControllerPort } from '@modules/geography/core/application/ports/get-basic-route-controller.port'; import { GetRouteControllerPort } from '@modules/geography/core/application/ports/get-route-controller.port';
@Controller() @Controller()
export class GetBasicRouteController implements GetBasicRouteControllerPort { export class GetBasicRouteController implements GetRouteControllerPort {
constructor( constructor(
private readonly queryBus: QueryBus, private readonly queryBus: QueryBus,
private readonly mapper: RouteMapper, private readonly mapper: RouteMapper,
@ -16,11 +16,7 @@ export class GetBasicRouteController implements GetBasicRouteControllerPort {
async get(data: GetRouteRequestDto): Promise<RouteResponseDto> { async get(data: GetRouteRequestDto): Promise<RouteResponseDto> {
const route: RouteEntity = await this.queryBus.execute( const route: RouteEntity = await this.queryBus.execute(
new GetRouteQuery(data.waypoints, { new GetRouteQuery(data.waypoints),
detailedDistance: false,
detailedDuration: false,
points: true,
}),
); );
return this.mapper.toResponse(route); return this.mapper.toResponse(route);
} }

View File

@ -0,0 +1,27 @@
import { QueryBus } from '@nestjs/cqrs';
import { RouteResponseDto } from '../dtos/route.response.dto';
import { GetRouteRequestDto } from './dtos/get-route.request.dto';
import { RouteEntity } from '@modules/geography/core/domain/route.entity';
import { GetRouteQuery } from '@modules/geography/core/application/queries/get-route/get-route.query';
import { RouteMapper } from '@modules/geography/route.mapper';
import { Controller } from '@nestjs/common';
import { GetRouteControllerPort } from '@modules/geography/core/application/ports/get-route-controller.port';
@Controller()
export class GetDetailedRouteController implements GetRouteControllerPort {
constructor(
private readonly queryBus: QueryBus,
private readonly mapper: RouteMapper,
) {}
async get(data: GetRouteRequestDto): Promise<RouteResponseDto> {
const route: RouteEntity = await this.queryBus.execute(
new GetRouteQuery(data.waypoints, {
detailedDistance: true,
detailedDuration: true,
points: true,
}),
);
return this.mapper.toResponse(route);
}
}