improve selector

This commit is contained in:
sbriat 2023-09-04 17:29:16 +02:00
parent f0440ed65f
commit e0030aba73
3 changed files with 79 additions and 21 deletions

View File

@ -7,6 +7,7 @@ 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';
@ -14,6 +15,7 @@ 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 {
@ -25,6 +27,8 @@ 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();
} }
@ -50,6 +54,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);
let algorithm: Algorithm; let algorithm: Algorithm;
switch (query.algorithmType) { switch (query.algorithmType) {

View File

@ -1,9 +1,11 @@
import { QueryBase } from '@mobicoop/ddd-library'; import { QueryBase } from '@mobicoop/ddd-library';
import { AlgorithmType } from '../../types/algorithm.types'; import { AlgorithmType } from '../../types/algorithm.types';
import { Waypoint } from '../../types/waypoint.type'; import { Waypoint } from '../../types/waypoint.type';
import { Frequency } from '@modules/ad/core/domain/ad.types'; import { Frequency, Role } from '@modules/ad/core/domain/ad.types';
import { MatchRequestDto } from '@modules/ad/interface/grpc-controllers/dtos/match.request.dto'; import { MatchRequestDto } from '@modules/ad/interface/grpc-controllers/dtos/match.request.dto';
import { DateTimeTransformerPort } from '../../ports/datetime-transformer.port'; import { DateTimeTransformerPort } from '../../ports/datetime-transformer.port';
import { Route } from '../../types/route.type';
import { RouteProviderPort } from '../../ports/route-provider.port';
export class MatchQuery extends QueryBase { export class MatchQuery extends QueryBase {
driver?: boolean; driver?: boolean;
@ -26,6 +28,7 @@ export class MatchQuery extends QueryBase {
maxDetourDurationRatio?: number; maxDetourDurationRatio?: number;
readonly page?: number; readonly page?: number;
readonly perPage?: number; readonly perPage?: number;
route?: Route;
constructor(props: MatchRequestDto) { constructor(props: MatchRequestDto) {
super(); super();
@ -160,6 +163,18 @@ export class MatchQuery extends QueryBase {
})); }));
return this; return this;
}; };
setRoutes = async (routeProvider: RouteProviderPort): Promise<MatchQuery> => {
const roles: Role[] = [];
if (this.driver) roles.push(Role.DRIVER);
if (this.passenger) roles.push(Role.PASSENGER);
try {
this.route = await routeProvider.getBasic(roles, this.waypoints);
} catch (e: any) {
throw new Error('Unable to find a route for given waypoints');
}
return this;
};
} }
type ScheduleItem = { type ScheduleItem = {

View File

@ -1,4 +1,4 @@
import { Role } from '@modules/ad/core/domain/ad.types'; import { Frequency, Role } from '@modules/ad/core/domain/ad.types';
import { Candidate } from '../../../types/algorithm.types'; import { Candidate } from '../../../types/algorithm.types';
import { Selector } from '../algorithm.abstract'; import { Selector } from '../algorithm.abstract';
import { AdReadModel } from '@modules/ad/infrastructure/ad.repository'; import { AdReadModel } from '@modules/ad/infrastructure/ad.repository';
@ -8,15 +8,16 @@ export class PassengerOrientedSelector extends Selector {
const queryStringRoles: QueryStringRole[] = []; const queryStringRoles: QueryStringRole[] = [];
if (this.query.driver) if (this.query.driver)
queryStringRoles.push({ queryStringRoles.push({
query: this.asDriverQueryString(), query: this.createQueryString(Role.DRIVER),
role: Role.DRIVER, role: Role.DRIVER,
}); });
if (this.query.passenger) if (this.query.passenger)
queryStringRoles.push({ queryStringRoles.push({
query: this.asPassengerQueryString(), query: this.createQueryString(Role.PASSENGER),
role: Role.PASSENGER, role: Role.PASSENGER,
}); });
console.log(queryStringRoles);
return ( return (
await Promise.all( await Promise.all(
queryStringRoles.map<Promise<AdsRole>>( queryStringRoles.map<Promise<AdsRole>>(
@ -42,29 +43,66 @@ export class PassengerOrientedSelector extends Selector {
.flat(); .flat();
}; };
private asPassengerQueryString = (): string => `SELECT private createQueryString = (role: Role): string =>
ad.uuid,driver,passenger,frequency,public.st_astext(matcher.ad.waypoints) as waypoints, [
"fromDate","toDate", this.createSelect(role),
"seatsProposed","seatsRequested", this.createFrom(),
strict, 'WHERE',
"driverDuration","driverDistance", this.createWhere(role),
"passengerDuration","passengerDistance", ].join(' ');
"fwdAzimuth","backAzimuth",
si.day,si.time,si.margin
FROM ad LEFT JOIN schedule_item si ON ad.uuid = si."adUuid"
WHERE driver=True`;
private asDriverQueryString = (): string => `SELECT private createSelect = (role: Role): string =>
[
`SELECT
ad.uuid,driver,passenger,frequency,public.st_astext(matcher.ad.waypoints) as waypoints, ad.uuid,driver,passenger,frequency,public.st_astext(matcher.ad.waypoints) as waypoints,
"fromDate","toDate", "fromDate","toDate",
"seatsProposed","seatsRequested", "seatsProposed","seatsRequested",
strict, strict,
"driverDuration","driverDistance",
"passengerDuration","passengerDistance",
"fwdAzimuth","backAzimuth", "fwdAzimuth","backAzimuth",
si.day,si.time,si.margin si.day,si.time,si.margin`,
FROM ad LEFT JOIN schedule_item si ON ad.uuid = si."adUuid" role == Role.DRIVER ? this.selectAsDriver() : this.selectAsPassenger(),
WHERE passenger=True`; ].join();
private selectAsDriver = (): string =>
`${this.query.route?.driverDuration} as duration,${this.query.route?.driverDistance} as distance`;
private selectAsPassenger = (): string =>
`"driverDuration" as duration,"driverDistance" as distance`;
private createFrom = (): string =>
'FROM ad LEFT JOIN schedule_item si ON ad.uuid = si."adUuid"';
private createWhere = (role: Role): string =>
[this.whereRole(role), this.whereStrict(), this.whereDate()].join(' AND ');
private whereRole = (role: Role): string =>
role == Role.PASSENGER ? 'driver=True' : 'passenger=True';
private whereStrict = (): string =>
this.query.strict
? this.query.frequency == Frequency.PUNCTUAL
? `frequency='${Frequency.PUNCTUAL}'`
: `frequency='${Frequency.RECURRENT}'`
: '';
private whereDate = (): string => {
const whereDate = `(
(
"fromDate" <= '${this.query.fromDate}' and "fromDate" <= '${this.query.toDate}' and
"toDate" >= '${this.query.toDate}' and "toDate" >= '${this.query.fromDate}'
) OR (
"fromDate" >= '${this.query.fromDate}' and "fromDate" <= '${this.query.toDate}' and
"toDate" <= '${this.query.toDate}' and "toDate" >= '${this.query.fromDate}'
) OR (
"fromDate" <= '${this.query.fromDate}' and "fromDate" <= '${this.query.toDate}' and
"toDate" <= '${this.query.toDate}' and "toDate" >= '${this.query.fromDate}'
) OR (
"fromDate" >= '${this.query.fromDate}' and "fromDate" <= '${this.query.toDate}' and
"toDate" >= '${this.query.toDate}' and "toDate" >= '${this.query.fromDate}'
)
)`;
return whereDate;
};
} }
export type QueryStringRole = { export type QueryStringRole = {