matcher/src/modules/ad/infrastructure/carpool-route-provider.ts

133 lines
4.1 KiB
TypeScript

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<CarpoolRoute> => {
const paths: Path[] = this.getPaths(roles, waypoints);
const typeRoutes: TypeRoute[] = await Promise.all(
paths.map(
async (path: Path) =>
<TypeRoute>{
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',
}