Skip to content

Commit

Permalink
Adjust overlaps check for zones and communities in /company route (#154)
Browse files Browse the repository at this point in the history
* Adjust overlaps check for zones and communities in /company route

* Format

* Add test for overlap check in /company route

	closes #143

* Run unit tests after e2e tests

* wip

* wip

* wip

* Rename tests for intersects

* Change intersects test

* Format

* wip
  • Loading branch information
nilspenzel authored Sep 26, 2024
1 parent 2472849 commit 7ce13f2
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 48 deletions.
2 changes: 1 addition & 1 deletion src/lib/bookingApiParameters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { BusStop } from './busStop';
import type { Capacities } from './capacities';
import type { Coordinates } from './location';

export type BookingRequestParameters = {
export type CheckBookingValidityParameters = {
userChosen: Coordinates;
busStops: BusStop[];
startFixed: boolean;
Expand Down
15 changes: 15 additions & 0 deletions src/lib/sqlHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,18 @@ export const covers = (
): RawBuilder<boolean> => {
return sql<boolean>`ST_Covers(zone.area, ST_SetSRID(ST_MakePoint(${coordinates!.lng}, ${coordinates!.lat}),${SRID}))`;
};

export const intersects = async (compulsory: number, community: number): Promise<boolean> => {
return (
(await db
.selectFrom('zone as compulsory_area')
.where('compulsory_area.id', '=', compulsory)
.innerJoin(
(eb) => eb.selectFrom('zone').where('id', '=', community).selectAll().as('community'),
(join) => join.onTrue()
)
.where(sql<boolean>`ST_Area(ST_Intersection(compulsory_area.area, community.area)) >= 1`)
.selectAll()
.executeTakeFirst()) != undefined
);
};
36 changes: 13 additions & 23 deletions src/routes/(user)/company/+page.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import type { PageServerLoad, Actions } from './$types.js';
import { fail } from '@sveltejs/kit';
import { db } from '$lib/database';
import { AddressGuess, geoCode } from '$lib/api.js';
import { sql } from 'kysely';
import { covers } from '$lib/sqlHelpers.js';
import type { Coordinates } from '$lib/location.js';
import { covers, intersects } from '$lib/sqlHelpers.js';

export const load: PageServerLoad = async (event) => {
const companyId = event.locals.user?.company;
Expand Down Expand Up @@ -72,32 +72,13 @@ export const actions = {
return fail(400, { error: 'Die Addresse konnte nicht gefunden werden.' });
}

if (
!(await db
.selectFrom('zone')
.where((eb) =>
eb.and([eb('zone.id', '=', community_area), covers(eb, bestAddressGuess!.pos)])
)
.executeTakeFirst())
) {
if (!(await contains(community_area, bestAddressGuess.pos))) {
return fail(400, {
error: 'Die Addresse liegt nicht in der ausgewählten Gemeinde.'
});
}

if (
!(await db
.selectFrom('zone as compulsory_area')
.where('compulsory_area.id', '=', zone)
.innerJoin(
(eb) =>
eb.selectFrom('zone').where('id', '=', community_area).selectAll().as('community'),
(join) => join.onTrue()
)
.where(sql<boolean>`ST_Intersects(compulsory_area.area, community.area)`)
.selectAll()
.executeTakeFirst())
) {
if (!(await intersects(zone, community_area))) {
return fail(400, {
error: 'Die Gemeinde liegt nicht im Pflichtfahrgebiet.'
});
Expand All @@ -119,3 +100,12 @@ export const actions = {
return { success: true };
}
} satisfies Actions;

const contains = async (community: number, coordinates: Coordinates): Promise<boolean> => {
return (
(await db
.selectFrom('zone')
.where((eb) => eb.and([eb('zone.id', '=', community), covers(eb, coordinates!)]))
.executeTakeFirst()) != undefined
);
};
87 changes: 87 additions & 0 deletions src/routes/(user)/company/intersects.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { db } from '$lib/database';
import { sql } from 'kysely';
import { describe, expect, it } from 'vitest';
import { intersects } from '$lib/sqlHelpers';

type ZonePair = {
compulsory: number;
community: number;
};

describe('intersects test', () => {
const useOldMethod = (zones: ZonePair[]) => {
return zones.map(
async (z) =>
(await db
.selectFrom('zone as compulsory_area')
.where('compulsory_area.id', '=', z.compulsory)
.innerJoin(
(eb) => eb.selectFrom('zone').where('id', '=', z.community).selectAll().as('community'),
(join) => join.onTrue()
)
.where(sql<boolean>`ST_Intersects(compulsory_area.area, community.area)`)
.selectAll()
.executeTakeFirst()) != undefined
);
};

const useNewMethod = (zones: ZonePair[]) => {
return zones.map(async (z) => await intersects(z.compulsory, z.community));
};

const noOverlaps = [
{ compulsory: 1, community: 34 },
{ compulsory: 1, community: 36 },
{ compulsory: 1, community: 37 },
{ compulsory: 1, community: 39 },
{ compulsory: 1, community: 40 },
{ compulsory: 1, community: 41 }
];
const oneDimensionalOverlaps = [
{ compulsory: 1, community: 35 },
{ compulsory: 1, community: 38 },
{ compulsory: 1, community: 49 },
{ compulsory: 1, community: 57 },
{ compulsory: 1, community: 59 },
{ compulsory: 1, community: 68 }
];
const twoDimensionalOverlaps = [
{ compulsory: 1, community: 7 },
{ compulsory: 1, community: 8 },
{ compulsory: 1, community: 9 },
{ compulsory: 1, community: 10 },
{ compulsory: 1, community: 11 },
{ compulsory: 1, community: 12 }
];

it('compare old and new Intersects method on zones and companies with no overlap', async () => {
const old = useOldMethod(noOverlaps);
for (let i = 0; i != old.length; ++i) {
expect(await old[i]).toBe(false);
}
const newIntersects = useNewMethod(noOverlaps);
for (let i = 0; i != newIntersects.length; ++i) {
expect(await newIntersects[i]).toBe(false);
}
});
it('compare old and new Intersects method on zones and companies with 1-dim overlap', async () => {
const old = useOldMethod(oneDimensionalOverlaps);
for (let i = 0; i != old.length; ++i) {
expect(await old[i]).toBe(true);
}
const newIntersects = useNewMethod(oneDimensionalOverlaps);
for (let i = 0; i != newIntersects.length; ++i) {
expect(await newIntersects[i]).toBe(false);
}
});
it('compare old and new Intersects method on zones and companies with 2-dim overlap', async () => {
const old = useOldMethod(twoDimensionalOverlaps);
for (let i = 0; i != old.length; ++i) {
expect(await old[i]).toBe(true);
}
const newIntersects = useNewMethod(twoDimensionalOverlaps);
for (let i = 0; i != newIntersects.length; ++i) {
expect(await newIntersects[i]).toBe(true);
}
});
});
48 changes: 24 additions & 24 deletions src/routes/api/blacklisting/blacklisting.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { BookingRequestParameters } from '$lib/bookingApiParameters';
import type { CheckBookingValidityParameters } from '$lib/bookingApiParameters';
import { Coordinates } from '$lib/location';
import { describe, it, expect, beforeEach } from 'vitest';
import { getViableBusStops } from './viableBusStops';
Expand Down Expand Up @@ -41,7 +41,7 @@ describe('blacklisting test', () => {
await setAvailability(taxi, dateInXMinutes(0), dateInXMinutes(90));
await setTour(taxi, dateInXMinutes(0), dateInXMinutes(90));

const r: BookingRequestParameters = {
const r: CheckBookingValidityParameters = {
userChosen: inNiesky,
busStops: [{ times: [dateInXMinutes(50)], coordinates: inNiesky }],
startFixed: true,
Expand All @@ -58,7 +58,7 @@ describe('blacklisting test', () => {

await setAvailability(taxi, dateInXMinutes(0), dateInXMinutes(90));

const r: BookingRequestParameters = {
const r: CheckBookingValidityParameters = {
userChosen: inNiesky,
busStops: [{ times: [dateInXMinutes(50)], coordinates: inNiesky }],
startFixed: true,
Expand All @@ -75,7 +75,7 @@ describe('blacklisting test', () => {

await setTour(taxi, dateInXMinutes(0), dateInXMinutes(90));

const r: BookingRequestParameters = {
const r: CheckBookingValidityParameters = {
userChosen: inNiesky,
busStops: [{ times: [dateInXMinutes(50)], coordinates: inNiesky }],
startFixed: true,
Expand All @@ -91,7 +91,7 @@ describe('blacklisting test', () => {
const taxi = await addTaxi(company, capacities);
await setTour(taxi, dateInXMinutes(0), dateInXMinutes(900));

const r: BookingRequestParameters = {
const r: CheckBookingValidityParameters = {
userChosen: inNiesky,
busStops: [
{ times: [dateInXMinutes(50), dateInXMinutes(10)], coordinates: inNiesky },
Expand All @@ -110,7 +110,7 @@ describe('blacklisting test', () => {
const taxi = await addTaxi(company, capacities);
await setTour(taxi, dateInXMinutes(0), dateInXMinutes(900));

const r: BookingRequestParameters = {
const r: CheckBookingValidityParameters = {
userChosen: inNiesky,
busStops: [{ times: [dateInXMinutes(50)], coordinates: inNiesky }],
startFixed: true,
Expand All @@ -126,7 +126,7 @@ describe('blacklisting test', () => {
const taxi = await addTaxi(company, capacities);
await setTour(taxi, dateInXMinutes(0), dateInXMinutes(900));

const r: BookingRequestParameters = {
const r: CheckBookingValidityParameters = {
userChosen: inNiesky,
busStops: [{ times: [dateInXMinutes(50)], coordinates: inZittau }],
startFixed: true,
Expand All @@ -142,7 +142,7 @@ describe('blacklisting test', () => {
const taxi = await addTaxi(company, capacities);
await setTour(taxi, dateInXMinutes(0), dateInXMinutes(900));

const r: BookingRequestParameters = {
const r: CheckBookingValidityParameters = {
userChosen: inZittau,
busStops: [{ times: [dateInXMinutes(50)], coordinates: inNiesky }],
startFixed: true,
Expand All @@ -158,7 +158,7 @@ describe('blacklisting test', () => {
const taxi = await addTaxi(company, capacities);
await setTour(taxi, dateInXMinutes(0), dateInXMinutes(900));

const r: BookingRequestParameters = {
const r: CheckBookingValidityParameters = {
userChosen: inNiesky,
busStops: [{ times: [dateInXMinutes(50)], coordinates: inNiesky }],
startFixed: true,
Expand All @@ -174,7 +174,7 @@ describe('blacklisting test', () => {
const taxi = await addTaxi(company, capacities);
await setTour(taxi, dateInXMinutes(0), dateInXMinutes(900));

const r: BookingRequestParameters = {
const r: CheckBookingValidityParameters = {
userChosen: inNiesky,
busStops: [{ times: [dateInXMinutes(50)], coordinates: inNiesky }],
startFixed: true,
Expand All @@ -190,7 +190,7 @@ describe('blacklisting test', () => {
const taxi = await addTaxi(company, capacities);
await setTour(taxi, dateInXMinutes(0), dateInXMinutes(900));

const r: BookingRequestParameters = {
const r: CheckBookingValidityParameters = {
userChosen: inNiesky,
busStops: [{ times: [dateInXMinutes(50)], coordinates: inNiesky }],
startFixed: true,
Expand All @@ -206,7 +206,7 @@ describe('blacklisting test', () => {
const taxi = await addTaxi(company, capacities);
await setTour(taxi, dateInXMinutes(0), dateInXMinutes(900));

const r: BookingRequestParameters = {
const r: CheckBookingValidityParameters = {
userChosen: inNiesky,
busStops: [{ times: [dateInXMinutes(50)], coordinates: inNiesky }],
startFixed: true,
Expand All @@ -219,7 +219,7 @@ describe('blacklisting test', () => {
it('blacklisting fail, no vehicle', async () => {
await addCompany(Zone.NIESKY);

const r: BookingRequestParameters = {
const r: CheckBookingValidityParameters = {
userChosen: inNiesky,
busStops: [{ times: [dateInXMinutes(50)], coordinates: inNiesky }],
startFixed: true,
Expand All @@ -230,7 +230,7 @@ describe('blacklisting test', () => {
});

it('blacklisting fail, no company', async () => {
const r: BookingRequestParameters = {
const r: CheckBookingValidityParameters = {
userChosen: inNiesky,
busStops: [{ times: [dateInXMinutes(50)], coordinates: inNiesky }],
startFixed: true,
Expand All @@ -244,7 +244,7 @@ describe('blacklisting test', () => {
const capacities: Capacities = { passengers: 3, bikes: 3, wheelchairs: 3, luggage: 3 };
const company = await addCompany(Zone.NIESKY);
await addTaxi(company, capacities);
const r: BookingRequestParameters = {
const r: CheckBookingValidityParameters = {
userChosen: inNiesky,
busStops: [{ times: [dateInXMinutes(50)], coordinates: inNiesky }],
startFixed: true,
Expand All @@ -260,7 +260,7 @@ describe('blacklisting test', () => {
const taxi = await addTaxi(company, capacities);
await setTour(taxi, dateInXMinutes(0), dateInXMinutes(900));

const r: BookingRequestParameters = {
const r: CheckBookingValidityParameters = {
userChosen: inNiesky,
busStops: [
{ times: [dateInXMinutes(50)], coordinates: inZittau },
Expand All @@ -281,7 +281,7 @@ describe('blacklisting test', () => {
const taxi = await addTaxi(company, capacities);
await setTour(taxi, dateInXMinutes(0), dateInXMinutes(900));

const r: BookingRequestParameters = {
const r: CheckBookingValidityParameters = {
userChosen: inNiesky,
busStops: [{ times: [dateInXMinutes(1000), dateInXMinutes(50)], coordinates: inNiesky }],
startFixed: true,
Expand All @@ -294,7 +294,7 @@ describe('blacklisting test', () => {
});

it('blacklisting, no busStops', async () => {
const r: BookingRequestParameters = {
const r: CheckBookingValidityParameters = {
userChosen: inNiesky,
busStops: [],
startFixed: true,
Expand All @@ -309,7 +309,7 @@ describe('blacklisting test', () => {
const company = await addCompany(Zone.NIESKY);
const taxi = await addTaxi(company, capacities);
await setTour(taxi, dateInXMinutes(0), dateInXMinutes(900));
const r: BookingRequestParameters = {
const r: CheckBookingValidityParameters = {
userChosen: inNiesky,
busStops: [
{ times: [], coordinates: inNiesky },
Expand All @@ -329,7 +329,7 @@ describe('blacklisting test', () => {
const company = await addCompany(Zone.NIESKY);
const taxi = await addTaxi(company, capacities);
await setTour(taxi, dateInXMinutes(0), dateInXMinutes(900));
const r: BookingRequestParameters = {
const r: CheckBookingValidityParameters = {
userChosen: inNiesky,
busStops: [{ times: [], coordinates: inNiesky }],
startFixed: true,
Expand All @@ -346,7 +346,7 @@ describe('blacklisting test', () => {

await setAvailability(taxi, dateInXMinutes(0), dateInXMinutes(90));

const r: BookingRequestParameters = {
const r: CheckBookingValidityParameters = {
userChosen: inNiesky,
busStops: [
{
Expand All @@ -368,7 +368,7 @@ describe('blacklisting test', () => {

await setAvailability(taxi, dateInXMinutes(0), dateInXMinutes(90));

const r: BookingRequestParameters = {
const r: CheckBookingValidityParameters = {
userChosen: inNiesky,
busStops: [
{
Expand All @@ -390,7 +390,7 @@ describe('blacklisting test', () => {

await setAvailability(taxi, dateInXMinutes(0), dateInXMinutes(90));

const r: BookingRequestParameters = {
const r: CheckBookingValidityParameters = {
userChosen: inNiesky,
busStops: [
{ times: [dateInXMinutesYMs(0, -MAX_PASSENGER_WAITING_TIME_PICKUP)], coordinates: inNiesky }
Expand All @@ -409,7 +409,7 @@ describe('blacklisting test', () => {

await setAvailability(taxi, dateInXMinutes(0), dateInXMinutes(90));

const r: BookingRequestParameters = {
const r: CheckBookingValidityParameters = {
userChosen: inNiesky,
busStops: [
{
Expand Down

0 comments on commit 7ce13f2

Please sign in to comment.