468 lines
14 KiB
TypeScript
468 lines
14 KiB
TypeScript
import { MatchQuery } from '@modules/ad/core/application/queries/match/match.query';
|
|
import { PassengerOrientedSelector } from '@modules/ad/core/application/queries/match/selector/passenger-oriented.selector';
|
|
import { AlgorithmType } from '@modules/ad/core/application/types/algorithm.types';
|
|
import { AdEntity } from '@modules/ad/core/domain/ad.entity';
|
|
import { CreateAdProps, Frequency } from '@modules/ad/core/domain/ad.types';
|
|
import { ScheduleItemProps } from '@modules/ad/core/domain/value-objects/schedule-item.value-object';
|
|
import { AdRepository } from '@modules/ad/infrastructure/ad.repository';
|
|
import { PrismaService } from '@modules/ad/infrastructure/prisma.service';
|
|
import { WaypointDto } from '@modules/ad/interface/grpc-controllers/dtos/waypoint.dto';
|
|
import { bareMockGeorouter } from '../unit/georouter.mock';
|
|
import {
|
|
Marseille,
|
|
Nice,
|
|
SaintRaphael,
|
|
Toulon,
|
|
driverNiceMarseille,
|
|
monday,
|
|
passengerToulonMarseille,
|
|
thursday,
|
|
wednesday,
|
|
} from './ad.fixtures';
|
|
import { integrationTestingModule } from './integration.setup';
|
|
function baseMatchQuery(
|
|
frequency: Frequency,
|
|
dates: [string, string],
|
|
scheduleItems: ScheduleItemProps[],
|
|
waypoints: WaypointDto[],
|
|
): MatchQuery {
|
|
return new MatchQuery(
|
|
{
|
|
algorithmType: AlgorithmType.PASSENGER_ORIENTED,
|
|
driver: false,
|
|
passenger: false,
|
|
frequency: frequency,
|
|
fromDate: dates[0],
|
|
toDate: dates[1],
|
|
useAzimuth: false,
|
|
useProportion: false,
|
|
remoteness: 15000,
|
|
schedule: scheduleItems,
|
|
strict: false,
|
|
waypoints: waypoints,
|
|
},
|
|
bareMockGeorouter,
|
|
);
|
|
}
|
|
|
|
function passengerQueryToulonMarseille(
|
|
frequency: Frequency,
|
|
dates: [string, string],
|
|
scheduleItems: ScheduleItemProps[],
|
|
): MatchQuery {
|
|
const matchQuery = baseMatchQuery(frequency, dates, scheduleItems, [
|
|
{ position: 0, ...Toulon },
|
|
{ position: 1, ...Marseille },
|
|
]);
|
|
matchQuery.passenger = true;
|
|
matchQuery.passengerRoute = {
|
|
distance: 64000,
|
|
duration: 2460,
|
|
points: [Toulon, Marseille],
|
|
// Not used by this query
|
|
fwdAzimuth: 0,
|
|
backAzimuth: 0,
|
|
distanceAzimuth: 0,
|
|
};
|
|
return matchQuery;
|
|
}
|
|
|
|
function driverQueryNiceMarseille(
|
|
frequency: Frequency,
|
|
dates: [string, string],
|
|
scheduleItems: ScheduleItemProps[],
|
|
): MatchQuery {
|
|
const matchQuery = baseMatchQuery(frequency, dates, scheduleItems, [
|
|
{ position: 0, ...Nice },
|
|
{ position: 1, ...Marseille },
|
|
]);
|
|
matchQuery.driver = true;
|
|
matchQuery.driverRoute = {
|
|
distance: 199000,
|
|
duration: 7668,
|
|
points: [Nice, SaintRaphael, Toulon, Marseille],
|
|
// Not used by this query
|
|
fwdAzimuth: 0,
|
|
backAzimuth: 0,
|
|
distanceAzimuth: 0,
|
|
};
|
|
return matchQuery;
|
|
}
|
|
|
|
describe('PassengerOriented selector', () => {
|
|
let prismaService: PrismaService;
|
|
let adRepository: AdRepository;
|
|
|
|
const insertAd = async (adProps: CreateAdProps): Promise<void> => {
|
|
const ad = AdEntity.create(adProps);
|
|
return adRepository.insertExtra(ad, 'ad');
|
|
};
|
|
|
|
beforeAll(async () => {
|
|
({ prismaService, adRepository } = await integrationTestingModule());
|
|
});
|
|
|
|
afterAll(async () => {
|
|
await prismaService.$disconnect();
|
|
});
|
|
|
|
beforeEach(async () => {
|
|
await prismaService.ad.deleteMany();
|
|
});
|
|
|
|
describe('select', () => {
|
|
it('should find a driver that departs on the same day', async () => {
|
|
await insertAd(
|
|
driverNiceMarseille(
|
|
Frequency.PUNCTUAL,
|
|
['2023-02-01', '2023-02-01'],
|
|
[wednesday('08:30')],
|
|
),
|
|
);
|
|
const passengerOrientedSelector = new PassengerOrientedSelector(
|
|
passengerQueryToulonMarseille(
|
|
Frequency.PUNCTUAL,
|
|
['2023-02-01', '2023-02-01'],
|
|
[wednesday('10:00')],
|
|
),
|
|
adRepository,
|
|
);
|
|
const candidates = await passengerOrientedSelector.select();
|
|
expect(candidates.length).toBe(1);
|
|
});
|
|
|
|
it('should find a passenger that departs on the same day', async () => {
|
|
await insertAd(
|
|
passengerToulonMarseille(
|
|
Frequency.PUNCTUAL,
|
|
['2023-02-01', '2023-02-01'],
|
|
[wednesday('10:00')],
|
|
),
|
|
);
|
|
const passengerOrientedSelector = new PassengerOrientedSelector(
|
|
driverQueryNiceMarseille(
|
|
Frequency.PUNCTUAL,
|
|
['2023-02-01', '2023-02-01'],
|
|
[wednesday('08:30')],
|
|
),
|
|
adRepository,
|
|
);
|
|
const candidates = await passengerOrientedSelector.select();
|
|
expect(candidates.length).toBe(1);
|
|
});
|
|
|
|
it('should find a driver that departs the day before', async () => {
|
|
await insertAd(
|
|
driverNiceMarseille(
|
|
Frequency.PUNCTUAL,
|
|
['2023-02-01', '2023-02-01'],
|
|
[wednesday('23:45')],
|
|
),
|
|
);
|
|
|
|
const passengerOrientedSelector = new PassengerOrientedSelector(
|
|
passengerQueryToulonMarseille(
|
|
Frequency.PUNCTUAL,
|
|
['2023-02-02', '2023-02-02'],
|
|
[thursday('01:15')],
|
|
),
|
|
adRepository,
|
|
);
|
|
const candidates = await passengerOrientedSelector.select();
|
|
expect(candidates.length).toBe(1);
|
|
});
|
|
|
|
it('should find a passenger that departs the day after', async () => {
|
|
await insertAd(
|
|
passengerToulonMarseille(
|
|
Frequency.PUNCTUAL,
|
|
['2023-02-02', '2023-02-02'],
|
|
[thursday('01:15')],
|
|
),
|
|
);
|
|
|
|
const passengerOrientedSelector = new PassengerOrientedSelector(
|
|
driverQueryNiceMarseille(
|
|
Frequency.PUNCTUAL,
|
|
['2023-02-01', '2023-02-01'],
|
|
[wednesday('23:45')],
|
|
),
|
|
adRepository,
|
|
);
|
|
const candidates = await passengerOrientedSelector.select();
|
|
expect(candidates.length).toBe(1);
|
|
});
|
|
|
|
it('should find a driver that departs shortly after midnight', async () => {
|
|
await insertAd(
|
|
driverNiceMarseille(
|
|
Frequency.PUNCTUAL,
|
|
['2023-02-02', '2023-02-02'],
|
|
//01:30 in Nice is 00:30 in UTC
|
|
[thursday('01:30')],
|
|
),
|
|
);
|
|
|
|
const passengerOrientedSelector = new PassengerOrientedSelector(
|
|
passengerQueryToulonMarseille(
|
|
Frequency.PUNCTUAL,
|
|
['2023-02-02', '2023-02-02'],
|
|
[thursday('03:00')],
|
|
),
|
|
adRepository,
|
|
);
|
|
const candidates = await passengerOrientedSelector.select();
|
|
expect(candidates.length).toBe(1);
|
|
});
|
|
|
|
it('should find a passenger that departs shortly after midnight', async () => {
|
|
await insertAd(
|
|
passengerToulonMarseille(
|
|
Frequency.PUNCTUAL,
|
|
['2023-02-02', '2023-02-02'],
|
|
[thursday('03:00')],
|
|
),
|
|
);
|
|
const passengerOrientedSelector = new PassengerOrientedSelector(
|
|
driverQueryNiceMarseille(
|
|
Frequency.PUNCTUAL,
|
|
['2023-02-02', '2023-02-02'],
|
|
[thursday('01:30')],
|
|
),
|
|
adRepository,
|
|
);
|
|
const candidates = await passengerOrientedSelector.select();
|
|
expect(candidates.length).toBe(1);
|
|
});
|
|
|
|
it('should NOT find a driver that departs the day after', async () => {
|
|
await insertAd(
|
|
driverNiceMarseille(
|
|
Frequency.PUNCTUAL,
|
|
['2023-02-02', '2023-02-02'],
|
|
[thursday('08:30')],
|
|
),
|
|
);
|
|
|
|
const passengerOrientedSelector = new PassengerOrientedSelector(
|
|
passengerQueryToulonMarseille(
|
|
Frequency.PUNCTUAL,
|
|
['2023-02-01', '2023-02-01'],
|
|
[wednesday('10:00')],
|
|
),
|
|
adRepository,
|
|
);
|
|
const candidates = await passengerOrientedSelector.select();
|
|
expect(candidates.length).toBe(0);
|
|
});
|
|
|
|
it('should NOT find a passenger that departs the day before', async () => {
|
|
await insertAd(
|
|
passengerToulonMarseille(
|
|
Frequency.PUNCTUAL,
|
|
['2023-02-01', '2023-02-01'],
|
|
[wednesday('10:00')],
|
|
),
|
|
);
|
|
const passengerOrientedSelector = new PassengerOrientedSelector(
|
|
driverQueryNiceMarseille(
|
|
Frequency.PUNCTUAL,
|
|
['2023-02-02', '2023-02-02'],
|
|
[thursday('08:30')],
|
|
),
|
|
adRepository,
|
|
);
|
|
const candidates = await passengerOrientedSelector.select();
|
|
expect(candidates.length).toBe(0);
|
|
});
|
|
|
|
it('should find a recurring driver that interesects', async () => {
|
|
await Promise.all([
|
|
insertAd(
|
|
driverNiceMarseille(
|
|
Frequency.RECURRENT,
|
|
['2023-02-01', '2023-02-28'],
|
|
[wednesday('08:30')],
|
|
),
|
|
),
|
|
insertAd(
|
|
driverNiceMarseille(
|
|
Frequency.RECURRENT,
|
|
['2023-02-01', '2023-02-18'],
|
|
[wednesday('08:30')],
|
|
),
|
|
),
|
|
insertAd(
|
|
driverNiceMarseille(
|
|
Frequency.RECURRENT,
|
|
['2023-02-12', '2023-02-28'],
|
|
[wednesday('08:30')],
|
|
),
|
|
),
|
|
insertAd(
|
|
driverNiceMarseille(
|
|
Frequency.RECURRENT,
|
|
['2023-02-12', '2023-02-18'],
|
|
[wednesday('08:30')],
|
|
),
|
|
),
|
|
]);
|
|
|
|
const passengerOrientedSelector = new PassengerOrientedSelector(
|
|
passengerQueryToulonMarseille(
|
|
Frequency.RECURRENT,
|
|
['2023-02-10', '2023-02-20'],
|
|
[wednesday('10:00')],
|
|
),
|
|
adRepository,
|
|
);
|
|
const candidates = await passengerOrientedSelector.select();
|
|
expect(candidates.length).toBe(4);
|
|
});
|
|
|
|
it("should NOT find a recurring driver that doesn't interesect", async () => {
|
|
await Promise.all([
|
|
insertAd(
|
|
driverNiceMarseille(
|
|
Frequency.RECURRENT,
|
|
['2023-02-01', '2023-02-10'],
|
|
[wednesday('08:30')],
|
|
),
|
|
),
|
|
insertAd(
|
|
driverNiceMarseille(
|
|
Frequency.RECURRENT,
|
|
['2023-02-20', '2023-02-28'],
|
|
[wednesday('08:30')],
|
|
),
|
|
),
|
|
]);
|
|
|
|
const passengerOrientedSelector = new PassengerOrientedSelector(
|
|
passengerQueryToulonMarseille(
|
|
Frequency.RECURRENT,
|
|
['2023-02-12', '2023-02-18'],
|
|
[wednesday('10:00')],
|
|
),
|
|
adRepository,
|
|
);
|
|
const candidates = await passengerOrientedSelector.select();
|
|
expect(candidates.length).toBe(0);
|
|
});
|
|
|
|
it('should find a recurring passenger that interesects', async () => {
|
|
await Promise.all([
|
|
insertAd(
|
|
passengerToulonMarseille(
|
|
Frequency.RECURRENT,
|
|
['2023-02-01', '2023-02-28'],
|
|
[wednesday('10:00')],
|
|
),
|
|
),
|
|
insertAd(
|
|
passengerToulonMarseille(
|
|
Frequency.RECURRENT,
|
|
['2023-02-01', '2023-02-18'],
|
|
[wednesday('10:00')],
|
|
),
|
|
),
|
|
insertAd(
|
|
passengerToulonMarseille(
|
|
Frequency.RECURRENT,
|
|
['2023-02-12', '2023-02-28'],
|
|
[wednesday('10:00')],
|
|
),
|
|
),
|
|
insertAd(
|
|
passengerToulonMarseille(
|
|
Frequency.RECURRENT,
|
|
['2023-02-12', '2023-02-18'],
|
|
[wednesday('10:00')],
|
|
),
|
|
),
|
|
]);
|
|
const passengerOrientedSelector = new PassengerOrientedSelector(
|
|
driverQueryNiceMarseille(
|
|
Frequency.RECURRENT,
|
|
['2023-02-10', '2023-02-20'],
|
|
[wednesday('08:30')],
|
|
),
|
|
adRepository,
|
|
);
|
|
const candidates = await passengerOrientedSelector.select();
|
|
expect(candidates.length).toBe(4);
|
|
});
|
|
|
|
it("should NOT find a recurring passenger that doesn't interesect", async () => {
|
|
await Promise.all([
|
|
insertAd(
|
|
passengerToulonMarseille(
|
|
Frequency.RECURRENT,
|
|
['2023-02-01', '2023-02-10'],
|
|
[wednesday('10:00')],
|
|
),
|
|
),
|
|
insertAd(
|
|
passengerToulonMarseille(
|
|
Frequency.RECURRENT,
|
|
['2023-02-20', '2023-02-28'],
|
|
[wednesday('10:00')],
|
|
),
|
|
),
|
|
]);
|
|
const passengerOrientedSelector = new PassengerOrientedSelector(
|
|
driverQueryNiceMarseille(
|
|
Frequency.RECURRENT,
|
|
['2023-02-12', '2023-02-18'],
|
|
[wednesday('08:30')],
|
|
),
|
|
adRepository,
|
|
);
|
|
const candidates = await passengerOrientedSelector.select();
|
|
expect(candidates.length).toBe(0);
|
|
});
|
|
|
|
it('should find a borderline driver that departs the day before a recurring query', async () => {
|
|
await insertAd(
|
|
driverNiceMarseille(
|
|
Frequency.PUNCTUAL,
|
|
['2023-02-01', '2023-02-01'],
|
|
[wednesday('23:45')],
|
|
),
|
|
);
|
|
|
|
const passengerOrientedSelector = new PassengerOrientedSelector(
|
|
passengerQueryToulonMarseille(
|
|
Frequency.RECURRENT,
|
|
['2023-02-02', '2023-02-28'],
|
|
[monday('13:45'), thursday('01:15')],
|
|
),
|
|
adRepository,
|
|
);
|
|
const candidates = await passengerOrientedSelector.select();
|
|
expect(candidates.length).toBe(1);
|
|
});
|
|
|
|
it('should find a borderline passenger that departs the day after a recurring query', async () => {
|
|
await insertAd(
|
|
passengerToulonMarseille(
|
|
Frequency.PUNCTUAL,
|
|
['2023-02-02', '2023-02-02'],
|
|
[thursday('01:15')],
|
|
),
|
|
);
|
|
|
|
const passengerOrientedSelector = new PassengerOrientedSelector(
|
|
driverQueryNiceMarseille(
|
|
Frequency.RECURRENT,
|
|
['2023-01-01', '2023-02-01'],
|
|
[monday('13:45'), wednesday('23:45')],
|
|
),
|
|
adRepository,
|
|
);
|
|
const candidates = await passengerOrientedSelector.select();
|
|
expect(candidates.length).toBe(1);
|
|
});
|
|
});
|
|
});
|