diff --git a/src/collections/match/helpers/match-finder-2/match-meeting-info.spec.ts b/src/collections/match/helpers/match-finder-2/match-meeting-info.spec.ts index 3833ee0c..ed2f347e 100644 --- a/src/collections/match/helpers/match-finder-2/match-meeting-info.spec.ts +++ b/src/collections/match/helpers/match-finder-2/match-meeting-info.spec.ts @@ -10,7 +10,11 @@ import { shuffler, } from "./match-testing-utils"; import assignMeetingInfoToMatches from "./match-meeting-info"; -import { MatchableUser, MatchWithMeetingInfo } from "./match-types"; +import { + CandidateMatchVariant, + MatchableUser, + MatchWithMeetingInfo, +} from "./match-types"; import otto_treider_test_users_year_0 from "./test-data/test_users_year_0.json"; import otto_treider_test_users_year_1 from "./test-data/test_users_year_1.json"; @@ -77,6 +81,59 @@ describe("Simple Matches", () => { ); }); + it("should assign users to a stand match time slot right after their final match", () => { + const matchFinder = new MatchFinder([audun, kristine], [siri]); + const matches = matchFinder.generateMatches(); + const standLocation = "Resepsjonen"; + const meetingDuration = 900000; // 15 minutes + const matchesWithMeetingInfo = assignMeetingInfoToMatches( + matches, + standLocation, + [{ name: "Sal 1" }, { name: "Sal 2" }], + new Date("2024-06-12T12:00:00+0100"), + meetingDuration, + ); + for (const matchWithMeetingInfo of matchesWithMeetingInfo) { + if (matchWithMeetingInfo.variant === CandidateMatchVariant.UserMatch) + continue; + const latestUserMatchForStandMatchCustomer = matchesWithMeetingInfo + .filter( + (match) => + match.variant === CandidateMatchVariant.UserMatch && + (match.senderId === matchWithMeetingInfo.userId || + match.receiverId === matchWithMeetingInfo.userId), + ) + .reduce((latest, next) => + next.meetingInfo.date.getTime() > latest.meetingInfo.date.getTime() + ? next + : latest, + ); + const latestUserMatchTime = + latestUserMatchForStandMatchCustomer.meetingInfo.date.getTime(); + expect(matchWithMeetingInfo.meetingInfo.date.getTime()).to.eq( + latestUserMatchTime + meetingDuration, + ); + } + }); + + it("should assign the StandMatch date to startTime if the user only has Stand Matches", () => { + const matchFinder = new MatchFinder([audun], [elRi]); + const matches = matchFinder.generateMatches(); + const startTime = new Date("2024-06-12T12:00:00+0100"); + const matchesWithMeetingInfo = assignMeetingInfoToMatches( + matches, + "Resepsjonen", + [{ name: "Sal 1" }, { name: "Sal 2" }], + startTime, + 900000, + ); + for (const matchWithMeetingInfo of matchesWithMeetingInfo) { + expect(matchWithMeetingInfo.meetingInfo.date.getTime()).to.eq( + startTime.getTime(), + ); + } + }); + it("should not be able to be more matches than the location limit at a given time", () => { const senders = createUserGroup("sender", 10, "A", "B", "C"); const receivers = createUserGroup("receiver", 10, "A", "B", "C"); diff --git a/src/collections/match/helpers/match-finder-2/match-meeting-info.ts b/src/collections/match/helpers/match-finder-2/match-meeting-info.ts index d6e6ba38..5f3c5880 100644 --- a/src/collections/match/helpers/match-finder-2/match-meeting-info.ts +++ b/src/collections/match/helpers/match-finder-2/match-meeting-info.ts @@ -107,15 +107,9 @@ function verifyStandMatches( standLocation: string, ) { if ( - standMatches.some( - (match) => - match.meetingInfo.date !== null || - match.meetingInfo.location !== standLocation, - ) + standMatches.some((match) => match.meetingInfo.location !== standLocation) ) { - throw new Error( - "All stand matches must have correct location and no assigned time slot", - ); + throw new Error("All stand matches must have correct location"); } } @@ -213,19 +207,6 @@ function assignMeetingInfoToMatches( startTime: Date, meetingDurationInMS: number, ): MatchWithMeetingInfo[] { - const standMatches: CandidateStandMatch[] = matches - .filter((match) => match.variant === CandidateMatchVariant.StandMatch) - .map((match) => match as CandidateStandMatch); - - const standMatchesWithMeetingInfo: StandMatchWithMeetingInfo[] = - standMatches.map((match) => ({ - ...match, - meetingInfo: { - location: standLocation, - date: null, - }, - })); - const userMatches: CandidateUserMatch[] = matches .filter((match) => match.variant === CandidateMatchVariant.UserMatch) .map((match) => match as CandidateUserMatch); @@ -300,8 +281,6 @@ function assignMeetingInfoToMatches( }); } } - - verifyStandMatches(standMatchesWithMeetingInfo, standLocation); verifyUserMatches( userMatches, userMatchesWithMeetingInfo, @@ -309,6 +288,33 @@ function assignMeetingInfoToMatches( userMatchLocations, ); + const standMatches: CandidateStandMatch[] = matches + .filter((match) => match.variant === CandidateMatchVariant.StandMatch) + .map((match) => match as CandidateStandMatch); + + const standMatchesWithMeetingInfo: StandMatchWithMeetingInfo[] = + standMatches.map((match) => ({ + ...match, + meetingInfo: { + location: standLocation, + date: new Date( + userMatchesWithMeetingInfo + .filter( + (matchWithMeetingInfo) => + matchWithMeetingInfo.senderId === match.userId || + matchWithMeetingInfo.receiverId === match.userId, + ) + .reduce((latestTime, next) => { + const potentialTime = + next.meetingInfo.date.getTime() + meetingDurationInMS; + return potentialTime > latestTime ? potentialTime : latestTime; + }, startTime.getTime()), + ), + }, + })); + + verifyStandMatches(standMatchesWithMeetingInfo, standLocation); + return [...userMatchesWithMeetingInfo, ...standMatchesWithMeetingInfo]; } diff --git a/src/collections/match/helpers/match-finder-2/match-types.ts b/src/collections/match/helpers/match-finder-2/match-types.ts index 63bf78d0..d7196c89 100644 --- a/src/collections/match/helpers/match-finder-2/match-types.ts +++ b/src/collections/match/helpers/match-finder-2/match-types.ts @@ -27,7 +27,7 @@ export type CandidateMatch = CandidateStandMatch | CandidateUserMatch; interface MatchMeetingInfo { meetingInfo: { location: string; - date: Date | null; + date: Date; }; } diff --git a/src/collections/match/match.schema.ts b/src/collections/match/match.schema.ts index ffd1cf21..2baafa02 100644 --- a/src/collections/match/match.schema.ts +++ b/src/collections/match/match.schema.ts @@ -38,8 +38,7 @@ const matchBaseSchema = { }, meetingInfo: { location: { type: String, required: true }, - // Can be null in case of a StandMatch - date: Date, + date: { type: Date, required: true }, }, };