diff --git a/src/modules/ad/ad.di-tokens.ts b/src/modules/ad/ad.di-tokens.ts index 592fcc5..4a69ae2 100644 --- a/src/modules/ad/ad.di-tokens.ts +++ b/src/modules/ad/ad.di-tokens.ts @@ -4,7 +4,7 @@ export const AD_MESSAGE_PUBLISHER = Symbol('AD_MESSAGE_PUBLISHER'); export const AD_GET_BASIC_ROUTE_CONTROLLER = Symbol( 'AD_GET_BASIC_ROUTE_CONTROLLER', ); -export const AD_CARPOOL_ROUTE_PROVIDER = Symbol('AD_CARPOOL_ROUTE_PROVIDER'); +export const AD_ROUTE_PROVIDER = Symbol('AD_ROUTE_PROVIDER'); export const PARAMS_PROVIDER = Symbol('PARAMS_PROVIDER'); export const TIMEZONE_FINDER = Symbol('TIMEZONE_FINDER'); export const TIME_CONVERTER = Symbol('TIME_CONVERTER'); diff --git a/src/modules/ad/ad.module.ts b/src/modules/ad/ad.module.ts index a1f9eb6..90610bd 100644 --- a/src/modules/ad/ad.module.ts +++ b/src/modules/ad/ad.module.ts @@ -4,7 +4,7 @@ import { AD_MESSAGE_PUBLISHER, AD_REPOSITORY, AD_DIRECTION_ENCODER, - AD_CARPOOL_ROUTE_PROVIDER, + AD_ROUTE_PROVIDER, AD_GET_BASIC_ROUTE_CONTROLLER, PARAMS_PROVIDER, TIMEZONE_FINDER, @@ -18,7 +18,7 @@ import { AdMapper } from './ad.mapper'; import { AdCreatedMessageHandler } from './interface/message-handlers/ad-created.message-handler'; import { PostgresDirectionEncoder } from '@modules/geography/infrastructure/postgres-direction-encoder'; import { GetBasicRouteController } from '@modules/geography/interface/controllers/get-basic-route.controller'; -import { CarpoolRouteProvider } from './infrastructure/carpool-route-provider'; +import { RouteProvider } from './infrastructure/route-provider'; import { GeographyModule } from '@modules/geography/geography.module'; import { CreateAdService } from './core/application/commands/create-ad/create-ad.service'; import { MatchGrpcController } from './interface/grpc-controllers/match.grpc-controller'; @@ -60,8 +60,8 @@ const adapters: Provider[] = [ useClass: PostgresDirectionEncoder, }, { - provide: AD_CARPOOL_ROUTE_PROVIDER, - useClass: CarpoolRouteProvider, + provide: AD_ROUTE_PROVIDER, + useClass: RouteProvider, }, { provide: AD_GET_BASIC_ROUTE_CONTROLLER, diff --git a/src/modules/ad/core/application/commands/create-ad/create-ad.service.ts b/src/modules/ad/core/application/commands/create-ad/create-ad.service.ts index fb84626..c197801 100644 --- a/src/modules/ad/core/application/commands/create-ad/create-ad.service.ts +++ b/src/modules/ad/core/application/commands/create-ad/create-ad.service.ts @@ -1,35 +1,29 @@ import { CommandHandler, ICommandHandler } from '@nestjs/cqrs'; import { CreateAdCommand } from './create-ad.command'; import { Inject } from '@nestjs/common'; -import { - AD_REPOSITORY, - AD_CARPOOL_ROUTE_PROVIDER, -} from '@modules/ad/ad.di-tokens'; +import { AD_REPOSITORY, AD_ROUTE_PROVIDER } from '@modules/ad/ad.di-tokens'; import { AdEntity } from '@modules/ad/core/domain/ad.entity'; import { AdRepositoryPort } from '../../ports/ad.repository.port'; import { AggregateID, ConflictException } from '@mobicoop/ddd-library'; import { AdAlreadyExistsException } from '@modules/ad/core/domain/ad.errors'; -import { CarpoolRouteProviderPort } from '../../ports/carpool-route-provider.port'; +import { RouteProviderPort } from '../../ports/route-provider.port'; import { Role } from '@modules/ad/core/domain/ad.types'; -import { CarpoolRoute } from '../../types/carpool-route.type'; +import { Route } from '../../types/carpool-route.type'; @CommandHandler(CreateAdCommand) export class CreateAdService implements ICommandHandler { constructor( @Inject(AD_REPOSITORY) private readonly repository: AdRepositoryPort, - @Inject(AD_CARPOOL_ROUTE_PROVIDER) - private readonly carpoolRouteProvider: CarpoolRouteProviderPort, + @Inject(AD_ROUTE_PROVIDER) + private readonly routeProvider: RouteProviderPort, ) {} async execute(command: CreateAdCommand): Promise { const roles: Role[] = []; if (command.driver) roles.push(Role.DRIVER); if (command.passenger) roles.push(Role.PASSENGER); - const carpoolRoute: CarpoolRoute = await this.carpoolRouteProvider.getBasic( - roles, - command.waypoints, - ); + const route: Route = await this.routeProvider.getBasic(command.waypoints); const ad = AdEntity.create({ id: command.id, driver: command.driver, @@ -42,13 +36,13 @@ export class CreateAdService implements ICommandHandler { seatsRequested: command.seatsRequested, strict: command.strict, waypoints: command.waypoints, - points: carpoolRoute.points, - driverDistance: carpoolRoute.driverDistance, - driverDuration: carpoolRoute.driverDuration, - passengerDistance: carpoolRoute.passengerDistance, - passengerDuration: carpoolRoute.passengerDuration, - fwdAzimuth: carpoolRoute.fwdAzimuth, - backAzimuth: carpoolRoute.backAzimuth, + points: route.points, + driverDistance: route.driverDistance, + driverDuration: route.driverDuration, + passengerDistance: route.passengerDistance, + passengerDuration: route.passengerDuration, + fwdAzimuth: route.fwdAzimuth, + backAzimuth: route.backAzimuth, }); try { diff --git a/src/modules/ad/core/application/ports/carpool-route-provider.port.ts b/src/modules/ad/core/application/ports/carpool-route-provider.port.ts deleted file mode 100644 index 24b7f5a..0000000 --- a/src/modules/ad/core/application/ports/carpool-route-provider.port.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Role } from '../../domain/ad.types'; -import { Waypoint } from '../types/waypoint.type'; -import { CarpoolRoute } from '../types/carpool-route.type'; - -export interface CarpoolRouteProviderPort { - /** - * Get a basic carpool route with points and overall duration / distance - */ - getBasic(roles: Role[], waypoints: Waypoint[]): Promise; -} diff --git a/src/modules/ad/core/application/ports/route-provider.port.ts b/src/modules/ad/core/application/ports/route-provider.port.ts new file mode 100644 index 0000000..7974886 --- /dev/null +++ b/src/modules/ad/core/application/ports/route-provider.port.ts @@ -0,0 +1,9 @@ +import { Route } from '@modules/geography/core/domain/route.types'; +import { Waypoint } from '../types/waypoint.type'; + +export interface RouteProviderPort { + /** + * Get a basic route with points and overall duration / distance + */ + getBasic(waypoints: Waypoint[]): Promise; +} diff --git a/src/modules/ad/core/application/queries/match/match.query-handler.ts b/src/modules/ad/core/application/queries/match/match.query-handler.ts index 7510a5f..14a8af5 100644 --- a/src/modules/ad/core/application/queries/match/match.query-handler.ts +++ b/src/modules/ad/core/application/queries/match/match.query-handler.ts @@ -7,7 +7,7 @@ import { Inject } from '@nestjs/common'; import { AdRepositoryPort } from '@modules/ad/core/application/ports/ad.repository.port'; import { AD_REPOSITORY, - AD_CARPOOL_ROUTE_PROVIDER, + AD_ROUTE_PROVIDER, INPUT_DATETIME_TRANSFORMER, PARAMS_PROVIDER, } from '@modules/ad/ad.di-tokens'; @@ -15,7 +15,7 @@ import { MatchEntity } from '@modules/ad/core/domain/match.entity'; import { DefaultParamsProviderPort } from '../../ports/default-params-provider.port'; import { DefaultParams } from '../../ports/default-params.type'; import { DateTimeTransformerPort } from '../../ports/datetime-transformer.port'; -import { CarpoolRouteProviderPort } from '../../ports/carpool-route-provider.port'; +import { RouteProviderPort } from '../../ports/route-provider.port'; @QueryHandler(MatchQuery) export class MatchQueryHandler implements IQueryHandler { @@ -27,8 +27,8 @@ export class MatchQueryHandler implements IQueryHandler { @Inject(AD_REPOSITORY) private readonly repository: AdRepositoryPort, @Inject(INPUT_DATETIME_TRANSFORMER) private readonly datetimeTransformer: DateTimeTransformerPort, - @Inject(AD_CARPOOL_ROUTE_PROVIDER) - private readonly carpoolRouteProvider: CarpoolRouteProviderPort, + @Inject(AD_ROUTE_PROVIDER) + private readonly routeProvider: RouteProviderPort, ) { this._defaultParams = defaultParamsProvider.getParams(); } @@ -54,7 +54,7 @@ export class MatchQueryHandler implements IQueryHandler { maxDetourDurationRatio: this._defaultParams.MAX_DETOUR_DURATION_RATIO, }) .setDatesAndSchedule(this.datetimeTransformer); - await query.setCarpoolRoute(this.carpoolRouteProvider); + await query.setRoutes(this.routeProvider); let algorithm: Algorithm; switch (query.algorithmType) { diff --git a/src/modules/ad/core/application/queries/match/match.query.ts b/src/modules/ad/core/application/queries/match/match.query.ts index a329da9..1b0c559 100644 --- a/src/modules/ad/core/application/queries/match/match.query.ts +++ b/src/modules/ad/core/application/queries/match/match.query.ts @@ -1,11 +1,11 @@ import { QueryBase } from '@mobicoop/ddd-library'; import { AlgorithmType } from '../../types/algorithm.types'; import { Waypoint } from '../../types/waypoint.type'; -import { Frequency, Role } from '@modules/ad/core/domain/ad.types'; +import { Frequency } from '@modules/ad/core/domain/ad.types'; import { MatchRequestDto } from '@modules/ad/interface/grpc-controllers/dtos/match.request.dto'; import { DateTimeTransformerPort } from '../../ports/datetime-transformer.port'; -import { CarpoolRoute } from '../../types/carpool-route.type'; -import { CarpoolRouteProviderPort } from '../../ports/carpool-route-provider.port'; +import { RouteProviderPort } from '../../ports/route-provider.port'; +import { Route } from '@modules/geography/core/domain/route.types'; export class MatchQuery extends QueryBase { driver?: boolean; @@ -28,7 +28,9 @@ export class MatchQuery extends QueryBase { maxDetourDurationRatio?: number; readonly page?: number; readonly perPage?: number; - carpoolRoute?: CarpoolRoute; + driverRoute?: Route; + passengerRoute?: Route; + backAzimuth?: number; constructor(props: MatchRequestDto) { super(); @@ -165,22 +167,68 @@ export class MatchQuery extends QueryBase { return this; }; - setCarpoolRoute = async ( - carpoolRouteProvider: CarpoolRouteProviderPort, - ): Promise => { - const roles: Role[] = []; - if (this.driver) roles.push(Role.DRIVER); - if (this.passenger) roles.push(Role.PASSENGER); + setRoutes = async (routeProvider: RouteProviderPort): Promise => { try { - this.carpoolRoute = await carpoolRouteProvider.getBasic( - roles, - this.waypoints, - ); + ( + await Promise.all( + this._getPaths().map(async (path: Path) => ({ + type: path.type, + route: await routeProvider.getBasic(path.waypoints), + })), + ) + ).forEach((typedRoute: TypedRoute) => { + if (typedRoute.type !== PathType.PASSENGER) { + this.driverRoute = typedRoute.route; + this.backAzimuth = typedRoute.route.backAzimuth; + } + if (typedRoute.type !== PathType.DRIVER) { + this.passengerRoute = typedRoute.route; + if (!this.backAzimuth) + this.backAzimuth = typedRoute.route.backAzimuth; + } + }); } catch (e: any) { throw new Error('Unable to find a route for given waypoints'); } return this; }; + + private _getPaths = (): Path[] => { + const paths: Path[] = []; + if (this.driver && this.passenger) { + if (this.waypoints.length == 2) { + // 2 points => same route for driver and passenger + paths.push(this._createGenericPath(this.waypoints)); + } else { + paths.push( + this._createDriverPath(this.waypoints), + this._createPassengerPath(this.waypoints), + ); + } + } else if (this.driver) { + paths.push(this._createDriverPath(this.waypoints)); + } else if (this.passenger) { + paths.push(this._createPassengerPath(this.waypoints)); + } + return paths; + }; + + private _createGenericPath = (waypoints: Waypoint[]): Path => + this._createPath(waypoints, PathType.GENERIC); + + private _createDriverPath = (waypoints: Waypoint[]): Path => + this._createPath(waypoints, PathType.DRIVER); + + private _createPassengerPath = (waypoints: Waypoint[]): Path => + this._createPath( + [waypoints[0], waypoints[waypoints.length - 1]], + PathType.PASSENGER, + ); + + private _createPath = (waypoints: Waypoint[], type: PathType): Path => ({ + type, + waypoints, + }); } export type ScheduleItem = { @@ -206,3 +254,19 @@ interface DefaultAlgorithmParameters { maxDetourDistanceRatio: number; maxDetourDurationRatio: number; } + +type Path = { + type: PathType; + waypoints: Waypoint[]; +}; + +enum PathType { + GENERIC = 'generic', + DRIVER = 'driver', + PASSENGER = 'passenger', +} + +type TypedRoute = { + type: PathType; + route: Route; +}; diff --git a/src/modules/ad/core/application/queries/match/selector/passenger-oriented.selector.ts b/src/modules/ad/core/application/queries/match/selector/passenger-oriented.selector.ts index 5c828ea..55a394d 100644 --- a/src/modules/ad/core/application/queries/match/selector/passenger-oriented.selector.ts +++ b/src/modules/ad/core/application/queries/match/selector/passenger-oriented.selector.ts @@ -39,7 +39,6 @@ export class PassengerOrientedSelector extends Selector { id: adReadModel.uuid, }, role: adsRole.role, - baseCarpoolRoute: this.query.carpoolRoute, }, ), ) @@ -69,7 +68,7 @@ export class PassengerOrientedSelector extends Selector { ].join(); private _selectAsDriver = (): string => - `${this.query.carpoolRoute?.driverDuration} as duration,${this.query.carpoolRoute?.driverDistance} as distance`; + `${this.query.driverRoute?.duration} as duration,${this.query.driverRoute?.distance} as distance`; private _selectAsPassenger = (): string => `"driverDuration" as duration,"driverDistance" as distance`; @@ -200,7 +199,7 @@ export class PassengerOrientedSelector extends Selector { private _whereAzimuth = (): string => { if (!this.query.useAzimuth) return ''; const { minAzimuth, maxAzimuth } = this._azimuthRange( - this.query.carpoolRoute?.backAzimuth as number, + this.query.backAzimuth as number, this.query.azimuthMargin as number, ); if (minAzimuth <= maxAzimuth) @@ -212,9 +211,9 @@ export class PassengerOrientedSelector extends Selector { if (!this.query.useProportion) return ''; switch (role) { case Role.PASSENGER: - return `(${this.query.carpoolRoute?.passengerDistance}>(${this.query.proportion}*"driverDistance"))`; + return `(${this.query.passengerRoute?.distance}>(${this.query.proportion}*"driverDistance"))`; case Role.DRIVER: - return `("passengerDistance">(${this.query.proportion}*${this.query.carpoolRoute?.driverDistance}))`; + return `("passengerDistance">(${this.query.proportion}*${this.query.driverRoute?.distance}))`; } }; @@ -238,7 +237,7 @@ export class PassengerOrientedSelector extends Selector { ${this.query.remoteness}`; case Role.DRIVER: const lineStringPoints: string[] = []; - this.query.carpoolRoute?.points.forEach((point: Point) => + this.query.driverRoute?.points.forEach((point: Point) => lineStringPoints.push( `public.st_makepoint(${point.lon},${point.lat})`, ), diff --git a/src/modules/ad/core/application/types/algorithm.types.ts b/src/modules/ad/core/application/types/algorithm.types.ts index 83cc2aa..d26b41d 100644 --- a/src/modules/ad/core/application/types/algorithm.types.ts +++ b/src/modules/ad/core/application/types/algorithm.types.ts @@ -1,5 +1,5 @@ +import { Waypoint } from '@modules/geography/core/domain/route.types'; import { Role } from '../../domain/ad.types'; -import { CarpoolRoute } from './carpool-route.type'; export enum AlgorithmType { PASSENGER_ORIENTED = 'PASSENGER_ORIENTED', @@ -11,9 +11,7 @@ export enum AlgorithmType { export type Candidate = { ad: Ad; role: Role; - baseCarpoolRoute: CarpoolRoute; - // driverRoute?: Route; ? - // crewRoute?: Route; ? + waypoints: Waypoint[]; }; export type Ad = { diff --git a/src/modules/ad/core/application/types/carpool-route.type.ts b/src/modules/ad/core/application/types/carpool-route.type.ts index b219701..7b23bfb 100644 --- a/src/modules/ad/core/application/types/carpool-route.type.ts +++ b/src/modules/ad/core/application/types/carpool-route.type.ts @@ -3,7 +3,7 @@ import { Point } from './point.type'; /** * A carpool route is a route with distance and duration as driver and / or passenger */ -export type CarpoolRoute = { +export type Route = { driverDistance?: number; driverDuration?: number; passengerDistance?: number; diff --git a/src/modules/ad/infrastructure/carpool-route-provider.ts b/src/modules/ad/infrastructure/carpool-route-provider.ts deleted file mode 100644 index 97e401e..0000000 --- a/src/modules/ad/infrastructure/carpool-route-provider.ts +++ /dev/null @@ -1,132 +0,0 @@ -import { Inject, Injectable } from '@nestjs/common'; -import { CarpoolRouteProviderPort } from '../core/application/ports/carpool-route-provider.port'; -import { CarpoolRoute } from '../core/application/types/carpool-route.type'; -import { Waypoint } from '../core/application/types/waypoint.type'; -import { Role } from '../core/domain/ad.types'; -import { GetBasicRouteControllerPort } from '@modules/geography/core/application/ports/get-basic-route-controller.port'; -import { AD_GET_BASIC_ROUTE_CONTROLLER } from '../ad.di-tokens'; -import { Route } from '@modules/geography/core/domain/route.types'; - -@Injectable() -export class CarpoolRouteProvider implements CarpoolRouteProviderPort { - constructor( - @Inject(AD_GET_BASIC_ROUTE_CONTROLLER) - private readonly getBasicRouteController: GetBasicRouteControllerPort, - ) {} - - getBasic = async ( - roles: Role[], - waypoints: Waypoint[], - ): Promise => { - const paths: Path[] = this._getPaths(roles, waypoints); - const typeRoutes: TypeRoute[] = await Promise.all( - paths.map( - async (path: Path) => - { - type: path.type, - route: await this.getBasicRouteController.get({ - waypoints, - }), - }, - ), - ); - return this._toCarpoolRoute(typeRoutes); - }; - - private _toCarpoolRoute = (typeRoutes: TypeRoute[]): CarpoolRoute => { - let baseRoute: Route; - let driverRoute: Route | undefined; - let passengerRoute: Route | undefined; - if ( - typeRoutes.some( - (typeRoute: TypeRoute) => typeRoute.type == PathType.GENERIC, - ) - ) { - driverRoute = passengerRoute = typeRoutes.find( - (typeRoute: TypeRoute) => typeRoute.type == PathType.GENERIC, - )?.route; - } else { - driverRoute = typeRoutes.some( - (typeRoute: TypeRoute) => typeRoute.type == PathType.DRIVER, - ) - ? typeRoutes.find( - (typeRoute: TypeRoute) => typeRoute.type == PathType.DRIVER, - )?.route - : undefined; - passengerRoute = typeRoutes.some( - (typeRoute: TypeRoute) => typeRoute.type == PathType.PASSENGER, - ) - ? typeRoutes.find( - (typeRoute: TypeRoute) => typeRoute.type == PathType.PASSENGER, - )?.route - : undefined; - } - if (driverRoute) { - baseRoute = driverRoute; - } else { - baseRoute = passengerRoute as Route; - } - return { - driverDistance: driverRoute?.distance, - driverDuration: driverRoute?.duration, - passengerDistance: passengerRoute?.distance, - passengerDuration: passengerRoute?.duration, - fwdAzimuth: baseRoute.fwdAzimuth, - backAzimuth: baseRoute.backAzimuth, - points: baseRoute.points, - }; - }; - - private _getPaths = (roles: Role[], waypoints: Waypoint[]): Path[] => { - const paths: Path[] = []; - if (roles.includes(Role.DRIVER) && roles.includes(Role.PASSENGER)) { - if (waypoints.length == 2) { - // 2 points => same route for driver and passenger - paths.push(this._createGenericPath(waypoints)); - } else { - paths.push( - this._createDriverPath(waypoints), - this._createPassengerPath(waypoints), - ); - } - } else if (roles.includes(Role.DRIVER)) { - paths.push(this._createDriverPath(waypoints)); - } else if (roles.includes(Role.PASSENGER)) { - paths.push(this._createPassengerPath(waypoints)); - } - return paths; - }; - - private _createGenericPath = (waypoints: Waypoint[]): Path => - this._createPath(waypoints, PathType.GENERIC); - - private _createDriverPath = (waypoints: Waypoint[]): Path => - this._createPath(waypoints, PathType.DRIVER); - - private _createPassengerPath = (waypoints: Waypoint[]): Path => - this._createPath( - [waypoints[0], waypoints[waypoints.length - 1]], - PathType.PASSENGER, - ); - - private _createPath = (waypoints: Waypoint[], type: PathType): Path => ({ - type, - waypoints, - }); -} - -type Path = { - type: PathType; - waypoints: Waypoint[]; -}; - -type TypeRoute = { - type: PathType; - route: Route; -}; - -enum PathType { - GENERIC = 'generic', - DRIVER = 'driver', - PASSENGER = 'passenger', -} diff --git a/src/modules/ad/infrastructure/route-provider.ts b/src/modules/ad/infrastructure/route-provider.ts new file mode 100644 index 0000000..52a0189 --- /dev/null +++ b/src/modules/ad/infrastructure/route-provider.ts @@ -0,0 +1,19 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { RouteProviderPort } from '../core/application/ports/route-provider.port'; +import { Waypoint } from '../core/application/types/waypoint.type'; +import { GetBasicRouteControllerPort } from '@modules/geography/core/application/ports/get-basic-route-controller.port'; +import { AD_GET_BASIC_ROUTE_CONTROLLER } from '../ad.di-tokens'; +import { Route } from '@modules/geography/core/domain/route.types'; + +@Injectable() +export class RouteProvider implements RouteProviderPort { + constructor( + @Inject(AD_GET_BASIC_ROUTE_CONTROLLER) + private readonly getBasicRouteController: GetBasicRouteControllerPort, + ) {} + + getBasic = async (waypoints: Waypoint[]): Promise => + await this.getBasicRouteController.get({ + waypoints, + }); +} diff --git a/src/modules/ad/tests/unit/core/create-ad.service.spec.ts b/src/modules/ad/tests/unit/core/create-ad.service.spec.ts index 9f53e98..d0cfb3e 100644 --- a/src/modules/ad/tests/unit/core/create-ad.service.spec.ts +++ b/src/modules/ad/tests/unit/core/create-ad.service.spec.ts @@ -1,8 +1,5 @@ import { Test, TestingModule } from '@nestjs/testing'; -import { - AD_REPOSITORY, - AD_CARPOOL_ROUTE_PROVIDER, -} from '@modules/ad/ad.di-tokens'; +import { AD_REPOSITORY, AD_ROUTE_PROVIDER } from '@modules/ad/ad.di-tokens'; import { AggregateID } from '@mobicoop/ddd-library'; import { AdEntity } from '@modules/ad/core/domain/ad.entity'; import { ConflictException } from '@mobicoop/ddd-library'; @@ -11,7 +8,7 @@ import { CreateAdService } from '@modules/ad/core/application/commands/create-ad import { CreateAdCommand } from '@modules/ad/core/application/commands/create-ad/create-ad.command'; import { AdAlreadyExistsException } from '@modules/ad/core/domain/ad.errors'; import { WaypointProps } from '@modules/ad/core/domain/value-objects/waypoint.value-object'; -import { CarpoolRouteProviderPort } from '@modules/ad/core/application/ports/carpool-route-provider.port'; +import { RouteProviderPort } from '@modules/ad/core/application/ports/route-provider.port'; const originWaypoint: WaypointProps = { position: 0, @@ -62,12 +59,10 @@ const mockAdRepository = { }), }; -const mockRouteProvider: CarpoolRouteProviderPort = { +const mockRouteProvider: RouteProviderPort = { getBasic: jest.fn().mockImplementation(() => ({ - driverDistance: 350101, - driverDuration: 14422, - passengerDistance: 350101, - passengerDuration: 14422, + distance: 350101, + duration: 14422, fwdAzimuth: 273, backAzimuth: 93, distanceAzimuth: 336544, @@ -99,7 +94,7 @@ describe('create-ad.service', () => { useValue: mockAdRepository, }, { - provide: AD_CARPOOL_ROUTE_PROVIDER, + provide: AD_ROUTE_PROVIDER, useValue: mockRouteProvider, }, CreateAdService, diff --git a/src/modules/ad/tests/unit/core/match.query-handler.spec.ts b/src/modules/ad/tests/unit/core/match.query-handler.spec.ts index 25b7a8a..275b97f 100644 --- a/src/modules/ad/tests/unit/core/match.query-handler.spec.ts +++ b/src/modules/ad/tests/unit/core/match.query-handler.spec.ts @@ -1,12 +1,12 @@ import { AD_REPOSITORY, - AD_CARPOOL_ROUTE_PROVIDER, + AD_ROUTE_PROVIDER, INPUT_DATETIME_TRANSFORMER, PARAMS_PROVIDER, } from '@modules/ad/ad.di-tokens'; import { DateTimeTransformerPort } from '@modules/ad/core/application/ports/datetime-transformer.port'; import { DefaultParamsProviderPort } from '@modules/ad/core/application/ports/default-params-provider.port'; -import { CarpoolRouteProviderPort } from '@modules/ad/core/application/ports/carpool-route-provider.port'; +import { RouteProviderPort } from '@modules/ad/core/application/ports/route-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'; @@ -74,8 +74,15 @@ const mockInputDateTimeTransformer: DateTimeTransformerPort = { time: jest.fn(), }; -const mockRouteProvider: CarpoolRouteProviderPort = { - getBasic: jest.fn(), +const mockRouteProvider: RouteProviderPort = { + getBasic: jest.fn().mockImplementation(() => ({ + distance: 350101, + duration: 14422, + fwdAzimuth: 273, + backAzimuth: 93, + distanceAzimuth: 336544, + points: [], + })), }; describe('Match Query Handler', () => { @@ -98,7 +105,7 @@ describe('Match Query Handler', () => { useValue: mockInputDateTimeTransformer, }, { - provide: AD_CARPOOL_ROUTE_PROVIDER, + provide: AD_ROUTE_PROVIDER, useValue: mockRouteProvider, }, ], diff --git a/src/modules/ad/tests/unit/core/match.query.spec.ts b/src/modules/ad/tests/unit/core/match.query.spec.ts index 3c8c4d5..17440de 100644 --- a/src/modules/ad/tests/unit/core/match.query.spec.ts +++ b/src/modules/ad/tests/unit/core/match.query.spec.ts @@ -1,6 +1,6 @@ import { DateTimeTransformerPort } from '@modules/ad/core/application/ports/datetime-transformer.port'; import { DefaultParams } from '@modules/ad/core/application/ports/default-params.type'; -import { CarpoolRouteProviderPort } from '@modules/ad/core/application/ports/carpool-route-provider.port'; +import { RouteProviderPort } from '@modules/ad/core/application/ports/route-provider.port'; import { MatchQuery } from '@modules/ad/core/application/queries/match/match.query'; import { AlgorithmType } from '@modules/ad/core/application/types/algorithm.types'; import { Waypoint } from '@modules/ad/core/application/types/waypoint.type'; @@ -24,6 +24,14 @@ const destinationWaypoint: Waypoint = { postalCode: '75000', country: 'France', }; +const intermediateWaypoint: Waypoint = { + position: 1, + lat: 48.966912, + lon: 4.3655, + locality: 'Châlons-en-Champagne', + postalCode: '51000', + country: 'France', +}; const defaultParams: DefaultParams = { DEPARTURE_TIME_MARGIN: 900, @@ -50,16 +58,47 @@ const mockInputDateTimeTransformer: DateTimeTransformerPort = { time: jest.fn().mockImplementation(() => '23:05'), }; -const mockRouteProvider: CarpoolRouteProviderPort = { +const mockRouteProvider: RouteProviderPort = { getBasic: jest .fn() .mockImplementationOnce(() => ({ - driverDistance: undefined, - driverDuration: undefined, - passengerDistance: 150120, - passengerDuration: 6540, - fwdAzimuth: 276, - backAzimuth: 96, + distance: 350101, + duration: 14422, + fwdAzimuth: 273, + backAzimuth: 93, + distanceAzimuth: 336544, + points: [], + })) + .mockImplementationOnce(() => ({ + distance: 340102, + duration: 13423, + fwdAzimuth: 273, + backAzimuth: 93, + distanceAzimuth: 336544, + points: [], + })) + .mockImplementationOnce(() => ({ + distance: 350101, + duration: 14422, + fwdAzimuth: 273, + backAzimuth: 93, + distanceAzimuth: 336544, + points: [], + })) + .mockImplementationOnce(() => ({ + distance: 350101, + duration: 14422, + fwdAzimuth: 273, + backAzimuth: 93, + distanceAzimuth: 336544, + points: [], + })) + .mockImplementationOnce(() => ({ + distance: 340102, + duration: 13423, + fwdAzimuth: 273, + backAzimuth: 93, + distanceAzimuth: 336544, points: [], })) .mockImplementationOnce(() => { @@ -143,8 +182,10 @@ describe('Match Query', () => { expect(matchQuery.seatsRequested).toBe(1); }); - it('should set route', async () => { + it('should set route for a driver only', async () => { const matchQuery = new MatchQuery({ + driver: true, + passenger: false, frequency: Frequency.PUNCTUAL, fromDate: '2023-08-28', toDate: '2023-08-28', @@ -155,9 +196,70 @@ describe('Match Query', () => { ], waypoints: [originWaypoint, destinationWaypoint], }); - await matchQuery.setCarpoolRoute(mockRouteProvider); - expect(matchQuery.carpoolRoute?.driverDistance).toBeUndefined(); - expect(matchQuery.carpoolRoute?.passengerDistance).toBe(150120); + await matchQuery.setRoutes(mockRouteProvider); + expect(matchQuery.driverRoute?.distance).toBe(350101); + expect(matchQuery.passengerRoute).toBeUndefined(); + }); + + it('should set route for a passenger only', async () => { + const matchQuery = new MatchQuery({ + driver: false, + passenger: true, + frequency: Frequency.PUNCTUAL, + fromDate: '2023-08-28', + toDate: '2023-08-28', + schedule: [ + { + time: '01:05', + }, + ], + waypoints: [originWaypoint, destinationWaypoint], + }); + await matchQuery.setRoutes(mockRouteProvider); + expect(matchQuery.passengerRoute?.distance).toBe(340102); + expect(matchQuery.driverRoute).toBeUndefined(); + }); + + it('should set route for a driver and passenger', async () => { + const matchQuery = new MatchQuery({ + driver: true, + passenger: true, + frequency: Frequency.PUNCTUAL, + fromDate: '2023-08-28', + toDate: '2023-08-28', + schedule: [ + { + time: '01:05', + }, + ], + waypoints: [originWaypoint, destinationWaypoint], + }); + await matchQuery.setRoutes(mockRouteProvider); + expect(matchQuery.driverRoute?.distance).toBe(350101); + expect(matchQuery.passengerRoute?.distance).toBe(350101); + }); + + it('should set route for a driver and passenger with 3 waypoints', async () => { + const matchQuery = new MatchQuery({ + driver: true, + passenger: true, + frequency: Frequency.PUNCTUAL, + fromDate: '2023-08-28', + toDate: '2023-08-28', + schedule: [ + { + time: '01:05', + }, + ], + waypoints: [ + originWaypoint, + intermediateWaypoint, + { ...destinationWaypoint, position: 2 }, + ], + }); + await matchQuery.setRoutes(mockRouteProvider); + expect(matchQuery.driverRoute?.distance).toBe(350101); + expect(matchQuery.passengerRoute?.distance).toBe(340102); }); it('should throw an exception if route is not found', async () => { @@ -175,7 +277,7 @@ describe('Match Query', () => { waypoints: [originWaypoint, destinationWaypoint], }); await expect( - matchQuery.setCarpoolRoute(mockRouteProvider), + matchQuery.setRoutes(mockRouteProvider), ).rejects.toBeInstanceOf(Error); }); }); diff --git a/src/modules/ad/tests/unit/core/passenger-oriented-geo-filter.spec.ts b/src/modules/ad/tests/unit/core/passenger-oriented-geo-filter.spec.ts index 9d34a9f..43f9533 100644 --- a/src/modules/ad/tests/unit/core/passenger-oriented-geo-filter.spec.ts +++ b/src/modules/ad/tests/unit/core/passenger-oriented-geo-filter.spec.ts @@ -48,56 +48,36 @@ const candidates: Candidate[] = [ id: 'cc260669-1c6d-441f-80a5-19cd59afb777', }, role: Role.DRIVER, - baseCarpoolRoute: { - driverDistance: 350101, - driverDuration: 14422, - passengerDistance: 350101, - passengerDuration: 14422, - fwdAzimuth: 273, - backAzimuth: 93, - points: [ - { - lon: 6.1765102, - lat: 48.689445, - }, - { - lon: 4.984578, - lat: 48.725687, - }, - { - lon: 2.3522, - lat: 48.8566, - }, - ], - }, + waypoints: [ + { + position: 0, + lat: 48.68874, + lon: 6.18546, + }, + { + position: 1, + lat: 48.87845, + lon: 2.36547, + }, + ], }, { ad: { id: '5600ccfb-ab69-4d03-aa30-0fbe84fcedc0', }, role: Role.PASSENGER, - baseCarpoolRoute: { - driverDistance: 350101, - driverDuration: 14422, - passengerDistance: 350101, - passengerDuration: 14422, - fwdAzimuth: 273, - backAzimuth: 93, - points: [ - { - lon: 6.1765102, - lat: 48.689445, - }, - { - lon: 4.984578, - lat: 48.725687, - }, - { - lon: 2.3522, - lat: 48.8566, - }, - ], - }, + waypoints: [ + { + position: 0, + lat: 48.69844, + lon: 6.168484, + }, + { + position: 1, + lat: 48.855648, + lon: 2.34645, + }, + ], }, ]; diff --git a/src/modules/ad/tests/unit/core/passenger-oriented-selector.spec.ts b/src/modules/ad/tests/unit/core/passenger-oriented-selector.spec.ts index 1b9860d..85911f1 100644 --- a/src/modules/ad/tests/unit/core/passenger-oriented-selector.spec.ts +++ b/src/modules/ad/tests/unit/core/passenger-oriented-selector.spec.ts @@ -48,13 +48,33 @@ const matchQuery = new MatchQuery({ strict: false, waypoints: [originWaypoint, destinationWaypoint], }); -matchQuery.carpoolRoute = { - driverDistance: 150120, - driverDuration: 6540, - passengerDistance: 150120, - passengerDuration: 6540, +matchQuery.driverRoute = { + distance: 150120, + duration: 6540, fwdAzimuth: 276, backAzimuth: 96, + distanceAzimuth: 148321, + points: [ + { + lat: 48.689445, + lon: 6.17651, + }, + { + lat: 48.7566, + lon: 4.3522, + }, + { + lat: 48.8566, + lon: 2.3522, + }, + ], +}; +matchQuery.passengerRoute = { + distance: 150120, + duration: 6540, + fwdAzimuth: 276, + backAzimuth: 96, + distanceAzimuth: 148321, points: [ { lat: 48.689445, diff --git a/src/modules/ad/tests/unit/core/passenger-oriented-waypoints-completer.spec.ts b/src/modules/ad/tests/unit/core/passenger-oriented-waypoints-completer.spec.ts index 5ca81c3..43d898b 100644 --- a/src/modules/ad/tests/unit/core/passenger-oriented-waypoints-completer.spec.ts +++ b/src/modules/ad/tests/unit/core/passenger-oriented-waypoints-completer.spec.ts @@ -48,56 +48,36 @@ const candidates: Candidate[] = [ id: 'cc260669-1c6d-441f-80a5-19cd59afb777', }, role: Role.DRIVER, - baseCarpoolRoute: { - driverDistance: 350101, - driverDuration: 14422, - passengerDistance: 350101, - passengerDuration: 14422, - fwdAzimuth: 273, - backAzimuth: 93, - points: [ - { - lon: 6.1765102, - lat: 48.689445, - }, - { - lon: 4.984578, - lat: 48.725687, - }, - { - lon: 2.3522, - lat: 48.8566, - }, - ], - }, + waypoints: [ + { + position: 0, + lat: 48.69, + lon: 6.18, + }, + { + position: 1, + lat: 48.87, + lon: 2.37, + }, + ], }, { ad: { id: '5600ccfb-ab69-4d03-aa30-0fbe84fcedc0', }, role: Role.PASSENGER, - baseCarpoolRoute: { - driverDistance: 350101, - driverDuration: 14422, - passengerDistance: 350101, - passengerDuration: 14422, - fwdAzimuth: 273, - backAzimuth: 93, - points: [ - { - lon: 6.1765102, - lat: 48.689445, - }, - { - lon: 4.984578, - lat: 48.725687, - }, - { - lon: 2.3522, - lat: 48.8566, - }, - ], - }, + waypoints: [ + { + position: 0, + lat: 48.63584, + lon: 6.148754, + }, + { + position: 1, + lat: 48.89874, + lon: 2.368745, + }, + ], }, ]; diff --git a/src/modules/ad/tests/unit/infrastructure/ad.repository.spec.ts b/src/modules/ad/tests/unit/infrastructure/ad.repository.spec.ts index ce217c6..1ba6e92 100644 --- a/src/modules/ad/tests/unit/infrastructure/ad.repository.spec.ts +++ b/src/modules/ad/tests/unit/infrastructure/ad.repository.spec.ts @@ -1,10 +1,10 @@ import { AD_DIRECTION_ENCODER, AD_MESSAGE_PUBLISHER, - AD_CARPOOL_ROUTE_PROVIDER, + AD_ROUTE_PROVIDER, } from '@modules/ad/ad.di-tokens'; import { AdMapper } from '@modules/ad/ad.mapper'; -import { CarpoolRouteProviderPort } from '@modules/ad/core/application/ports/carpool-route-provider.port'; +import { RouteProviderPort } from '@modules/ad/core/application/ports/route-provider.port'; import { Frequency } from '@modules/ad/core/domain/ad.types'; import { AdReadModel, @@ -24,7 +24,7 @@ const mockDirectionEncoder: DirectionEncoderPort = { decode: jest.fn(), }; -const mockRouteProvider: CarpoolRouteProviderPort = { +const mockRouteProvider: RouteProviderPort = { getBasic: jest.fn(), }; @@ -173,7 +173,7 @@ describe('Ad repository', () => { useValue: mockDirectionEncoder, }, { - provide: AD_CARPOOL_ROUTE_PROVIDER, + provide: AD_ROUTE_PROVIDER, useValue: mockRouteProvider, }, { diff --git a/src/modules/ad/tests/unit/infrastructure/carpool-route-provider.spec.ts b/src/modules/ad/tests/unit/infrastructure/carpool-route-provider.spec.ts deleted file mode 100644 index 3e96571..0000000 --- a/src/modules/ad/tests/unit/infrastructure/carpool-route-provider.spec.ts +++ /dev/null @@ -1,230 +0,0 @@ -import { AD_GET_BASIC_ROUTE_CONTROLLER } from '@modules/ad/ad.di-tokens'; -import { CarpoolRoute } from '@modules/ad/core/application/types/carpool-route.type'; -import { Point } from '@modules/ad/core/application/types/point.type'; -import { Role } from '@modules/ad/core/domain/ad.types'; -import { CarpoolRouteProvider } from '@modules/ad/infrastructure/carpool-route-provider'; -import { GetBasicRouteControllerPort } from '@modules/geography/core/application/ports/get-basic-route-controller.port'; -import { Test, TestingModule } from '@nestjs/testing'; - -const originPoint: Point = { - lat: 48.689445, - lon: 6.17651, -}; -const destinationPoint: Point = { - lat: 48.8566, - lon: 2.3522, -}; -const additionalPoint: Point = { - lon: 48.7566, - lat: 4.4498, -}; - -const mockGetBasicRouteController: GetBasicRouteControllerPort = { - get: jest - .fn() - .mockImplementationOnce(() => ({ - distance: 350101, - duration: 14422, - fwdAzimuth: 273, - backAzimuth: 93, - distanceAzimuth: 336544, - points: [ - { - lon: 6.1765102, - lat: 48.689445, - }, - { - lon: 4.984578, - lat: 48.725687, - }, - { - lon: 2.3522, - lat: 48.8566, - }, - ], - })) - .mockImplementationOnce(() => ({ - distance: 350102, - duration: 14423, - fwdAzimuth: 273, - backAzimuth: 93, - distanceAzimuth: 336545, - points: [ - { - lon: 6.1765103, - lat: 48.689446, - }, - { - lon: 4.984579, - lat: 48.725688, - }, - { - lon: 2.3523, - lat: 48.8567, - }, - ], - })) - .mockImplementationOnce(() => ({ - distance: 350100, - duration: 14421, - fwdAzimuth: 273, - backAzimuth: 93, - distanceAzimuth: 336543, - points: [ - { - lon: 6.1765101, - lat: 48.689444, - }, - { - lon: 4.984577, - lat: 48.725686, - }, - { - lon: 2.3521, - lat: 48.8565, - }, - ], - })) - .mockImplementationOnce(() => ({ - distance: 350107, - duration: 14427, - fwdAzimuth: 273, - backAzimuth: 93, - distanceAzimuth: 336548, - points: [ - { - lon: 6.1765101, - lat: 48.689444, - }, - { - lon: 4.984577, - lat: 48.725686, - }, - { - lon: 2.3521, - lat: 48.8565, - }, - ], - })) - .mockImplementationOnce(() => ({ - distance: 350108, - duration: 14428, - fwdAzimuth: 273, - backAzimuth: 93, - distanceAzimuth: 336548, - points: [ - { - lon: 6.1765101, - lat: 48.689444, - }, - { - lon: 4.984577, - lat: 48.725686, - }, - { - lon: 2.3521, - lat: 48.8565, - }, - ], - })) - .mockImplementationOnce(() => []), -}; - -describe('Carpool route provider', () => { - let carpoolRouteProvider: CarpoolRouteProvider; - - beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - CarpoolRouteProvider, - { - provide: AD_GET_BASIC_ROUTE_CONTROLLER, - useValue: mockGetBasicRouteController, - }, - ], - }).compile(); - - carpoolRouteProvider = - module.get(CarpoolRouteProvider); - }); - - it('should be defined', () => { - expect(carpoolRouteProvider).toBeDefined(); - }); - - it('should provide a carpool route for a driver only', async () => { - const carpoolRoute: CarpoolRoute = await carpoolRouteProvider.getBasic( - [Role.DRIVER], - [ - { - position: 0, - ...originPoint, - }, - { - position: 1, - ...destinationPoint, - }, - ], - ); - expect(carpoolRoute.driverDistance).toBe(350101); - expect(carpoolRoute.passengerDuration).toBeUndefined(); - }); - - it('should provide a carpool route for a passenger only', async () => { - const carpoolRoute: CarpoolRoute = await carpoolRouteProvider.getBasic( - [Role.PASSENGER], - [ - { - position: 0, - ...originPoint, - }, - { - position: 1, - ...destinationPoint, - }, - ], - ); - expect(carpoolRoute.passengerDistance).toBe(350102); - expect(carpoolRoute.driverDuration).toBeUndefined(); - }); - - it('should provide a simple carpool route for a driver and passenger', async () => { - const carpoolRoute: CarpoolRoute = await carpoolRouteProvider.getBasic( - [Role.DRIVER, Role.PASSENGER], - [ - { - position: 0, - ...originPoint, - }, - { - position: 1, - ...destinationPoint, - }, - ], - ); - expect(carpoolRoute.driverDuration).toBe(14421); - expect(carpoolRoute.passengerDistance).toBe(350100); - }); - - it('should provide a complex carpool route for a driver and passenger', async () => { - const carpoolRoute: CarpoolRoute = await carpoolRouteProvider.getBasic( - [Role.DRIVER, Role.PASSENGER], - [ - { - position: 0, - ...originPoint, - }, - { - position: 1, - ...additionalPoint, - }, - { - position: 2, - ...destinationPoint, - }, - ], - ); - expect(carpoolRoute.driverDistance).toBe(350107); - expect(carpoolRoute.passengerDuration).toBe(14428); - }); -}); diff --git a/src/modules/ad/tests/unit/infrastructure/route-provider.spec.ts b/src/modules/ad/tests/unit/infrastructure/route-provider.spec.ts new file mode 100644 index 0000000..4791b9b --- /dev/null +++ b/src/modules/ad/tests/unit/infrastructure/route-provider.spec.ts @@ -0,0 +1,76 @@ +import { AD_GET_BASIC_ROUTE_CONTROLLER } from '@modules/ad/ad.di-tokens'; +import { Point } from '@modules/ad/core/application/types/point.type'; +import { RouteProvider } from '@modules/ad/infrastructure/route-provider'; +import { GetBasicRouteControllerPort } from '@modules/geography/core/application/ports/get-basic-route-controller.port'; +import { Route } from '@modules/geography/core/domain/route.types'; +import { Test, TestingModule } from '@nestjs/testing'; + +const originPoint: Point = { + lat: 48.689445, + lon: 6.17651, +}; +const destinationPoint: Point = { + lat: 48.8566, + lon: 2.3522, +}; + +const mockGetBasicRouteController: GetBasicRouteControllerPort = { + get: jest.fn().mockImplementationOnce(() => ({ + distance: 350101, + duration: 14422, + fwdAzimuth: 273, + backAzimuth: 93, + distanceAzimuth: 336544, + points: [ + { + lon: 6.1765102, + lat: 48.689445, + }, + { + lon: 4.984578, + lat: 48.725687, + }, + { + lon: 2.3522, + lat: 48.8566, + }, + ], + })), +}; + +describe('Route provider', () => { + let routeProvider: RouteProvider; + + beforeAll(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + RouteProvider, + { + provide: AD_GET_BASIC_ROUTE_CONTROLLER, + useValue: mockGetBasicRouteController, + }, + ], + }).compile(); + + routeProvider = module.get(RouteProvider); + }); + + it('should be defined', () => { + expect(routeProvider).toBeDefined(); + }); + + it('should provide a route', async () => { + const route: Route = await routeProvider.getBasic([ + { + position: 0, + ...originPoint, + }, + { + position: 1, + ...destinationPoint, + }, + ]); + expect(route.distance).toBe(350101); + expect(route.duration).toBe(14422); + }); +}); diff --git a/src/modules/geography/core/domain/route.types.ts b/src/modules/geography/core/domain/route.types.ts index 9340718..43855bc 100644 --- a/src/modules/geography/core/domain/route.types.ts +++ b/src/modules/geography/core/domain/route.types.ts @@ -27,7 +27,7 @@ export type Route = { backAzimuth: number; distanceAzimuth: number; points: Point[]; - steps: Step[]; + steps?: Step[]; }; export type Point = { diff --git a/src/modules/geography/interface/dtos/route.response.dto.ts b/src/modules/geography/interface/dtos/route.response.dto.ts index c157585..21d2ec1 100644 --- a/src/modules/geography/interface/dtos/route.response.dto.ts +++ b/src/modules/geography/interface/dtos/route.response.dto.ts @@ -1,10 +1,11 @@ import { Point, Step } from '@modules/geography/core/domain/route.types'; export class RouteResponseDto { - distance?: number; - duration?: number; + distance: number; + duration: number; fwdAzimuth: number; backAzimuth: number; distanceAzimuth: number; - points: Step[] | Point[]; + points: Point[]; + steps?: Step[]; } diff --git a/src/modules/geography/route.mapper.ts b/src/modules/geography/route.mapper.ts index c7d6eef..6353bad 100644 --- a/src/modules/geography/route.mapper.ts +++ b/src/modules/geography/route.mapper.ts @@ -16,12 +16,8 @@ export class RouteMapper { toResponse = (entity: RouteEntity): RouteResponseDto => { const response = new RouteResponseDto(); - response.distance = entity.getProps().distance - ? Math.round(entity.getProps().distance as number) - : undefined; - response.duration = entity.getProps().duration - ? Math.round(entity.getProps().duration as number) - : undefined; + response.distance = Math.round(entity.getProps().distance); + response.duration = Math.round(entity.getProps().duration); response.fwdAzimuth = Math.round(entity.getProps().fwdAzimuth); response.backAzimuth = Math.round(entity.getProps().backAzimuth); response.distanceAzimuth = Math.round(entity.getProps().distanceAzimuth); diff --git a/src/modules/geography/tests/unit/infrastructure/graphhopper-georouter.spec.ts b/src/modules/geography/tests/unit/infrastructure/graphhopper-georouter.spec.ts index 1a40b5d..9686644 100644 --- a/src/modules/geography/tests/unit/infrastructure/graphhopper-georouter.spec.ts +++ b/src/modules/geography/tests/unit/infrastructure/graphhopper-georouter.spec.ts @@ -4,7 +4,7 @@ import { GeorouterUnavailableException, RouteNotFoundException, } from '@modules/geography/core/domain/route.errors'; -import { Route } from '@modules/geography/core/domain/route.types'; +import { Route, Step } from '@modules/geography/core/domain/route.types'; import { GEODESIC, PARAMS_PROVIDER, @@ -411,8 +411,8 @@ describe('Graphhopper Georouter', () => { }, ); expect(route.steps).toHaveLength(2); - expect(route.steps[1].duration).toBe(1800); - expect(route.steps[1].distance).toBeUndefined(); + expect((route.steps as Step[])[1].duration).toBe(1800); + expect((route.steps as Step[])[1].distance).toBeUndefined(); }); it('should create one route with points and missed waypoints extrapolations', async () => { @@ -468,8 +468,8 @@ describe('Graphhopper Georouter', () => { points: true, }, ); - expect(route.steps.length).toBe(3); - expect(route.steps[1].duration).toBe(990); - expect(route.steps[1].distance).toBe(25000); + expect(route.steps).toHaveLength(3); + expect((route.steps as Step[])[1].duration).toBe(990); + expect((route.steps as Step[])[1].distance).toBe(25000); }); });